2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Android端末におけるMSALを使用したSSO認証

Posted at

急に「これやりたいから調べてくれない?」と言われた自分用メモ

結論

https://docs.microsoft.com/ja-jp/azure/active-directory/develop/quickstart-v2-android
https://github.com/Azure-Samples/ms-identity-android-java
公式のクイックスタートとサンプルリポジトリのREADMEとソースを読むと良い。ドキュメントたくさんあるし自分がこれを書く必要なくない?

アプリの初起動

PublicClientApplication.createSingleAccountPublicClientApplication()を叩いてISingleAccountPublicClientApplicationインスタンスを取得する。
このインスタンスを使用して、サインインやサインアウト、アカウントの状態確認等ができる。

auth_config_single_account.jsonはMSALで使用する構成ファイル
Azureにアプリ登録した際のIDとか、リダイレクトURIとかの設定が記載されている。

PublicClientApplication.createSingleAccountPublicClientApplication(
    getContext(),
    R.raw.auth_config_single_account, // res/raw/auth_config_single_account.jsonのリソースID
    new IPublicClientApplication.ISingleAccountApplicationCreatedListener() {
        @Override
        public void onCreated(ISingleAccountPublicClientApplication application) {
            mSingleAccountApp = application;
            // 現在のアカウント状態を読み込む
        }

        @Override
        public void onError(MsalException exception) {
            displayError(exception);
        }
    });

アプリの構成が正しく読み込めたら、mSingleAccountApp.getCurrentAccountAsyncを呼び出して、現在のアカウントの状態を読み込む。
処理が終われば引数に設定したリスナーのonAccountLoadedが呼び出されて、引数にアカウント情報が入ってくる。
一度もサインインしていない場合は引数にnullが設定されるので、サインインする。

mSingleAccountApp.getCurrentAccountAsync(new ISingleAccountPublicClientApplication.CurrentAccountCallback() {
    @Override
    public void onAccountLoaded(@Nullable IAccount activeAccount) {
        if(activeAccount == null){
            // サインインの処理
        } else {
            // 必要であればトークンの更新
        }
    }

    @Override
    public void onAccountChanged(@Nullable IAccount priorAccount, @Nullable IAccount currentAccount) {
        // ログインアカウントを変更する場合に呼び出される
    }

    @Override
    public void onError(@NonNull MsalException exception) {
        displayError(exception);
    }
});

サインイン

サインインはmSingleAccountApp.signIn(activity, hint, scope, callback); を呼び出せばOK
activityは現在のアクティビティ
hintは事前入力用の文字列(nullable)
scopeは要求する権限
callbackはサインインの結果を受け取るリスナー

呼び出すとMSAL側のログインアクティビティが立ち上がってユーザーに認証を求めてくる。
サインインできればコールバックのonSuccessメソッドが呼び出される。

要望としてこっそりサインインさせたいんだけどって言われたけど
引数にアクティビティは必須だし、ログイン用のアクティビティが立ち上がるので
こっそりログインさせるのは無理そう

2回目以降の起動(トークンの取得・更新)

アプリ構成とログインしているアカウントの情報がコールバックの引数に入ってくるはずなので、そこから確認できる。
トークンを取得したい場合はmSingleAccountApp.acquireTokenメソッドか
mSingleAccountApp.acquireTokenSilentAsyncメソッドを呼び出すことで取得できる。
有効なアクセストークンがなくても、自動的にリフレッシュトークンを使用して更新してくれる。

基本はmSingleAccountApp.acquireTokenSilentAsyncを使用して、
エラーが発生する等のユーザが操作する必要がある場合にmSingleAccountApp.acquireTokenを使う感じだと思います。

トークンってどこに保存されているの

IntuneもしくはMicrosoft Authenticatorが入っていて、会社等でデバイスを管理していれば、このアプリがトークンを保存している。

もしもIntuneとAuthenticatorが入っていない場合は、Androidで設定しているブラウザもしくはWebViewを使用する。
開くブラウザが異なると何度もサインインを求められるので注意。

その他ハマったポイント

リダイレクトURIについて

MSAL構成ファイルのリダイレクトURIはパーセントエンコーディングする必要があり、
AndroidManifest.xmlに記載するpathは、頭に/をつけてデコードした文字列を設定する必要がある。
例えば、以下のようなMSAL構成ファイルだった場合は

auth_config_single_account.json
{
  "client_id" : "0984a7b6-bc13-4141-8b0d-8f767e136bb7",
  "authorization_user_agent" : "DEFAULT",
  "redirect_uri" : "msauth://com.azuresamples.msalandroidapp/1wIqXSqBj7w%2Bh11ZifsnqwgyKrY%3D",
  "account_mode" : "SINGLE",
  "broker_redirect_uri_registered": true,
  "authorities" : [
    {
      "type": "AAD",
      "authority_url": "https://login.microsoftonline.com/common"
    }
  ]
}

以下のようなAndroidManifest.xmlになる。
(%2B+に、%3D=に変わっている。)

AndroidManifest.xml
<activity android:name="com.microsoft.identity.client.BrowserTabActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <data
            android:host="com.azuresamples.msalandroidapp"
            android:path="/1wIqXSqBj7w+h11ZifsnqwgyKrY="
            android:scheme="msauth" />
    </intent-filter>
</activity>

疲れたので終わり

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?