在 Android 上使用 Microsoft 進行驗證

您可以透過 Firebase 驗證使用者,方法是使用 Firebase SDK 將網頁型一般 OAuth 登入服務整合至應用程式,藉此執行端對端登入流程,並使用 Microsoft Azure Active Directory 等 OAuth 提供者。

事前準備

如要使用 Microsoft 帳戶 (Azure Active Directory 和個人 Microsoft 帳戶) 登入使用者,請先為 Firebase 專案啟用 Microsoft 做為登入供應商:

  1. 將 Firebase 新增至 Android 專案

  2. Firebase 控制台中,開啟「Auth」(驗證) 專區。
  3. 在「登入方式」分頁中,啟用「Microsoft」供應商。
  4. 將該供應商開發人員控制台的「用戶端 ID」和「用戶端密鑰」新增至供應商設定:
    1. 如要註冊 Microsoft OAuth 用戶端,請按照「 快速入門:使用 Azure Active Directory v2.0 端點註冊應用程式」一文中的操作說明進行。 請注意,這個端點支援使用 Microsoft 個人帳戶和 Azure Active Directory 帳戶登入。進一步瞭解 Azure Active Directory v2.0。
    2. 向這些供應商註冊應用程式時,請務必將專案的 *.firebaseapp.com 網域註冊為應用程式的重新導向網域。
  5. 按一下 [儲存]
  6. 如果尚未指定應用程式的 SHA-1 指紋,請前往 Firebase 控制台的「設定」頁面進行設定。如要瞭解如何取得應用程式的 SHA-1 指紋,請參閱「驗證用戶端」一文。

使用 Firebase SDK 處理登入流程

如果您要建構 Android 應用程式,使用者的 Microsoft 帳戶驗證 Firebase 最簡單的方法,就是使用 Firebase Android SDK 處理整個登入流程。

