🐥

KeycloakでのOpenID Connectお勉強メモ #2

2021/07/11に公開

はじめに

#1 からのつづきです。前回はこのフローを作りました。
今回はこの内容を詳しく見ていきます。

フロー図


Flow_OIDC

参考文献

調べていくにあたり以下の資料を見ながら進めて行きます。

OpenID Connect フローには種類があるということを知る

OpenID Connect Basic Client Implementer's Guide 1.0 日本語訳 - 2. Protocol Elementsに書いてあるように OpenID Connect には以下の種類があります。

  • Authorization Code Flow
  • Implicit Flow
  • Hybrid Flow

ここでは Authorization Code Flow (最も一般的な方法) でやっています。

まずはこれを見ときます。

OpenID Connect Basic Client Implementer's Guide 1.0 日本語訳 - 2.1. Code Flow

Code Flow は以下のステップからなる.

  1. Client は必要なリクエストパラメータを含んだ Authentication Request を構築する.
  2. Client は Authorization Server にリクエストを送信する.
  3. Authorization Server は End-User を認証する.
  4. Authorization Server は End-User の Consent/Authorization を取得する.
  5. Authorization Server は End-User を code とともに Client に戻す.
  6. Client は code を Token Endpoint に送信し, Access Token と ID Token を受け取る.
  7. Client はそれらのトークンを検証し, End-User の Subject Identifier を取得する.

おおざっぱに構成を理解する


-page-1

End-User

ブラウザを操作する人

Relying Party (RP)

OpenID Connect を利用する側

  • Apache + mod-auth-openidc

  • PHP 公式のDockerコンテナを使う

    • apache2が入っている
    • libapache2-mod-auth-openidcも入れます
    • 詳細は Dockerfile 参照
  • libapache2-mod-auth-openidc

    • Apacheのモジュール(アドオンみたいなもの?)でこれを付けるとApacheがOpenID Connectで話せるようになる便利なもの
    • Protected Resource を定義するだけでOPに問い合わせてくれます
    • 今回の場合 /secure 以下のリソースを Protected Resource にしてこのリソースにリクエストがあれば Keycloak に問い合わせするようになります。
  • サイトの構成は以下の通り

    /
    ├── index.html           --- TOP 画面
    ├── loggedout.html       --- ログアウト後の画面
    └── secure (Protedted Resource)
        └── welcome.php      --- ログイン後の画面
    

OpenID Provider (OP)

OpenID Connect を提供する側

  • Keycloak

  • 操作者(End-User)の Account(アカウント) を保持する

    • Account は UserInfoCredential で構成される
      • UserInfo - 名前とかメールアドレスとか
      • Credential - パスワード
  • RP-Apache(mod-auth-openidc) からリダイレクトされてEnd-userの認証認可を行う

  • RP-Apache(mod-auth-openidc) からのリクエストでEnd-userのUserInfoを提供する

画面フロー

    1. ブラウザから index.html にアクセスしてTOP画面を表示する
    1. Login with Keycloak をクリックすると /secure/welcome.php に遷移する
    1. が、しかし /securemod-auth-openidc が管理する Protected Resource なのである
    1. mod-auth-openidc はすかさず Keycloak にリダイレクトする
    1. Keycloak はログイン画面を表示する
    1. 無事ログインできたら Welcome画面( /secure/welcome.php )を画面に表示する
    1. welcome画面で Logout をクリックするとログアウト処理をして ログアウト完了画面に遷移する
    1. ログアウト完了画面で Goto Top をクリックするとTOP画面に戻る

memo : 今回は 7) 8)の詳細は調査していません、次の記事で...


Screen_Diagram

Keycloakのエンドポイント

フロー図に書いているエンドポイント

Configuration Endpoint

Authorization Endpoint(認可エンドポイント)

