MSAL.NET 中的 AuthenticationResult 屬性
獲取權杖的方法會回傳 AuthenticationResult
。 若是非同步方法,會傳回 Task<AuthenticationResult>
。
在 MSAL.NET 中,會出現 AuthenticationResult
:
-
AccessToken
適用於存取資源的 Web API。 此參數是字串,通常是 Base-64 編碼的 JWT。 用戶端絕不應該查看存取權杖內部。 此格式不保證會維持穩定,並可針對資源將其加密。 撰寫的程式碼相依於用戶端上的存取權杖內容,是最常造成錯誤和用戶端邏輯破碎的來源之一。 如需詳細資訊,請參閱存取權杖。
-
IdToken
,對象為使用者。 此參數是編碼的 JWT。 如需詳細資訊,請參閱識別碼權杖。
-
ExpiresOn
告知權杖到期的日期和時間。
-
TenantId
包含找到使用者時其所在的租用戶。 對於 Microsoft Entra B2B 情境中的來賓使用者,租戶 ID 是來賓租戶,而不是唯一租戶。
當使用者傳遞權杖時,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。 與 HomeAccountId 和 HomeAccountId.Identifier 不同(它們不會是 Null),此字串可以是 Null。 此屬性會取代舊版 MSAL.NET 版本中 DisplayableId 的 IUser 屬性。 |
Environment |
包含此帳戶身分識別提供者的字串,例如 login.microsoftonline.com 。 此屬性取代了 IUser 的 IdentityProvider 屬性,但 IdentityProvider 不僅有關於雲端環境的資訊,還包括租用戶相關的資訊。 在這裡,此值僅限於主機。 |
HomeAccountId |
使用者主帳戶的帳戶識別碼。 此屬性可在 Microsoft Entra 組織中唯一地識別使用者。 |
使用權杖呼叫受保護的 API
MSAL 在 AuthenticationResult
中傳回 result
之後,請先將傳回的內容新增至 HTTP 授權標頭,再進行呼叫以存取受保護的 Web API。
httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
// Call the web API.
HttpResponseMessage response = await _httpClient.GetAsync(apiUri);
...
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
PublicClientApplication pca = PublicClientApplication.builder(clientId)
.authority(authority)
.build();
// Acquire a token, acquireTokenHelper would call publicClientApplication's acquireTokenSilently then acquireToken
// see https://github.com/Azure-Samples/ms-identity-java-desktop for a full example
IAuthenticationResult authenticationResult = acquireTokenHelper(pca);
// Set the appropriate header fields in the request header.
conn.setRequestProperty("Authorization", "Bearer " + authenticationResult.accessToken);
conn.setRequestProperty("Accept", "application/json");
String response = HttpClientHelper.getResponseStringFromConn(conn);
int responseCode = conn.getResponseCode();
if(responseCode != HttpURLConnection.HTTP_OK) {
throw new IOException(response);
}
JSONObject responseObject = HttpClientHelper.processResponse(responseCode, response);
在適用於 iOS 和 macOS 的 MSAL 中呼叫 Web API
用來取得權杖的方法會傳回 MSALResult
物件。
MSALResult
會公開可用來呼叫 Web API 的 accessToken
屬性。 請先將存取權杖新增至 HTTP 授權標頭,然後才進行呼叫以存取受保護的 Web API。
Objective-C:
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];
Swift:
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()
呼叫數個 API:增量同意和條件式存取
若要為相同使用者呼叫數個 API,請在取得第一個 API 的權杖之後呼叫 AcquireTokenSilent
。 大多數時候,您都會以無訊息的方式取得其他 API 的權杖。
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();
}
使用 HTTP 用戶端 (例如 Axios),以存取權杖作為授權持有人來呼叫 API 端點 URI。
const axios = require('axios');
async function callEndpointWithToken(endpoint, accessToken) {
const options = {
headers: {
Authorization: `Bearer ${accessToken}`
}
};
console.log('Request made at: ' + new Date().toString());
const response = await axios.default.get(endpoint, options);
return response.data;
}
endpoint = "url to the API"
http_headers = {'Authorization': 'Bearer ' + result['access_token'],
'Accept': 'application/json',
'Content-Type': 'application/json'}
data = requests.get(endpoint, headers=http_headers, stream=False).json()