SAMLとOIDCの違いを「もう調べ直さなくていい」レベルで整理する
はじめに
SAMLとOIDC、AWSを触っていると必ず出てくるのに、トピックに上がるたびに毎回調べ直していました。
「なんとなくOIDCが新しいからそっちの方がいいんだろうな」くらいのふわっとした理解のまま、何度も同じ記事を読んでは忘れる、を繰り返していたので、今回きちんと整理しました。
この記事は OpenClaw と壁打ちしながらまとめたものなので、誤りがある可能性があります。お気づきの点があればコメントいただけると嬉しいです。
前提:どちらも解決したい課題は同じ
SAMLもOIDCも、やりたいことは同じです。
「サービスごとにID/パスワードを管理するのやめて、1箇所で認証をまとめたい」
外部のIdP(認証サーバー)に認証を任せる仕組みです。違うのは生まれた時代と想定しているユースケースです。
SAMLとOIDCの違い
| SAML (2005年〜) | OIDC (2014年〜) | |
|---|---|---|
| 生まれた背景 | 企業が社内システムのSSOをやりたかった | モバイルアプリやWebサービスで「Googleでログイン」をやりたかった |
| データ形式 | XML(重い) | JSON(軽い) |
| 得意な場面 | 企業のSSO(Azure AD → AWS、Salesforce等) | コンシューマ向けアプリ、API連携 |
| ベースの技術 | 独自プロトコル | OAuth 2.0の拡張 |
| 認証結果の形式 | XMLアサーション | JWT(IDトークン + アクセストークン) |
AWSで「SAML連携」がよく出てくるのは、企業がAzure ADやOktaで社員を管理していて、そこからAWSにSSOしたいというユースケースが多いからです。企業向けIdPがSAMLを長くサポートしてきた歴史的経緯があります。
OIDCが「API連携に強い」理由
ここがSAMLとOIDCの一番大きな違いです。
認証した後に何が手に入るかを比べると:
- SAML: 「この人は認証済みです」というXMLの証明書が手に入る
- OIDC: 「この人は認証済みです」というIDトークン + アクセストークンが手に入る
このアクセストークンがポイントです。OIDCはOAuth 2.0の上に作られているので、認証と同時に「このユーザーに代わってAPIを叩く権限」も一緒にもらえます。
SAMLの場合:ブラウザでログインして終わり
社員 → Azure ADでSAML認証 → AWSコンソールに入れる
(ブラウザ上での操作はできる)
(でもAPIを叩くトークンはもらえない)
OIDCの場合:ログイン + API連携
ユーザー → Cognitoで認証 → IDトークン + アクセストークンを取得
→ アクセストークンでAPI Gatewayを叩く
→ Lambdaが処理して結果を返す
Lambda、Cognito、JWT、API Gatewayあたりの話が出てくる時はOIDCの世界。IAM Identity CenterやAzure AD連携の話が出てくる時はSAMLの世界。このマッピングを覚えておくだけでも混乱が減ります。
IDトークンとアクセストークン
OIDCで返ってくる2つのトークンの違いも整理しておきます。
IDトークン = 「この人は誰か」の身分証明書
{
"sub": "user-123",
"name": "Taro",
"email": "taro@example.com",
"iss": "https://cognito-idp.ap-northeast-1.amazonaws.com/xxx",
"exp": 1741960800
}
アプリが「ログインしたのは誰か」を知るために使います。UIで「ようこそ○○さん」と表示するための情報です。
アクセストークン = 「何をしていいか」の許可証
{
"sub": "user-123",
"scope": "read write",
"client_id": "my-app",
"exp": 1741960800
}
APIにリクエストを送る時に使います。API側はこれを見て「誰が」「何の権限で」リクエストしてきたかを判断します。
使い分け
| IDトークン | アクセストークン | |
|---|---|---|
| 用途 | 認証(あなたは誰?) | 認可(何していい?) |
| 使う場所 | アプリの中だけ | APIに送る |
| 例えると | 履歴書(詳しい個人情報) | 社員証(IDと権限だけ) |
実際のAPIリクエストで送るのはアクセストークンだけです。
GET /api/users/me
Authorization: Bearer <アクセストークン>
IDトークンをAPIに投げるのはアンチパターンです。APIのゲートに履歴書を見せる必要はなく、社員証で十分です。
JWTとは
IDトークンもアクセストークンも、JWT (JSON Web Token) という形式で作られています。
JWTは「情報を安全に運ぶための箱」です。中身はJSONで、署名がついています。
eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyLTEyMyIsImVtYWlsIjoiLi4uIn0.署名部分
署名がついているので改ざんできません。受け取った側は署名を検証するだけで「これは本物だ」と確認できます。IdPに毎回問い合わせる必要がないので、効率的です。
まとめると:
| 何か | 例えると | |
|---|---|---|
| JWT | データ形式(箱) | カードの素材(プラスチック) |
| IDトークン | 身分証明書(JWTで作られる) | 運転免許証 |
| アクセストークン | 許可証(JWTで作られる) | 入館カード |
JWTは形式、IDトークンとアクセストークンは用途が違う2種類のJWTです。
Bearer認証と認証方式の進化
APIリクエストのヘッダに書く Authorization: Bearer <トークン> の「Bearer」は「持参人」という意味です。このトークンを持っている人にアクセスを許可してください、ということです。
認証方式の進化
Basic → Digest → Bearer + HTTPS(現在の主流)
Basic認証: ID:パスワードをBase64エンコードして毎回送る方式です。URLにベタ書きしたり、ヘッダに載せたりしますが、Base64は暗号化ではなくただのエンコードなので、デコードすれば一瞬でパスワードが見えます。
Digest認証: パスワードそのものではなく、パスワードのハッシュ値を送る方式です。盗聴されてもパスワード自体はバレません。ただし、HTTPSの普及でBasicでも盗聴されなくなったため、実装の面倒さに見合わなくなりました。
Bearer認証: 期限付きトークンを送る方式です。パスワードそのものを毎回送らないので、万が一漏れても有効期限が切れれば無効になります。権限(scope)も細かく制御できます。
| Basic | Bearer | |
|---|---|---|
| 送るもの | ID + パスワード(毎回) | トークン(毎回) |
| 漏れた時の被害 | パスワード変更するまでアクセス可能 | 有効期限が切れたら終わり |
| 権限の細かさ | なし(認証できたら全部OK) | scopeで制限できる |
今のAPI認証はほぼBearer一択です。OIDCで取得したアクセストークンをBearerで投げるのがお決まりのパターンです。
SAMLにも強みはある
「OIDCが新しくて全部良い」ではありません。SAMLが向いている場面もあります。
- 属性の受け渡しが豊富: SAMLは認証時に「部署」「役職」「権限グループ」など細かい属性を一緒に渡すのが得意です。Azure AD → AWSで「この人はDevOpsチームだからAdminロール」のようなマッピングはSAMLの得意技です
- IdP起点のSSO: 社内ポータルのアイコンをクリック → 各SaaSに直接ログイン、という流れはSAMLの方が得意です。OIDCは基本「アプリ側から認証を始める」設計です
- 連携先がSAMLしか対応していない: 古めのSaaS、政府系システム、金融系システムではSAMLのみということがまだ多いです
結局どう使い分けるのか
実務では「どっちが良いか」ではなく、連携先が何に対応しているかで決まることが多いです。
- 企業の既存IdP(Azure AD、Okta)と連携する → まずSAMLを検討
- モバイルアプリやSPAのAPI認証 → OIDC
- 新規構築で選べる状況 → OIDCの方がシンプル
- 連携先がSAMLしか対応していない → SAML
最近はAzure ADもOktaもOIDC対応しているので、新規構築ならOIDCで組むケースも増えています。
まとめ
| SAML | OIDC | |
|---|---|---|
| 一言で | 企業SSOの老舗 | OAuth 2.0 + 認証 |
| データ形式 | XML | JSON (JWT) |
| 認証結果 | XMLアサーション | IDトークン + アクセストークン |
| API連携 | 別途仕組みが必要 | アクセストークンでそのまま叩ける |
| 今の立ち位置 | 企業向け・レガシー連携で現役 | 新規構築の主流 |
今回の学習で一番腹落ちしたのは、OIDCはSAMLの後継ではなく、解決したい課題が微妙に違うということです。SAMLは「ブラウザでSSOする」ための仕組み、OIDCは「認証してAPIも叩く」ための仕組み。この違いを意識するだけで、もう調べ直さなくて済むはずです。