Azure AD B2C客户端凭证流中/oauth2/v2.0/token端点nonce未返回至access_token问题及重放攻击验证方案咨询
Hey there, let's tackle this issue step by step. The core problem here is that Azure AD B2C's client credentials flow (used for service-to-service authentication) doesn't natively support including a nonce claim in the access token—this claim is primarily designed for user-interactive flows like authorization code or implicit grant, where it ties the authorization request to the token response to prevent replay attacks.
But don't worry, there are two paths you can take to add replay protection for your API:
1. Use Alternative Replay Protection Mechanisms (No Custom Policy Needed)
If you don't want to modify B2C policies, these built-in approaches work well for service-to-service scenarios:
- Shorten Token Lifetimes: Configure your Azure AD B2C app registration to issue access tokens with a short expiry (e.g., 1 hour) to limit the window for potential replay attacks.
- Validate Token Metadata: Always verify the
aud(audience) andiss(issuer) claims in the access token to ensure it was issued specifically for your API and by your trusted B2C tenant. - Implement a Token Blacklist: Maintain a server-side list of revoked or already-used tokens (store their
jticlaim, which is a unique token ID) and check against this list during validation.
2. Add Nonce to Access Token via Custom B2C Policy
If you specifically need the nonce claim in the token, you'll need to extend Azure AD B2C with a custom policy. Here's how to set it up:
Step 1: Define the Nonce Claim in Your Policy Schema
First, add a nonce claim type to your policy's ClaimsSchema section:
<ClaimsSchema> <ClaimType Id="nonce"> <DisplayName>Nonce</DisplayName> <DataType>string</DataType> <UserHelpText>A random value to prevent replay attacks.</UserHelpText> </ClaimType> </ClaimsSchema>
Step 2: Map the Request Nonce to the Token Claim
Next, update the technical profile responsible for issuing JWT tokens to pull the nonce parameter from your token request and include it in the output access token:
<TechnicalProfile Id="JwtIssuance"> <!-- Existing configuration --> <InputClaims> <!-- Add this line to capture the nonce from the request --> <InputClaim ClaimTypeReferenceId="nonce" PartnerClaimType="nonce" /> </InputClaims> <OutputClaims> <!-- Add this line to include nonce in the access token --> <OutputClaim ClaimTypeReferenceId="nonce" /> </OutputClaims> </TechnicalProfile>
Step 3: Pass Nonce as a Form Parameter in Your Token Request
Instead of sending nonce as a query parameter, include it in the application/x-www-form-urlencoded body of your POST request:
POST /{tenant}/oauth2/v2.0/token Host: login.microsoftonline.com Content-Type: application/x-www-form-urlencoded client_id={client-id}&scope=https://{tenant}/{app_id}/.default&client_secret=sampleCredentia1s&grant_type=client_credentials&nonce=your_unique_random_value
After applying these changes, your access token will include the nonce claim, which you can validate in your API (e.g., check that it matches a value stored in your request context, or ensure it hasn't been used before).
内容的提问来源于stack exchange,提问作者Deepak Tekchandani

