Share via


取得呼叫 Web API 的行動應用程式令牌

您的應用程式必須先有存取令牌,應用程式才能呼叫受保護的 Web API。 本文將逐步引導您使用 Microsoft 驗證連結庫 (MSAL) 取得令牌的程式。

定義範圍

當您要求令牌時,請定義範圍。 範圍會決定您的應用程式可以存取的數據。

定義範圍最簡單的方式是將所需的 Web API App ID URI 與範圍 .default結合在一起。 此定義會告知 Microsoft 身分識別平台 您的應用程式需要入口網站中設定的所有範圍。

Android

String[] SCOPES = {"https://graph.microsoft.com/.default"};

iOS

let scopes = ["https://graph.microsoft.com/.default"]

Xamarin

var scopes = new [] {"https://graph.microsoft.com/.default"};

取得令牌

透過 MSAL 取得令牌

MSAL 可讓應用程式以無訊息和互動方式取得令牌。 當您呼叫 AcquireTokenSilent()AcquireTokenInteractive()時,MSAL 會傳回所要求範圍的存取令牌。 正確的模式是發出無訊息要求,然後回復為互動式要求。

Android

String[] SCOPES = {"https://graph.microsoft.com/.default"};
PublicClientApplication sampleApp = new PublicClientApplication(
                    this.getApplicationContext(),
                    R.raw.auth_config);

// Check if there are any accounts we can sign in silently.
// Result is in the silent callback (success or error).
sampleApp.getAccounts(new PublicClientApplication.AccountsLoadedCallback() {
    @Override
    public void onAccountsLoaded(final List<IAccount> accounts) {

        if (accounts.isEmpty() && accounts.size() == 1) {
            // TODO: Create a silent callback to catch successful or failed request.
            sampleApp.acquireTokenSilentAsync(SCOPES, accounts.get(0), getAuthSilentCallback());
        } else {
            /* No accounts or > 1 account. */
        }
    }
});

[...]

// No accounts found. Interactively request a token.
// TODO: Create an interactive callback to catch successful or failed requests.
sampleApp.acquireToken(getActivity(), SCOPES, getAuthInteractiveCallback());

iOS

請先嘗試以無訊息方式取得權杖:


NSArray *scopes = @[@"https://graph.microsoft.com/.default"];
NSString *accountIdentifier = @"my.account.id";

MSALAccount *account = [application accountForIdentifier:accountIdentifier error:nil];

MSALSilentTokenParameters *silentParams = [[MSALSilentTokenParameters alloc] initWithScopes:scopes account:account];
[application acquireTokenSilentWithParameters:silentParams completionBlock:^(MSALResult *result, NSError *error) {

    if (!error)
    {
        // You'll want to get the account identifier to retrieve and reuse the account
        // for later acquireToken calls
        NSString *accountIdentifier = result.account.identifier;

        // Access token to call the web API
        NSString *accessToken = result.accessToken;
    }

    // Check the error
    if (error && [error.domain isEqual:MSALErrorDomain] && error.code == MSALErrorInteractionRequired)
    {
        // Interactive auth will be required, call acquireTokenWithParameters:error:
        return;
    }
}];

let scopes = ["https://graph.microsoft.com/.default"]
let accountIdentifier = "my.account.id"

guard let account = try? application.account(forIdentifier: accountIdentifier) else { return }
let silentParameters = MSALSilentTokenParameters(scopes: scopes, account: account)
application.acquireTokenSilent(with: silentParameters) { (result, error) in

    guard let authResult = result, error == nil else {

    let nsError = error! as NSError

    if (nsError.domain == MSALErrorDomain &&
        nsError.code == MSALError.interactionRequired.rawValue) {

            // Interactive auth will be required, call acquireToken()
            return
         }
         return
     }

    // You'll want to get the account identifier to retrieve and reuse the account
    // for later acquireToken calls
    let accountIdentifier = authResult.account.identifier

    // Access token to call the web API
    let accessToken = authResult.accessToken
}

如果 MSAL 傳 MSALErrorInteractionRequired回 ,請嘗試以互動方式取得令牌:

UIViewController *viewController = ...; // Pass a reference to the view controller that should be used when getting a token interactively
MSALWebviewParameters *webParameters = [[MSALWebviewParameters alloc] initWithAuthPresentationViewController:viewController];
MSALInteractiveTokenParameters *interactiveParams = [[MSALInteractiveTokenParameters alloc] initWithScopes:scopes webviewParameters:webParameters];
[application acquireTokenWithParameters:interactiveParams completionBlock:^(MSALResult *result, NSError *error) {
    if (!error)
    {
        // You'll want to get the account identifier to retrieve and reuse the account
        // for later acquireToken calls
        NSString *accountIdentifier = result.account.identifier;

        NSString *accessToken = result.accessToken;
    }
}];
let viewController = ... // Pass a reference to the view controller that should be used when getting a token interactively
let webviewParameters = MSALWebviewParameters(authPresentationViewController: viewController)
let interactiveParameters = MSALInteractiveTokenParameters(scopes: scopes, webviewParameters: webviewParameters)
application.acquireToken(with: interactiveParameters, completionBlock: { (result, error) in

    guard let authResult = result, error == nil else {
        print(error!.localizedDescription)
        return
    }

    // Get access token from result
    let accessToken = authResult.accessToken
})

適用於 iOS 和 macOS 的 MSAL 支援各種修飾詞,以互動或無訊息方式取得令牌:

Xamarin

