1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【セキュリティ入門】第3回 OpenID Connect(OIDC)とは?OAuthとの違いを図解で理解する

1
Posted at

はじめに

第2回の最後で「OAuth はログインの仕組みではない」という話をしました。でも世の中には「Googleでログイン」ボタンが山ほどあります。

実はあのボタンの多くは、OAuth そのものではなく、OAuth の上にもう一枚乗った仕組みで動いています。その一枚が OpenID Connect(OIDC)です。

しかも、OAuth のリクエストに openid という1語を足すだけで、その一枚が有効になります。なぜ1語で「ログイン」として成立するのか。それを追いかけるのが今回です。

この記事でわかること

  • OAuth だけでログインを作ると、何が足りないのか
  • openid の1語を足すと、何が増えて返ってくるのか
  • ID トークンに何が書かれていて、信じてよいかをどう確かめるのか
  • ログインできないとき、どこから順に見ればよいのか
  • OAuth だけで足りる場面と、OIDC が要る場面の見分け方

読み終わったときに「OIDC は OAuth に何を足したものか」を自分の言葉で説明できて、ID トークンを何をどの順で確かめるかを理由付きで言える。そこがゴールです。

この記事の対象読者

  • 第2回(OAuth 2.0)を読んで、「引換券を交換してトークンをもらう」流れがなんとなく追える人
  • 「OAuth と OIDC、結局どっちを使えばいいの?」で止まっている人
  • 仕様書を開いてみたけれど、クレーム名の羅列で心が折れた人

前提知識

第1回・第2回の内容を前提にしますが、忘れていても読めるように途中で補います。

  • 第1回「認証と認可のちがい」: 認証=あなたは誰か/認可=あなたは何をしてよいか
  • 第2回「OAuth 2.0とは?」: 引換券(認可コード)→ アクセストークンの流れ、state と redirect_uri

今回は JWT(ジョット)・署名・公開鍵という言葉が出てきますが、いまは次の1行だけ分かっていれば読めます。

署名付きのデータ = 中身をこっそり書き換えられていれば、受け取った側が気づける形式。

JWT そのものの分解は第4回の担当です。この記事では「何を確かめるか」に集中します。

本編

まず、OAuth だけだと何が困るのか

第2回で、アクセストークンは「入館パス」だと説明しました。「この人は資料室の3番棚まで入ってよい」と書かれた札です。

大事なのは、入館パスには「誰の」パスなのかが書かれていないこと。資料室の係員が知りたいのは「入っていいか」だけなので、書く必要がないんです。

ところが「ログイン」でやりたいのは、まったく別のことです。いま来たこの人は、うちのシステムのどのアカウントの人なのか。それを確定させたい。

だからアプリ側は仕方なく、「このパスでプロフィール API を叩いて、返ってきた id をユーザー ID として使おう」という実装をしていました。これがまずいのは、次の点です。

困ること たとえると
その応答が誰宛てに発行されたものかを確かめる標準的な方法がない 拾った入館パスで問い合わせても、同じように答えが返ってきてしまう
プロフィール API の形がサービスごとにバラバラ 連携先を増やすたびに、読み取りコードを書き直すことになる

oauth-only-login-problems.png

そこで「認証したという事実」を検証できる形の紙にして渡すことにしたのが OIDC です。仕様の名前は OpenID Connect Core 1.0 といいます。

OIDC は OAuth の「上に」乗っている

OIDC は OAuth の代わりではなく、OAuth の上に足された追加レイヤです。

第2回で覚えた流れ(受付に行く → 引換券をもらう → 裏でトークンに交換する)は、そのまま何も変わりません。足されるのは、たった3つです。

oidc-adds-three-things.png

「新しい仕組みを覚え直す」のではなく、「追加分だけ覚える」で足ります。

呼び名だけが変わる

混乱しやすいのが登場人物の呼び名です。役割は第2回とまったく同じなのに、名前だけ別なので初見では別物に見えてしまいます。

