快速入門:從Android應用程式登入使用者並呼叫 Microsoft Graph API

歡迎! 這可能不是您預期的頁面。 我們目前正在處理修正程式,但目前請使用下列連結 - 它應該會帶您前往正確的文章:

快速入門:從Android應用程式登入使用者並呼叫 Microsoft Graph

我們為不便道歉,並感謝您的耐心,同時我們努力解決這個問題。

在本快速入門中,您會下載並執行程式碼範例,示範 Android 應用程式如何登入使用者,並取得存取令牌來呼叫 Microsoft Graph API。

請參閱 範例 的運作方式以取得圖例。

應用程式必須以 Microsoft Entra ID 中的應用程式物件來表示,讓 Microsoft 身分識別平台 可以提供令牌給您的應用程式。

必要條件

  • 具有有效訂用帳戶的 Azure 帳戶。 免費建立帳戶
  • Android Studio
  • Android 16+

步驟 1:在 Azure 入口網站 中設定您的應用程式

若要讓本快速入門中的程式碼範例能夠運作,請新增 與 Auth Broker 相容的重新導向 URI

Already configured 您的應用程式已使用這些屬性進行設定

步驟 2:下載專案

使用 Android Studio 執行專案。

步驟 3:您的應用程式已設定並準備好執行

我們已使用您應用程式屬性的值來設定您的專案,且已準備好執行。 範例應用程式會在 [單一帳戶模式] 畫面上啟動。 預設會提供預設範圍 user.read,這是在 Microsoft Graph API 呼叫期間讀取您自己的配置文件數據時使用。 預設會提供 Microsoft Graph API 呼叫的 URL。 如有需要,您可以變更這兩者。

MSAL sample app showing single and multiple account usage

使用應用程式功能表來變更單一和多個帳戶模式。

在單一帳戶模式中,使用公司或家庭帳戶登入:

  1. 選取 [以互動方式 取得圖形數據],以提示使用者輸入其認證。 您會在畫面底部看到呼叫 Microsoft Graph API 的輸出。
  2. 登入之後,請以無訊息方式選取 [取得圖形數據] 以呼叫 Microsoft Graph API,而不提示使用者再次輸入認證。 您會在畫面底部看到呼叫 Microsoft Graph API 的輸出。

在多個帳戶模式中,您可以重複相同的步驟。 此外,您可以移除已登入的帳戶,這也會移除該帳戶的快取令牌。

注意

Enter_the_Supported_Account_Info_Here

範例的運作方式

Screenshot of the sample app

程式代碼會組織成片段,示範如何撰寫單一和多個帳戶 MSAL 應用程式。 程式代碼檔案的組織方式如下:

檔案 示範
MainActivity 管理UI
MSGraphRequestWrapper 使用 MSAL 提供的令牌呼叫 Microsoft Graph API
MultipleAccountModeFragment 初始化多帳戶應用程式、載入用戶帳戶,並取得令牌以呼叫 Microsoft Graph API
SingleAccountModeFragment 初始化單一帳戶應用程式、載入用戶帳戶,並取得令牌以呼叫 Microsoft Graph API
res/auth_config_multiple_account.json 多個帳戶組態檔
res/auth_config_single_account.json 單一帳戶組態檔
Gradle Scripts/build.grade (Module:app) MSAL 連結庫相依性會在這裡新增

我們現在會更詳細地查看這些檔案,並在每個檔案中呼叫 MSAL 特定的程式代碼。

將 MSAL 新增至應用程式

MSAL (com.microsoft.identity.client) 是連結庫,用來登入使用者,並要求用來存取受 Microsoft 身分識別平台 保護之 API 的令牌。 當您將下列內容新增至 [相依性] 下的 Gradle 腳本>build.gradle (Module: app) 時,Gradle 3.0+ 會安裝連結庫:

dependencies {
    ...
    implementation 'com.microsoft.identity.client:msal:2.+'
    ...
}

這會指示 Gradle 從 maven 中央下載和建置 MSAL。

您也必須將 maven 的參考新增至 build.gradle (Module: app) 的 allprojects>存放庫 部分 如下所示:

allprojects {
    repositories {
        mavenCentral()
        google()
        mavenLocal()
        maven {
            url 'https://pkgs.dev.azure.com/MicrosoftDeviceSDK/DuoSDK-Public/_packaging/Duo-SDK-Feed/maven/v1'
        }
        maven {
            name "vsts-maven-adal-android"
            url "https://identitydivision.pkgs.visualstudio.com/_packaging/AndroidADAL/maven/v1"
            credentials {
                username System.getenv("ENV_VSTS_MVN_ANDROIDADAL_USERNAME") != null ? System.getenv("ENV_VSTS_MVN_ANDROIDADAL_USERNAME") : project.findProperty("vstsUsername")
                password System.getenv("ENV_VSTS_MVN_ANDROIDADAL_ACCESSTOKEN") != null ? System.getenv("ENV_VSTS_MVN_ANDROIDADAL_ACCESSTOKEN") : project.findProperty("vstsMavenAccessToken")
            }
        }
        jcenter()
    }
}

MSAL 匯入

與 MSAL 連結庫相關的匯入為 com.microsoft.identity.client.*。 例如,您會看到 import > com.microsoft.identity.client.PublicClientApplication; 哪一個是 類別的 PublicClientApplication 命名空間,代表您的公用用戶端應用程式。

SingleAccountModeFragment.java

此檔案示範如何建立單一帳戶 MSAL 應用程式並呼叫 Microsoft Graph API。

單一帳戶應用程式只能由單一使用者使用。 例如,您可能只有一個用來登入對應應用程式的帳戶。

單一帳戶 MSAL 初始化

在 中auth_config_single_account.jsononCreateView(),會使用儲存在 檔案中的auth_config_single_account.json組態資訊來建立單一帳戶PublicClientApplication。 這是您初始化 MSAL 連結庫以用於單一帳戶 MSAL 應用程式的方式:

