OpenID Flow / Keycloak

OpenIDにはいくつかのフローがありますが、ここではまず前回試した認可コードフローとインプリシットフローについての差異を詳しく調べてみました。
(リダイレクトによる連携などをするフローはこの二つ)
※クライアント・クレデンシャルズフローについて、またPKCEについて最下部に追記(2023/4/7)

「OAuth 2.0 全フローの図解と動画」
https://qiita.com/TakahikoKawasaki/items/200951e5b5929f840a1f
「KeycloakでOpenID Connectを使ってシングルサインオンをしてみる(認可コードフロー(Authorization Code Flow)編)」
https://qiita.com/rawr/items/d4f45e094c39ef43cbdf
「KeycloakでOpenID Connectを使ってシングルサインオンをしてみる(他のフロー(Implicit Flow、Resource Owner Password Credentials、Client Credentials)編」
https://qiita.com/rawr/items/5fde71da850c1f65373a

環境
環境は前回のものと同じですが、KeycloakとApacheのサーバを分けてみました。
Webブラウザ: 192.168.1.228 / Chrome / windows
Keycloak(n07): 192.168.1.148 / Ubuntu 20.04
Apache(n03): 192.168.1.147 / Ubuntu 22.04

また時刻のズレがあると以下のエラーが以下のエラーがでるため、

ブラウザ

OpenID Connect Provider error: Error in handling response type.

/var/log/apache/error.log

[auth_openidc:error] [pid 199611:tid 140239976773184] [client 192.168.1.228:49840] oidc_proto_parse_idtoken: id_token payload could not be validated, aborting, referer: http://192.168.1.147/private/callback

下記のように時間同期サービスの再起動と確認をしました。

sudo systemctl restart systemd-timesyncd.service
timedatectl

設定
認可コードフロー(Code Flow)

auth_openidc.conf

インプリシットフロー(Implicit Flow)

auth_openidc.confは、OIDCResponseTypeを”token id_token”に変更

tcpdumpを使って実際に動かしたときのパケットキャプチャをとり(Apache側)、シーケンス図にまとめてみました。(※ログイン時メールアドレスではなく、ユーザ名を入力)

Code Flow

Implicit Flow

認可コードフローと、インプリシットフローの大きな違いはアクセストークンの受け取り方ですが、その違いを確認することできました。先入観としてインプリシットフローの方がシンプルなのかと思いましたが、そうではありませんでした。
インプリシットフローのアクセストークンを受け取るしくみが、確認ができなかったためKeycloak側のバケットも確認したところ、リダイレクトURLに#が含まれており、パラメータがApache側のtcpdumpに現れないことに気づきました。
またリダイレクトもJavaScriptでPostOnLoadというロード時に、#以下の文字列をバースして変数をセットしてPOSTリダイレクトするという、ちょっとトリッキーなことをやっています。(普通にリダイレクトするとGETになってしまう)

概念図とあわせて実際にパケットを追ってみると理解が深まります。他のフローもまた確認してみたいと思っています。

最後に、長くなりますがパケットキャプチャの結果を載せておきます。(意外と後からいろいろと確認したいことが多いため)
表示制限をしているためLocationヘッダが切れている部分もありますが(トークンがながすぎるため)、実際テストでは、表示数を増やして確認し、上記シーケンス図に反映させています。
CodeFlow

Implicit Flow

※クライアント・クレデンシャルズフロー
参考) https://www.appsdeveloperblog.com/keycloak-client-credentials-grant-example/
管理画面より
クライアントの設定
・Service Accounts Enabled : ON
クライアントのCredentials
・シークレットキーのコピー

access_tokenの取得

curl –location –request POST ‘http://localhost:8080/auth/realms/demo/protocol/openid-connect/token’ \
–header ‘Content-Type: application/x-www-form-urlencoded’ \
–data-urlencode ‘client_id=client-credentials’ \
–data-urlencode ‘client_secret=9e9aad32-e86f-4b48-a657-4e89004c0706’ \
–data-urlencode ‘scope=email’ \
–data-urlencode ‘grant_type=client_credentials’ | jq

上記アクセストークンを使用して、イントロスペクションの実行(トークンが有効なら、”active”: true)
参考) https://docs.nginx.com/nginx-management-suite/acm/tutorials/introspection-keycloak

curl -D – –location –request POST ‘http://localhost:8080/auth/realms/demo/protocol/openid-connect/token/introspect’ \
–header ‘Content-Type: application/x-www-form-urlencoded’ \
–data-urlencode ‘client_id=client-credentials’ \
–data-urlencode ‘client_secret=9e9aad32-e86f-4b48-a657-4e89004c0706’ \
–data-urlencode ‘token=eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSl…………’

※PKCE
管理画面よりクライアント設定(S256)

/etc/apache2/mods-enabled/auth_openidc.conf に追記

OIDCPKCEMethod S256

※認可コードフロー(Code Flow)の設定がベース

設定をすると、リクエストパラメータに

code_challenge
code_challenge_method
code_verifier

が追加される

n03->ブラウザ(Location)

http://192.168.1.148:8080/auth/realms/apache/protocol/openid-connect/auth?response_type=code&scope=openid&client_id=apache24&state=bSMPa_w34-G0o7TMXIU3n5ikvq8&redirect_uri=http%3A%2F%2F192.168.1.147%2Fprivate%2Fcallback&nonce=Y6-q5o3HlwTcQv6P7aDfl6rV0rVFwb2XnzGvauv-XPo&code_challenge=IAMPa5v90qbL6S-00U05Mp4AYz9le9CAfEVyafQNVOg&code_challenge_method=S256

n03->n07

POST /auth/realms/apache/protocol/openid-connect/token
grant_type=authorization_code&code=0451bf18-9b23-4e8f-bfb9-db80ba587bef.0d2983c3-13e5-4dd5-b9e0-c4a1aa702044.2dd726c9-e815-42e6-8c53-b57bd27bb3b0&redirect_uri=http%3A%2F%2F192.168.1.147%2Fprivate%2Fcallback&code_verifier=hTezQCGJsHONEMFEN3PussSXcpnAujk2VzH8McJi2BY