Application Load BalancerとAuth0連携させてOIDC認証する方法
記事の概要
AWSのApplication Load Balancer(以下ALB)には、 OpenID Connect(以下OIDC)準拠のIdPと連携する機能が備わっています。本記事では、ALB,Auth0,Webアプリ間でどのようなデータがやりとりされているかを解説した後、ALBとAuth0の連携方法を解説します。
ALBのOIDC連携の概要
詳細なフローはAWSの公式ドキュメントに掲載されていますので、こちらをご覧いただくのも良いかと思います。
① Auth0で認証
ユーザーが認証されていない状態でALBにアクセスを行うとAuth0のログイン画面にリダイレクトし、認証情報の入力が求められます。認証されているか否かはSession Cookieによって判断されます。
② トークンを発行
ユーザーが認証されるとAuth0は各種トークン(ID Token, Access Token, Refresh Token)を発行します。
トークンに関してはALB側で保存されます。基本的にRefresh Tokenの有効期限が長めに設定されているので、ID Token, Access Tokenの有効期限が切れた場合は、Refresh Tokenを使ってALBがID Token, Access Tokenの再取得を行います。このトークンの再取得はALBが裏側でよしなにやってくれます!
トークンの管理を実装しなくてすむので非常に便利です(※)
※ ちなみにAuth0にはRefresh Tokenの取得もよしなにやってくれるSilent Authenticationなる機能も存在します。
③ Cookieを発行
ALBからAWSELBAuthSessionCookieというCookieがユーザーのブラウザに発行されます。これはUser <-> ALB間のセッションを管理するためのものです。ちなみに、このCookieをexpireさせることによりログアウト処理が実装できます。
④ Cookie付きでリクエスト
ユーザーは③で取得したAWSELBAuthSessionCookieをHTTPリクエストにのせてALBにアクセスします。ALBが認証済であると判断し、今回はAuth0にはリダイレクトされません。
⑤ header付きでリクエスト
ALBはTarget Groupに対して、3つのヘッダーを付与してHTTPリクエストを投げます。
x-amzn-oidc-accesstoken
Auth0から取得されたAccess Tokenです。Access TokenはJWT({header}.{payload}.{signature})の形式になっています。Base64でエンコードされています。payload部分をデコードすると以下のようなテキストを取得できます。
{
"iss": "https://e-dash-app-dummy.jp.auth0.com/",
"sub": "auth0|123bc3a782a6145d6577f0e5",
"aud": [
"https://e-dash-app-dummy.jp.auth0.com/api/v2/",
"https://e-dash-app-dummy.jp.auth0.com/userinfo"
],
"iat": 1718495511,
"exp": 1718499111,
"scope": "openid profile offline_access",
"azp": "xnieW123euh5t02VRtZIpMj34SW86W1F"
}
x-amzn-oidc-data
Auth0から取得されたID Tokenに含まれるユーザークレームがJWT形式で格納されます(ID Tokenそのものではありません!)
x-amzn-oidc-accesstoken同様にpayload部分をデコードすると以下のようなテキストを取得できます。
{
"sub": "auth0|123bc3a782a6145d6577f0e5",
"nickname": "kohekohe",
"name": "KoheKohe",
"picture": "https://s.gravatar.com/avatar/xxxxxxxxx.png",
"updated_at": "2024-06-15T12:26:52.579Z",
"exp": 1718495631,
"iss": "https://e-dash-app-dummy.jp.auth0.com/"
}
x-amzn-oidc-identity
ユーザークレームのsubになります。つまるところAuth0におけるユーザーIDになります。
auth0|123bc3a782a6145d6577f0e5
Webアプリケーション側ではヘッダーからこれらの値を取得し、ユーザー情報の取得であったり、リクエストの正当性をチェックするとよいでしょう。
Auth0とALBを連携させる
概要を理解したところで、実際にAuth0と連携する方法を解説していきます。
前提条件
- AWS環境にて、ALB・Target Groupを作成済みで、背後にWebアプリがEC2やECS等で起動している(ALBのHTTPSのリスナーが設定されており、Target Groupへ転送される状態)
- Auth0にてApplicationが作成済であり、各種Application URIsが適切に設定済。
- ログイン画面はAuth0のUniversal Loginを想定。
Auth0側の設定
① ApplicationsにてID Tokenの有効期限を設定
ID Tokenの有効期限を設定します。ここでは例として86,400秒(24時間)を設定しています。
② ApplicationsにてRefresh Tokenを有効化
Refresh Token ExpirationのAbsolute ExpirationとInactivity Expirationを有効化しておきます。例ではLifetimeの値はデフォルト値としています。
③ APIs > SettingsにてAccess Tokenの有効期限を設定
Access Tokenの有効期限を設定します。ここでは例として86,400秒(24時間)を設定しています。特に理由がなければID Tokenと同じ値にすると良いでしょう。
④ APIs > SettingsにてAllow Skipping User Consentを有効化
Access Settingsにて、Allow Skipping User Consentを有効化しておきます。これを有効化しておかないと、初回ログイン時に余計な確認画面が表示されてしまいます。
ALB側の設定
① Auth0のコンソールから各種情報を取得
Applications > Settingsから各種情報を取得します。Domain
・Client ID
・Client Secret
の3つを控えておきます。
② ALBのHTTPSのリスナーを設定
ALB > HTTPS:443リスナー > リスナーの編集 よりALBの設定を変更します。
OpenID または Amazon Cognitoを使用するを選択し、①で取得した情報を元に以下の通り入力します。
アイデンティティプロバイダー:OIDCを選択
発行者:https://{Domain}/
認証エンドポイント:https://{Domain}/authorize
トークンエンドポイント:https://{Domain}/oauth/token
ユーザー情報エンドポイント:https://{Domain}/userinfo
クライアントID:Client IDを入力
クライアントのシークレット:Client Secretを入力
高度な認証設定を以下の通り設定します。
スコープにはアプリの仕様に応じて適切な値を設定しましょう。例ではopenid profile offline_access
を設定しています。
(openidを設定しないとID Token, offline_accessを設定しないとRefresh Tokenが取得できません)
追加のリクエストパラメータを以下の通り設定します。
キー/値 = audience / https:/{Domain}/api/v2/
この状態でALBにアクセスを行うと、Auth0のログイン画面にリダイレクトします。その後、認証情報入力するとWebアプリにアクセスできるはずです。
ハマりポイント
私が構築を行う上でハマったポイントを2つ取り上げます。
① Access TokenのPayloadが取得できない
ALBの追加のリクエストパラメータにaudience
を設定しないとAccess Tokenが不完全な形式で取得されます。必ず設定するようにしましょう。
AWSのコンソール上には省略可能
と記載されているので見逃しがちです。
② Refresh Tokenが取得されない
ALBの高度な認証設定にて、スコープにoffline_access
を設定しないとRefresh Tokenが取得されません。
Refresh Tokenが取得できないと、Access TokenやID Tokenの有効期限が切れた場合にALBが再取得を行ってくれません。
offline_access
が必要なことはOpenIDConnectの仕様に記載されています。
また、Auth0のコンソール上でRefresh Tokenの有効期限が設定されていない場合もRefresh Tokenが取得できないので注意です。
まとめ
ALBのOIDC連携の概要と、ALBとAuth0を連携させる方法を解説しました。
ALBの同機能は非常に便利なので、Webアプリの構築の際は利用を検討するとよいかと思います。
少しでも参考になれば幸いです。
採用情報
e-dashエンジニアチームは現在一緒にはたらく仲間を募集中です!
同じ夢について語り合える仲間と一緒に、環境問題を解決するプロダクトを作りませんか?
Discussion