Authenticate Endpoint

  • End-Userが提示したCredentialを検証するエンドポイント
  • ここで Credential の検証OKとなるとAuthorization Code(認可コード) を発行して End-User に返す
  • OpenID Connectで明確に定義されたエンドポイントではなく、Authorization Endpointが提供する機能の一部という扱い
  • OpenID Connect Core 1.0 - 3.1.2.3. Authorization Server Authenticates End-User あたりの説明が参考になる
    • ↑に書いてあるとおり End-User の認証方式については規定範疇外 となっていて認証のやり方の細かい方法は書いていないです。このへんが OpenID Connect と FIDO は補完関係 ということなんですね。

Token Endpoint(トークンエンドポイント)

jwks_uri(証明書エンドポイント)

UserInfo Endpoint(ユーザー情報エンドポイント)

フローの詳細

0. Start

ログインを開始するまでのフロー


  • ブラウザ(End-user)が RP の 管理するリソース index.html にアクセスする


-page-2

  • index.html は ログインする前に表示する画面(Protected Resouce ではない)なので、そのまま 200 OK でレスポンスを返す


test-oidc-rp_1.png


1. Login

Keycloakのログイン画面を表示するまでのフロー

  • Login with Keycloak をクリックすると、./secure/welcome.php に遷移(GET)する


-page-2_1

  • リクエストを受けたRPのmod-auth-openidc は 認証が必要なリソースであることを検知する

    memo : 認可が必要なリソースの定義は auth_openidc.conf<Location /secure> でされている

  • mod-auth-openidcはまだアクセストークンを持っていないため、Keycloakからアクセストークンを取得するフローを開始する

    memo : アクセストークンの取得フローが openid-connect であることは auth_openidc.conf で設定されている


  • mod-auth-openidcはまずKeyCloakからOpenID Configuration を取得する

    memo : OpenID Configurationのエンドポイントは auth_openidc.conf で定義されている


-page-3


  • mod-auth-openidc は End-user へレスポンス 302 Found(リダイレクト) を返す

レスポンスは以下の通り

パラメータ 説明 取得元
Location /protocol/openid-connect/auth 認可エンドポイント にリダイレクトすることを指定する OpenID Configurationauthorization_endpoint
response_type code トークン発行手順がcodeであることを示す auth_openidc.confOIDCResponseType
scope openid ID トークンの発行を要求することを示す auth_openidc.confOIDCClientID
client_id test KeyCloakで設定されているクライアント auth_openidc.confOIDCScope
redirect_uri http://test-oidc-rp:8081/secure Keycoakで認証が完了した後にリダイレクトさせてほしい場所。
ここからはKeycloakの制御になって操作を行うがその後にRPに戻ってきてほしいんでここで指定しておく(*1)
auth_openidc.confOIDCRedirectURI

memo : state/nonceもついているけど省略

  • End-user は レスポンスを受け取り、KeyCloak の 認可エンドポイント にすっ飛んで行く

    GET /auth/realms/master/protocol/openid-connect/auth
    	?response_type=code
    	&scope=openid
    	&client_id=test
    	&state=28bO9uWjEJxcWw-W-k4J2VEmXYw
    	&redirect_uri=http%3A%2F%2Ftest-oidc-rp%3A8081%2Fsecure
    	&nonce=0Q3u5PmRIscEEgnIUeRiT9D8fI7HmwTQFd2dZ8Pk7aI
    


-page-4


  • Keycloak は ログイン画面を返す

    memo : Cookieが大量についてくるけど省略


-page-5


Sign_in_to_Keycloak

2. Get Authorization Code

Username/Passwordを取得してから**Authorization Code(認可コード)**を取得するまでのフロー

memo
操作者がログイン画面でUsername/Passwordを入力して Sign In ボタンをクリックするところから始まります。
ここから先がゴチャゴチャしているんですがフローはノンストップなので操作者にとっては一瞬です。


  • ログイン画面でUsername/Passwordを入力して Sign In すると End-user は KeyCloak の Authenticate Endpoint に POST する

    memo : クエリパラメータでめっちゃ色々ついているけど省略

    • Formデータ

      Form item 説明
      username hoge ユーザー名
      password xxx パスワード


