Azure App ServiceにはAuthentication (Easy Authとも呼ばれる)なる機能があり、Azure AD (B2Cも含む)やソーシャルプロバイダーを用いた認証を簡単に組み込むことができるようになっている。
一般にはクッキーなどで管理された認証情報をサーバーに渡し、その情報をバリデートしてユーザ情報を取得するなどの一連の流れを自前で実装する必要がある。
Authenticationを使うことでApp Service上のサーバーへのリクエストヘッダーにアクセストークンやユーザ情報など必要な情報を詰め込んでくれるので、認証認可周りの実装負荷が大きく軽減できることになる。
今回はこの記事を参考にしつつAzure AD B2Cというコンシューマー向けの認証プラットフォームとApp Serviceを連携することで、認証機能を手軽に実現しようとしたときにハマったポイントを備忘録的に残しておく。
Implicit grantじゃないとWebアプリでエラーになるっぽい
Implict grant有効化すれば行ける
Azure AD B2CのアプリのAuthenticationから認可エンドポイントがAccess tokensとID tokensを発行するように設定する。こうすることによってtoken用エンドポイントからトークンを発行するのではなく、認可時にトークンが得られるようになる様子 (つまりImplicit grant)。
これを設定しないとAzure App ServiceでAuthenticationの設定をしてもWebアプリにアクセスした際に下記のようなエラーが出た。
Stackoverflowで質問した際にAuthorization code grantももちろん使えるぜ〜というコメントがあったが、どちらもチェックしないとエラーがでるのでどうしようもなさそう。
Authorization code grant試したものの…
後述する additionalLoginParams
で response_type=code id_token
と指定しているためauthorizeのエンドポイントから直接id_tokenが返却されている。(OIDCにおけるresponse_typeはこの記事が参考になる)
これにによって、implicit flowが必要となるのかなと思い、 response_type=code
にしてB2Cの先程のチェックを外してみたら、 authorize
と ./auth/login/aad/callback
に数回リクエストを繰り返した後最終的に ./auth/login/aad/callback
で401となり終了。
ただ リクエストにはちゃんと code
が含まれていおり authorize
からきちんとトークン生成用のコードは取得できてそう。
そもそもApp ServiceのAuthenticationが response_type=code
に対応しているのか? がドキュメントを調べてもはっきりわからなかった。
B2C自体はサポートしているようだが…
Access code grantを使って認可ができる方法をご存知の方がいればぜひ教えていただきたいです 🙇
Azure App ServiceのAuthentication v2だとAzure Resource Explorerが使えない?
App ServiceのAuthenticationは4月に新しくなり従来のAuthentication/AuthorizationはAuthentication (classic)となったみたい。新しいAuthenticationがv2と呼ばれているようだ。
問題はv2のAuthenticationを使っている場合、Azure Resource Explorer (ポータルからは設定できない項目を設定できる) を使って additionalLoginParams
を設定しようとすると、v2は設定できないぜ!って怒られる。
~~これもStackoverflowで質問したが回答がなく、~~結局v1 (classicの方)を使うことにした。 公式ドキュメント によるとCLIとかでAuthenticationの管理ができなくなるとのこと。 CLIなどは結局裏でREST APIを叩いており、Resource Explorerも同じくREST APIを使っているのでエラーになっているのだろうのこと。 なので現時点では、v2にマイグレーションしてしまっている場合はApp Serviceを再作成し、v1を使うようにするしか無いっぽい
フロントエンドアプリをv1で認証するなら、API側 (Azure Functions)もv1でないといけない (確信ない)
これはドキュメントなどに書かれておらず自分の経験則のみによるものなので、実際は間違っている可能性がある。
もともとフロントエンド側もAPI側もどちらもv2のAuthenticationを使っていたのだが、上記の理由からフロントエンド側はv1にした。
そうすると、APIに対してちゃんと Authorization: Bearer <フロントエンドアプリから取得したacess_token>
を指定してリクエストを送ると下記の結果が返ってきた。 (Status codeは401)
IDX10501: Signature validation failed. Unable to match keys:
ひょっとしてと思ってAPI側のAuthenticationをv1に変更する (要するにFunctionsの作り直す)とうまく呼べるようになった。。。謎。
まとめ: Authenticationは便利だがドキュメントが少ない
App ServiceのAuthenticationは自前でトークンをパースしたりするなどの手間が減るのでめちゃ便利な感じではあるが、なんせドキュメントが乏しいので結構詰まったりする。(単純に自分の知識、実力不足もあるが…)