今日やること
タイトルの通りです(笑
OpenAMのセッションは、通常iPlanetDirectoryPro
という名前のドメインCookie(SSO Token)で保持されます。Policy Agentを使ったシングルサインオンの場合は、このSSO TokenがOpenAMとPolicy Agentが導入されたアプリケーションの双方のセッションを保持する役目を負っています。ゆえに、SSO TokenをOpenAM上でInvalidationすれば、シングルログアウトができます。
ただし、Federationでシングルサインオンした場合はそうはいきません。Relying PartyはOpenID Providerから連携されたAssertion(ID Token)をVerifyし、自分でも認証したことにするために、セッションを払い出します。この場合、シングルログアウトを実現するには、Relying PartyのセッションとOpenAMのセッション、さらには**ID Token(やAccess Token)**をInvalidationする必要があります。
mod_auth_openidcのセッション
mod_auth_openidcはOpenID Providerから連携されたID TokenのVerifyが終わると、自分のセッションを払い出します。下記はOpenID Providerで認証後、Relying Partyにアクセスが完了した後のCookie一覧です。mod_auth_openidc_session
という名前のCookieがそれに当たります。
OpenID Connectにおけるセッション関連の仕様
2016年12月時点で、未だドラフトです。今年は8月に更新されて以降音沙汰なしといった感じです。
この中の5. RP-Initiated Logoutを今日は試していきます。このRelyig Party Initiated Logoutというのは簡潔に言うと、Relying Partyが起点となってセッション(RPとOP)とトークン(ID Tokenなど)を消していくといったものです。
mod_auth_openidcにおけるRP Initiated Logoutの設定
mod_auth_openidcはRP Initiated Logoutの仕様に対応しています。以下のような流れで実行されます。
- Relying Party上のRedirect URIのQuery Stringに
logout
というパラメータを載せて、リクエストを送る - Relying Partyのセッション(mod_auth_openidc_session)がInvalidationされる
- Relying PartyはOpenID Providerのend_session_endpointにID TokenとInvalidation後にリダイレクトするURLをリクエストする
- OpenID Providerはセッション(iPlanetDirectoryPro)とトークン(ID Tokenなど)をInvalidationしてから、Invalidation後にリダイレクトするURLにリダイレクトする
- Invalidation後にリダイレクトするURLはシングルログアウト完了画面にしておく
このend_session_endpointは3回ほど前の記事でOpenID Provider(OpenAM)のDiscovery Endpoint(/openam/oauth2/.well-known/openid-configuration)をたたいたときのレスポンスに含まれています。
では設定をしていきましょう。
OpenID Providerの設定
前々回登録したRelying Partyの設定を以下に変更します。
param | value | option |
---|---|---|
名前 | relyingparty | 変更なし |
パスワード | password | 変更なしclient secret |
リダイレクトURI | https://rp.example.com:443/protected/redirect_uri | redirect_uriのパスを変更 |
スコープ | openid profile | 変更なし |
ポストログアウトリダイレクト URI | https://rp.example.com:443/logout.html | 追加する |
このポストログアウトリダイレクトURIというのは先ほどのInvalidation後にリダイレクトするURLを指します。Open Redirectorにならないように、ちゃんとValidationします。
Relying Partyの設定
mod_auth_openidcの設定も少し変更します。下記は/etc/httpd/conf.d/openidc.conf
です。
LoadModule auth_openidc_module modules/mod_auth_openidc.so
OIDCProviderMetadataURL https://iam.example.com:443/openam/oauth2/.well-known/openid-configuration
OIDCClientID relyingparty
OIDCClientSecret password
OIDCRedirectURI https://rp.example.com:443/protected/redirect_uri
OIDCCryptoPassphrase passphrase
OIDCScope "openid profile"
OIDCSSLValidateServer Off
<Location /protected>
AuthType openid-connect
Require valid-user
</Location>
変更したのは、OIDCRedirectURI
だけです。設定変更後はApacheを再起動しましょう。
$ sudo systemctl restart httpd.service
コンテンツの配置
下記のコンテンツを/var/www/html
以下に配置します。
$ tree
.
├── logout.html
└── protected
└── logoutlink.html
1 directory, 2 files
- logout.html
<h1>YOU HAVE BEEN LOGGED OUT.</h1>
- logoutlink.html
<a href="https://rp.example.com:443/protected/redirect_uri?logout=https://rp.example.com:443/logout.html">Logout</a>
繰り返しになりますが、logout.htmlはInvalidation後にリダイレクトするURLです。logout.linkはend_session_endpointにリクエストを送るためのリンクを作っています。
動作確認
まず、Relying Partyのlogout.linkにアクセスすると、OpenID ConnectのAuthorization Code Flowが開始されます。
前回作ったアカウント(ユーザー名はgnanashi
)でサインインします。
ユーザー属性の連携同意画面が表示されるので、同意します。
シングルログアウトリンクが表示されますので、クリックし、end_session_endpointにログアウト要求を送信します。
その後、logout.htmlのコンテンツが表示されます。
この時点で、Relying Partyのセッション(mod_auth_openidc_session)、OpenID Providerはセッション(iPlanetDirectoryPro)とトークン(ID Tokenなど)のInvalidationは完了しています。表示されていますが、OpenID Provider(OpenAM)上では無効なセッションとして扱われます。
ちなみに、end_session_endpointには下記のようなリクエストが送られています。RP-Initiated Logoutの仕様通りですね。
GET
/openam/oauth2/connect/endSession?
id_token_hint=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
.
eyJhdF9oYXNoIjoiTURxUlYyUGFlN3R1M3F1bGdPaFFjdyIsInN1YiI6ImduYW5hc2hpIiwiYXVkaXRUcmFja2luZ0lkIjoiZDcxNDQ0ODEtNmY3Ny00OTM5LTk0ZDYtYzViZjEzYzZiMmRkLTkzNTgiLCJpc3MiOiJodHRwczovL2lhbS5leGFtcGxlLmNvbTo0NDMvb3BlbmFtL29hdXRoMiIsInRva2VuTmFtZSI6ImlkX3Rva2VuIiwibm9uY2UiOiI1VGdaYW5xM29fTkMwZWRGcmZ2UF85X2hJRGx2VXdGbDFUcUdzUWd5WGVBIiwiYXVkIjoicmVseWluZ3BhcnR5IiwiY19oYXNoIjoibnhEOTAxOHVYdWlpTjdpM2FIYTRyUSIsIm9yZy5mb3JnZXJvY2sub3BlbmlkY29ubmVjdC5vcHMiOiJhNmVjOWQ3Zi01MGQ5LTRjZTYtYjdkNi01ZDMxOWE0ZWEyYjUiLCJhenAiOiJyZWx5aW5ncGFydHkiLCJhdXRoX3RpbWUiOjE0ODE0MjEwNDcsInJlYWxtIjoiLyIsImV4cCI6MTQ4MTQyNDY4OCwidG9rZW5UeXBlIjoiSldUVG9rZW4iLCJpYXQiOjE0ODE0MjEwODh9
.
Kcuqe1YXTUuG30GAYcM8m1-Mkt75s37ehrEGFviPftg
&
post_logout_redirect_uri=https%3A%2F%2Frp.example.com%3A443%2Flogout.html
まとめ
- Federationでシングルサインオンしたとき、シングルログアウトを実現するのはちょっと難しい
- mod_auth_openidcはRP-Initiated Logoutができる
- OpenID Provider側のend_session_endpointはDiscovery Endpointでパスが公開されている
長々と書いたけど、ぶっちゃけブラウザ落とせばいいんじゃないの?
予定とは何だったのか状態になってきましたね~
明日はなにしよう~(◞‸◟)
ばい!