第2回での呼び名 OIDC での呼び名 役割(変わりません)
Authorization Server(認可サーバ) OP(OpenID Provider) 本人確認をして、パスや証明書を発行する受付
Client(アプリ) RP(Relying Party) 発行された証明書を信じて頼る側のアプリ

Relying Party は直訳すると「頼る当事者」。証明書を信じる側、という意味です。以降はこの記事でも OP / RP を使います。

OAuth と OIDC の違い(並べて比較)

観点 OAuth 2.0 OpenID Connect
何のための仕組み? 認可(権限を貸す) 認証(誰がログインしたか)+ 認可
主にもらえるもの アクセストークン(入館パス) ID トークン(本人確認の証明書)+ アクセストークン
形式は決まっている? 決まっていない ID トークンは JWT 形式で固定
誰なのかを知る方法 標準化されていない UserInfo という標準の窓口がある
確かめ方 受け取る側の実装しだい 仕様で手順が決められている

oauth-vs-oidc-compare.png

「形式が決まっている」「確かめ方が決まっている」。この2つが OIDC の本質で、要はバラバラだったものを標準化しただけです。

openid の1語で何が変わるのか

第2回で見た認可リクエストの URL に、2つ足すだけです。

GET /oauth2/authorize
  ?response_type=code
  &client_id=1example23456789
  &redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
  &scope=openid%20profile%20email        ← ここに openid を入れたら OIDC
  &state=xYz123...                       ← 第2回でやった CSRF 対策
  &nonce=n-0S6_WzA2Mj...                 ← 今回の新顔(あとで説明します)

そして引換券をトークンに交換したときのレスポンスに、id_token が1行増えます。

// POST /oauth2/token のレスポンス(値は例)
{
  "access_token": "eyJraWQiOiJ...",
  "id_token": "eyJraWQiOiJ...",          // ← openid を付けたから増えた
  "refresh_token": "eyJjdHkiOiJ...",
  "token_type": "Bearer",
  "expires_in": 3600
}

逆に言うと、openid を入れ忘れたら id_token は返ってきません。「ログインできない」の原因としてかなり多いパターンです。

用語メモ:Scope(スコープ)とは?
「どこまでお願いするか」の指定です。OIDC では、これに「属性がほしい」という指定も混ぜられます。

  • openid … OIDC を使うという宣言(これが無いと始まらない)
  • profile … 名前やプロフィール画像など
  • email … メールアドレスと、それが確認済みかどうか
  • phone … 電話番号と、それが確認済みかどうか

注意点がひとつ。

どの Scope が使えるかは受付(OP)次第です。

たとえば Amazon Cognito の予約スコープは openid / email / phone / profile / aws.cognito.signin.user.admin の5つです。他の解説記事によく出てくる offline_access は、この一覧に含まれていません(認可コードの流れなら、要求しなくてもリフレッシュトークンが返ります)。email / phone / profile は openid と一緒でないと要求できない点も要注意です。

「記事に書いてあった Scope を書いたのに動かない」ときは、使っている OP の対応表を見るのが正解です。

全体の流れを図で

第2回の図に OIDC 分が足されただけ、と思って見てください。

大事なのは最後の1行です。

ID トークンは確認したらそこで役目が終わります。理由はあとで説明します。

ID トークン =「本人確認しましたよ」という証明書

ID トークンを一言でたとえるなら、役所が発行する証明書です。

Base64URL という方式でデコードすると、こんな JSON が出てきます。

// ID トークンの中身(値は例)
{
  "iss": "https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_abcd1234",
  "sub": "a1b2c3d4-1111-2222-3333-444455556666",
  "aud": "1example23456789",
  "exp": 1735689600,
  "iat": 1735686000,
  "auth_time": 1735686000,
  "nonce": "n-0S6_WzA2Mj...",
  "token_use": "id",
  "email": "user@example.com",
  "email_verified": true
}