-page-6


  • Keycloak は usernamepassword を検証して認証OKとなれば End-user へレスポンス 302 Found(リダイレクト) を返す

memo : ここに 認可コード が入っている

パラメータ 説明
Location http://test-oidc-rp:8081/secure リダイレクト先
(*1)で指定されたもの
code 050ab57b-64e1-410a-・・・ 認可コード(Authorization Code)
  • End-user は リダイレクトのレスポンスを受けたので、そのままリダイレクト先に飛んでいく


-page-7

3. Get Access Token & ID Token

認可コードを取得してから Access Token(アクセストークン) と ID Token(IDトークン) を取得するまでのフロー


  • mod-auth-openidc は Keycloak の トークンエンドポイント にPOSTする

    • このとき Authorization ヘッダに Basic を設定する

      ヘッダ 説明
      Authorization Basic dGVz... Basic認証であることを示す

      ↑の値なんですが

      Basic dGVzdDozM2I3MzJjNS0wMDZjLTQxNjMtOWM3Yy01NzVhNjBhMmEzNDg=
      

      これは Basic認証であることを意味していて、Basic 以降のBase64をデコードすると

      test:33b732c5-006c-4163-9c7c-575a60a2a348
      

      となっています。

      要はこの値で接続してくるクライアントを認証しています。→9. Client Authentication

      クライアントIDとシークレットは auth_openidc.confOIDCClientID,OIDCClientSecretです。

    • Form

      Form item 説明
      grant_type authorization_code 3.1.3.1. Token Request
      code 050ab57b-64e1-410a-・・・ 先程取得した 認可コード
      redirect_uri http://test-oidc-rp:8081/secure RPからOPに直接リクエストするバックチャネル通信なんでOPがリダイレクトのレスポンスしてくるわけではないと思うのですが Validation するため必須。
      3.1.3.2. Token Request Validation
      >redirect_uri パラメータの値が, 最初の Authorization Request に含まれていた redirect_uri パラメータの値と同一であることを確認
      ということみたい。


-page-8


  • Keycloak は Authorizationヘッダの値とか認可コードを検証してOKであればmod-auth-openidcにレスポンス を返す。
    レスポンスはJSON形式で**Access Token(アクセストークン) と ID Token(IDトークン)**が含まれている。

    Key Value 説明
    access_token JWT形式のデータ アクセストークン
    expires_in 60 アクセストークンの有効期限(60秒=1分)
    refresh_expires JWT形式のデータ リフレッシュトークン
    refresh_expires_in 1800 リフレッシュトークンの有効期限(1800秒=30分)
    token_type Bearer トークンタイプ
    id_token JWT形式のデータ IDトークン


-page-9

アクセストークンとは何か

リソースにアクセスするときの許可証。OAuthのそれと同じ。

IDトークンとは何か

ユーザーをちゃんと認証したよ、という証明書みたいなもの。ユーザー名とかの属性も入っている。

詳細は以下のサイトを見たほうがいい


  • 続けざまに KeyCloak の jwks_url(証明書エンドポイント) から証明書をGETする。

    • 証明書 = アクセストークン、IDトークンのJWTの署名を検証するために使う公開鍵

    • ここに入っている公開鍵でJWTを検証することでアクセストークン、IDトークンが改ざんされていないことを確認する

      memo : jwks_url は OpenID Configuration に入っている


    -page-10


  • UserInfo Endpoint(ユーザー情報エンドポイント) からユーザー情報をGETする。

  • ユーザー情報 = UsernameとかEmailとか

    • ユーザー情報エンドポイントにアクセスする際のAuthorizationヘッダはBearerで、先程取得した アクセストークン を指定する

    memo : UserInfo Endpoint は OpenID Configuration に入っている


-page-11


  • ここまででmod-auth-openidc は必要な情報を全て取得したことになる。End-userには一番最初にアクセスを要求されたURLに遷移するリダイレクトのレスポンスを返す。
パラメータ 説明
Location http://test-oidc-rp:8081/secure/welcome.php リダイレクト先


-page-12

4. Resource access

