現在仕様策定中の OpenID Connect RP-Initiated Logout 1.0 とは

こんばんは ritouです。

むかーしむかし、あるところにOIDCのセッション管理に関する3つの仕様がありました。

(2015年の記事)

ritou.hatenablog.com

(Session Managementについてのさらに古い 2013年の記事)

ritou.hatenablog.com

いわゆるソーシャルログインと呼ばれる使い方ではRP/OP間のセッションの整合性をあまり意識しない感じになっていますが、 昔から使われている "SSO" 的な使われ方においてはそのあたりが意識されるかもしれません。 これらの仕様ではRP/OP間でセッションに変更がないか、ログアウトさせるいくつかの方法が定義されています。

これらは最近どうしてるのかな?というところで現状を見てみると、4つの仕様として策定が進められています。

[Openid-specs-ab] RP-Initiated Logout is now its own specification

また、既にOpenID Certificationにはテストも用意されており、パスしたOPも書かれています。

openid.net

f:id:ritou:20200819024520p:plain

というところで、今回はこのRP-Initiated Logoutについて概要(not 翻訳)を紹介します。

openid.net

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の値をヒントとして指定。RECOMMENDED
  • ui_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)とあります。これを行うとユーザーの意図せぬ挙動を防ぐのと同時に、後述するトラッキング判定に対しても効果があるかもしれません。

ここまでの流れを図にしました。

f:id:ritou:20200825010654p:plain

複数のRPに接続済みのOPはログアウト後に、SessionManagementでのセッション判定で "状態変更あり" を示したり、Front-Channel/back-Channel Logoutの仕様でRPにログアウト通知を送ります。

さらに、RP->OP->RPと戻る場合はパラメータが変わります。

  • id_token_hint : OPからRPに過去に発行されたID Tokenの値をヒントとして指定。REQUIRED
  • post_logout_redirect_uri : OPのログアウト後にRPに戻したい時に指定する戻り先URL。このURLが指定されるときは id_token_hint の値が必須となる。検証の際は完全一致。
  • state : 戻り先がある時のCSRF対策のための...(略。必須でいいだろ(OPTIONAL)!
  • ui_locales : OP上での優先言語、スクリプトの指定。OPTIONAL

f:id:ritou:20200825010923p:plain

この場合は 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あたりのサンプル実装をしたことがあったのですがどっか行ってしまったので、またどこかのタイミングで動作確認ができる環境を用意したいと思います。

ではまた!

f:id:ritou:20200821032656p:plain