用語メモ:クレーム(Claim)とは?
「主張」という意味で、要するにこの JSON の1行1行のことです。
「発行元はここです」「この人の ID はこれです」といった言い分が並んでいます。
言い分なので、そのまま鵜呑みにせず確かめる。これが後半のテーマです。

証明書にたとえると、それぞれの意味はこうなります。

クレーム 証明書でいうと 意味
iss 発行した役所の名前 どこが発行したか(Issuer)
sub 会員番号 ユーザーを一意に表す ID(Subject)
aud 宛名 誰に向けて発行したか(Audience)
exp 有効期限 いつまで有効か
iat 発行日時 いつ発行されたか
auth_time 本人確認をした日時 実際にログイン操作が行われた時刻
nonce こちらが指定した受付番号 自分が出した申請への返答かを確かめる値

上の JSON には azp と at_hash は入っていませんが、条件によっては付いてきます。名前が並んで出てくる割に、役割は別物です。

  • azp … このトークンを受け取ることを認められた相手はどこか。「本命の宛先」を示す値で、あとの検証手順にも出てきます
  • at_hash … 一緒に発行されたアクセストークンはどれか。アクセストークンだけをすり替えられていないかを確かめるための値です

独自クレームが混ざることに注意

サンプルにある token_use は Cognito が独自に付けているクレームで、OIDC の標準ではありません。

ここは実務でハマるポイントです。

  • 標準クレームしか無い前提でコードを書く → 独自クレームの前提で作られた検証処理が抜ける
  • 独自クレームに依存してコードを書く → OP を別のサービスに替えたときに動かなくなる

「どれが標準で、どれがそのサービス独自か」を意識しておくと、あとで移行するときに困りません。

ユーザー ID には sub を使う(email ではなく)

メールアドレスは変わります。転職、改姓、単なる乗り換え。変わった瞬間に別人扱いになったら困ります。

一方 sub はその人に固定で振られる番号なので、識別に向いています。

ただし sub にはさらに注意点が2つあります。

  • sub が一意なのはその OP の中だけです。別の OP の sub とたまたま同じ値になる可能性は排除できません
    • だから実務では「発行元(iss)+会員番号(sub)」のセットで人を識別します
  • OP によっては、アプリごとに違う sub を配るモード(pairwise)を持つものがあります(Cognito は全アプリ共通の public だけです)
    • public から切り替えると、既存ユーザーの紐付けが全部切れます。設定の変更自体はできても、実質的に後戻りできないものだと思ってください

nonce という新しい防具

第2回では state という防具が出てきました。今回は nonce(ノンス)が増えます。

名前が似ていて紛らわしいので、何を守っているかで区別してください。

用語メモ:nonce とは?
アプリが認可リクエストのときに作る使い捨てのランダムな文字列です。
OP はこれを ID トークンの中にそのまま書き込んで返してきます。
アプリは「自分が出した値と同じか」を確かめることで、「これは確かに自分がいま始めたログインへの返答だ」と判断できます。

病院の受付番号札を思い浮かべてください。自分が受け取った番号と、呼ばれた番号が一致して初めて「自分の番だ」と分かる。あれと同じです。

state nonce
守っているもの 引換券(認可レスポンス) ID トークン
防ぐ攻撃 他人の手続きの続きを掴まされる(CSRF) 他人の/使い回しの ID トークンを掴まされる
どこで確かめる? 受付から戻ってきた瞬間 ID トークンを検証するとき

state-vs-nonce.png

守っている対象が違うので、片方があれば片方は要らない、という関係ではありません。

ただし「必須かどうか」は、両者で事情が違います。

  • CSRF を防ぐこと自体は必須ですが、その手段は state / PKCE / nonce のどれでもよいとされています(RFC 9700)
    • なので「state を必ず送らなければならない」ではなく、「CSRF 対策が何もない状態にしてはいけない」が正確です
  • 一方 nonce のほうは、送ったなら必ず照合します。照合しないなら送る意味がありません

