2025年12月13日·1分で読めます

社内アプリのSSO:SAML/OIDCクレームをロールとチームにマッピングする

社内アプリ向けSSOを安全にする:SAMLやOIDCのクレームをロールやチームにマップし、アカウント連携やデータ欠落時の安全なデフォルトを設定する方法。

社内アプリのSSO:SAML/OIDCクレームをロールとチームにマッピングする

なぜクレームマッピングが社内アプリで重要なのか

シングルサインオンは一見簡単に思えます:「Oktaでサインイン」や「Azure ADでサインイン」をクリックすればログイン完了。問題はその後に何が起きるかです。クレームマッピングが曖昧だと、サポート担当が給与情報を見られるなど過剰な権限が付与されたり、新入社員が初日から必要なツールを開けないといったことが起きます。

社内アプリは公開アプリより扱いが難しいことが多いです。複数のチームで共有され、頻繁に変わるからです。1つのツールをSupport、Finance、Salesが同時に使うことも珍しくありません。組織図が変わり、契約社員が出入りし、チーム名が変わったり分割されたりします。アクセスルールが人の頭の中だけにあると、SSOはその混乱をそのままアプリにコピーしてしまいます。

クレームマッピングは、IdP(グループ、部署、役職など)から来る識別情報を、アプリが理解できる権限に変換する仕組みです。通常、次のような判断が必要になります:

  • アプリ内でどのロールが存在するのか(admin, manager, viewer など)
  • ユーザーがどのチームやワークスペースに属するか
  • 各ロールが何をできるか、各チームが何を閲覧できるか
  • 誰が自動でアクセスを得て、誰が承認を必要とするか

多くの問題は次の2つに起因します:

  • 誤ったマッピング。グループ名が誤って別のロールに一致する、あるいは「All Employees」のような広いグループが誤って管理者権限を与えてしまう。
  • クレームが欠落している。IdPが一部のユーザーにグループを送らない、属性が空である、トークンが大きすぎて切り詰められる。

アプリ側は、安全なデフォルトを用意して、欠落や予期せぬデータが偶発的なアクセスにつながらないようにする必要があります。

SAMLとOIDCのクレームを簡単に説明すると

SSOでサインインすると、IdPはアプリに対してあなたに関する小さな情報の束を送ります。各情報はクレームで、たとえば「email = [email protected]」や「department = Finance」のようなラベル付きフィールドです。

SAMLとOIDCは似たような情報を運べますが、パッケージの仕方が違います。

SAMLは古い企業向けの設定でよく使われ、通常は属性を含むXMLドキュメント(アサーション)を送ります。これらの属性がアプリが読むクレームです。

OIDCは新しく、OAuth 2.0上に構築されています。署名されたJSONトークン(IDトークン)と任意のユーザー情報を送るのが一般的で、トークン内のフィールドがクレームになります。

社内アプリでは、通常次のような少数のクレームを重視します:

  • メールアドレス
  • IdPからの安定したユーザーID(subject)
  • フルネーム(または名と姓)
  • グループ所属(チーム、セキュリティグループ)
  • 部署や役職

1つの区別は混乱を防ぎます:

認証(Authentication)は「この人は誰か」を答えます。subやメールのようなクレームはSSOログインを既存アカウントにリンクするのに役立ちます。

認可(Authorization)は「何ができるか」を答えます。グループや部署のようなクレームは、アプリ内のロールやチームへのマッピングに使います。

2人が正しく認証されても、Billing画面に入れるのは「Finance」グループのクレームを持つ人だけにする、という区別が必要です。

ロールとチーム:何をマップするか決める

SAML属性をマップする前、またはOIDCクレームを権限に変換する前に、アプリが知るべき2つの要素を明確にしてください:

  • ロールは「何ができるか(権限)」を定義します。
  • チームは「どこに属しているか(スコープ)」を定義します。

ロールは「閲覧できるか?編集できるか?承認できるか?エクスポートできるか?ユーザー管理や設定変更はできるか?」といった問いに答えます。

チームは「どの部署、地域、キュー、コストセンターに所属しているか、どのレコードを見られるか?」を決めます。

ロールは小さく安定させてください。多くの社内アプリは、人が移動してもめったに変わらない少数のロールで十分です。チームは日々の実態を反映するようにします:Support Tier 2、EMEA担当、臨時キューの所有者など。

