從行動應用程式呼叫 Web API
您的應用程式登入使用者並接收令牌之後,Microsoft 驗證連結庫 (MSAL) 會公開使用者、用戶環境和已發行令牌的相關信息。 您的應用程式可以使用這些值來呼叫 Web API,或向使用者顯示歡迎訊息。
在本文中,我們將先查看 MSAL 結果。 然後,我們將探討如何使用 或 result
的AuthenticationResult
存取令牌來呼叫受保護的 Web API。
MSAL 結果
MSAL 提供下列值:
AccessToken
在 HTTP 持有人要求中呼叫受保護的 Web API。IdToken
包含登入使用者的相關實用資訊。 這項資訊包括用戶的名稱、主租使用者,以及記憶體的唯一標識碼。ExpiresOn
是令牌的到期時間。 MSAL 會處理應用程式的自動重新整理。TenantId
是使用者登入之租用戶的標識碼。 對於 Microsoft Entra B2B 中的來賓使用者,此值會識別使用者登入所在的租使用者。 此值不會識別使用者的主租使用者。Scopes
表示使用令牌授與的範圍。 授與的範圍可能是您所要求範圍的子集。
MSAL 也提供值的抽象概念 Account
。 值 Account
代表目前使用者的登入帳戶:
HomeAccountIdentifier
識別使用者的主租使用者。UserName
是使用者慣用的用戶名稱。 對於 Azure AD B2C 使用者而言,此值可能是空的。AccountIdentifier
識別已登入的使用者。 在大部分情況下,除非使用者是另一個租使用者中的來賓,否則此值與值相同HomeAccountIdentifier
。
呼叫 API
取得存取令牌之後,您可以呼叫 Web API。 您的應用程式會使用令牌來建置 HTTP 要求,然後執行要求。
Android
RequestQueue queue = Volley.newRequestQueue(this);
JSONObject parameters = new JSONObject();
try {
parameters.put("key", "value");
} catch (Exception e) {
// Error when constructing.
}
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, MSGRAPH_URL,
parameters,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) {
// Error.
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
// Put access token in HTTP request.
headers.put("Authorization", "Bearer " + authResult.getAccessToken());
return headers;
}
};
request.setRetryPolicy(new DefaultRetryPolicy(
3000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
queue.add(request);
適用於 iOS 和 macOS 的 MSAL
取得令牌的方法會傳回 MSALResult
物件。 MSALResult
accessToken
會公開 屬性。 您可以使用 accessToken
來呼叫 Web API。 在呼叫 以存取受保護的 Web API 之前,請先將此屬性新增至 HTTP 授權標頭。
NSMutableURLRequest *urlRequest = [NSMutableURLRequest new];
urlRequest.URL = [NSURL URLWithString:"https://contoso.api.com"];
urlRequest.HTTPMethod = @"GET";
urlRequest.allHTTPHeaderFields = @{ @"Authorization" : [NSString stringWithFormat:@"Bearer %@", accessToken] };
NSURLSessionDataTask *task =
[[NSURLSession sharedSession] dataTaskWithRequest:urlRequest
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {}];
[task resume];
let urlRequest = NSMutableURLRequest()
urlRequest.url = URL(string: "https://contoso.api.com")!
urlRequest.httpMethod = "GET"
urlRequest.allHTTPHeaderFields = [ "Authorization" : "Bearer \(accessToken)" ]
let task = URLSession.shared.dataTask(with: urlRequest as URLRequest) { (data: Data?, response: URLResponse?, error: Error?) in }
task.resume()
Xamarin
MSAL.NET 中的 AuthenticationResult 屬性
取得權杖的方法會傳回 AuthenticationResult
。 針對異步方法, Task<AuthenticationResult>
會傳回 。
在 MSAL.NET 中, AuthenticationResult
公開:
AccessToken
供 Web API 存取資源。 此參數是字串,通常是Base-64編碼的JWT。 用戶端絕對不應該在存取令牌內查看。 格式不保證會保持穩定,而且可以加密資源。 撰寫依賴用戶端存取令牌內容的程式代碼,是錯誤和客戶端邏輯中斷的最大來源之一。 如需詳細資訊,請參閱 存取令牌。IdToken
使用者。 此參數是編碼的 JWT。 如需詳細資訊,請參閱 標識符令牌。ExpiresOn
告知令牌到期的日期和時間。TenantId
包含找到使用者的租使用者。 針對 Microsoft Entra B2B 案例中的來賓使用者,租使用者標識碼是來賓租使用者,而不是唯一租使用者。 為用戶傳遞令牌時,AuthenticationResult
也包含此用戶的相關信息。 對於要求令牌且沒有應用程式使用者的機密用戶端流程,此使用者資訊為 null。Scopes
發出權杖的 。- 使用者的唯一識別碼。
IAccount
MSAL.NET 透過 IAccount
介面定義帳戶的概念。 這項重大變更提供正確的語意。 相同的用戶可以在不同的 Microsoft Entra 目錄中擁有數個帳戶。 此外,MSAL.NET 客體案例中提供更佳的信息,因為提供主帳戶資訊。
下圖顯示 介面的結構 IAccount
。
類別 AccountId
會識別特定租使用者中的帳戶,其中包含下表所示的屬性。
屬性 | 說明 |
---|---|
TenantId |
GUID 的字串表示,這是帳戶所在租用戶的標識碼。 |
ObjectId |
GUID 的字串表示,這是在租用戶中擁有帳戶的使用者標識碼。 |
Identifier |
帳戶的唯一標識碼。 Identifier 是的 ObjectId 串連,並以 TenantId 逗號分隔。 它們不是Base 64編碼。 |
介面 IAccount
代表單一帳戶的相關信息。 相同的使用者可以存在於不同的租使用者中,這表示使用者可以有多個帳戶。 下表顯示其成員。
屬性 | 說明 |
---|---|
Username |
字串,包含 UserPrincipalName (UPN) 格式的可顯示值,例如 john.doe@contoso.com。 此字串可以是 null,不同於 HomeAccountId 和 HomeAccountId.Identifier,這不會是 Null。 這個屬性會 DisplayableId 取代舊版 MSAL.NET 中的屬性 IUser 。 |
Environment |
字串,包含此帳戶的識別提供者,例如 login.microsoftonline.com 。 這個屬性會 IdentityProvider 取代的 IUser 屬性,但 IdentityProvider 除了雲端環境之外,也包含租用戶的相關信息。 在這裡,值只是主機。 |
HomeAccountId |
使用者主帳戶的帳戶標識碼。 此屬性可唯一識別 Microsoft Entra 租用戶的使用者。 |
使用令牌來呼叫受保護的 API
在 中result
由 MSAL 傳回 之後AuthenticationResult
,請先將它新增至 HTTP 授權標頭,再進行呼叫以存取受保護的 Web API。
httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
// Call the web API.
HttpResponseMessage response = await _httpClient.GetAsync(apiUri);
...
}
提出數個 API 要求
若要呼叫相同的 API 數次,或呼叫多個 API,請在建置應用程式時考慮下列主題:
累加同意:Microsoft 身分識別平台 可讓應用程式在需要許可權時取得使用者同意,而不是在啟動時取得全部許可權。 每次您的應用程式準備好呼叫 API 時,都應該只要求它所需的範圍。
條件式存取:當您提出數個 API 要求時,在某些情況下,您可能需要符合其他條件式存取需求。 如果第一個要求沒有條件式存取原則,而且您的應用程式嘗試以無訊息方式存取需要條件式存取的新 API,需求可能會以這種方式增加。 若要處理此問題,請務必從無訊息要求攔截錯誤,並準備好提出互動式要求。 如需詳細資訊,請參閱 條件式存取的指引。
使用累加式同意和條件式存取呼叫數個 API
若要為相同的使用者呼叫數個 API,在取得使用者的令牌之後,您可以藉由後續呼叫 AcquireTokenSilent
來取得令牌,避免重複要求使用者提供認證:
var result = await app.AcquireTokenXX("scopeApi1")
.ExecuteAsync();
result = await app.AcquireTokenSilent("scopeApi2")
.ExecuteAsync();
在下列情況下需要互動:
- 使用者已同意第一個 API,但現在需要同意更多範圍。 在此情況下,您會使用累加式同意。
- 第一個 API 不需要 多重要素驗證,但下一個 API 會執行。
var result = await app.AcquireTokenXX("scopeApi1")
.ExecuteAsync();
try
{
result = await app.AcquireTokenSilent("scopeApi2")
.ExecuteAsync();
}
catch(MsalUiRequiredException ex)
{
result = await app.AcquireTokenInteractive("scopeApi2")
.WithClaims(ex.Claims)
.ExecuteAsync();
}
下一步
請移至此案例中的下一篇文章, 移至生產環境。