そして、初級者がいちばんやりがちな失敗が「nonce を生成して送ったのに、保存していない」です。

受付番号札を渡したのに控えを取っていないようなもので、戻ってきても照合できません。

生成 → 保存 → 照合 → 捨てる までが1セットだと覚えてください(state も同じです)。

確かめる材料はどこから来るのか

「証明書を確かめる」と言っても、材料が要ります。

  • この役所(OP)の窓口の URL はどこか
  • 印影を照合するための公式な印鑑の見本はどこにあるか

これを固定の URL から JSON で取ってこられるようにしたのが Discovery です。

用語メモ:Discovery とは?
OP の設定情報(各窓口の URL、対応 Scope、署名方式など)をまとめた案内ページです。
<発行元の URL>/.well-known/openid-configuration という決まった場所に置かれています。
これのおかげで、アプリ側に URL をベタ書きしなくて済みます。

// GET https://<issuer>/.well-known/openid-configuration(抜粋・Cognito の例)
{
  "issuer": "https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_abcd1234",
  "authorization_endpoint": "https://example.auth.ap-northeast-1.amazoncognito.com/oauth2/authorize",
  "token_endpoint": "https://example.auth.ap-northeast-1.amazoncognito.com/oauth2/token",
  "userinfo_endpoint": "https://example.auth.ap-northeast-1.amazoncognito.com/oauth2/userInfo",
  "jwks_uri": "https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_abcd1234/.well-known/jwks.json",
  "scopes_supported": ["openid", "email", "phone", "profile"],
  "id_token_signing_alg_values_supported": ["RS256"],
  "subject_types_supported": ["public"],
  "response_types_supported": ["code", "token"]
}

用語メモ:JWKS(ジェイ・ダブリュー・ケー・エス)とは?
JSON Web Key Set の略で、公開鍵の一覧です。上の jwks_uri から取得します。
証明書のたとえで言えば「役所の公式印鑑の見本帳」。届いた証明書のハンコが本物かを、この見本帳と照らし合わせて確かめます。
見本帳には複数のハンコが載っていて、証明書側には「どのハンコを使ったか」を示す kid(Key ID)という番号が書かれています。番号で見本を引いて照合する、という流れです。

落とし穴1:Discovery そのものも確かめる

取ってきた案内ページの issuer の値が、自分が問い合わせた URL と一致しているかを確認しなければいけません。

一致を確認しないと、偽の OP の案内ページを掴んだまま、そこに書かれた偽の公開鍵で偽の証明書を「検証成功」と判定してしまいます。以降の検証が全部素通りするので、ここが崩れると何をやっても意味がありません。

「案内ページに書いてある発行元名」「自分がアクセスした URL」「ID トークンの iss」。この3つが揃って初めて信用できる、と覚えてください。

落とし穴2:Discovery は「その OP のすべて」ではない

上の例で scopes_supported を見ると4つしか載っていませんが、実は Cognito では aws.cognito.signin.user.admin も要求できます。載っていないだけです。

つまり Discovery は「OP の全機能一覧」ではなく「OP が案内として広告している範囲」でしかありません。

最終的には、使っているサービスの公式ドキュメントで確認するのが確実です。

落とし穴3:公開鍵のキャッシュ設計

見本帳(JWKS)はたまに差し替わります(鍵のローテーション)。ここで両極端に振ると、どちらも事故ります。

やり方 何が起きるか
毎回取りに行く OP が落ちたら自分のログインも落ちる。遅くもなる
一度取ったらずっと使う 鍵が差し替わった瞬間、全ユーザーがログインできなくなる

実務的な答えはその中間で、一定時間キャッシュする + 知らない kid が来たときだけ1回取りに行く(連打しないように制御する)。

落とし穴4:Cognito には発行元(Issuer)が2種類ある

Cognito 特有ですが、ハマると被害が大きいので触れておきます。