最小権限(Least privilege)が最も安全なデフォルトです。多くの内部アプリは次の3つのロールで足ります:

  • Viewer:データを閲覧し検索を実行できる
  • Editor:レコードを作成・更新できる
  • Admin:設定、ユーザー、アクセスルールを管理できる

各ロールが何を許可するかを分かりやすく書き残してください。これによりグループ名が変わったときの「思わぬ管理者付与」を防ぎ、後でレビューしやすくなります。

グループベースのアクセス:IdPグループの考え方

グループベースのアクセスとは、アプリがユーザー個別に権限を決めるのではなく、IdPがグループ所属を管理し、アプリはそのグループをロールやチームにマッピングする方式です。

まずグループが何を与えるのかを決めます。多くのツールでは1つのグループが1つのロール(例:「Support Agent」)と任意で1つのチーム(例:「Tier 2」)にマップされます。重要なのはマッピングが退屈で予測可能であること:同じグループは常に同じアクセスを意味する、ということです。

ユーザーが複数のグループに属している場合

人はしばしば複数のIdPグループに所属します。その場合にどう解決するかルールが必要で、安定していることが重要です。

一般的なアプローチ:

  • 加算ルール:一致する全てのグループから権限を合算する(権限が狭く分割されている場合に有効)
  • 優先順位ルール:優先度が最も高いグループを選び、他は無視する(ロールが衝突する場合に有用)
  • ハイブリッド:チームは加算、ロールは優先順位で決める

何を選んでも、必ず文書化してください。後でこれを変えると、ユーザーが突然権限を得たり失ったりします。

スケールできる命名規則を使う

分かりやすいグループ名はミスを減らし、監査を簡単にします。実用的なパターンの例:

  • <app>-<env>-<role>

例:support-tool-prod-agent や finance-tool-staging-viewer。これにより「Admins」のような曖昧な名前を複数アプリで使うことを避けられます。

該当するグループにユーザーがいない場合、デフォルトはアクセス無し(または明確に制限されたゲスト状態)にして、アクセス申請方法を説明するメッセージを表示してください。

アカウント連携:SSOユーザーをアプリアカウントに一致させる

Choose your deployment path
Deploy to your cloud or export source code when you need more control over hosting.
Try It

SSOは本人確認をしますが、アプリはその識別をどの既存アカウントに紐づけるか決めなければなりません。アカウント連携がないと、同じ人がメール変更やIdP切り替えで複数アカウントを作ってしまうことがあります。

一次の安定した一意キーを選んでください。

  • OIDCでは通常subクレーム(subject)がこれに当たります。
  • SAMLでは永続的なNameIDや専用の不変ユーザーID属性が使われます。

その値を「IdPユーザーID」として、IdPのissuer/entity IDと一緒に保存してください。これにより別のIdPから同じsubが来ても衝突しません。

メールは便利ですが、それを真の情報源にしないでください。メールはリネーム、ドメイン移行、合併で変わることがあり、エイリアスや共有受信箱が予期せぬマッチを生むこともあります。メールでマッチする場合は、IdPの信号が確認されているときだけにし、ワンタイム確認を検討してください。

初回ログイン時、内部ツールは通常次のいずれかの導入パターンを取ります:

  • 自動作成:アカウントを即座に作成し、最小限のアクセスを付与する
  • 招待のみ:事前作成(あるいは承認済み)のユーザーだけログインを許可する
  • 承認フロー:アカウントを作成するが、ロール/チームの割当てが管理者承認されるまでアクセスをブロックする

安全なデフォルトは、自動作成でロールは付与しない、そしてグループや承認に基づいてアクセスを与える、という方法です。

ステップバイステップ:クレームをロールとチームにマッピングする

Handle team changes cleanly
Update team membership on login so org changes don’t leave permissions stuck forever.
Start App

良いクレームマッピングはSSOを目立たなくします。人はサインインして正しい場所に正しい権限で着地します。

まずアクセスモデルを平易な言葉で書き出してください。各ロール(Viewer, Agent, Manager, Admin)と各チーム(Support, Finance, IT)、それぞれ誰が何故それを持つべきかを列挙します。

次に、IdPが実際に何を送れるか確認します。SAMLでもOIDCでも、安定したユーザーID(subjectやNameID)、メール、1つ以上のグループ属性が欲しいところです。グループ値は実際の表記(大文字小文字、接頭辞を含む)を正確に拾ってください。「Support」と「support」は同一ではありません。