リダイレクト先に遷移する。リクエストを受けた mod-auth-openidc はアクセスを許可しHTMLを返す。

note : mod-auth-openidc は Cookie mod_auth_openidc_session にアクセストークンを紐付けていてアクセストークンの有効性を確認しているようです。mod_auth_openidc_sessionを削除するとKeycloakに問い合わせて再度アクセストークンをもらってきているのでしょう。


-page-13

おつかれさまでした

よくわからないことがまだあるなぁ...

  • ログアウトの動作 (Logout)
  • ログインしたままTOPに戻って再度ログインしたときの動作(Return to top wthile logged in)
  • アクセストークン/IDトークンの有効期限が切れたときの動作

蛇足(データサンプル)

OpenID Configuration

{
  "issuer": "http://test-oidc-keycloak:8080/auth/realms/master",
  "authorization_endpoint": "http://test-oidc-keycloak:8080/auth/realms/master/protocol/openid-connect/auth",
  "token_endpoint": "http://test-oidc-keycloak:8080/auth/realms/master/protocol/openid-connect/token",
  "introspection_endpoint": "http://test-oidc-keycloak:8080/auth/realms/master/protocol/openid-connect/token/introspect",
  "userinfo_endpoint": "http://test-oidc-keycloak:8080/auth/realms/master/protocol/openid-connect/userinfo",
  "end_session_endpoint": "http://test-oidc-keycloak:8080/auth/realms/master/protocol/openid-connect/logout",
  "jwks_uri": "http://test-oidc-keycloak:8080/auth/realms/master/protocol/openid-connect/certs",
  "check_session_iframe": "http://test-oidc-keycloak:8080/auth/realms/master/protocol/openid-connect/login-status-iframe.html",
  "grant_types_supported": [
    "authorization_code",
    "implicit",
    "refresh_token",
    "password",
    "client_credentials",
    "urn:ietf:params:oauth:grant-type:device_code",
    "urn:openid:params:grant-type:ciba"
  ],
  "response_types_supported": [
    "code",
    "none",
    "id_token",
    "token",
    "id_token token",
    "code id_token",
    "code token",
    "code id_token token"
  ],
  "subject_types_supported": [
    "public",
    "pairwise"
  ],
  "id_token_signing_alg_values_supported": [
    "PS384",
    "ES384",
    "RS384",
    "HS256",
    "HS512",
    "ES256",
    "RS256",
    "HS384",
    "ES512",
    "PS256",
    "PS512",
    "RS512"
  ],
  "id_token_encryption_alg_values_supported": [
    "RSA-OAEP",
    "RSA-OAEP-256",
    "RSA1_5"
  ],
  "id_token_encryption_enc_values_supported": [
    "A256GCM",
    "A192GCM",
    "A128GCM",
    "A128CBC-HS256",
    "A192CBC-HS384",
    "A256CBC-HS512"
  ],
  "userinfo_signing_alg_values_supported": [
    "PS384",
    "ES384",
    "RS384",
    "HS256",
    "HS512",
    "ES256",
    "RS256",
    "HS384",
    "ES512",
    "PS256",
    "PS512",
    "RS512",
    "none"
  ],
  "request_object_signing_alg_values_supported": [
    "PS384",
    "ES384",
    "RS384",
    "HS256",
    "HS512",
    "ES256",
    "RS256",
    "HS384",
    "ES512",
    "PS256",
    "PS512",
    "RS512",
    "none"
  ],
  "response_modes_supported": [
    "query",
    "fragment",
    "form_post"
  ],
  "registration_endpoint": "http://test-oidc-keycloak:8080/auth/realms/master/clients-registrations/openid-connect",
  "token_endpoint_auth_methods_supported": [
    "private_key_jwt",
    "client_secret_basic",
    "client_secret_post",
    "tls_client_auth",
    "client_secret_jwt"
  ],
  "token_endpoint_auth_signing_alg_values_supported": [
    "PS384",
    "ES384",
    "RS384",
    "HS256",
    "HS512",
    "ES256",
    "RS256",
    "HS384",
    "ES512",
    "PS256",
    "PS512",
    "RS512"
  ],
  "introspection_endpoint_auth_methods_supported": [
    "private_key_jwt",
    "client_secret_basic",
    "client_secret_post",
    "tls_client_auth",
    "client_secret_jwt"
  ],
  "introspection_endpoint_auth_signing_alg_values_supported": [
    "PS384",
    "ES384",
    "RS384",
    "HS256",
    "HS512",
    "ES256",
    "RS256",
    "HS384",
    "ES512",
    "PS256",
    "PS512",
    "RS512"
  ],
  "claims_supported": [
    "aud",
    "sub",
    "iss",
    "auth_time",
    "name",
    "given_name",
    "family_name",
    "preferred_username",
    "email",
    "acr"
  ],
  "claim_types_supported": [
    "normal"
  ],
  "claims_parameter_supported": true,
  "scopes_supported": [
    "openid",
    "email",
    "roles",
    "profile",
    "web-origins",
    "offline_access",
    "address",
    "microprofile-jwt",
    "phone"
  ],
  "request_parameter_supported": true,
  "request_uri_parameter_supported": true,
  "require_request_uri_registration": true,
  "code_challenge_methods_supported": [
    "plain",
    "S256"
  ],
  "tls_client_certificate_bound_access_tokens": true,
  "revocation_endpoint": "http://test-oidc-keycloak:8080/auth/realms/master/protocol/openid-connect/revoke",
  "revocation_endpoint_auth_methods_supported": [
    "private_key_jwt",
    "client_secret_basic",
    "client_secret_post",
    "tls_client_auth",
    "client_secret_jwt"
  ],
  "revocation_endpoint_auth_signing_alg_values_supported": [
    "PS384",
    "ES384",
    "RS384",
    "HS256",
    "HS512",
    "ES256",
    "RS256",
    "HS384",
    "ES512",
    "PS256",
    "PS512",
    "RS512"
  ],
  "backchannel_logout_supported": true,
  "backchannel_logout_session_supported": true,
  "device_authorization_endpoint": "http://test-oidc-keycloak:8080/auth/realms/master/protocol/openid-connect/auth/device",
  "backchannel_token_delivery_modes_supported": [
    "poll"
  ],
  "backchannel_authentication_endpoint": "http://test-oidc-keycloak:8080/auth/realms/master/protocol/openid-connect/ext/ciba/auth"
}