種類 URL の形 位置づけ
Original issuer https://cognito-idp.{region}.amazonaws.com/{userPoolId} 従来からのもの(2026年8月時点の既定)
Updated issuer https://issuer-cognito-idp.{region}.amazonaws.com/{userPoolId} 複数リージョンで同じ鍵を配る新しい形(AWS 推奨)

アプリ側は iss の期待値を設定として固定するので、どちらを使う設定なのかを取り違えると iss 不一致でログインが全滅します。

なお Updated issuer は、AWS 公式ドキュメントに「現時点では ALB の Cognito 認証および API Gateway の Cognito オーソライザーと非互換」と明記されています(2026年8月時点)。

「推奨だから」と安易に切り替えないでください。

証明書を確かめる手順

ID トークンを受け取ったら、次の項目を確かめます。仕様(OIDC Core §3.1.3.7)が決めているのは「何を確かめるか」で、確かめる順番までは縛っていません。以下は切り分けがしやすい順に並べたものです。

  1. ハンコは本物か(公開鍵で署名を確認する)
  2. どこの役所が出したか(iss が期待どおりか)
  3. 宛名は自分か(aud に自分の client_id が入っているか)
  4. 本命の宛先も自分か(azp が入っているなら、その値が自分の client_id か)
  5. 期限は切れていないか(exp を過ぎていないか)
  6. 自分の受付番号か(nonce を送ったなら、その値と一致するか)

窓口で身分証を受け取ったときに「ハンコ → 発行元 → 宛名 → 期限」の順に目を走らせるのと同じです。

ここで絶対に外してはいけない注意点が2つあります。

1. トークンに書いてある「署名方式」を鵜呑みにしてはいけない

ID トークンには「どの方式で署名したか」(alg)が書かれていますが、それはトークン自身の自己申告です。攻撃者が書き換えられる場所でもあります。

なので、許可する方式はアプリ側で固定します。Cognito なら RS256 です。

なぜ鵜呑みにすると危ないのか、具体的な攻撃手法は第4回で扱います。

2. ライブラリに任せても、設定は自分の責任

検証ライブラリを使うのが普通ですが、iss と aud の期待値だけはライブラリの初期値には入っていません。「どこの役所を信じるか」「宛名は誰か」は、そのアプリ固有の情報だからです。

ここを設定し忘れると、検証しているつもりで素通りします。

自分のライブラリがどれを確認していて、どれが未設定だと素通りするかは把握しておきましょう。

確認に失敗したときの見方(フローチャート)

上の手順を、そのまま切り分けの順番として使えます。

(図では手順4の azp を省いています。azp が入っているときだけ効く分岐で、Cognito では通常付かないので、まずはこの流れを覚えてください。逆に token_use は Cognito 独自のクレームなので、他の OP を使うときはこの分岐がありません)

コツは上から順に見ることです。署名が通っていないのに nonce を疑っても意味がないので、順番を飛ばさないでください。

そしてもうひとつ。この図が探せるのは「失敗の原因」だけです。alg の固定漏れのように、検証が失敗せずに素通りしてしまう欠陥は、この図では見つかりません。図を通ったから安全、とは考えないでください。

図の四角にたどり着いたら、次はここを見ます。

行き着いた原因 よくあるきっかけ 最初に見る場所
scope に openid が無い 第2回のリクエストをコピーしてきた 認可リクエストの scope と、アプリクライアントの許可スコープ
鍵が見つからない 鍵が差し替わったのにキャッシュが古い/別の User Pool を見ている 公開鍵の一覧と、トークンに書かれた kid
発行元の取り違え 環境ごとの発行元をベタ書きしている/リージョンや Pool ID 違い Discovery の issuer とアプリの設定値
アクセストークンを ID トークンとして検証している 2種類のトークンを同じ検証関数に渡している トークンの token_use と、呼び出し側が渡しているトークン
別アプリ向けのトークン アプリの登録を作り直した/複数アプリで設定を使い回している トークンの aud と使用中の client_id
発行直後なのに期限切れ サーバの時計がずれている(時刻同期に加えて、数分程度のずれを許容する設定も入れておく) 検証する側のサーバの時刻同期
nonce の保存漏れ サーバが複数台でセッションを共有していない/リロードで作り直している セッションの保存・取り出しのログ

