はじめに
2年目のピヨピヨエンジニアです。
今さらQiita始めました。よろしくお願いします。
AWS系の業務に関わりたくて、いろいろ作った記録を残していく予定です(多分)。
今回なにやったの?
今回は Amazon Cognito(Hosted UI) を使って、Google をIdPとしてOIDC連携してみました。
で、「実際どんな通信してるの?」って気になったので、
SAMLトレーサー(※ややこしくてすみません。追いかけるのはOIDCです)で追いかけてみます。
業務でパフォーマンス測定のためにOIDCの流れをJMeterに書いたりしてた経験を活かして頑張ります。
たぶん何とかなるはず……!
間違ってたらやさしくツッコミください。
この記事は要するに
「CognitoでGoogleログインすると中身こうなってるんだよ〜」
の記事です。
ざっくり全体像(今回のログで見えた流れ)
登場人物
| 役割 | 内容 |
|---|---|
| App | ….cloudfront.net |
| Cognito | aitchat-dev-...amazoncognito.com |
| accounts.google.com | |
| Browser | Chrome(ユーザー操作するやつ) |
流れ(超ざっくり)
- アプリ「Googleでログインさせて〜」
- Cognito「了解、まずGoogleのところ行ってきて〜」(302で飛ばす)
- Google「ログインして同意してね」
- Google「OK、Cognitoに結果返すね」(認可コード付きで戻す)
- Cognito「じゃあそのコードをトークンに交換するね」
- ログイン完了!
画面としてはこんな流れです。
Googleの同意画面に遷移(画像省略)
1) まずCognitoに「ログイン開始」って言う(/oauth2/authorize)
例(概略)
https://aitchat-dev-...amazoncognito.com/oauth2/authorize
?client_id=...
&response_type=code
&scope=openid+email+profile
&redirect_uri=https%3A%2F%2Fd2h1sc61c6z4n2.cloudfront.net%2F
&state=...
&code_challenge=...
&code_challenge_method=S256
&identity_provider=Google
ひとことで言うと
「認可コード(authorization code)を取りに行く」開始リクエストです。
そしてこのタイミングで“手土産”(パラメータ)をいっぱい持たされます。
これがないと、ちゃんと戻れなかったり、セキュリティ的に危なかったりします。
/oauth2/authorize のパラメータ表
| パラメータ | 例 | 意味 | メモ |
|---|---|---|---|
| client_id | 6m0ut0... | Cognito側のアプリ(App Client)識別子 | Cognitoに登録されているやつ |
| response_type | code | Authorization Code Flow を使う | まず code を取りに行く |
| scope | openid email profile | 欲しい権限/属性の範囲 | openid が入ってるので OIDC |
| redirect_uri | https://...cloudfront.net/ | 最後に戻るURL | Cognitoの許可リストと完全一致必須 |
| state | aa13c5... | CSRF対策 + 整合性確認 | 戻りでも同じ値が返るので照合する |
| code_challenge | SnoV3... | PKCE用 | code_verifier から作られる |
| code_challenge_method | S256 | code_challenge の作り方 | S256がよく使われる |
| identity_provider | どの外部IdPを使うか | 今回はGoogleへ飛ばす指定 |
2) PKCE(Proof Key for Code Exchange)って何がうれしいの?
めちゃざっくり言うと、
認可コード(code)が途中で盗まれても、そのままトークンに交換できないようにする仕組みです。
- クライアント側でまず
code_verifier(秘密の文字列)を作って手元に保持 - それを変換して
code_challengeを作る - S256のイメージ
code_challenge = BASE64URL( SHA256(code_verifier) )
- authorize では
code_challengeだけ送る(code_verifierは秘密のまま) - token で
code_verifierを出して照合 → OKならトークン交換できる
3) 次にGoogleの認可エンドポイントへ連れて行かれる(/o/oauth2/v2/auth)
例(概略)
https://accounts.google.com/o/oauth2/v2/auth
?client_id=...
&redirect_uri=https%3A%2F%2Faitchat-dev-...amazoncognito.com%2Foauth2%2Fidpresponse
&scope=openid+email+profile
&response_type=code
&state=...
&access_type=offline
ここでブラウザは Googleのログイン/同意画面 に誘導されます。
ポイント
- Google視点の相手(client)は 「あなたのアプリ」ではなくCognito
- Cognitoが仲介しているので Google → Cognito に戻す構図になる
Google /o/oauth2/v2/auth のパラメータ表
| パラメータ | 例 | 意味 | メモ |
|---|---|---|---|
| client_id | 10857...apps.googleusercontent.com | Google側のOAuthクライアントID | Google視点の“相手”はCognito側 |
| redirect_uri | https://...amazoncognito.com/oauth2/idpresponse | Googleが戻す先 | アプリではなくCognitoに戻る |
| response_type | code | Googleも認可コードを返す | ここでも code |
| scope | openid email profile | Googleに要求する範囲 | 同意画面に影響 |
| state | H4sIA... | 整合性確認用 | 戻りで照合される |
| access_type | offline | refresh tokenが欲しい意図 | 最終的にアプリが持つとは限らない |
4) Google画面周りのURLがいっぱい出るやつ
途中で以下のようなURLが大量に出てきます。ここはよくわかりませんでした。
AIさんに聞いておきました。
https://accounts.google.com/ServiceLogin?...
https://accounts.google.com/signin/oauth/consent?...
.../accountchooser?...
.../_/OAuthUi/...
だいたい以下のセットです。
- アカウント選択
- ログイン(パスワード/2段階認証)
- 同意画面
- UIのJS/CSS/内部通信
認可フローの本筋は
「authに行って、ユーザー操作して、redirectで戻る」
なので、ここは深追いしすぎないのが読みやすい気がします。
5) Googleの結果をCognitoが受け取る(/oauth2/idpresponse)
例(概略)
https://aitchat-dev-...amazoncognito.com/oauth2/idpresponse
?state=...
&code=...
&scope=...
&authuser=0
&prompt=consent
これは Googleが発行した認可コードをCognitoに渡してるところです。
/oauth2/idpresponse のパラメータ表
| パラメータ | 例 | 意味 | メモ |
|---|---|---|---|
| code | 4/0ASc3g... | Googleが発行した authorization code | トークンじゃない(交換が必要) |
| state | H4sIA... | 整合性確認用 | 最初の state と一致するかチェック |
| scope | email profile openid | 同意されたスコープ | 状況によって増減 |
| authuser | 0 | Google側のアカウント選択文脈 | UI寄り |
| prompt | consent | 同意を促す指定 | 状況次第で付く |
6) 最後にトークン交換(/oauth2/token)
ここで 認可コード → トークン に交換します。
(このリクエストを投げるのがフロントなのかBFFなのかは構成次第。
今回のログでは少なくとも /token が呼ばれているのは見えました。)
/oauth2/token で送るもの(概念)
| 項目 | 例 | 意味 | メモ |
|---|---|---|---|
| grant_type | authorization_code | 認可コードを交換したい宣言 | いつもの |
| client_id | ... | Cognito側のクライアントID | App Client |
| code | ... | 認可コード | 構成で見え方が変わる |
| redirect_uri | https://... | 事前に指定した戻り先 | authorizeと一致 |
| code_verifier | ... | PKCEの秘密文字列 | 超重要 |
成功時のレスポンス例
- id_token(OIDCのJWT)
- access_token
- refresh_token(場合によって)
- expires_in / token_type
これでログイン成功です。
おまけ:nonceがログに出てこなかったんだけど?
今回のURLには nonce=... が見当たりませんでした。
考えられるのは
「このフロー(または実装)が nonce をURLに載せていない」
というケースです。
nonce は OIDC のリプレイ対策でよく出てきますが、
- PKCE
- state
- トークン検証(iss / aud / exp / 署名)
を重視して、nonce を前面に出さない構成もあります。
(ここ、有識者の補足があればぜひ教えてください 🙏)
おわりに
「SAMLトレーサーでOIDCを追う」でも、
リダイレクトの流れと主要パラメータが見えるので、個人的にかなり腹落ちしました。
次は トークン(id_token)の中身(iss / aud / exp あたり) も
ちゃんと眺めてみたいです。


