🌐

Application Load BalancerとAuth0連携させてOIDC認証する方法

2024/06/26に公開

記事の概要

AWSのApplication Load Balancer(以下ALB)には、 OpenID Connect(以下OIDC)準拠のIdPと連携する機能が備わっています。本記事では、ALB,Auth0,Webアプリ間でどのようなデータがやりとりされているかを解説した後、ALBとAuth0の連携方法を解説します。

ALBのOIDC連携の概要

outline

詳細なフローは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と連携する方法を解説していきます。

前提条件

  1. AWS環境にて、ALB・Target Groupを作成済みで、背後にWebアプリがEC2やECS等で起動している(ALBのHTTPSのリスナーが設定されており、Target Groupへ転送される状態)
  2. Auth0にてApplicationが作成済であり、各種Application URIsが適切に設定済。
  3. ログイン画面はAuth0のUniversal Loginを想定。

Auth0側の設定

① ApplicationsにてID Tokenの有効期限を設定
ID Tokenの有効期限を設定します。ここでは例として86,400秒(24時間)を設定しています。

auth0_02


② ApplicationsにてRefresh Tokenを有効化
Refresh Token ExpirationのAbsolute ExpirationとInactivity Expirationを有効化しておきます。例ではLifetimeの値はデフォルト値としています。

auth0_03


③ APIs > SettingsにてAccess Tokenの有効期限を設定
Access Tokenの有効期限を設定します。ここでは例として86,400秒(24時間)を設定しています。特に理由がなければID Tokenと同じ値にすると良いでしょう。

auth0_04


④ APIs > SettingsにてAllow Skipping User Consentを有効化
Access Settingsにて、Allow Skipping User Consentを有効化しておきます。これを有効化しておかないと、初回ログイン時に余計な確認画面が表示されてしまいます。

auth0_05

ALB側の設定

① Auth0のコンソールから各種情報を取得
Applications > Settingsから各種情報を取得します。DomainClient IDClient Secretの3つを控えておきます。

auth0_10


② 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を入力  

auth0_11


高度な認証設定を以下の通り設定します。
スコープにはアプリの仕様に応じて適切な値を設定しましょう。例ではopenid profile offline_accessを設定しています。
(openidを設定しないとID Token, offline_accessを設定しないとRefresh Tokenが取得できません)

auth0_12


追加のリクエストパラメータを以下の通り設定します。

キー/値 = audience / https:/{Domain}/api/v2/

auth0_13


この状態で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