MRが楽しい

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

Microsoft Authentication Library(MSAL)を使ってHoloLens2でOpenIDConnectの認可コードフローを試す

本日はHoloLens2の小ネタ枠です。
Microsoft Authentication Library(MSAL)を使ってHoloLens2でOpenIDConnectの認可コードフローを行う方法を記事にします。

Microsoft Authentication Library(MSAL)

Microsoft Authentication Library (MSAL) を使用すると開発者はユーザ認証のためにMicrosoft IDプラットフォームからセキュリティトークンを取得できます。
MSALは、.NET、JavaScriptJavaPythonAndroidiOSなどの様々なアプリケーションアーキテクチャとプラットフォームをサポートします。
learn.microsoft.com

前提条件

HoloLens2アプリでMSALを試すため、MRTKを利用してサンプルプロジェクトを作成しました。
MRTKの環境構築手順は以下の記事を参照ください。
bluebirdofoz.hatenablog.com

原因は不明ですがUnityバージョン 2022.3でMSALを利用したところ、アプリが強制終了する事象を確認したため、今回はバージョン 2021.3を利用しています。

本記事のサンプルでの認証先として以下の記事で作成した環境のアプリケーションIDとディレクトリIDを利用します。
bluebirdofoz.hatenablog.com

UWPで利用可能なライブラリをインポートする

UWPでWebAPIを利用するため、Microsoft.Identity.Clientパッケージをプロジェクトにインポートします。
learn.microsoft.com

Microsoft.Identity.ClientパッケージをHoloLens2アプリで利用するにはNuGet Galleryから過去バージョンのdllファイルを直接取得する必要があります。
以下のMicrosoft.Identity.Clientパッケージのバージョン4.44.0のページを開きます。
www.nuget.org

[Download package]をクリックします。

~.nupkgファイルがダウンロードできます。

本ファイルはZIP形式で圧縮されたファイルなので、拡張子を~.zipに変更して展開します。

lib/uap 10.0フォルダに含まるDLLファイルがUWPで利用可能なので、これをプロジェクトに取り込みます。

取り込んだMicrosoft.Identity.Client.dllのInspectorビューを開きます。
[Select platforms for plugin]の設定を[WSAPlayer]のみ有効にして[Apply]します。

これでライブラリのインポートは完了です。

サンプルシーンの作成

ボタン押下でMicrosoft.Identity.Clientを利用して認証を開始する以下のサンプルスクリプトを作成しました。

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();
            });
        }
        
        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
                    {
                        // ログインヒントでユーザー名を指定するとユーザ名の入力画面を省略できる
                        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
        }
    }
}

シーンにボタンと結果表示のTextUIを配置してスクリプトを設定します。
ApplicationIDとDirectoryIDのフィールドにそれぞれアプリケーションIDとディレクトリIDを入力して準備完了です。

動作確認

プロジェクトをビルドしてHoloLens2にデプロイします。
ボタンを押すと認証画面が開きます。

認証画面はキャプチャできないようなので、以下の画像は重ね合わせのイメージになります。

その他エラーケースのメモ

NugetForUnityを利用してMicrosoft.Identity.Clientをインポートするとスクリプト実行時に以下のエラーが発生したため、今回は直接DLLファイルを取得しました。

System.PlatformNotSupportedException

Microsoft.Identity.Clientの最新版を利用するとビルド時に以下のエラーが発生したため、今回は本エラーが発生しないバージョン4.44.0を利用しました。

Assembly 'Microsoft.Identity.Client' with identity 'Microsoft.Identity.Client, Version=4.58.1.0, Culture=neutral' uses 'System.Runtime, Version=4.2.1.0

参考記事

以下の記事ではUWPプラットフォームで提供されているWeb認証ブローカーを利用するパターンを記事にしています。
learn.microsoft.com