確認が通った後の ID トークンの扱い

ここを間違えると、せっかくの検証が無意味になります。

ID トークンは使い捨て

証明書は、窓口で見せて確認された時点で役目が終わりです。そのあとは、自分のアプリが発行する会員証(セッション)で回します。

なぜそのまま持ち回してはいけないのか。

ID トークンは「あの日あの時、本人確認をしました」という過去の記録であって、「いまこの人は有効な利用者です」という現在の状態ではないからです。

期限(exp)が切れれば自然に無効になりますが、「この人を今すぐログアウトさせたい」と思っても発行元から取り消せません。

だから、確認したら自分のセッションに変換する。

保管場所は「漏れたら終わり」の前提で決める

ID トークンには email などの個人情報がそのまま載っています。

ブラウザの localStorage に置く実装をよく見かけますが、ここは XSS で読み出せます。

用語メモ:XSS とは?
Cross-Site Scripting の略で、ページに攻撃者の JavaScript を紛れ込ませる攻撃です。
紛れ込ませられた時点で、そのページから読める値は全部読まれます。localStorage は JavaScript から普通に読めるので、まるごと持っていかれます。

そのほか、やってはいけないこと4つ

# やってはいけないこと 理由
1 URL に載せる 履歴・ログ・Referer に残ります(第2回)。個人情報が載っている分、より深刻です
2 exp を延ばして「ログイン維持」 漏れたときに使える時間を自分で伸ばしているだけ。維持はリフレッシュトークンの仕事です
3 トークン本体や client_secret をログに出す 出してよいのは kid / iss / aud と「どのクレームが合わなかったか」まで。切り分けにはそれで足ります
4 redirect_uri の照合を緩める 第2回の完全一致は OIDC でも同じ。入口が開いていたら、金庫の鍵の強さは関係ありません

UserInfo で属性をあとから聞く

ID トークンに全部の属性を詰め込むとトークンが大きくなります。そこで「必要になったら聞きに行く」ための標準の窓口が UserInfo です。

GET /oauth2/userInfo
Authorization: Bearer <アクセストークン>   ← ID トークンではない

送るのはアクセストークン(入館パス)です。ID トークンを送ると 401 になります。

証明書は本人確認の記録、パスは窓口を使う権利。用途が違うと考えれば納得しやすいはずです。

// レスポンス(値は例)
{
  "sub": "a1b2c3d4-1111-2222-3333-444455556666",   // ← ID トークンの sub と一致すること
  "email": "user@example.com",
  "email_verified": true
}

そして、見落としがちな必須手順があります。

返ってきた sub が ID トークンの sub と一致することを必ず確認し、一致しなければ拒否する。

省略すると別のユーザーの属性を掴まされ、「ログインしたのは A さんなのに、画面には B さんのメールアドレスが出る」という事故につながります。

Cognito を使う場合の注意も1つ。

UserInfo が受け付けるのは、/oauth2/token から発行された openid スコープ付きのアクセストークンだけです。

InitiateAuth など別の API で取ったアクセストークンはスコープを持たないため拒否されます。

「トークンは有効なはずなのに UserInfo だけ通らない」の典型パターンです。

結局、OAuth と OIDC のどっちを使う?

判断軸はひとつだけ覚えてください。

そのユーザーを、自分のアプリのアカウントに紐付けたいか。紐付けたいなら OIDC です。