Access Token

https://jwt.io/ でデコードできる

JWT

eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJwSmdoalAxUVJLZ1lEWnFJVzNKV1dETnI3eUc5aEJiVGk4VV94SXh0Tmc4In0.eyJleHAiOjE2MjQ3NDc2MzIsImlhdCI6MTYyNDc0NzU3MiwiYXV0aF90aW1lIjoxNjI0NzQ3NTcxLCJqdGkiOiI2ZmU0NjkwNy1iZTFjLTQ2YWUtODlhYi03ZGIxMjI4YTJlMDYiLCJpc3MiOiJodHRwOi8vdGVzdC1vaWRjLWtleWNsb2FrOjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImFjMDg0OGU4LTUzZTMtNDQ4My1hNzM5LWQ3NjIzMTdhZjQ0NCIsInR5cCI6IkJlYXJlciIsImF6cCI6InRlc3QiLCJub25jZSI6IlVudkUtWjhwUS13MmxPSUVyd2F2WDF4dEo4eXlCNlhhV0l4cjRMQmxiZzAiLCJzZXNzaW9uX3N0YXRlIjoiZDk2OTQyNzctMDFhNy00OWRjLWJlMDktNTRhMzg3MDY2ZDkxIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLW1hc3RlciIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJob2dlIn0.ETQpOLqEPvTSBfwts85YwDMen8tw8ZUeF21w5LqdBaVquS7DuNcQpI-A_4RM3OR2L3XuwIfMYLk3AmGObZz_4bY7d1yfeBJYNwXXS1A6VJDQU3kZdGr9VZPAUoHcoMD6R4EZbG4nCl_idJ0b_bg4WEeY5IjdNLjcxrZZ4fax0TpuvBIoRJmnOIKMsKg5W7HyJYZ8nqKxFw1a3aGV2sy5tqeyAYordAO7_T4pgt-WpH73IJFqT7mNXorEnNEROqZQR7FAqU4Rs2mFBynAN1Sq_ICB8avYzF9QkLrUmud7A5oFvCjVi2WWHNxhhkM6x7Gv7gjqwlsaEofp9awkjqfFew

