MRが楽しい

MRやVRについて学習したことを書き残す

Microsoft Authentication Library(MSAL)を使ってHoloLens2でOpenIDConnectの認可コードフローを試す その2(トークンキャッシュを利用する)

本日はHoloLens2の小ネタ枠です。
Microsoft Authentication Library(MSAL)を使ってHoloLens2でOpenIDConnectの認可コードフローを行う方法を記事にします。
本記事はトークンキャッシュを利用する方法についてです。

前回記事

以下の前回記事の続きです。
bluebirdofoz.hatenablog.com

トークンキャッシュを利用する

GetAccountsAsync関数を利用するとアプリケーション内に保存されているユーザー・トークンを取得できます。
取得したユーザー・トークンを利用することで、ユーザの認証操作を省略することができます。
learn.microsoft.com

var app = PublicClientApplicationBuilder.Create(clientId).Build();
// 利用可能なユーザー・トークンのリストを取得する
var accounts = await app.GetAccountsAsync();
// リストの中からユーザ名が一致するトークンを取得する
var account = accountList.FirstOrDefault(account => account.Username == username)

サンプルスクリプト

前回記事で作成したサンプルスクリプトを以下の通り修正しました。
テキストUIにログインしたことのあるユーザ名を入力してボタンを押下すると、キャッシュされているトークンを取得して認証を行います。
・AzureMsalTest.cs

using System;
using Microsoft.MixedReality.Toolkit.UI;
using TMPro;
using UnityEngine;

#if WINDOWS_UWP
using System.Linq;
using Microsoft.Identity.Client;
#endif

namespace MSAL
{
    public class AzureMsalTest : MonoBehaviour
    {
        [SerializeField]
        private string applicationID = "";
    
        [SerializeField]
        private string directoryID = "";

        [SerializeField]
        private TMP_InputField loginUsername = null;
        
        [SerializeField]
        private TMP_Text outputText = null;

        [SerializeField]
        private Interactable startButton;

        private static readonly string[] scopes = { "openid" };

        void Start()
        {
            startButton.OnClick.AddListener(async () =>
            {
                outputText.text = "start";
                AuthorizeRequest();
            });
        }
        
        [ContextMenu("AuthorizeRequest")]
        public async void AuthorizeRequest()
        {
#if WINDOWS_UWP
                try
                {
                    var app = PublicClientApplicationBuilder
                        .Create(applicationID)
                        .WithAuthority(AzureCloudInstance.AzurePublic, directoryID)
                        .WithRedirectUri("http://localhost:50000/")
                        .Build();

                    // ユーザー名を指定してログインする
                    string username = loginUsername.text;
                    
                    AuthenticationResult result;
                    if (string.IsNullOrEmpty(username))
                    {
                        // ユーザー名を指定しない場合は認証画面で入力させる
                        result = await app.AcquireTokenInteractive(scopes)
                            .ExecuteAsync();
                    }
                    else
                    {
                        var accounts = await app.GetAccountsAsync();
                        // accountsの中にusernameが一致するアカウント情報が含まれているかチェックする
                        var accountList = accounts.ToList();
                        if (accountList.Any(account => account.Username == username))
                        {
                            // 一致するアカウント情報があればキャッシュを使って認証画面を省略してログインする
                            result = await app.AcquireTokenSilent(
                                    scopes, 
                                    accountList.FirstOrDefault(account => account.Username == username))
                                .ExecuteAsync();
                        }
                        else
                        {
                            // 一致するアカウント情報がなければ認証画面で入力させる
                            result = await app.AcquireTokenInteractive(scopes)
                                .WithLoginHint(username)
                                .ExecuteAsync();
                        }
                    }
                    
                    // 取得したIDトークンを表示する
                    var idToken = result.IdToken;
                    outputText.text = idToken;
                }
                catch (Exception e)
                {
                    outputText.text = e + Environment.NewLine + e.Message;
                }
#endif
        }
    }
}

動作確認

プロジェクトを再ビルドしてHoloLens2にデプロイします。
初回認証時はボタンを押すと認証画面が開き、通常の認証操作が要求されます。

2回目以降はキャッシュされたトークンを利用して認証が行われるため、ボタン押下で即座に結果が返るようになります。