Apache HTTP Server で Google 認証
認証認可モジュールに統合されているので簡単
mod_auth_openidc
Apache に OpenID Connect (OIDC) の Relying Party (RP) としての認証機能を付与するモジュール
ID Token を使った認証部分と、claims を使った認可部分を併せ持つ
認証ユーザーは REMOTE_USER として参照可能
ID Token の claims をサーバー変数やリクエストヘッダとして参照可能
Apache で動作するアプリまたはリバースプロキシとして活用しやすい
CentOS 7 では標準リポジトリに含まれている(1.8.8 と古いので一部設定できない項目はある)
Google アカウントを OpenID Provider (OP) とする場合
Google Cloud Console でプロジェクトを作成し、アプリを登録して OAuth2 credential を発行する
アプリケーションの前段に Apache HTTP Server を導入
もう少し具体的な例は Rundeck を Google 認証で使うの方に
code:httpd.conf
<VirtualHost *:443>
OIDCProviderMetadataURL https://accounts.google.com/.well-known/openid-configuration
OIDCClientID <Client ID>
OIDCClientSecret <Client Secret>
OIDCCryptoPassphrase <任意の文字列> # Cookie 暗号化用キー
# mod_auth_openidc のために割り当てた専用の URL
# OpenID Connect との通信に使われるだけでなく、アプリケーションからモジュールを操作する際にも使われる
OIDCRedirectURI https://<your-server-authority>/auth/redirect
# アクセス許可ドメインを絞り込む場合
OIDCAuthRequestParams hd=example.com
# メールアドレスを REMOTE_USER に
OIDCScope "openid email profile"
OIDCRemoteUserClaim email
# 全てのアクセスに認証を要求する
<Location />
AuthType openid-connect
Require valid-user
</Location>
# 一部は除外する (Let's Encrypt とか)
<Location /.well-known/>
Require all granted
</Location>
# リバースプロキシする場合
ProxyPass /.well-known !
ProxyPass / http://localhost:8080/ retry=60
ProxyPassReverse / http://localhost:8080/
RequestHeader set X-Forwarded-Proto %{REQUEST_SCHEME}s
ProxyPreserveHost On
ProxyRequests Off
# REMOTE_USER をバックエンドにヘッダで送る場合
OIDCAuthNHeader X-Auth-User
# ... ServerName や SSLEngine 等
</VirtualHost>
アプリから資格情報を参照
資格情報はサーバー環境変数およびリクエストヘッダとして参照可能
table:参照可能な情報
REMOTE_USER 既定は <sub>@<iss のホスト> OIDCRemoteUserClaim で値を変更可能
OIDC_access_token アクセストークン
OIDC_access_token_expires 有効期限 (Unix time)
OIDC_refresh_token リフレッシュトークン OIDCPassRefreshToken に On を指定した場合
OIDC_CLAIM_<claim> Claim の個別情報 OIDCPassIDTokenAs に claims が含まれる場合(既定)
OIDC_id_token 生の id_token JWT OIDCPassIDTokenAs に serialized が含まれる場合
OIDC_id_token_payload ペイロードの JSON OIDCPassIDTokenAs に payload が含まれる場合
OIDC_userinfo_json UserInfo の JSON OIDCPassUserInfoAs に json が含まれる場合
OIDC_userinfo_jwt UserInfo の JWT OIDCPassUserInfoAs に jwt が含まれる場合
OIDC_CLAIM_<claim> は claims の数だけ展開される
OIDC_CLAIM_ 部分は OIDCClaimPrefix で変更可能
OIDCBlackListedClaims で展開しない claim の指定が可能(あるものが除外される。OIDCWhiteListedClaims より優先)
OIDCWhiteListedClaims で展開する claim の指定が可能(ないものは除外される)
OIDCPassIDTokenAs に claims を指定しない場合一切展開されない
REMOTE_USER は既定で変数のみ
Apache の authn に組み込まれるのでログに記録される
OIDCRemoteUserClaim で細かく調整可能
OIDCRemoteUserClaim email などに設定すればメールアドレスにも変えることができる
ただし email claim を受け取るためには OIDCScope "openid email" のように email スコープが必要
算出値をヘッダ出力したい場合は OIDCAuthNHeader にリクエストヘッダ名を指定すれば出力してくれる
アプリから OAuth2 のリソースにアクセス
OIDCScope に追加のスコープを指定することで、アクセストークンに他のリソースへのアクセス権が付与される
OIDC_access_token を使ってリソースにアクセスすれば良い
アクセストークンの有効期限が切れた場合は以下にリダイレクトすることで更新可能
<OIDCRedirectURI>?refresh=<redirect_uri>&access_token=<access_token>
<redirect_uri> は更新後にリダイレクトする URI。通常はリクエスト元(現在)の URL
<access_token> は古いアクセストークン。モジュール内の値と一致しているか確認されるだけで有効期限は関係ない
更新後新しい情報と共に <redirect_uri> にリダイレクトされるので処理をやりなおす
セッション
OP 側のセッション管理拡張 OpenID Connect Session Management の RP 側応答に対応している
OpenID Connect Front-Channel Logout に対しては <OIDCRedirectURI>?logout=get で連動する
PingFederate の Track User Sessions for Logout に対しては <OIDCRedirectURI>?logout=img で連動する
RP としてのセッション管理はモジュール内部にキャッシュされる
table:セッション内部の値
iat セッション開始日時
access_token アクセストークン
access_token_expires アクセストークンの有効期限
refresh_token リフレッシュトークン
id_token OP から受け取った id_token
userinfo UserInfo エンドポイントの値
セッションのデータは OIDCSessionInactivityTimeout の間アクセスがなければ破棄される
既定で 300 秒。アクセスすると有効期限が延長される
セッションのデータは最大 OIDCSessionMaxDuration の間キャッシュされる
既定で 8 時間。0 を指定した場合は id_token の有効期限まで
OP を経由した認証が発生した場合のみ内部データが作成・更新され、有効期限が延長される
通常は OIDCSessionInactivityTimeout の方がシビア
セッションは専用の Cookie にてブラウザとの関係性が維持される
OIDCSessionType が server-cache (既定)の場合セッション Cookie(ブラウザを閉じるまで)
OIDCSessionType が server-cache:persistent の場合 Cookie は OIDCSessionInactivityTimeout の有効期限となる
ブラウザを開き直してもセッションが維持される
OIDCCookie で名前を変更可能
OIDCCookieDomain, OIDCCookiePath, OIDCCookieHTTPOnly で Cookie のパラメータを調整可能
セッションが切れた場合、OP に対して最初から OpenID Connect の認可を行うことになる
通常 OP は独自にログイン状態をブラウザに記憶させているため、OP 側の画面がスキップされることがある
この場合、セッションは一旦切れたが、利用者には継続ログインしているように見える
ログアウト
悩ましい
<OIDCRedirectURI>?logout=<redirect_uri> にアクセスすることでログアウトを開始する
OpenID Connect Session Management 拡張に対応している OP の場合内部で RP-Initiated Logout が実行される
モジュールが保持しているセッションをクリアし、セッション Cookie も期限切れとなる
ログアウト処理完了後 <redirect_uri> にリダイレクトされる
<redirect_uri> がモジュールの認証対象になっている場合
OpenID Connect のフローが再開する
OpenID Connect Session Management に対応してる場合
OP でもログアウト済みなので OP のログイン or 承認画面になる
OpenID Connect Session Management に対応してない場合(Google 等)
通常 OP は独自にログイン・承認状態を維持している
OP の承認情報が残っている場合、確認なしに再ログインされてるので、ログアウトの意味がない
OpenID Connect の prompt パラメータに login や consent を指定することで強制的に OP の画面は出せる
prompt は OIDCAuthRequestParams で設定する(hd などと一緒に指定する場合は & で連結)
ただしこの場合、ログアウトを意図していない RP 側のセッション切れでも OP で画面が出ることになる
<redirect_uri> がモジュールの認証対象になってない場合
ログアウト画面を表示すれば良い
ログアウト画面で参照しているリソースもモジュールの認証対象から外さないといけない点に注意
参照
https://github.com/zmartzone/mod_auth_openidc
ほぼここに書いてあるとおりで動作する
#auth