Xamarin.Forms で使える Azure AD 認証付きの WebAPI を実装するには
この記事は Xamarin Advent Calendar 2019 の 9 日目の記事です。
タイトルを実装するのにこれといったベストプラクティスが見つからずになかなかハマりました。
というテーマで、昨日登壇させていただいたのでその最後のベストプラクティスを手順にしてみました。
www.slideshare.net
- Azure AD にアプリケーションを登録する
- AppService に認証(EasyAuth)を設定する
- Xamarin.Forms にログインを実装する
- Xamarin で認証付き WebAPI をたたく
- Azure AD の認証付き WebAPI を実装する
- API を POSTMAN でテストする
- 取得したアクセストークンを調べる
- Xamarin.Forms のソースコード
- さいごに
Azure AD にアプリケーションを登録する
Azure Portal から Azure AD のアプリケーションを登録します。
- ポータルから Azure Active Directory を選択
- アプリの登録→新規登録→任意の名前を入力して、「任意の組織ディレクトリ内のアカウント (任意の Azure AD ディレクトリ - マルチテナント) と個人の Microsoft アカウント (Skype、Xbox など) 」(長い!)を選択→登録
概要でアプリケーションID(クライアントID)とディレクトリ(テナントID)をコピペします(後で使います)
認証→リダイレクトURIで
msal9999...://auth
とあるところにチェックを入れて→保存をクリック これが Xamarin 用のリダイレクト URI になります。
- 証明書とシークレットで、新しいクライアントシークレットをクリック→任意の名前(secret など)→有効期限なし→追加 これをコピペします。
AppService に認証(EasyAuth)を設定する
AppService は作成済みとして、ポータルから AppService のサイトに移動します。
- 認証/承認をクリック
- App Service 認証を ON
- Azure Active Directory をクリック
- クライアント ID 、クライアントシークレット(上記で取得済み)をコピペ
- 発行者の URL はテナント ID (上記で取得済み)を使って以下をコピペ
https://login.microsoftonline.com/{テナントID}/v2.0/.well-known/openid-configuration
- 許可されるトークン対象ユーザーは以下の形式でコピペ
https://{Your AppService}.azurewebsites.net/.auth/login/aad/callback
- OK をクリック
- 要求が承認されない場合に実行するアクション→ Azure Active Directory でのログイン を選択(忘れやすいので注意!) → 保存をクリック
Xamarin.Forms にログインを実装する
ログイン画面を実装して API で使用するアクセストークンを取得します。
比較的簡単に実装できる AppCenter Auth は Azure AD B2C のみ対応なので(2019年12月1日現在)使えない(ちなみにロードマップには Azure AD があるので近々対応されるはず)。
となると、Xamarin.Forms(以下 Xamarin ) の場合 MSAL(Microsoft Authentication Library)一択になるわけですが、最初はログイン画面に遷移して2回目以降はキャッシュを取得して画面遷移しないみたいな感じで書きます。この時、ログイン情報をキャッシュするとか有効期限を更新するとかはライブラリにお任せです。
MSAL は nuget から Microsoft.Identity.Client
(バージョンは 4.1.0
)で取得します。
using Microsoft.Identity.Client; // ログインしてアクセストークンを取得する private async string SignInAsync() { AuthenticationResult authResult = null; try { // キャッシュにあればログイン画面に遷移しない IAccount firstAccount = accounts.FirstOrDefault(); authResult = await App.PCA.AcquireTokenSilent(App.Scopes, firstAccount) .ExecuteAsync(); } catch (MsalUiRequiredException ex) { try { // なければログイン画面に遷移する authResult = await App.PCA.AcquireTokenInteractive(App.Scopes) .WithParentActivityOrWindow(App.ParentWindow) .ExecuteAsync(); } catch (Exception ex2) { } } return authResult?.AccessToken; }
Xamarin で認証付き WebAPI をたたく
取得したアクセストークンを Bearer で渡して WebAPI を叩きます。
最近は HttpClient
を using
で囲うと犯罪者扱いされるみたいですが...(ry
using (var client = new HttpClient()) { // アクセストークンを使ってAPIをたたく client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var res = await client.GetAsync(apiUrl); if (!res.IsSuccessStatusCode) { throw new Exception(res.ToString()); } // 結果のJSONを受け取る var resultText = await res.Content.ReadAsStringAsync(); ...
Azure AD の認証付き WebAPI を実装する
VSCode で ASP.Net Core で Azure AD 認証付きの Web API を作成します。
azure-v2-app というアプリを作る場合、コンソールから以下をたたきます。
mkdir azure-v2-app cd azure-v2-app dotnet new webapi code -r .
VSCode が起動するので、表示→ターミナルを開いて、
dotnet build dotnet run
これで VSCode がローカルでサーバーを実行している状態になるので、ブラウザや POSTMAN などで、
とたたくと JSON が返ってくるはずです。これを Azure の AppService にデプロイします。
- VSCode の拡張機能で Azure App Service を追加します(入れてない場合は)。
- VSCode の左側の Azure のロゴをクリックして、デプロイする App Service を選択します
- 右クリックで
Deploy to Web App
をクリックするとデプロイされます(初回はいくつか質問されますがそのまま OK をクリック)。
API を POSTMAN でテストする
デプロイした WebAPI は EasyAuth で認証されたサイトになっているので、そのままたたくと401( Unauthorized )が返ってきます。 これにトークンを設定して 200 が返ってくれば OK ということになります。
まずはブラウザを使って id_token
を取得します。
- 作成したサイトが https://azuread-v2-app.azurewebsites.net
であれば、https://azuread-v2-app.azurewebsites.net/WeatherForecast
にブラウザでアクセスします
- ログインされていなければ Azure AD のログイン画面に遷移します。ログイン済みであれば白い画面が表示されます
- 同じ画面で、https://azuread-v2-app.azurewebsites.net/.auth/me
とたたくとトークンが取得できるので id_token
をコピーします
次に POSTMAN を使って認証済みのサイトにアクセスしてみます。
- POSTMAN で URL に https://azuread-v2-app.azurewebsites.net/WeatherForecast
をコピペ
- Authorization → Bearer Token → id_token
をコピペ
- Send をクリックして ステータスが 200(OK) と JSON が返ってくればOKです。
取得したアクセストークンを調べる
取得した id_token
や access_token
を https://jwt.ms/
にコピペするとトークンの中身を確認することができます。
MSAL で Azure AD の認証を行う場合 V2 のエンドポイントである必要があるので、 iss
が https://login.microsoftonline.com/{テナントID}/v2.0
であることを確認します。ちなみに、V1 のエンドポイントは https://sts.windows.net/{テナントID}/
。
Xamarin.Forms のソースコード
これで Xamarin.Forms から 認証付き WebAPI をたたけるようになったはずです。あとで Xamarin.Forms のサンプルを GitHub にあげます。
さいごに
401(Unauhtorized)なんて怖くない!より良い認証ライフを!!