Omdat risico's en beleid in realtime worden geëvalueerd, kan de levensduur van een resource-API-token met maximaal 28 uur toenemen. Deze langlevende tokens worden proactief vernieuwd door de Microsoft Authentication Library (MSAL), waardoor de tolerantie van uw toepassingen wordt verhoogd.
Als u CAE wilt gebruiken, moeten zowel uw app als de resource-API die toegang heeft, CAE zijn ingeschakeld. Als een resource-API CAE implementeert en uw toepassing declareert dat deze CAE kan verwerken, ontvangt uw app CAE-tokens voor die resource. Als u daarom uw app CAE-gereed declareert, moet uw toepassing de CAE-claimvraag afhandelen voor alle resource-API's die toegangstokens voor Microsoft Identity accepteren.
Het voorbereiden van uw code ter ondersteuning van RESOURCES met CAE beperkt echter niet de mogelijkheid om te werken met API's die GEEN ONDERSTEUNING bieden voor CAE. Als uw app CAE-antwoorden niet correct verwerkt, kan het herhaaldelijk opnieuw proberen om een API-aanroep uit te voeren met behulp van een token dat technisch geldig is, maar wordt ingetrokken vanwege CAE.
Begin met het toevoegen van code om reacties van de resource-API af te handelen die de aanroep weigert vanwege CAE. Met CAE retourneren API's een 401-status en een WWW-Authenticate
header wanneer het toegangstoken wordt ingetrokken of detecteert de API een wijziging in het gebruikte IP-adres. De WWW-Authenticate
header bevat een claimvraag die de toepassing kan gebruiken om een nieuw toegangstoken te verkrijgen.
Wanneer aan deze voorwaarden wordt voldaan, kan de app de claimvraag extraheren en decoderen met behulp van de MSAL.NET-klasseWwwAuthenticateParameters
.
if (APIresponse.IsSuccessStatusCode)
{
// ...
}
else
{
if (APIresponse.StatusCode == System.Net.HttpStatusCode.Unauthorized
&& APIresponse.Headers.WwwAuthenticate.Any())
{
string claimChallenge = WwwAuthenticateParameters.GetClaimChallengeFromResponseHeaders(APIresponse.Headers);
Uw app gebruikt vervolgens de claimvraag om een nieuw toegangstoken voor de resource te verkrijgen.
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);
}
// ...
Zodra uw toepassing klaar is om de claimvraag af te handelen die wordt geretourneerd door een resource met CAE-functionaliteit, kunt u aan Microsoft Identity zien dat uw app gereed is voor CAE. U doet dit in uw MSAL-toepassing door uw openbare client te bouwen met behulp van de clientmogelijkheden van "cp1"
.
_clientApp = PublicClientApplicationBuilder.Create(App.ClientId)
.WithDefaultRedirectUri()
.WithAuthority(authority)
.WithClientCapabilities(new [] {"cp1"})
.Build();
Wanneer aan deze voorwaarden wordt voldaan, kan de app de claimuitdaging als volgt extraheren uit de API-antwoordheader:
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;
}
Uw app gebruikt vervolgens de claimvraag om een nieuw toegangstoken voor de resource te verkrijgen.
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);
}
}
Zodra uw toepassing klaar is om de claimvraag af te handelen die wordt geretourneerd door een resource met CAE-functionaliteit, kunt u aan Microsoft Identity zien dat uw app gereed is voor CAE door een clientCapabilities
eigenschap toe te voegen in de MSAL-configuratie.
const msalConfig = {
auth: {
clientId: 'Enter_the_Application_Id_Here',
clientCapabilities: ["CP1"]
// remaining settings...
}
}
const msalInstance = new PublicClientApplication(msalConfig);
Wanneer aan deze voorwaarden wordt voldaan, kan de app de claimuitdaging als volgt extraheren uit de API-antwoordheader:
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)
Ondersteuning declareren voor de CP1-clientmogelijkheid
In uw toepassingsconfiguratie moet u declareren dat uw toepassing CAE ondersteunt door de CP1
clientmogelijkheid op te geven. Dit wordt opgegeven met behulp van de client_capabilities
JSON-eigenschap.
{
"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"
}
}
]
}
Reageren op CAE-uitdagingen tijdens runtime
Maak een aanvraag naar een resource als het antwoord een claimvraag bevat, extraheer deze en voer deze terug in MSAL voor gebruik in de volgende aanvraag.
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
De volgende codefragmenten beschrijven de stroom van het verkrijgen van een token op de achtergrond, het maken van een HTTP-aanroep naar de resourceprovider en vervolgens het verwerken van een CAE-aanvraag. Er kan een extra interactieaanroep vereist zijn als de stille aanroep is mislukt met claims.
Ondersteuning declareren voor CP1-clientmogelijkheid
In uw toepassingsconfiguratie moet u declareren dat uw toepassing CAE ondersteunt door de CP1
clientmogelijkheid op te geven. Dit wordt opgegeven met behulp van de clientCapabilities
eigenschap.
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)
Implementeer een helperfunctie voor het parseren van claims.
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)
}
Catch & parse 401 /claims uitdagingen.
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
}
Wanneer aan deze voorwaarden wordt voldaan, kan de app de claimuitdaging als volgt extraheren uit de API-antwoordheader:
Clientmogelijkheden adverteren.
client, err := New("client-id", WithAuthority(authority), WithClientCapabilities([]string{"cp1"}))
parseer de WWW-Authenticate
header en geef de resulterende uitdaging door in MSAL-Go.
// No snippet provided at this time
Probeer een token op de achtergrond te verkrijgen met de claimvraag.
var ar AuthResult;
ar, err := client.AcquireTokenSilent(ctx, tokenScope, public.WithClaims(claims))
U kunt uw toepassing testen door u aan te melden bij een gebruiker en vervolgens de Azure-portal te gebruiken om de sessie van de gebruiker in te trekken. De volgende keer dat de app de API met CAE aanroept, wordt de gebruiker gevraagd om opnieuw te verifiëren.