Decoded-Payload

{
  "exp": 1625894396,
  "iat": 1625894336,
  "auth_time": 1625894336,
  "jti": "193cba26-dcba-4704-9d39-31f88ee8339b",
  "iss": "http://test-oidc-keycloak:8080/auth/realms/master",
  "aud": "account",
  "sub": "9e9e8079-e8c4-4eaa-baaf-bcd22707d9a7",
  "typ": "Bearer",
  "azp": "test",
  "nonce": "B-3iE7nRNtsVs4D0r7YZw88-PPwBsQDoDKpOxrN3o9o",
  "session_state": "ef353a37-809a-4945-b3f2-0d04d6d01e32",
  "acr": "1",
  "realm_access": {
    "roles": [
      "offline_access",
      "uma_authorization"
    ]
  },
  "resource_access": {
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },
  "scope": "openid profile email",
  "email_verified": false,
  "preferred_username": "hoge",
  "email": "aa@aa.com"
}

ID Token

JWT

eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJwSmdoalAxUVJLZ1lEWnFJVzNKV1dETnI3eUc5aEJiVGk4VV94SXh0Tmc4In0.eyJleHAiOjE2MjQ3NDc2MzIsImlhdCI6MTYyNDc0NzU3MiwiYXV0aF90aW1lIjoxNjI0NzQ3NTcxLCJqdGkiOiJjYjI3YmY1MC0zYmZjLTQxN2QtOWU1NS1jMzc4M2UyODFiMzEiLCJpc3MiOiJodHRwOi8vdGVzdC1vaWRjLWtleWNsb2FrOjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjoidGVzdCIsInN1YiI6ImFjMDg0OGU4LTUzZTMtNDQ4My1hNzM5LWQ3NjIzMTdhZjQ0NCIsInR5cCI6IklEIiwiYXpwIjoidGVzdCIsIm5vbmNlIjoiVW52RS1aOHBRLXcybE9JRXJ3YXZYMXh0Sjh5eUI2WGFXSXhyNExCbGJnMCIsInNlc3Npb25fc3RhdGUiOiJkOTY5NDI3Ny0wMWE3LTQ5ZGMtYmUwOS01NGEzODcwNjZkOTEiLCJhdF9oYXNoIjoiUlZadkNhaEdCYWk2TlVydkVKam9mZyIsImFjciI6IjEiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInByZWZlcnJlZF91c2VybmFtZSI6ImhvZ2UifQ.rMcNKLdfd64W0r9QIPIlXVIiyTi6MUhmAQX2H_Bp6eviEecRoPYHxawG5fXZS2iNKAzDL5OjHbGl_Yzxkjr2UPBB7UWfgVIcjfD3BiOQO-V4haa8O3gGPMx0Xm1LD6r5QVV6eARm5_FTvpO8xwmgVzW0KXRfn9M-HyofE4NEjsMQTAel8TY_U7H1KJsqTezEZRfHrtU7EwyO0OVRvfVXp58F9Ly5GtXNrMDlekQWdaTA222_Rk6Tm6h3KNgwUKwbigtBwMDK19ZXeJ94_sFcbHfKcbgnFhnzEYyZ-3rSM9SKtPh0JUlordUOU7FUQVqKxviOgwrj7Wqi-2kekBZnxg

Decoded JSON

