しばやん雑記

Azure Serverless とメイドさんが大好きなフリーランスのプログラマーのブログ

App Service Authentication が OpenID Connect Provider をサポートするようになった

タイトルの通り App Service の Authentication (Easy Auth) で OpenID Connect に対応したプロバイダーを追加出来るようになりました。プレビュー公開されたのは数か月前だったのですが、諸々の事情によって動かないパターンのが多かったためお蔵入り状態になっていました。

設定がまだ若干特殊なのでドキュメントを読みこんで作業する必要がありますが、将来的には Azure Portal や ARM Template からの設定も出来るようになりそうです。*1

ドキュメントにもサンプルで書かれているように Sign in with Apple 向け機能という感じです。むしろ当初は Apple でしか動作確認をしていなかったのでは疑惑まであります。

現在分かっている制限は以下のような感じです。普通の OpenID Connect Provider なら使えるはずです。

  • 認可コードフローのみの対応
  • response_modequeryform_post に対応
  • id_token の署名は RS256ES256 に対応
    • 恐らく RS384 / RS512 / ES384 / ES512 にも対応している
  • PKCE には非対応
  • User Info API の面倒までは見ない

App Service Authentication の実装的には PKCE はサポートしていなくても良いかなという感はあります。id_token の署名については HMAC を使った HS には非対応です。

実際に OpenID Connect Provider を App Service Authentication に追加して動作を確認してみました。手順が若干面倒なので、先に新しい設定を使う方法から書きます。

OpenID Connect Provider を使う時の共通手順

OpenID Connect Provider の設定は Resource Manager レベルでの対応が正式にはまだ行われていないので、以下のドキュメントにあるようにファイルベースの設定を有効にする必要があります。

アプリケーションと一緒に管理出来ますが、本来なら ARM Template や Terraform で管理するべき項目だと思います。Static Web App の場合にはどうなるのか気になるところです。

既に Auth0 での手順を Azure Functions チームの Anthony Chu 氏が書いているので、こちらも見つつ進めた方が良いですね。特に設定の有効化は ARM Explorer か Azure CLI が必要になるので若干分かりにくいです。

App Service Authentication の設定が定義されたファイルは auth.json という名前で wwwroot 以下に保存しておきます。ファイル名やパスは変更出ますが、ドキュメント通りにしておいた方が安全です。

wwwroot の下にあるのでアプリケーションと一緒にデプロイが出来るという仕組みです。

f:id:shiba-yan:20200718224928p:plain

ファイルを置いたら設定を有効にするコマンドを実行します。とりあえず自分は ARM Explorer で行いましたが、以下のように既存のプロパティをほぼ全て消して上書きするので若干抵抗があります。

f:id:shiba-yan:20200718225123p:plain

一目でわかると思いますが isAuthFromFileauthFilePath が今回追加になっているプロパティです。

この設定後は Azure Portal から App Service Authentication の設定が出来なくなるので、もし戻す場合は同じように ARM Explorer か Azure CLI を使う必要があります。

Azure AD B2C を使う

説明と準備が長かったですが、実際に OpenID Connect Provider を追加して試していきます。まずは使う機会が地味に多い Azure AD B2C からです。

中々このエントリを公開できなかった理由が Azure AD B2C だと動かないことにありました。フィードバックをし続けた結果、最近のアップデートで使えるようになりました。

それ以外は設定としては他の OpenID Connect Provider の時と代わり映えしません。

wellKnownOpenIdConfiguration に User Flow 毎に用意されているメタデータの URL を設定して、ClientId と Client Secret を追加すれば大体終わりです。

{
  "platform": {
    "enabled": true
  },
  "globalValidation": {
    "requireAuthentication": true,
    "unauthenticatedClientAction": "RedirectToLoginPage",
    "redirectToProvider": "aadb2c"
  },
  "identityProviders": {
    "openIdConnectProviders": {
      "aadb2c": {
        "enabled": true,
        "registration": {
          "clientId": "00000000-0000-0000-0000-000000000000",
          "clientCredential": {
            "secretSettingName": "AADB2C_CLIENT_SECRET"
          },
          "openIdConnectConfiguration": {
            "wellKnownOpenIdConfiguration": "https://***.b2clogin.com/***.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=B2C_1A_signup_signin"
          }
        },
        "login": {
          "nameClaimType": "name",
          "scope": [ "openid" ],
          "loginParameterNames": []
        }
      }
    }
  },
  "login": {
    "tokenStore": {
      "enabled": true
    }
  }
}

