急に「これやりたいから調べてくれない?」と言われた自分用メモ
結論
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構成ファイルだった場合は
{
"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
が=
に変わっている。)
<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>
疲れたので終わり