実践的なフロー:

  • ロールとチームを定義し、各項目にオーナー(変更を承認できる人)を割り当てる。
  • IdPから使えるクレームと正確なグループ名を列挙する(契約社員や共有受信箱などの特殊ケースも含める)。
  • マッピングルールを書く:group→role、group→team、複数グループが一致したときの優先順位。
  • 実際のIdPアカウントで3〜5種類のユーザー(新入社員、マネージャー、契約社員、管理者など)を使ってテストする。
  • 各テストユーザーについて、まず期待されるロール/チーム結果を書き、実際にサインインして比較する。

小さな具体例を1つ持っておくとルールが具体化されます。例:ユーザーがokta-supportに所属していればSupportチームでAgentロールになる。もし同時にokta-support-managersに所属していれば、ManagerロールがAgentを上書きする。

最後にデバッグしやすい仕組みを作ってください。受け取った生のクレーム(安全に)、一致したルール、最終的なロール/チーム結果をログに残します。誰かが「サインインしたのにツールが見えない」と言ったとき、これがあれば原因調査が短時間で済みます。

クレームが欠落している場合の安全なデフォルト

クレームの欠落はよくあることです。サービスアカウントにグループが送られないこともあるし、コネクタがフィールドを省略することも、ユーザーが移行途中であることもあります。「データ無し」は「信頼無し」と扱ってください。

最も安全なデフォルトは拒否(deny-by-default)です:ロールなし、チームなし、アクセスなし。アクセス申請のためにログインは許す場合でも読み取り専用など明確に制限された状態にしてください。

1つの振る舞いを選んで文書化しましょう:

  • ログインをブロックし、明確なメッセージを表示:「アクセスが割り当てられていません。管理者に連絡してください。」
  • 警告付きで限定アクセスを許可し、機微な操作を無効にする
  • ユーザー記録は作るがロールやチームは承認まで割り当てない

決して一時的であっても管理者権限をデフォルトにしないでください。

部分的なデータに備えてください。メールは来るがグループがない場合はアカウントを作成して承認へ回すことができます。グループは来るが安定した識別子がない場合は、既存アカウントへ自動で結びつけないでください。誤って別人に紐づく可能性があります。

障害時のエスカレーション経路を用意してください:

  • 担当オーナー(ITやアプリ管理者)がアクセス承認できる
  • 手動のロール割当フローと監査ノート
  • 次回ログインでクレームを再チェックする仕組み
  • 「保留中アクセス」アカウントのタイムアウト

変更、権限剥奪、オフボーディングの扱い

Design safe defaults
Set deny-by-default onboarding so missing groups never become accidental access.
Create App

人はチームを移動し、上司が変わり、退職します。これを普通のこととして扱う仕組みを作ってください。

チーム変更時は次回ログインでアクセスを更新してください:グループクレームを再評価して現在のマッピングを適用します。かつて与えたアクセスがいつまでも残る「sticky」な状態は避けてください。

退職者は別問題です。次回ログインを待っていてはいけません。アクセスを速やかに止めたいなら、IdPで無効化し、アプリは無効化や欠落した識別を即時ブロックする必要があります。

ディプロビジョニングは予測可能であるべきです:ユーザーを無効化し、チーム所属を解除し、監査データは保持します。承認やコメント、履歴などの記録は残しつつ、新しい操作はできないようにします。

契約社員や一時的アクセスには特別な配慮を。IdP側で期限付きのグループに入れる、あるいはロールにレビュー日を付けてプロジェクト終了後に残らないようにしてください。

実用的なオフボーディング方針:

  • ログインごとにクレームを再チェックし、IdPからチーム所属を更新する
  • 必要グループから外れたら、権限を速やかに剥奪する(次回ログインまたは次回同期)
  • アカウントを無効化しつつ監査ログや所有履歴を保持する
  • 契約者アクセスには終了日を要求し、更新前にレビューする
  • 財務や管理者のような機微なロールは定期的なアクセスレビューを行う

よくあるミスと罠

多くのSSO障害はSAMLやOIDC自体が難しいからではありません。アプリが人、グループ、識別子について危険な仮定をしていることが原因です。

よくあるミスの一つはロールマッピングとチームマッピングを混同することです。ロールは「何ができるか」、チームは「どこに属しているか」です。チームグループをそのまま強力なロール(Adminなど)に割り当てると、そのチームに属する誰もが広範な権限を持ってしまいます。

