共用方式為


教學課程:在 Android (Kotlin) 行動應用程式中登入使用者

這是教學課程系列中的第三個教學課程,會引導您使用 Microsoft Entra 外部 ID 登入使用者。

在本教學課程中,您將會:

  • 登入使用者
  • 登出使用者

必要條件

教學課程:準備 Android 應用程式以進行驗證

登入使用者

使用適用於 Android 的 Microsoft 驗證程式庫 (MSAL) 登入使用者有兩個主要選項:以互動方式或以無訊息方式取得權杖。

  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.");
            }
        }
    }
    

    該程式碼片段會定義函式 getAuthInteractiveCallback,用於傳回 AuthenticationCallback 的執行個體。 在此函式中,將會建立實作 AuthenticationCallback 介面的匿名類別。

    驗證成功時 (onSuccess),程式碼會記錄成功的驗證、擷取識別碼權杖和宣告、使用 CoroutineScope 以非同步方式更新存取權杖,並使用新的存取權杖來更新 UI。 程式碼會從 authenticationResult 擷取識別碼權杖並加以記錄。 權杖中的宣告包含使用者的相關資訊,例如其名稱、電子郵件或其他設定檔資訊。 您可以存取 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 介面,並覆寫兩種方法。 在 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 介面,並覆寫兩種方法。

onSignOut 方法中,程序會讓目前的帳戶為 Null,並對使用者介面進行相應更新。 在 onError 方法中,程序會記錄登出程序期間發生的任何錯誤,並使用對應的例外狀況訊息更新文字記錄檔。

請確定您包含 import 陳述式。 Android Studio 應該會自動包含 import 陳述式。

下一步

教學課程:在 Android (Kotlin) 應用程式中呼叫受保護的 Web API