ClientId は JSON にそのまま書きますが、Client Secret は App Settings 経由で読み込むので JSON にはキー名を書いて、実際の値は App Settings に追加する形になります。

f:id:shiba-yan:20200718224820p:plain

これで設定はすべて完了なので、ファイルをアップロードした後に App Service を再起動して反映すれば、ページへアクセスしたタイミングで Azure AD B2C のログイン画面へリダイレクトされるはずです。

f:id:shiba-yan:20201209003629p:plain

App Service の再起動ではなくワーカープロセスが再起動出来ればよいので、アプリケーションのデプロイと同時に行うと常に再読み込みが行われるので安全ではあります。

ログイン後に /.auth/me へアクセスすると id_token が取得できるので、適当に jwt.ms などに張り付けると含まれているクレームを確認できます。

f:id:shiba-yan:20201209004214p:plain

ちゃんと Azure AD B2C が発行した id_token であることが確認できました。

Yahoo! ID連携 v2 を使う

Azure AD B2C は User Flow 単位の関係上、特殊な形式になっていたので他の OpenID Connect Provider でも試します。Auth0 は既に試されていたので、調べていて目についた Yahoo! ID連携 v2 を試してみました。

ドキュメントを読む限りは極めて普通な OpenID Connect のようなので動くはずです。

Azure AD B2C は id_token に含めるクレームを設定可能でしたが、Yahoo! ID連携 v2 では必要最低限のクレームのみ含まれていて、ユーザー情報は User Info API を叩く必要があるようです。

App Service Authentication は User Info API までは面倒を見てくれないので、この辺りの情報が必要な場合は自前で実装する必要があります。

{
  "platform": {
    "enabled": true
  },
  "globalValidation": {
    "requireAuthentication": true,
    "unauthenticatedClientAction": "RedirectToLoginPage",
    "redirectToProvider": "yahoo"
  },
  "identityProviders": {
    "openIdConnectProviders": {
      "yahoo": {
        "enabled": true,
        "registration": {
          "clientId": "*******************************",
          "clientCredential": {
            "secretSettingName": "YAHOO_CLIENT_SECRET"
          },
          "openIdConnectConfiguration": {
            "wellKnownOpenIdConfiguration": "https://auth.login.yahoo.co.jp/yconnect/v2/.well-known/openid-configuration"
          }
        },
        "login": {
          "nameClaimType": "name",
          "scope": [ "openid", "profile" ],
          "loginParameterNames": []
        }
      }
    }
  },
  "login": {
    "tokenStore": {
      "enabled": true
    }
  }
}

id_token には名前は返ってきませんが、一応 nameClaimType は適当に残しておきます。

例によって Client Secret は App Settings に追加した後にアクセスしてみると、Yahoo! のログイン画面にリダイレクトされました。ログインすると App Service に戻ってきてページが正しく表示されます。

f:id:shiba-yan:20201209004410p:plain

リクエストヘッダー経由で id_tokenaccess_token が渡されるので、必要であれば User Info API を実行してユーザー情報を取得すれば良いと思います。

Sign in with Apple は要注意

Sign in with Apple に関しては最新バージョンで専用の設定が用意されましたが、中身は他の OpenID Connect Provider と同じなので設定方法で悩むことはないでしょう。

ドキュメントも OpenID Connect 関連で Apple だけはちゃんと追加されています。

結論から言えばドキュメントの通りに設定すれば動きますが、Sign in with Apple は他のプロバイダーと異なり Client Secret を 180 日毎に更新する必要があるので、恐らく確実に 180 日後に事故ります。

この辺りは Azure AD B2C にも言えることですが、Client Secret の生成まで実装されるのを待つか、CI などで定期的に作って更新するかなどの方法が必要になります。

LINE Login は使えない

App Service Authentication でどうしても使えなかったのが LINE Login でした。理由としては LINE Login の id_tokenHS256 で署名されているという 1 点だけです。

ID の偉い人が言っているように LINE Login はメタデータでは ES256 と宣言しつつも、実際の id_token では HS256 で署名されるというよく分からない仕様です。

実装して理解するLINE LoginとOpenID Connect入門

一応 App Service チームの人と話はしましたが「なんで宣言通り ES256 じゃないの?」みたいな返事だったので LINE Login はちょっと期待薄かもしれません。

*1:authsettingsV2 というリソースがひっそりと増えている模様