もう一つの落とし穴は、アカウント連携の主キーとしてメールだけを使うことです。メールは変わりますし、エイリアスは重複を生みます。安定したIdPユーザーID(subNameIDなど)を一次キーにし、メールは表示や通知に使う程度に留めてください。

その他の頻出問題:

  • グループが欠落したときに開放してしまう(欠落時にはアクセスなしか低権限にする)
  • 開発・ステージング・本番で曖昧なグループ名を使い回す
  • グループ所属を単なる権限リストと見なして、その意味をレビューしない
  • マルチチームのユーザーが複数領域にアクセスする必要があるのに、ルールが1チームしか許さず管理者化してしまう
  • パートナーや契約社員を従業員専用チームから分離していない

ローンチ前にエッジケースをテストしてください。たとえば、インシデント対応で参画するファイナンスのアナリストは2つのチームと1つの昇格ロールを必要とするかもしれません。ルールが1チームしか許さないと、アクセスを失うか過剰権限を与えてしまいます。

本番前の簡単チェックリスト

Automate access approvals
Build a manager approval step for access requests when groups are missing or unclear.
Try Workflow

全員にSSOを有効化する前に、各チームから数アカウントでドライランを行ってください。新入社員、ロール変更、オフボーディングのテストで大抵の問題は出てきます。

まずアカウント連携を確認します。時間が経っても変わらない一意の識別子を1つ選び、それを使い続けてください。OIDCでは通常sub、SAMLではNameIDや特定の不変属性がこれに該当します。

次に、クレームが欠落したときにどう振る舞うか決めます。最も安全なのは、グループやロールのクレームがない場合に昇格した権限を与えない(多くはアクセス自体を与えない)ことです。ワークフローに合うなら、機微な操作をできない低権限ロールを1つ用意しておくと良いでしょう。

簡単な事前チェックリスト:

  • 連携に使う識別子が安定で一意であることを確認(ログに出ること)
  • グループクレームの欠落が高い権限を与えないことを検証する
  • 管理者アクセスは明示的な管理者グループの一致+追加承認ステップを要求する(手動でも良い)
  • ユーザーがグループを離れたら、アクセスが次回ログインまたは同期で落ちることをテストする
  • マッピングルールを1ページにまとめて、チームメンバーが理解できるようにする

例:サポートとファイナンスの内部ツールとSSOグループ

Ship web and mobile together
Generate backend, web, and native mobile apps from one project for internal teams.
Generate App

日常的にSupport、Finance、数名のマネージャーが使う運用ツールを想像してください。人がサインインすると自動的に正しい画面と操作が割り当てられ、管理者が手動で修正する必要がないようにしたいとします。

いくつかのIdPグループを作り、アプリ内のロールとチームにマッピングします:

  • ops-support → ロール:Support Agent、チーム:Support
  • ops-finance → ロール:Finance Analyst、チーム:Finance
  • ops-managers → ロール:Manager、チーム:Management

ここでの振る舞いは次の通りです。

UserIdP identifier used for linkingIdP groups claimIn-app resultNotes
Maya (Support)sub=00u8...k3ops-supportSupport Agent, Support teamチケットの閲覧、返信、タグ付けはできるが請求ページは見られない
Omar (Manager)sub=00u2...p9ops-support, ops-managersManager, Management teamマッピングルールは上位のロールを選び、Financeは別に扱われる
Lina (Finance)sub=00u5...w1Missing (group claim not sent)デフォルト:アクセスなし(または読み取り専用ゲスト)安全なデフォルトで過剰アクセスを防ぐ。Linaには「アクセスが割り当てられていません。管理者に連絡してください。」が表示される

次にメール変更のケース:Omarが[email protected]から[email protected]に変わっても、アプリがsub(またはSAMLの永続的NameID)でアカウントをリンクしていれば重複アカウントは作られません。履歴や監査トレイルは維持されます。

推測を避けるために、「effective access(実効アクセス)」ビューを用意すると便利です。ユーザーのリンクされたIdP識別、受け取ったグループ、決定されたロール、チームが表示されれば、問題が起きたときにIdP側の問題かマッピングルールの問題か、あるいはクレームの欠落かがすぐ分かります。

次の一手:組織が変わってもアクセスを予測可能に保つ

最初の導入が一番難しいわけではありません。再編や新チーム、例外対応が増えてもアクセスを保守することが最も難しい部分です。

