次の方法で共有


チュートリアル: Android (Kotlin) モバイル アプリでユーザーをサインインさせる

これは、Microsoft Entra 外部 ID を使用してユーザーをサインインさせる方法を説明するチュートリアル シリーズの 3 番目のチュートリアルです。

このチュートリアルでは、次のことについて説明します。

  • ユーザーのサインイン
  • ユーザーをサインアウトする

前提条件

チュートリアル: 認証用に Android アプリを準備する

ユーザーのサインイン

Android 用 Microsoft 認証ライブラリ (MSAL) を使用してユーザーをサインインさせるための主なオプションとしては、対話形式またはサイレント モードでのトークンの取得の 2 つがあります。

  1. 対話形式でユーザーをサインインさせるには、次のコードを使用します。

        private fun acquireTokenInteractively() {
        binding.txtLog.text = ""
    
        if (account != null) {
            Toast.makeText(this, "An account is already signed in.", Toast.LENGTH_SHORT).show()
            return
        }
    
        /* Extracts a scope array from text, i.e. from "User.Read User.ReadWrite" to ["user.read", "user.readwrite"] */
        val scopes = scopes.lowercase().split(" ")
        val parameters = AcquireTokenParameters.Builder()
            .startAuthorizationFromActivity(this@MainActivity)
            .withScopes(scopes)
            .withCallback(getAuthInteractiveCallback())
            .build()
    
        authClient.acquireToken(parameters)
    }
    

    このコードは、Android 用 MSAL を使用して対話形式でトークンを取得するプロセスを開始します。 最初にテキスト ログ フィールドをクリアします。 その後、サインインしたアカウントが既に存在するかどうかを確認し、存在する場合は、アカウントがすでにサインインしていることを示すトースト メッセージを表示して戻ります。

    次に、テキスト入力からスコープを抽出し、それらを小文字に変換してから配列に分割します。 これらのスコープを使用して、現在のアクティビティからの承認プロセスの開始やコールバックの指定など、トークンを取得するためのパラメーターを構築します。 最後に、構築されたパラメーターを使用して認証クライアント上で acquireToken() を呼び出し、トークン取得プロセスを開始します。

    コールバックを指定するコードでは、getAuthInteractiveCallback() という関数を使用します。 関数には次のコードが必要です。

    private fun getAuthInteractiveCallback(): AuthenticationCallback {
        return object : AuthenticationCallback {
    
            override fun onSuccess(authenticationResult: IAuthenticationResult) {
                /* Successfully got a token, use it to call a protected resource - Web API */
                Log.d(TAG, "Successfully authenticated")
                Log.d(TAG, "ID Token: " + authenticationResult.account.claims?.get("id_token"))
                Log.d(TAG, "Claims: " + authenticationResult.account.claims
    
                /* Reload account asynchronously to get the up-to-date list. */
                CoroutineScope(Dispatchers.Main).launch {
                    accessToken = authenticationResult.accessToken
                    getAccount()
    
                    binding.txtLog.text = getString(R.string.log_token_interactive) +  accessToken
                }
            }
    
            override fun onError(exception: MsalException) {
                /* Failed to acquireToken */
                Log.d(TAG, "Authentication failed: $exception")
    
                accessToken = null
                binding.txtLog.text = getString(R.string.exception_authentication) + exception
    
                if (exception is MsalClientException) {
                    /* Exception inside MSAL, more info inside MsalError.java */
                } else if (exception is MsalServiceException) {
                    /* Exception when communicating with the STS, likely config issue */
                }
            }
    
            override fun onCancel() {
                /* User canceled the authentication */
                Log.d(TAG, "User cancelled login.");
            }
        }
    }
    

    このコード スニペットは、AuthenticationCallback のインスタンスを返す関数 getAuthInteractiveCallback を定義します。 この関数内に、AuthenticationCallback インターフェイスを実装する匿名クラスが作成されます。

    認証が成功すると (onSuccess)、認証の成功をログに記録し、ID トークンとクレームを取得し、CoroutineScope を使用してアクセス トークンを非同期的に更新し、新しいアクセス トークンで UI を更新します。 このコードは、authenticationResult から ID トークンを取得し、ログに記録します。 トークン内のクレームには、ユーザーの名前、メール アドレス、その他のプロファイル情報など、ユーザーに関する情報が含まれます。 authenticationResult.account.claims にアクセスすると、現在のアカウントに関連付けられているクレームを取得できます。

    認証エラー (onError) が発生した場合は、エラーをログに記録し、アクセス トークンをクリアし、エラー メッセージで UI を更新し、MsalClientExceptionMsalServiceException に対するより具体的な処理を行います。 ユーザーによって認証がキャンセルされた場合は (onCancel)、キャンセルされたことをログに記録します。

    必ず import ステートメントを含めます。 Android Studio では、自動的に import ステートメントが含められます。

  2. サイレント モードでユーザーをサインインさせるには、次のコードを使用します。

        private fun acquireTokenSilently() {
        binding.txtLog.text = ""
    
        if (account == null) {
            Toast.makeText(this, "No account available", Toast.LENGTH_SHORT).show()
            return
        }
    
        /* Extracts a scope array from text, i.e. from "User.Read User.ReadWrite" to ["user.read", "user.readwrite"] */
        val scopes = scopes.lowercase().split(" ")
        val parameters = AcquireTokenSilentParameters.Builder()
            .forAccount(account)
            .fromAuthority(account!!.authority)
            .withScopes(scopes)
            .forceRefresh(false)
            .withCallback(getAuthSilentCallback())
            .build()
    
        authClient.acquireTokenSilentAsync(parameters)
    }
    

    このコードは、サイレント モードでトークンを取得するプロセスを開始します。 最初にテキスト ログをクリアします。 その後、使用可能なアカウントがあるかどうかを確認します。ない場合は、そのことを示すトースト メッセージを表示して終了します。 次に、テキスト入力からスコープを抽出し、それらを小文字に変換して配列に分割します。

    これらのスコープを使用して、アカウント、権限、スコープ、コールバックを指定して、トークンをサイレント モードで取得するためのパラメーターを構築します。 最後に、構築されたパラメータを使用して認証クライアント上で acquireTokenSilentAsync() を非同期的にトリガーし、サイレント トークン取得プロセスを開始します。

    コールバックを指定するコードでは、getAuthSilentCallback() という関数を使用します。 関数には次のコードが必要です。

    private fun getAuthSilentCallback(): SilentAuthenticationCallback {
        return object : SilentAuthenticationCallback {
            override fun onSuccess(authenticationResult: IAuthenticationResult?) {
                Log.d(TAG, "Successfully authenticated")
    
                /* Display Access Token */
                accessToken = authenticationResult?.accessToken
                binding.txtLog.text = getString(R.string.log_token_silent) + accessToken
            }
    
            override fun onError(exception: MsalException?) {
                /* Failed to acquireToken */
                Log.d(TAG, "Authentication failed: $exception")
    
                accessToken = null
                binding.txtLog.text = getString(R.string.exception_authentication) + exception
    
                when (exception) {
                    is MsalClientException -> {
                        /* Exception inside MSAL, more info inside MsalError.java */
                    }
                    is MsalServiceException -> {
                        /* Exception when communicating with the STS, likely config issue */
                    }
                    is MsalUiRequiredException -> {
                        /* Tokens expired or no session, retry with interactive */
                    }
                }
            }
    
        }
    }
    

    このコードは、サイレント認証のコールバックを定義します。 SilentAuthenticationCallback インターフェイスを実装し、2 つのメソッドをオーバーライドします。 onSuccess メソッドでは、認証が成功したことをログに記録し、アクセス トークンを表示します。

    onError メソッドでは、認証エラーをログに記録し、MsalClientExceptionMsalServiceException などのさまざまな種類の例外を処理し、必要に応じて対話型認証を使用して再試行することを提案します。

    必ず import ステートメントを含めます。 Android Studio では、自動的に import ステートメントが含められます。

サインアウト

Android 用 MSAL を使用して Android (Kotlin) アプリからユーザーをサインアウトさせるには、次のコードを使用します。

private fun removeAccount() {
    binding.userName.text = ""
    binding.txtLog.text = ""

    authClient.signOut(signOutCallback())
}

このコードは、アプリケーションからアカウントを削除します。 表示されているユーザー名とテキストログをクリアします。 次に、認証クライアントを使用してサインアウト プロセスをトリガーし、サインアウト操作の完了を処理するサインアウト コールバックを指定します。

コールバックを指定するコードでは、signOutCallback() という関数を使用します。 関数には次のコードが必要です。

private fun signOutCallback(): ISingleAccountPublicClientApplication.SignOutCallback {
    return object : ISingleAccountPublicClientApplication.SignOutCallback {
        override fun onSignOut() {
            account = null
            updateUI(account)
        }

        override fun onError(exception: MsalException) {
            binding.txtLog.text = getString(R.string.exception_remove_account) + exception
        }
    }
}

このコードは、パブリック クライアント アプリケーション内の単一アカウントに対するサインアウト コールバックを定義します。 ISingleAccountPublicClientApplication.SignOutCallback インターフェイスを実装し、2 つのメソッドをオーバーライドします。

onSignOut メソッドでは、現在のアカウントを無効にし、それに応じてユーザー インターフェイスを更新します。 onError メソッドでは、サインアウト プロセス中に発生したエラーをログに記録し、対応する例外メッセージでテキスト ログを更新します。

必ず import ステートメントを含めます。 Android Studio では、自動的に import ステートメントが含められます。

次のステップ

チュートリアル: Android (Kotlin) アプリで保護された Web API を呼び出す