如要使用 Firebase Android SDK 處理登入流程,請按照下列步驟操作:

  1. 使用 Builder 和供應商 ID microsoft.com,建構 OAuthProvider 的執行個體。

    Kotlin

    val provider = OAuthProvider.newBuilder("microsoft.com")

    Java

    OAuthProvider.Builder provider = OAuthProvider.newBuilder("microsoft.com");

  2. 選用:指定要隨 OAuth 要求傳送的其他自訂 OAuth 參數。

    Kotlin

    // Target specific email with login hint.
    // Force re-consent.
    provider.addCustomParameter("prompt", "consent")
    
    // Target specific email with login hint.
    provider.addCustomParameter("login_hint", "user@firstadd.onmicrosoft.com")

    Java

    // Target specific email with login hint.
    // Force re-consent.
    provider.addCustomParameter("prompt", "consent");
    
    // Target specific email with login hint.
    provider.addCustomParameter("login_hint", "user@firstadd.onmicrosoft.com");

    如要瞭解 Microsoft 支援的參數,請參閱 Microsoft OAuth 說明文件。請注意,您無法使用 setCustomParameters() 傳遞 Firebase 必要參數。這些參數包括 client_idresponse_typeredirect_uristatescoperesponse_mode

    如要只允許特定 Azure AD 租戶的使用者登入應用程式,可以使用 Azure AD 租戶的易記網域名稱或租戶的 GUID ID。如要執行這項操作,請在自訂參數物件中指定「tenant」欄位。

    Kotlin

    // Optional "tenant" parameter in case you are using an Azure AD tenant.
    // eg. '8eaef023-2b34-4da1-9baa-8bc8c9d6a490' or 'contoso.onmicrosoft.com'
    // or "common" for tenant-independent tokens.
    // The default value is "common".
    provider.addCustomParameter("tenant", "TENANT_ID")

    Java

    // Optional "tenant" parameter in case you are using an Azure AD tenant.
    // eg. '8eaef023-2b34-4da1-9baa-8bc8c9d6a490' or 'contoso.onmicrosoft.com'
    // or "common" for tenant-independent tokens.
    // The default value is "common".
    provider.addCustomParameter("tenant", "TENANT_ID");

  3. 選用:指定基本設定檔以外的其他 OAuth 2.0 範圍,以便向驗證供應商提出要求。

    Kotlin

    // Request read access to a user's email addresses.
    // This must be preconfigured in the app's API permissions.
    provider.scopes = listOf("mail.read", "calendars.read")

    Java

    // Request read access to a user's email addresses.
    // This must be preconfigured in the app's API permissions.
    List<String> scopes =
            new ArrayList<String>() {
                {
                    add("mail.read");
                    add("calendars.read");
                }
            };
    provider.setScopes(scopes);

    詳情請參閱 Microsoft 權限和同意聲明說明文件

  4. 使用 OAuth 供應商物件向 Firebase 進行驗證。請注意,與其他 FirebaseAuth 作業不同,這項作業會彈出 Custom Chrome Tab,接管您的 UI。因此,請勿在您附加的 OnSuccessListenerOnFailureListener 中參照 Activity,因為作業啟動 UI 時,這些項目會立即分離。

    請先確認是否已收到回覆。透過這種方式登入會將活動置於背景,也就是說,系統可能會在登入流程期間回收活動。為確保使用者不會在發生這種情況時重試,您應檢查是否已存在結果。

    如要檢查是否有待處理的結果,請呼叫 getPendingAuthResult

    Kotlin

    val pendingResultTask = firebaseAuth.pendingAuthResult
    if (pendingResultTask != null) {
        // There's something already here! Finish the sign-in for your user.
        pendingResultTask
            .addOnSuccessListener {
                // User is signed in.
                // IdP data available in
                // authResult.getAdditionalUserInfo().getProfile().
                // The OAuth access token can also be retrieved:
                // ((OAuthCredential)authResult.getCredential()).getAccessToken().
                // The OAuth secret can be retrieved by calling:
                // ((OAuthCredential)authResult.getCredential()).getSecret().
            }
            .addOnFailureListener {
                // Handle failure.
            }
    } else {
        // There's no pending result so you need to start the sign-in flow.
        // See below.
    }

    Java

    Task<AuthResult> pendingResultTask = firebaseAuth.getPendingAuthResult();
    if (pendingResultTask != null) {
        // There's something already here! Finish the sign-in for your user.
        pendingResultTask
                .addOnSuccessListener(
                        new OnSuccessListener<AuthResult>() {
                            @Override
                            public void onSuccess(AuthResult authResult) {
                                // User is signed in.
                                // IdP data available in
                                // authResult.getAdditionalUserInfo().getProfile().
                                // The OAuth access token can also be retrieved:
                                // ((OAuthCredential)authResult.getCredential()).getAccessToken().
                                // The OAuth secret can be retrieved by calling:
                                // ((OAuthCredential)authResult.getCredential()).getSecret().
                            }
                        })
                .addOnFailureListener(
                        new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                // Handle failure.
                            }
                        });
    } else {
        // There's no pending result so you need to start the sign-in flow.
        // See below.
    }

    如要啟動登入流程,請呼叫 startActivityForSignInWithProvider

    Kotlin

    firebaseAuth
        .startActivityForSignInWithProvider(activity, provider.build())
        .addOnSuccessListener {
            // User is signed in.
            // IdP data available in
            // authResult.getAdditionalUserInfo().getProfile().
            // The OAuth access token can also be retrieved:
            // ((OAuthCredential)authResult.getCredential()).getAccessToken().
            // The OAuth secret can be retrieved by calling:
            // ((OAuthCredential)authResult.getCredential()).getSecret().
        }
        .addOnFailureListener {
            // Handle failure.
        }

    Java

    firebaseAuth
            .startActivityForSignInWithProvider(/* activity= */ this, provider.build())
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // User is signed in.
                            // IdP data available in
                            // authResult.getAdditionalUserInfo().getProfile().
                            // The OAuth access token can also be retrieved:
                            // ((OAuthCredential)authResult.getCredential()).getAccessToken().
                            // The OAuth secret can be retrieved by calling:
                            // ((OAuthCredential)authResult.getCredential()).getSecret().
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Handle failure.
                        }
                    });

    成功完成後,即可從傳回的 OAuthCredential 物件中,擷取與提供者相關聯的 OAuth 存取權杖。

    您可以使用 OAuth 存取權杖呼叫 Microsoft Graph API

    與 Firebase Auth 支援的其他供應商不同,Microsoft 不會提供相片網址,而是必須透過 Microsoft Graph API 要求個人資料相片的二進位資料。

    除了 OAuth 存取權杖,使用者的 OAuth ID 權杖也可以從 OAuthCredential 物件中擷取。ID 權杖中的 sub 聲明是應用程式專屬,不會與 Firebase Auth 使用的聯合使用者 ID 相符,且無法透過 user.getProviderData().get(0).getUid() 存取。請改用 oid 聲明欄位。使用 Azure AD 租戶登入時,oid 權杖附加資訊會完全相符。不過,如果不是租戶案例,oid 欄位會經過填補。如果是同盟 ID 4b2eabcdefghijkl,則 oid 的形式為 00000000-0000-0000-4b2e-abcdefghijkl

  5. 雖然上述範例著重於登入流程,但您也可以使用 startActivityForLinkWithProvider,將 Microsoft 供應商連結至現有使用者。舉例來說,您可以將多個供應商連結至同一位使用者,讓使用者透過任一供應商登入。

    Kotlin

    // The user is already signed-in.
    val firebaseUser = firebaseAuth.currentUser!!
    firebaseUser
        .startActivityForLinkWithProvider(activity, provider.build())
        .addOnSuccessListener {
            // Provider credential is linked to the current user.
            // IdP data available in
            // authResult.getAdditionalUserInfo().getProfile().
            // The OAuth access token can also be retrieved:
            // authResult.getCredential().getAccessToken().
            // The OAuth secret can be retrieved by calling:
            // authResult.getCredential().getSecret().
        }
        .addOnFailureListener {
            // Handle failure.
        }

    Java

    // The user is already signed-in.
    FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
    
    firebaseUser
            .startActivityForLinkWithProvider(/* activity= */ this, provider.build())
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // Provider credential is linked to the current user.
                            // IdP data available in
                            // authResult.getAdditionalUserInfo().getProfile().
                            // The OAuth access token can also be retrieved:
                            // authResult.getCredential().getAccessToken().
                            // The OAuth secret can be retrieved by calling:
                            // authResult.getCredential().getSecret().
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Handle failure.
                        }
                    });

  6. 您可以使用 startActivityForReauthenticateWithProvider 採用相同模式,擷取需要最近登入的敏感作業的新憑證。

    Kotlin

    // The user is already signed-in.
    val firebaseUser = firebaseAuth.currentUser!!
    firebaseUser
        .startActivityForReauthenticateWithProvider(activity, provider.build())
        .addOnSuccessListener {
            // User is re-authenticated with fresh tokens and
            // should be able to perform sensitive operations
            // like account deletion and email or password
            // update.
        }
        .addOnFailureListener {
            // Handle failure.
        }

    Java

    // The user is already signed-in.
    FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
    
    firebaseUser
            .startActivityForReauthenticateWithProvider(/* activity= */ this, provider.build())
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // User is re-authenticated with fresh tokens and
                            // should be able to perform sensitive operations
                            // like account deletion and email or password
                            // update.
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Handle failure.
                        }
                    });

後續步驟

使用者首次登入後,系統會建立新的使用者帳戶,並連結至使用者登入時使用的憑證 (即使用者名稱和密碼、電話號碼或驗證供應商資訊)。這個新帳戶會儲存在 Firebase 專案中,可用於識別專案中每個應用程式的使用者,無論使用者登入方式為何。

  • 在應用程式中,您可以從 FirebaseUser 物件取得使用者的基本個人資料資訊。請參閱「 管理使用者」。

  • Firebase Realtime DatabaseCloud Storage 安全規則中,您可以從 auth 變數取得已登入使用者的專屬使用者 ID, 並使用該 ID 控制使用者可存取的資料。

您可以將驗證供應商憑證連結至現有使用者帳戶,允許使用者透過多個驗證供應商登入應用程式。

如要登出使用者,請呼叫 signOut

Kotlin

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();