やりたいこと 選ぶもの 理由
外部 API を代わりに叩きたいだけ OAuth 2.0(認可コードグラント) 「誰か」を知る必要がない
自分のアプリにログインさせたい OIDC 本人確認の事実を、検証できる形で受け取る必要がある
ユーザーの名前やメールを画面に出したい OIDC 属性の取り方が標準化されている
人が関わらないサーバ同士のバッチ処理 OAuth 2.0(クライアントクレデンシャルグラント) そもそもユーザーがいない
社内の認証基盤が SAML しかない 変換するか SAML 使えるプロトコルは既存の基盤側で決まる。間に Cognito を挟めば OIDC に変換して受け取れる。

表に出てくる2つのグラントは、どちらも OAuth 2.0 の中にある「トークンの取り方」です。Client Credentials は OAuth 2.0 と別の仕組みではありません。

人がログインして、その人の権限を借りるのが認可コードグラント。人がおらず、アプリ自身の権限で動くのがクライアントクレデンシャルグラントです。後者にはユーザーがいないので、ID トークンも nonce も redirect_uri も出てきません。

そして第2回の結論に戻ります。OAuth でログインを作ると脆くなる。だから OIDC がある。

これが OIDC を選ぶいちばんの理由です。

よくある誤解

よくある誤解 実際は
「ID トークンを API 呼び出しに使ってよい」 用途違いです。API に送るのはアクセストークン
「sub はどこでも同じ値」 その OP の中でだけ一意です。設定によってはアプリごとにも変わります
「state を確認していれば nonce は要らない」 守っている対象が別です。そして nonce は送るだけでは無意味で、照合して初めて効きます
「UserInfo が返した情報はそのまま使える」 sub の一致確認が必須です
「検証はライブラリ任せでOK」 iss / aud の期待値と許可する署名方式は、アプリ側の設定責任です。初期値では埋まりません

まとめ

観点 押さえるポイント
位置づけ OIDC は OAuth の上に「認証」を足した仕様。流れも窓口も第2回と同じ
OIDC の宣言 scope に openid を入れることが OIDC の宣言で、これで id_token が返る
ID トークンの正体 「本人確認しましたよ」という証明書。中の1項目1項目をクレームと呼ぶ
検証すること ハンコ(署名)・発行元(iss)・宛名(aud、azp があればそれも)・期限(exp)・受付番号(nonce)。順番は仕様では決まっていない
検証の材料 Discovery(案内ページ)と JWKS(印鑑の見本帳)から取る。案内ページ自体の issuer 確認も忘れずに
検証したあと 確認が終わったら ID トークンは捨てて、自分のアプリのセッションに変換する。URL に載せない、期限を延ばさない
ユーザーの識別 iss + sub の組で。メールアドレスは使わない
OAuth との分かれ目 「自分のアプリのアカウントに紐付けるか」が判断軸

もっと深く知りたくなったら

この記事は「なぜこの形なのか」を、たとえ中心でなぞりました。

次のような疑問が湧いてきたら、末尾の参考リンクから原典にあたるのが近道です。

  • 各クレームやパラメータが仕様上 REQUIRED / OPTIONAL のどれなのか
  • azp と at_hash がどういう条件で付き、いつ確認が必須になるのか
  • max_age と auth_time を使った再認証の要求方法
  • Cognito の Original issuer / Updated issuer の非互換の詳細
  • ID トークン検証の手順を、OIDC Core の条文(§3.1.3.7)に沿って追う

次回予告

第4回「JWTとは?Header・Payload・Signatureを徹底解説」。

前回: 第2回「OAuth 2.0とは?認可の仕組みを図解で理解する」

この記事では「署名を確認する」とだけ書いて中身に踏み込みませんでした。第4回では、そのトークンをバラバラに分解して、なぜ書き換えると気づけるのか、そしてなぜ alg を鵜呑みにしてはいけないのかを見ていきます。

参考リンク

本記事に出てくる Amazon Cognito の仕様(予約スコープ、Issuer の種類、userInfo の要件など)は、2026年8月に以下の AWS 公式ドキュメントで確認したものです。

仕様は更新されることがあるので、実装前に最新版をご確認ください。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?