1ページのマッピングドキュメントを用意して、次を明記しておきます:

  • どのIdPグループがどのアプリロールとチームにマップされるか
  • クレームが欠落したときのデフォルト(誰が変更を承認するか)
  • 高リスクロール(財務管理者、ユーザー管理者、データエクスポートなど)の所有者
  • 契約社員やサービスアカウントの扱い
  • 真のソースオブトゥルースがIdPかアプリかどこにあるか

境界が明確な部署で小さなパイロットを行い、エッジケースを直してからルールを増やさずに拡張してください。月次で管理者や高リスクロールのレビュー、四半期ごとに通常ロールのレビューなど、定期的な見直しも設定してください。

内部アプリを自分で開発する場合、ロール、チーム、業務ロジックを近くに置いておくと変更のテストが楽になります。AppMaster(appmaster.io)は、ロールやワークフローを視覚的にモデル化して、要件変更に合わせてバックエンド、Web、モバイルのコードを再生成できるオプションの一つです。ワンオフの権限修正を積み上げることなく管理できます。

よくある質問

What is claim mapping in SSO, and why do internal apps need it?

クレームマッピングとは、IdP(グループ、部署、役職など)が送る情報をアプリのアクセス制御で使うロールやチームに変換する工程です。これがないと、SSOのログインは成功しても、ユーザーが誤った権限でログインしてしまうことがあります。

What should my app do if group claims are missing or empty?

安全なデフォルトは「拒否」を基本にすることです。ユーザーを作成または認識しても、既知のマッピングが一致するまではロールやチームを割り当てないようにします。要件でアクセス申請のための入り口を許可する場合でも、権限は限定的にし、欠落したデータを権限と見なさないでください。

What is the safest way to link an SSO login to an existing app account?

IdPから得られる安定した不変の識別子を一次キーとして使うのが最も安全です。例えばOIDCではsubクレーム、SAMLでは永続的なNameIDや不変の属性を使用します。IdPの発行元(issuer/entity ID)と一緒に保存して、異なるIdPから同じ値が来ても衝突しないようにします。

Why shouldn’t I use email as the main identifier for account linking?

メールは便利な属性として使えますが、唯一の真実のキーにはしないでください。メールは改名、ドメイン変更、合併などで変わることがあります。メールでマッチさせる場合は、IdP側での確認を必須にするか、ワンタイムの確認手順を入れて誤リンクを避けてください。

What’s the difference between roles and teams in an internal app?

ロールは「その人が何をできるか(権限)」を定義し、チームは「どこに属しているか(表示範囲)」を定義します。例:ロールは編集や承認、ユーザー管理など、チームは部署や地域、キュー、コストセンターのようなスコープです。

How many roles should I start with for a typical internal tool?

典型的な内部ツールなら、まずは3つのロールから始めるのが実用的です:Viewer(閲覧のみ)、Editor(作成・更新可能)、Admin(設定やユーザー・アクセス管理)。定義を明文化しておくことで、組織の変化時に誤った権限付与を防げます。

How do I handle users who belong to multiple IdP groups?

一貫した解決ルールを決めて文書化してください。多くのチームはハイブリッド方式を使います:チームの所属は加算(所属を全部合算)、ロールは優先順位で決める(矛盾する場合は優先度の高い方を採用)。

How should we name IdP groups to avoid accidental access?

分かりやすい命名規則を採用してください。アプリ名、環境、ロールを含めるとスケールしやすいです。例:<app>-<env>-<role>。これにより『Admins』のような曖昧なグループ名の使い回しを防げます。

What should I log to debug access issues without guessing?

トークン内容をそのままさらすことなく、到着したクレーム、どのマッピングルールが一致したか、最終的に割り当てられたロール/チームをログに残してください。これがあれば「ツールが見えない」という問い合わせも、クレーム対ルールの照合で素早く原因を特定できます。

How do I keep access accurate when people change teams or leave the company?

ログインごと、あるいは定期同期でクレームを再評価して、アクセスが現在のグループ所属に追随するようにしてください。退職者については次回ログインを待たず、IdP側で無効化されたら即座にアクセスを遮断する仕組みが必要です。操作履歴や承認履歴などの監査データは残しつつ、新たな操作を禁止します。

始めやすい
何かを作成する 素晴らしい

無料プランで AppMaster を試してみてください。
準備が整ったら、適切なサブスクリプションを選択できます。

始める