{
  "exp": 1624747632,
  "iat": 1624747572,
  "auth_time": 1624747571,
  "jti": "cb27bf50-3bfc-417d-9e55-c3783e281b31",
  "iss": "http://test-oidc-keycloak:8080/auth/realms/master",
  "aud": "test",
  "sub": "ac0848e8-53e3-4483-a739-d762317af444",
  "typ": "ID",
  "azp": "test",
  "nonce": "UnvE-Z8pQ-w2lOIErwavX1xtJ8yyB6XaWIxr4LBlbg0",
  "session_state": "d9694277-01a7-49dc-be09-54a387066d91",
  "at_hash": "RVZvCahGBai6NUrvEJjofg",
  "acr": "1",
  "email_verified": false,
  "preferred_username": "hoge"
}

jwks_uri Keys

{
  "keys": [
    {
      "kid": "pJghjP1QRKgYDZqIW3JWWDNr7yG9hBbTi8U_xIxtNg8",
      "kty": "RSA",
      "alg": "RS256",
      "use": "sig",
      "n": "zSlLHc3Znj4mpnGyyxr32XgT-cCP4YPUCGxQ4s7yuplhAeePO2vUUytlx0oekP1M8xVa4fFsmv1VNkbj8iF6k_gmyRJAoBjA6CEiV7p42-nQcwSV6i_V-iyXKejKoH7PKAQZmhUsz21fNEWhpprRL3s3iGQS5EQpdJf_ACIbSWAvU2GxczFUxTReVGBSjwWrtqdC1N-qvyVFoD_1o1HKD0wGGIxJS3Bt4qvYKuxrpXb_5iaK1lSYXj8r2nwd2tgs7qe1WgTFDpvh_ncLPIkNf08OLsH7CxoDs-sPQvbKgufsU1vTFhh0fXi6Z1pheO1mTnncs6KgLy_nlC7JskPM2Q",
      "e": "AQAB",
      "x5c": [
        "MIICmzCCAYMCBgF6KFytNzANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjEwNjIwMDczODIwWhcNMzEwNjIwMDc0MDAwWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNKUsdzdmePiamcbLLGvfZeBP5wI/hg9QIbFDizvK6mWEB5487a9RTK2XHSh6Q/UzzFVrh8Wya/VU2RuPyIXqT+CbJEkCgGMDoISJXunjb6dBzBJXqL9X6LJcp6Mqgfs8oBBmaFSzPbV80RaGmmtEvezeIZBLkRCl0l/8AIhtJYC9TYbFzMVTFNF5UYFKPBau2p0LU36q/JUWgP/WjUcoPTAYYjElLcG3iq9gq7Guldv/mJorWVJhePyvafB3a2Czup7VaBMUOm+H+dws8iQ1/Tw4uwfsLGgOz6w9C9sqC5+xTW9MWGHR9eLpnWmF47WZOedyzoqAvL+eULsmyQ8zZAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIqK00VqPXHVl8gpybKsyyZCnz+w3HoFO+7c4pVtWHy7eREPdmY4pgyqWKyY4064J/ZJ7TK8JNs6tQf1/LZUmp6fRMXQVRJglJyGz/J4ZBg7kqmzxi9kroNRhcStMidYjEkUHhpTK3dIOfUZ4vaf/OfN3WE8JzsXG5Jxz7DY9wN3oUCeZf6/ju2Lb8gIKAq+7wmxhmkZEZNU21Rx9S6bz4mYMSFaEQ7ldg3y14doiCZYCeVSJSoq74uOdAv+kxdo/FsnGZT8GRKsvCwQMSYAe/l5ccHVceFK3Isxp2EZVNwD/6ytjMkUgUTibakJAGVJMouRZStiy2n2srQ2egDjKhA="
      ],
      "x5t": "HaBzJVfpnNV6jtIK9ZtDn0F7mYA",
      "x5t#S256": "VPN7LyGrZXA_gb6WBOkk-4pUWuzxxctuKAWtdm5mYzk"
    }
  ]
}

Userinfo

{
	"sub": "9e9e8079-e8c4-4eaa-baaf-bcd22707d9a7",
	"email_verified": false,
	"preferred_username": "hoge",
	"email": "aa@aa.com"
}

Discussion