こんばんは ritouです。
むかーしむかし、あるところにOIDCのセッション管理に関する3つの仕様がありました。
(2015年の記事)
(Session Managementについてのさらに古い 2013年の記事)
いわゆるソーシャルログインと呼ばれる使い方ではRP/OP間のセッションの整合性をあまり意識しない感じになっていますが、 昔から使われている "SSO" 的な使われ方においてはそのあたりが意識されるかもしれません。 これらの仕様ではRP/OP間でセッションに変更がないか、ログアウトさせるいくつかの方法が定義されています。
これらは最近どうしてるのかな?というところで現状を見てみると、4つの仕様として策定が進められています。
- OpenID Connect Session Management 1.0 - draft XX
- RPからOPへのログアウト要求部分が分離されました OpenID Connect RP-Initiated Logout 1.0 - draft XX
- HTTP-Based Logout -> OpenID Connect Front-Channel Logout 1.0 - draft XX
- Back-Channel Logout -> OpenID Connect Back-Channel Logout 1.0 - draft XX
[Openid-specs-ab] RP-Initiated Logout is now its own specification
また、既にOpenID Certificationにはテストも用意されており、パスしたOPも書かれています。
というところで、今回はこのRP-Initiated Logoutについて概要(not 翻訳)を紹介します。
This specification complements the OpenID Connect Core 1.0 specification by enabling the Relying Party to request that an End-User be logged out by the OpenID Provider.
これはOPによるエンドユーザーのログアウトをRPから要求できるようにするための拡張仕様です。
新しい用語
これぐらいです。
- Logout Endpoint : RPがログアウトのリクエストを送るターゲットとなるOPのエンドポイント
RPはこの値を後述する metadata から取得したりドキュメントとかで把握する必要があります。
RPからOPへのログアウト要求
RPがOPにログアウトを要求するパターンとして、2つあります。
- RP -> OP と遷移して終わるパターン
- RP -> OP -> RP に戻ってくるパターン
前者の場合、必要なパラメータは
id_token_hint
: OPからRPに過去に発行されたID Tokenの値をヒントとして指定。RECOMMENDEDui_locales
: OP上での優先言語、スクリプトの指定。OPTIONAL
となります。AuthZ(AuthN) Requestのように client_id パラメータを用いて明示的に Client を指定したりはありません。
id_token_hint
パラメータがあった場合、事前に ID Token にセッション識別子である sid
を入れておくことで現在のセッションと一致するかどうかの判定ができますが、ない場合や検証不可な場合はOPとしてはユーザーがどこから来たのかさえわからない(信用できない)状態になります。
セッションとIDTokenの関連というと今までも何度か記事を書いてきましたが、今回のようなセッション関連の仕様を読むときは、IDTokenをセッション識別という目的で一定期間保持することを想定しなければなりません。有効期限はサーバー時間のずれに影響でないぐらいになるべく短くしIDTokenを取得したタイミングで "ID連携" を行う、という本来のOIDCの考え方との違いについてよく頭の体操をしておく必要があるでしょう。(個人的には id_token_hint
という使い方が大っ嫌いなのですが精一杯大人な書き方をしています。)
また、仕様中に突然出てくる sid
ですが、これは OpenID Connect Front-Channel Logout で定義されています。仕様の最初の方で他のセッション関連の拡張仕様との関連について言及はありますが、sid
がどこで定義されたものかが言及されていないと、初めて見た開発者は混乱するかもしれません。
Draft: OpenID Connect Front-Channel Logout 1.0 - draft 04
sid Identifier for the Session.
OPはログアウトURLでユーザーに対して「ログアウトしますか?」と尋ねるべき(SHOULD)とあります。これを行うとユーザーの意図せぬ挙動を防ぐのと同時に、後述するトラッキング判定に対しても効果があるかもしれません。
ここまでの流れを図にしました。
複数のRPに接続済みのOPはログアウト後に、SessionManagementでのセッション判定で "状態変更あり" を示したり、Front-Channel/back-Channel Logoutの仕様でRPにログアウト通知を送ります。
さらに、RP->OP->RPと戻る場合はパラメータが変わります。
id_token_hint
: OPからRPに過去に発行されたID Tokenの値をヒントとして指定。REQUIREDpost_logout_redirect_uri
: OPのログアウト後にRPに戻したい時に指定する戻り先URL。このURLが指定されるときはid_token_hint
の値が必須となる。検証の際は完全一致。state
: 戻り先がある時のCSRF対策のための...(略。必須でいいだろ(OPTIONAL)!ui_locales
: OP上での優先言語、スクリプトの指定。OPTIONAL
この場合は id_token_hint
も必須になりますが、ここまでやるならAuthZ Requestのように client_id
などを利用する方が良いのではないかと個人的には思います。
この仕様の概要としてはこんな感じです。
Metadata
OP/RPのURLの扱いが書かれています。
OpenID Provider Metadata
OpenID Provider Metadata では RP が Logout Endpoint を Discovery できるように、end_session_endpoint
という値を定義します。
Client Registration Metadata
OP が RP-Initiated LogoutとDynamic Registrationをサポートする場合、post_logout_redirect_uris
という値を事前に登録します。
ITP, SameSite Cookieとセッション関連仕様への影響
ちょうど先日、OpenID TechNight vol.17 ~ with コロナ編でiframeを使うユースケースへの影響について説明されていました。
https://www.youtube.com/watch?v=0856pHMoTDs
その中で、iframeを使っているために影響が考えられる仕様として2つが紹介されていました。
- Session Management
- Front-Channel Logout
それぞれの仕様にもこの影響については言及があります。
- Session Management - 5.1. User Agents Blocking Access to Third-Party Content「RPコンテキストで呼び出したOPのフレームがCookieにアクセスできず、ログイン状態が変更されたという応答を返し、再認証されまくるかも」
- Front-Channel Logout - 4.1. User Agents Blocking Access to Third-Party Content「frontframe_logout_uriがOPによってレンダリングされた時にRPのログイン状態にアクセスできなくてログアウトされないかも」
今回のRP Initiated Logoutでは、OPはLogout EndpointへのアクセスでGET/POSTをサポートしなければならない(MUST)とあります。 よって、POSTパラメータとなると2つのパターンの前者ではOP、後者ではOP/RP両方でログアウト機能に関連するHTTP CookieのSameSite属性を意識する必要があります。
そう言えばチャチャッとSameSite属性毎の挙動を確認するためのツールを用意しましたので良かったら記事を読んでみてください。 medium.com
また、ログアウトしますか?のようなユーザーインタラクションを省略すると今度はトラッカー判定の方にも関連してきそうなので、この辺りの仕様とブラウザのHTTP Cookie, トラッカー判定事情の関係は今後も注意深くみていく必要がありそうです。
まとめ
- RPからOPへのログアウト要求を送る方法が定義されている
- OPからRPに戻るかどうかで2種類の挙動がある
- POSTの場合はHTTP CookieのSameSite属性に気を付けろ
昔SessionManagementあたりのサンプル実装をしたことがあったのですがどっか行ってしまったので、またどこかのタイミングで動作確認ができる環境を用意したいと思います。
ではまた!