社内アプリの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ユーザーをアプリアカウントに一致させる
SSOは本人確認をしますが、アプリはその識別をどの既存アカウントに紐づけるか決めなければなりません。アカウント連携がないと、同じ人がメール変更やIdP切り替えで複数アカウントを作ってしまうことがあります。
一次の安定した一意キーを選んでください。
- OIDCでは通常
subクレーム(subject)がこれに当たります。 - SAMLでは永続的な
NameIDや専用の不変ユーザーID属性が使われます。
その値を「IdPユーザーID」として、IdPのissuer/entity IDと一緒に保存してください。これにより別のIdPから同じsubが来ても衝突しません。
メールは便利ですが、それを真の情報源にしないでください。メールはリネーム、ドメイン移行、合併で変わることがあり、エイリアスや共有受信箱が予期せぬマッチを生むこともあります。メールでマッチする場合は、IdPの信号が確認されているときだけにし、ワンタイム確認を検討してください。
初回ログイン時、内部ツールは通常次のいずれかの導入パターンを取ります:
- 自動作成:アカウントを即座に作成し、最小限のアクセスを付与する
- 招待のみ:事前作成(あるいは承認済み)のユーザーだけログインを許可する
- 承認フロー:アカウントを作成するが、ロール/チームの割当てが管理者承認されるまでアクセスをブロックする
安全なデフォルトは、自動作成でロールは付与しない、そしてグループや承認に基づいてアクセスを与える、という方法です。
ステップバイステップ:クレームをロールとチームにマッピングする
良いクレームマッピングは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やアプリ管理者)がアクセス承認できる
- 手動のロール割当フローと監査ノート
- 次回ログインでクレームを再チェックする仕組み
- 「保留中アクセス」アカウントのタイムアウト
変更、権限剥奪、オフボーディングの扱い
人はチームを移動し、上司が変わり、退職します。これを普通のこととして扱う仕組みを作ってください。
チーム変更時は次回ログインでアクセスを更新してください:グループクレームを再評価して現在のマッピングを適用します。かつて与えたアクセスがいつまでも残る「sticky」な状態は避けてください。
退職者は別問題です。次回ログインを待っていてはいけません。アクセスを速やかに止めたいなら、IdPで無効化し、アプリは無効化や欠落した識別を即時ブロックする必要があります。
ディプロビジョニングは予測可能であるべきです:ユーザーを無効化し、チーム所属を解除し、監査データは保持します。承認やコメント、履歴などの記録は残しつつ、新しい操作はできないようにします。
契約社員や一時的アクセスには特別な配慮を。IdP側で期限付きのグループに入れる、あるいはロールにレビュー日を付けてプロジェクト終了後に残らないようにしてください。
実用的なオフボーディング方針:
- ログインごとにクレームを再チェックし、IdPからチーム所属を更新する
- 必要グループから外れたら、権限を速やかに剥奪する(次回ログインまたは次回同期)
- アカウントを無効化しつつ監査ログや所有履歴を保持する
- 契約者アクセスには終了日を要求し、更新前にレビューする
- 財務や管理者のような機微なロールは定期的なアクセスレビューを行う
よくあるミスと罠
多くのSSO障害はSAMLやOIDC自体が難しいからではありません。アプリが人、グループ、識別子について危険な仮定をしていることが原因です。
よくあるミスの一つはロールマッピングとチームマッピングを混同することです。ロールは「何ができるか」、チームは「どこに属しているか」です。チームグループをそのまま強力なロール(Adminなど)に割り当てると、そのチームに属する誰もが広範な権限を持ってしまいます。
もう一つの落とし穴は、アカウント連携の主キーとしてメールだけを使うことです。メールは変わりますし、エイリアスは重複を生みます。安定したIdPユーザーID(subやNameIDなど)を一次キーにし、メールは表示や通知に使う程度に留めてください。
その他の頻出問題:
- グループが欠落したときに開放してしまう(欠落時にはアクセスなしか低権限にする)
- 開発・ステージング・本番で曖昧なグループ名を使い回す
- グループ所属を単なる権限リストと見なして、その意味をレビューしない
- マルチチームのユーザーが複数領域にアクセスする必要があるのに、ルールが1チームしか許さず管理者化してしまう
- パートナーや契約社員を従業員専用チームから分離していない
ローンチ前にエッジケースをテストしてください。たとえば、インシデント対応で参画するファイナンスのアナリストは2つのチームと1つの昇格ロールを必要とするかもしれません。ルールが1チームしか許さないと、アクセスを失うか過剰権限を与えてしまいます。
本番前の簡単チェックリスト
全員にSSOを有効化する前に、各チームから数アカウントでドライランを行ってください。新入社員、ロール変更、オフボーディングのテストで大抵の問題は出てきます。
まずアカウント連携を確認します。時間が経っても変わらない一意の識別子を1つ選び、それを使い続けてください。OIDCでは通常sub、SAMLではNameIDや特定の不変属性がこれに該当します。
次に、クレームが欠落したときにどう振る舞うか決めます。最も安全なのは、グループやロールのクレームがない場合に昇格した権限を与えない(多くはアクセス自体を与えない)ことです。ワークフローに合うなら、機微な操作をできない低権限ロールを1つ用意しておくと良いでしょう。
簡単な事前チェックリスト:
- 連携に使う識別子が安定で一意であることを確認(ログに出ること)
- グループクレームの欠落が高い権限を与えないことを検証する
- 管理者アクセスは明示的な管理者グループの一致+追加承認ステップを要求する(手動でも良い)
- ユーザーがグループを離れたら、アクセスが次回ログインまたは同期で落ちることをテストする
- マッピングルールを1ページにまとめて、チームメンバーが理解できるようにする
例:サポートとファイナンスの内部ツールとSSOグループ
日常的にSupport、Finance、数名のマネージャーが使う運用ツールを想像してください。人がサインインすると自動的に正しい画面と操作が割り当てられ、管理者が手動で修正する必要がないようにしたいとします。
いくつかのIdPグループを作り、アプリ内のロールとチームにマッピングします:
ops-support→ ロール:Support Agent、チーム:Supportops-finance→ ロール:Finance Analyst、チーム:Financeops-managers→ ロール:Manager、チーム:Management
ここでの振る舞いは次の通りです。
| User | IdP identifier used for linking | IdP groups claim | In-app result | Notes |
|---|---|---|---|---|
| Maya (Support) | sub=00u8...k3 | ops-support | Support Agent, Support team | チケットの閲覧、返信、タグ付けはできるが請求ページは見られない |
| Omar (Manager) | sub=00u2...p9 | ops-support, ops-managers | Manager, Management team | マッピングルールは上位のロールを選び、Financeは別に扱われる |
| Lina (Finance) | sub=00u5...w1 | Missing (group claim not sent) | デフォルト:アクセスなし(または読み取り専用ゲスト) | 安全なデフォルトで過剰アクセスを防ぐ。Linaには「アクセスが割り当てられていません。管理者に連絡してください。」が表示される |
次にメール変更のケース:Omarが[email protected]から[email protected]に変わっても、アプリがsub(またはSAMLの永続的NameID)でアカウントをリンクしていれば重複アカウントは作られません。履歴や監査トレイルは維持されます。
推測を避けるために、「effective access(実効アクセス)」ビューを用意すると便利です。ユーザーのリンクされたIdP識別、受け取ったグループ、決定されたロール、チームが表示されれば、問題が起きたときにIdP側の問題かマッピングルールの問題か、あるいはクレームの欠落かがすぐ分かります。
次の一手:組織が変わってもアクセスを予測可能に保つ
最初の導入が一番難しいわけではありません。再編や新チーム、例外対応が増えてもアクセスを保守することが最も難しい部分です。
1ページのマッピングドキュメントを用意して、次を明記しておきます:
- どのIdPグループがどのアプリロールとチームにマップされるか
- クレームが欠落したときのデフォルト(誰が変更を承認するか)
- 高リスクロール(財務管理者、ユーザー管理者、データエクスポートなど)の所有者
- 契約社員やサービスアカウントの扱い
- 真のソースオブトゥルースがIdPかアプリかどこにあるか
境界が明確な部署で小さなパイロットを行い、エッジケースを直してからルールを増やさずに拡張してください。月次で管理者や高リスクロールのレビュー、四半期ごとに通常ロールのレビューなど、定期的な見直しも設定してください。
内部アプリを自分で開発する場合、ロール、チーム、業務ロジックを近くに置いておくと変更のテストが楽になります。AppMaster(appmaster.io)は、ロールやワークフローを視覚的にモデル化して、要件変更に合わせてバックエンド、Web、モバイルのコードを再生成できるオプションの一つです。ワンオフの権限修正を積み上げることなく管理できます。
よくある質問
クレームマッピングとは、IdP(グループ、部署、役職など)が送る情報をアプリのアクセス制御で使うロールやチームに変換する工程です。これがないと、SSOのログインは成功しても、ユーザーが誤った権限でログインしてしまうことがあります。
安全なデフォルトは「拒否」を基本にすることです。ユーザーを作成または認識しても、既知のマッピングが一致するまではロールやチームを割り当てないようにします。要件でアクセス申請のための入り口を許可する場合でも、権限は限定的にし、欠落したデータを権限と見なさないでください。
IdPから得られる安定した不変の識別子を一次キーとして使うのが最も安全です。例えばOIDCではsubクレーム、SAMLでは永続的なNameIDや不変の属性を使用します。IdPの発行元(issuer/entity ID)と一緒に保存して、異なるIdPから同じ値が来ても衝突しないようにします。
メールは便利な属性として使えますが、唯一の真実のキーにはしないでください。メールは改名、ドメイン変更、合併などで変わることがあります。メールでマッチさせる場合は、IdP側での確認を必須にするか、ワンタイムの確認手順を入れて誤リンクを避けてください。
ロールは「その人が何をできるか(権限)」を定義し、チームは「どこに属しているか(表示範囲)」を定義します。例:ロールは編集や承認、ユーザー管理など、チームは部署や地域、キュー、コストセンターのようなスコープです。
典型的な内部ツールなら、まずは3つのロールから始めるのが実用的です:Viewer(閲覧のみ)、Editor(作成・更新可能)、Admin(設定やユーザー・アクセス管理)。定義を明文化しておくことで、組織の変化時に誤った権限付与を防げます。
一貫した解決ルールを決めて文書化してください。多くのチームはハイブリッド方式を使います:チームの所属は加算(所属を全部合算)、ロールは優先順位で決める(矛盾する場合は優先度の高い方を採用)。
分かりやすい命名規則を採用してください。アプリ名、環境、ロールを含めるとスケールしやすいです。例:<app>-<env>-<role>。これにより『Admins』のような曖昧なグループ名の使い回しを防げます。
トークン内容をそのままさらすことなく、到着したクレーム、どのマッピングルールが一致したか、最終的に割り当てられたロール/チームをログに残してください。これがあれば「ツールが見えない」という問い合わせも、クレーム対ルールの照合で素早く原因を特定できます。
ログインごと、あるいは定期同期でクレームを再評価して、アクセスが現在のグループ所属に追随するようにしてください。退職者については次回ログインを待たず、IdP側で無効化されたら即座にアクセスを遮断する仕組みが必要です。操作履歴や承認履歴などの監査データは残しつつ、新たな操作を禁止します。