下列範例示範以互動方式取得令牌的最小程序代碼。 此範例會使用 Microsoft Graph 來讀取使用者的配置檔。

string[] scopes = new string[] {"user.read"};
var app = PublicClientApplicationBuilder.Create(clientId).Build();
var accounts = await app.GetAccountsAsync();
AuthenticationResult result;
try
{
 result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
             .ExecuteAsync();
}
catch(MsalUiRequiredException)
{
 result = await app.AcquireTokenInteractive(scopes)
             .ExecuteAsync();
}

MSAL.NET 中的強制參數

AcquireTokenInteractive 只有一個強制參數: scopesscopes參數會列舉定義需要令牌範圍的字串。 如果令牌適用於 Microsoft Graph,您可以在每個 Microsoft Graph API 的 API 參考中找到所需的範圍。 在參考中,移至 [許可權] 區段。

例如,若要 列出用戶的聯繫人,請使用範圍 「User.Read」、“Contacts.Read”。 如需詳細資訊,請參閱 Microsoft Graph 權限參考

在 Android 上,您可以使用 來建立應用程式 PublicClientApplicationBuilder時指定父活動。 如果您當時未指定父活動,稍後您可以使用 ,如下一節所示加以指定 .WithParentActivityOrWindow 。 如果您指定父活動,則令牌會在互動之後回到該父活動。 如果您未指定,則 .ExecuteAsync() 呼叫會擲回例外狀況。

MSAL.NET 中的特定選擇性參數

下列各節說明 MSAL.NET 中的選擇性參數。

WithPrompt

參數 WithPrompt() 會藉由指定提示,控制與用戶的互動。

Image showing the fields in the Prompt structure. These constant values control interactivity with the user by defining the type of prompt displayed by the WithPrompt() parameter.

類別會定義下列常數:

  • SelectAccount 會強制安全性令牌服務 (STS) 呈現帳戶選取對話方塊。 對話框包含使用者具有會話的帳戶。 當您想要讓使用者在不同的身分識別之間選擇時,可以使用此選項。 此選項會驅動 MSAL 傳送 prompt=select_account 至識別提供者。

    SelectAccount 數是預設值,而且會根據可用資訊有效地提供最佳的可能體驗。 可用的資訊可能包括帳戶、使用者的會話存在等等。 除非您有充分的理由這麼做,否則請勿變更此預設值。

  • Consent 可讓您提示使用者同意,即使之前已授與同意也一樣。 在此情況下,MSAL 會傳送 prompt=consent 至識別提供者。

    您可能想要在 Consent 組織控管要求使用者每次使用應用程式時看到同意對話框的安全性焦點應用程式中的常數。

  • ForceLogin 可讓服務提示使用者輸入認證,即使不需要提示也一樣。

    如果令牌擷取失敗,而且您想要讓使用者再次登入,這個選項就很有用。 在此情況下,MSAL 會傳送 prompt=login 至識別提供者。 您可能想要在以安全性為主的應用程式中使用此選項,其中組織控管要求使用者在每次存取應用程式的特定部分時登入。

  • Never僅適用於 .NET 4.5 和 Windows 執行階段 (WinRT)。 此常數不會提示使用者,但會嘗試使用儲存在隱藏內嵌網頁檢視中的 Cookie。 如需詳細資訊,請參閱 搭配 MSAL.NET 使用網頁瀏覽器。

    如果此選項失敗,則會 AcquireTokenInteractive 擲回例外狀況,通知您需要UI互動。 然後使用另一個 Prompt 參數。

  • NoPrompt 不會傳送提示給識別提供者。

    此選項僅適用於 Azure Active Directory B2C 中的編輯配置文件原則。 如需詳細資訊,請參閱 B2C 細節

WithExtraScopeToConsent

WithExtraScopeToConsent在您希望用戶預先同意數個資源的進階案例中使用 修飾詞。 當您不想使用累加式同意時,您可以使用這個修飾詞,這通常與 MSAL.NET 或 Microsoft 身分識別平台 搭配使用。 如需詳細資訊,請參閱 讓使用者事先同意數個資源

以下是程式代碼範例:

var result = await app.AcquireTokenInteractive(scopesForCustomerApi)
                     .WithExtraScopeToConsent(scopesForVendorApi)
                     .ExecuteAsync();
其他選擇性參數

若要瞭解 的其他選擇性參數 AcquireTokenInteractive,請參閱 AcquireTokenInteractiveParameterBuilder 的參考檔。

透過通訊協定取得令牌

我們不建議直接使用通訊協定來取得令牌。 如果您這麼做,則應用程式不支援一些涉及單一登錄(SSO)、裝置管理和條件式存取的案例。

當您使用通訊協定來取得行動應用程式的令牌時,請提出兩個要求:

  • 取得授權碼。
  • 交換令牌的程序代碼。

取得授權碼

https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=<CLIENT_ID>
&response_type=code
&redirect_uri=<ENCODED_REDIRECT_URI>
&response_mode=query
&scope=openid%20offline_access%20https%3A%2F%2Fgraph.microsoft.com%2F.default
&state=12345

取得存取權並重新整理令牌

POST /{tenant}/oauth2/v2.0/token HTTP/1.1
Host: https://login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

client_id=<CLIENT_ID>
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq3n8b2JRLk4OxVXr...
&redirect_uri=<ENCODED_REDIRECT_URI>
&grant_type=authorization_code

下一步

請移至此案例中的下一篇文章, 呼叫 Web API