...
// Creates a PublicClientApplication object with res/raw/auth_config_single_account.json
PublicClientApplication.createSingleAccountPublicClientApplication(getContext(),
        R.raw.auth_config_single_account,
        new IPublicClientApplication.ISingleAccountApplicationCreatedListener() {
            @Override
            public void onCreated(ISingleAccountPublicClientApplication application) {
                /**
                 * This test app assumes that the app is only going to support one account.
                 * This requires "account_mode" : "SINGLE" in the config json file.
                 **/
                mSingleAccountApp = application;
                loadAccount();
            }

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

登入使用者

在 中 SingleAccountModeFragment.java,使用者登入的程式代碼位於 initializeUI()中,在 Click 處理程式中 signInButton

嘗試取得權杖之前先呼叫 signIn()signIn() 行為如同 acquireToken() 呼叫,導致使用者登入的互動式提示。

登入用戶是異步操作。 會傳遞回呼,它會呼叫 Microsoft Graph API,並在使用者登入後更新 UI:

mSingleAccountApp.signIn(getActivity(), null, getScopes(), getAuthInteractiveCallback());

註銷使用者

SingleAccountModeFragment.java中,註銷使用者的程式代碼位於 initializeUI()中,按兩下處理程式中 signOutButton 。 將用戶註銷是異步操作。 將用戶註銷也會清除該帳戶的令牌快取。 一旦用戶帳戶註銷,就會建立回呼來更新UI:

mSingleAccountApp.signOut(new ISingleAccountPublicClientApplication.SignOutCallback() {
    @Override
    public void onSignOut() {
        updateUI(null);
        performOperationOnSignOut();
    }

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

以互動方式或以無訊息方式取得令牌

若要向用戶呈現最少的提示數目,您通常會以無訊息方式取得令牌。 然後,如果發生錯誤,請嘗試以互動方式取得令牌。 應用程式第一次呼叫 signIn()時,它會有效地作為 對 acquireToken()的呼叫,這會提示使用者輸入認證。

在某些情況下,系統可能會提示用戶選取其帳戶、輸入其認證,或同意您應用程式所要求的許可權:

  • 使用者第一次登入應用程式時
  • 如果使用者重設其密碼,則必須輸入其認證
  • 如果撤銷同意
  • 如果您的應用程式明確需要同意
  • 當您的應用程式第一次要求存取資源時
  • 需要 MFA 或其他條件式存取原則時

以互動方式取得令牌的程序代碼,也就是將涉及使用者的UI, SingleAccountModeFragment.java位於 ,在中 initializeUI(),在按兩下處理程式中 callGraphApiInteractiveButton

/**
 * If acquireTokenSilent() returns an error that requires an interaction (MsalUiRequiredException),
 * invoke acquireToken() to have the user resolve the interrupt interactively.
 *
 * Some example scenarios are
 *  - password change
 *  - the resource you're acquiring a token for has a stricter set of requirement than your Single Sign-On refresh token.
 *  - you're introducing a new scope which the user has never consented for.
 **/
mSingleAccountApp.acquireToken(getActivity(), getScopes(), getAuthInteractiveCallback());

如果使用者已經登入,acquireTokenSilentAsync()則允許應用程式以無訊息方式要求令牌,如 按兩下處理程式所示>initializeUI()callGraphApiSilentButton

/**
 * Once you've signed the user in,
 * you can perform acquireTokenSilent to obtain resources without interrupting the user.
 **/
  mSingleAccountApp.acquireTokenSilentAsync(getScopes(), AUTHORITY, getAuthSilentCallback());

載入帳戶

載入帳戶的程式代碼位於 SingleAccountModeFragment.javaloadAccount()。 載入使用者帳戶是異步操作,因此當帳戶載入、變更或發生錯誤時,回呼會處理到 MSAL。 下列程式代碼也會處理 onAccountChanged(),這會在移除帳戶時發生、用戶變更為另一個帳戶等等。

private void loadAccount() {
    ...

    mSingleAccountApp.getCurrentAccountAsync(new ISingleAccountPublicClientApplication.CurrentAccountCallback() {
        @Override
        public void onAccountLoaded(@Nullable IAccount activeAccount) {
            // You can use the account data to update your UI or your app database.
            updateUI(activeAccount);
        }

        @Override
        public void onAccountChanged(@Nullable IAccount priorAccount, @Nullable IAccount currentAccount) {
            if (currentAccount == null) {
                // Perform a cleanup task as the signed-in account changed.
                performOperationOnSignOut();
            }
        }

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

呼叫 Microsoft Graph

當使用者登入時,會透過在 中SingleAccountModeFragment.java定義的 HTTP 要求來callGraphAPI()呼叫 Microsoft Graph。 此函式是一種包裝函式,可藉由執行一些工作來簡化範例,例如從 authenticationResult 取得存取令牌,以及封裝對 MSGraphRequestWrapper 的呼叫,以及顯示呼叫的結果。

private void callGraphAPI(final IAuthenticationResult authenticationResult) {
    MSGraphRequestWrapper.callGraphAPIUsingVolley(
            getContext(),
            graphResourceTextView.getText().toString(),
            authenticationResult.getAccessToken(),
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {
                    /* Successfully called graph, process data and send to UI */
                    ...
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    ...
                }
            });
}

auth_config_single_account.json

這是使用單一帳戶之 MSAL 應用程式的組態檔。

如需這些欄位的說明,請參閱 瞭解 Android MSAL 配置檔

請注意 , "account_mode" : "SINGLE"其會將此應用程式設定為使用單一帳戶。

"client_id" 已預先設定為使用 Microsoft 維護的應用程式物件註冊。 "redirect_uri"已預先設定為使用程式碼範例所提供的簽署金鑰。

{
  "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",
      "audience": {
        "type": "AzureADandPersonalMicrosoftAccount",
        "tenant_id": "common"
      }
    }
  ]
}

MultipleAccountModeFragment.java

此檔案示範如何建立多個帳戶 MSAL 應用程式並呼叫 Microsoft Graph API。

多個帳戶應用程式的範例是一個郵件應用程式,可讓您使用多個用戶帳戶,例如工作帳戶和個人帳戶。

多個帳戶 MSAL 初始化

在檔案中MultipleAccountModeFragment.javaonCreateView()使用 儲存在 中的auth_config_multiple_account.json file組態資訊來建立多個帳戶應用程式物件 (IMultipleAccountPublicClientApplication) :

// Creates a PublicClientApplication object with res/raw/auth_config_multiple_account.json
PublicClientApplication.createMultipleAccountPublicClientApplication(getContext(),
        R.raw.auth_config_multiple_account,
        new IPublicClientApplication.IMultipleAccountApplicationCreatedListener() {
            @Override
            public void onCreated(IMultipleAccountPublicClientApplication application) {
                mMultipleAccountApp = application;
                loadAccounts();
            }

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

建立 MultipleAccountPublicClientApplication 的物件會儲存在類別成員變數中,以便用來與 MSAL 連結庫互動,以取得令牌並載入和移除使用者帳戶。

載入帳戶

多個帳戶應用程式通常會呼叫 getAccounts() 來選取要用於 MSAL 作業的帳戶。 載入帳戶的程式代碼位於 的檔案中MultipleAccountModeFragment.javaloadAccounts()。 載入用戶帳戶是異步操作。 因此,回呼會處理帳戶載入、變更或發生錯誤的情況。

/**
 * Load currently signed-in accounts, if there's any.
 **/
private void loadAccounts() {
    if (mMultipleAccountApp == null) {
        return;
    }

    mMultipleAccountApp.getAccounts(new IPublicClientApplication.LoadAccountsCallback() {
        @Override
        public void onTaskCompleted(final List<IAccount> result) {
            // You can use the account data to update your UI or your app database.
            accountList = result;
            updateUI(accountList);
        }

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

以互動方式或以無訊息方式取得令牌

在某些情況下,系統可能會提示用戶選取其帳戶、輸入其認證,或同意您應用程式所要求的許可權:

  • 使用者第一次登入應用程式時
  • 如果使用者重設其密碼,則必須輸入其認證
  • 如果撤銷同意
  • 如果您的應用程式明確需要同意
  • 當您的應用程式第一次要求存取資源時
  • 需要 MFA 或其他條件式存取原則時

多個帳戶應用程式通常應該以互動方式取得令牌,也就是與使用者相關的UI,並呼叫 acquireToken()。 以互動方式取得令牌的程式代碼位於 中的檔案中MultipleAccountModeFragment.java,在 click 處理程式中callGraphApiInteractiveButtoninitializeUI> ()

/**
 * Acquire token interactively. It will also create an account object for the silent call as a result (to be obtained by > getAccount()).
 *
 * If acquireTokenSilent() returns an error that requires an interaction,
 * invoke acquireToken() to have the user resolve the interrupt interactively.
 *
 * Some example scenarios are
 *  - password change
 *  - the resource you're acquiring a token for has a stricter set of requirement than your SSO refresh token.
 *  - you're introducing a new scope which the user has never consented for.
 **/
mMultipleAccountApp.acquireToken(getActivity(), getScopes(), getAuthInteractiveCallback());

應用程式不應該要求使用者在每次要求令牌時登入。 如果使用者已經登入, acquireTokenSilentAsync() 可讓應用程式要求令牌,而不提示使用者,如 MultipleAccountModeFragment.java 檔案所示,按下initializeUI() 處理程式中的 callGraphApiSilentButton

/**
 * Performs acquireToken without interrupting the user.
 *
 * This requires an account object of the account you're obtaining a token for.
 * (can be obtained via getAccount()).
 */
mMultipleAccountApp.acquireTokenSilentAsync(getScopes(),
    accountList.get(accountListSpinner.getSelectedItemPosition()),
    AUTHORITY,
    getAuthSilentCallback());

拿掉帳戶

要移除帳戶的程序代碼,以及帳戶的任何快取令牌,位於 MultipleAccountModeFragment.java [移除帳戶] 按鈕之處理程式中的 檔案 initializeUI() 中。 您必須先從和 acquireToken()getAccounts() MSAL 方法取得帳戶物件,才能移除帳戶物件。 因為移除帳戶是異步操作, onRemoved 因此會提供回呼來更新UI。

/**
 * Removes the selected account and cached tokens from this app (or device, if the device is in shared mode).
 **/
mMultipleAccountApp.removeAccount(accountList.get(accountListSpinner.getSelectedItemPosition()),
        new IMultipleAccountPublicClientApplication.RemoveAccountCallback() {
            @Override
            public void onRemoved() {
                ...
                /* Reload account asynchronously to get the up-to-date list. */
                loadAccounts();
            }

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

auth_config_multiple_account.json

這是使用多個帳戶之 MSAL 應用程式的組態檔。

如需各種欄位的說明,請參閱 瞭解 Android MSAL 配置檔

不同於auth_config_single_account.json組態檔,此組態檔具有 "account_mode" : "MULTIPLE" ,而不是"account_mode" : "SINGLE"因為這是多個帳戶應用程式。

"client_id" 已預先設定為使用 Microsoft 維護的應用程式物件註冊。 "redirect_uri"已預先設定為使用程式碼範例所提供的簽署金鑰。

{
  "client_id" : "0984a7b6-bc13-4141-8b0d-8f767e136bb7",
  "authorization_user_agent" : "DEFAULT",
  "redirect_uri" : "msauth://com.azuresamples.msalandroidapp/1wIqXSqBj7w%2Bh11ZifsnqwgyKrY%3D",
  "account_mode" : "MULTIPLE",
  "broker_redirect_uri_registered": true,
  "authorities" : [
    {
      "type": "AAD",
      "audience": {
        "type": "AzureADandPersonalMicrosoftAccount",
        "tenant_id": "common"
      }
    }
  ]
}

說明與支援 

如果您需要協助、想要回報問題,或想要了解支援選項,請參閱 開發人員的說明和支援。

下一步

移至 Android 教學課程,在其中建置 Android 應用程式,以從 Microsoft 身分識別平台 取得存取令牌,並使用它來呼叫 Microsoft Graph API。