Vzhledem k tomu, že se rizika a zásady vyhodnocují v reálném čase, může se doba života tokenů rozhraní API prostředků zvýšit až o 28 hodin. Tyto dlouhodobé tokeny jsou proaktivně aktualizovány knihovnou MSAL (Microsoft Authentication Library) a zvyšují odolnost vašich aplikací.
Pokud chcete používat CAE, musí být vaše aplikace i rozhraní API prostředků, ke které přistupuje, povolenou službou CAE. Pokud rozhraní API prostředků implementuje CAE a vaše aplikace deklaruje, že dokáže zpracovat CAE, vaše aplikace obdrží tokeny CAE pro tento prostředek. Z tohoto důvodu, pokud deklarujete, že vaše aplikace je připravená, musí vaše aplikace zpracovat výzvu deklarace identity CAE pro všechna rozhraní API prostředků, která přijímají přístupové tokeny Microsoft Identity.
Příprava kódu na podporu prostředků s podporou CAE ale neomezuje jeho schopnost pracovat s rozhraními API, která nepodporují CAE. Pokud vaše aplikace nezpracuje správně odpovědi CAE, může opakovaně opakovat volání rozhraní API pomocí technicky platného tokenu, ale je odvolán z důvodu caE.
Začněte přidáním kódu pro zpracování odpovědí z rozhraní API prostředků, které odmítlo volání kvůli CAE. V případě caE vrátí rozhraní API stav 401 a hlavičku WWW-Authenticate
, když je přístupový token odvolán nebo rozhraní API zjistí změnu použité IP adresy. Hlavička WWW-Authenticate
obsahuje výzvu deklarací identity, kterou může aplikace použít k získání nového přístupového tokenu.
Po splnění těchto podmínek může aplikace extrahovat a dekódovat výzvu deklarací pomocí třídy MSAL.NETWwwAuthenticateParameters
.
if (APIresponse.IsSuccessStatusCode)
{
// ...
}
else
{
if (APIresponse.StatusCode == System.Net.HttpStatusCode.Unauthorized
&& APIresponse.Headers.WwwAuthenticate.Any())
{
string claimChallenge = WwwAuthenticateParameters.GetClaimChallengeFromResponseHeaders(APIresponse.Headers);
Aplikace pak pomocí výzvy deklarací identity získá nový přístupový token prostředku.
try
{
authResult = await _clientApp.AcquireTokenSilent(scopes, firstAccount)
.WithClaims(claimChallenge)
.ExecuteAsync()
.ConfigureAwait(false);
}
catch (MsalUiRequiredException)
{
try
{
authResult = await _clientApp.AcquireTokenInteractive(scopes)
.WithClaims(claimChallenge)
.WithAccount(firstAccount)
.ExecuteAsync()
.ConfigureAwait(false);
}
// ...
Jakmile je vaše aplikace připravená na zpracování výzvy deklarace identity vrácené prostředkem s povoleným caE, můžete zjistit, jestli je vaše aplikace připravená na cae. Chcete-li to provést v aplikaci MSAL, sestavte veřejný klient pomocí schopností "cp1"
klienta .
_clientApp = PublicClientApplicationBuilder.Create(App.ClientId)
.WithDefaultRedirectUri()
.WithAuthority(authority)
.WithClientCapabilities(new [] {"cp1"})
.Build();
Po splnění těchto podmínek může aplikace extrahovat výzvu deklarací identity z hlavičky odpovědi rozhraní API následujícím způsobem:
try {
const response = await fetch(apiEndpoint, options);
if (response.status === 401 && response.headers.get('www-authenticate')) {
const authenticateHeader = response.headers.get('www-authenticate');
const claimsChallenge = parseChallenges(authenticateHeader).claims;
// use the claims challenge to acquire a new access token...
}
} catch(error) {
// ...
}
// helper function to parse the www-authenticate header
function parseChallenges(header) {
const schemeSeparator = header.indexOf(' ');
const challenges = header.substring(schemeSeparator + 1).split(',');
const challengeMap = {};
challenges.forEach((challenge) => {
const [key, value] = challenge.split('=');
challengeMap[key.trim()] = window.decodeURI(value.replace(/['"]+/g, ''));
});
return challengeMap;
}
Aplikace pak pomocí výzvy deklarací identity získá nový přístupový token prostředku.
const tokenRequest = {
claims: window.atob(claimsChallenge), // decode the base64 string
scopes: ['User.Read'],
account: msalInstance.getActiveAccount()
};
let tokenResponse;
try {
tokenResponse = await msalInstance.acquireTokenSilent(tokenRequest);
} catch (error) {
if (error instanceof InteractionRequiredAuthError) {
tokenResponse = await msalInstance.acquireTokenPopup(tokenRequest);
}
}
Jakmile je vaše aplikace připravená na zpracování výzvy deklarace identity vrácené prostředkem s povoleným caE, můžete zjistit, že je vaše aplikace připravená službou CAE, a to tak, že do konfigurace MSAL přidáte clientCapabilities
vlastnost.
const msalConfig = {
auth: {
clientId: 'Enter_the_Application_Id_Here',
clientCapabilities: ["CP1"]
// remaining settings...
}
}
const msalInstance = new PublicClientApplication(msalConfig);
Po splnění těchto podmínek může aplikace extrahovat výzvu deklarací identity z hlavičky odpovědi rozhraní API následujícím způsobem:
import msal # pip install msal
import requests # pip install requests
import www_authenticate # pip install www-authenticate==0.9.2
# Once your application is ready to handle the claim challenge returned by a CAE-enabled resource, you can tell Microsoft Identity your app is CAE-ready. To do this in your MSAL application, build your Public Client using the Client Capabilities of "cp1".
app = msal.PublicClientApplication("your_client_id", client_capabilities=["cp1"])
...
# When these conditions are met, the app can extract the claims challenge from the API response header as follows:
response = requests.get("<your_resource_uri_here>")
if response.status_code == 401 and response.headers.get('WWW-Authenticate'):
parsed = www_authenticate.parse(response.headers['WWW-Authenticate'])
claims = parsed.get("bearer", {}).get("claims")
# Your app would then use the claims challenge to acquire a new access token for the resource.
if claims:
auth_result = app.acquire_token_interactive(["scope"], claims_challenge=claims)
Deklarace podpory pro funkci klienta CP1
V konfiguraci aplikace musíte deklarovat, že vaše aplikace podporuje CAE zahrnutím CP1
funkce klienta. To je určeno pomocí client_capabilities
vlastnosti JSON.
{
"client_id" : "<your_client_id>",
"authorization_user_agent" : "DEFAULT",
"redirect_uri" : "msauth://<pkg>/<cert_hash>",
"multiple_clouds_supported":true,
"broker_redirect_uri_registered": true,
"account_mode": "MULTIPLE",
"client_capabilities": "CP1",
"authorities" : [
{
"type": "AAD",
"audience": {
"type": "AzureADandPersonalMicrosoftAccount"
}
}
]
}
Reakce na výzvy CAE za běhu
Vytvořte požadavek na prostředek, pokud odpověď obsahuje výzvu deklarací identity, extrahujte ji a vložte ji zpět do knihovny MSAL pro použití v další žádosti.
final HttpURLConnection connection = ...;
final int responseCode = connection.getResponseCode();
// Check the response code...
if (200 == responseCode) {
// ...
} else if (401 == responseCode) {
final String authHeader = connection.getHeaderField("WWW-Authenticate");
if (null != authHeader) {
final ClaimsRequest claimsRequest = WWWAuthenticateHeader
.getClaimsRequestFromWWWAuthenticateHeaderValue(authHeader);
// Feed the challenge back into MSAL, first silently, then interactively if required
final AcquireTokenSilentParameters silentParameters = new AcquireTokenSilentParameters.Builder()
.fromAuthority(authority)
.forAccount(account)
.withScopes(scope)
.withClaims(claimsRequest)
.build();
try {
final IAuthenticationResult silentRequestResult = mPublicClientApplication.acquireTokenSilent(silentParameters);
// If successful - your business logic goes here...
} catch (final Exception e) {
if (e instanceof MsalUiRequiredException) {
// Retry the request interactively, passing in any claims challenge...
}
}
}
} else {
// ...
}
// Don't forget to close your connection
Následující fragmenty kódu popisují tok získání tokenu bezobslužně, volání HTTP poskytovatele prostředků a následné zpracování případu CAE. Pokud tiché volání selhalo s deklaracemi identity, může být vyžadováno další volání interakce.
Deklarace podpory pro možnosti klienta CP1
V konfiguraci aplikace musíte deklarovat, že vaše aplikace podporuje CAE zahrnutím CP1
funkce klienta. Toto je určeno pomocí clientCapabilities
vlastnosti.
let clientConfigurations = MSALPublicClientApplicationConfig(clientId: "contoso-app-ABCDE-12345",
redirectUri: "msauth.com.contoso.appbundle://auth",
authority: try MSALAuthority(url: URL(string: "https://login.microsoftonline.com/organizations")!))
clientConfigurations.clientApplicationCapabilities = ["CP1"]
let applicationContext = try MSALPublicClientApplication(configuration: clientConfigurations)
Implementujte pomocnou funkci pro analýzu problémů s deklaracemi identity.
func parsewwwAuthenticateHeader(headers:Dictionary<AnyHashable, Any>) -> String? {
// !! This is a sample code and is not validated, please provide your own implementation or fully test the sample code provided here.
// Can also refer here for our internal implementation: https://github.com/AzureAD/microsoft-authentication-library-common-for-objc/blob/dev/IdentityCore/src/webview/embeddedWebview/challangeHandlers/MSIDPKeyAuthHandler.m#L112
guard let wwwAuthenticateHeader = headers["WWW-Authenticate"] as? String else {
// did not find the header, handle gracefully
return nil
}
var parameters = [String: String]()
// regex mapping
let regex = try! NSRegularExpression(pattern: #"(\w+)="([^"]*)""#)
let matches = regex.matches(in: wwwAuthenticateHeader, range: NSRange(wwwAuthenticateHeader.startIndex..., in: wwwAuthenticateHeader))
for match in matches {
if let keyRange = Range(match.range(at: 1), in: wwwAuthenticateHeader),
let valueRange = Range(match.range(at: 2), in: wwwAuthenticateHeader) {
let key = String(wwwAuthenticateHeader[keyRange])
let value = String(wwwAuthenticateHeader[valueRange])
parameters[key] = value
}
}
guard let jsonData = try? JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) else {
// cannot convert params into json date, end gracefully
return nil
}
return String(data: jsonData, encoding: .utf8)
}
Zachyťte a parsujte 401 / problémy s deklaracemi.
let response = .... // HTTPURLResponse object from 401'd service response
switch response.statusCode {
case 200:
// ...succeeded!
break
case 401:
let headers = response.allHeaderFields
// Parse header fields
guard let wwwAuthenticateHeaderString = self.parsewwwAuthenticateHeader(headers: headers) else {
// 3.7 no valid wwwAuthenticateHeaderString is returned from header, end gracefully
return
}
let claimsRequest = MSALClaimsRequest(jsonString: wwwAuthenticateHeaderString, error: nil)
// Create claims request
let parameters = MSALSilentTokenParameters(scopes: "Enter_the_Protected_API_Scopes_Here", account: account)
parameters.claimsRequest = claimsRequest
// Acquire token silently again with the claims challenge
applicationContext.acquireTokenSilent(with: parameters) { (result, error) in
if let error = error {
// error happened end flow gracefully, and handle error. (e.g. interaction required)
return
}
guard let result = result else {
// no result end flow gracefully
return
}
// Success - You got a token!
}
break
default:
break
}
Po splnění těchto podmínek může aplikace extrahovat výzvu deklarací identity z hlavičky odpovědi rozhraní API následujícím způsobem:
Inzerujte možnosti klienta.
client, err := New("client-id", WithAuthority(authority), WithClientCapabilities([]string{"cp1"}))
parsujte hlavičku WWW-Authenticate
a předejte výslednou výzvu do MSAL-Go.
// No snippet provided at this time
Pokus o získání tokenu bezobslužně s výzvou deklarací identity
var ar AuthResult;
ar, err := client.AcquireTokenSilent(ctx, tokenScope, public.WithClaims(claims))
Aplikaci můžete otestovat přihlášením uživatele a následným použitím webu Azure Portal k odvolání relace uživatele. Při příštím volání rozhraní API s podporou CAE se uživateli zobrazí výzva k opětovnému ověření.