Start now →

Capturing Custom Query Parameters in Azure AD B2C: A Journey of Discovery

By suman saha · Published March 6, 2026 · 6 min read · Source: Level Up Coding
Blockchain
Capturing Custom Query Parameters in Azure AD B2C: A Journey of Discovery

Two days. That’s how long I spent chasing HTTP Referer headers, wiring up REST APIs, and digging through Azure AD B2C documentation — only to find that the answer was a single line of XML that Microsoft had documented all along. If you’re building a multi-tenant authentication system and need to capture where your users came from, let me save you those two days.

The Problem

You’re building a multi-tenant authentication system where different applications (web portals, mobile apps, SaaS platforms) need to authenticate through Azure AD B2C. Each application needs to know where the user came from so it can redirect them back after authentication and track which origin initiated the login.

Your requirement: Capture the originating application URL as a custom claim in the ID token.

Example: When a user starts at https://your-app.example.com/portal/dashboard, B2C should capture this URL and include it in the JWT token as "consumerAppReferrer": "https://your-app.example.com/portal/dashboard".

The Dead Ends

Approach 1: HTTP Referer Headers

Initial Idea: Use the HTTP Referer header that browsers send with requests.

Why it Failed:

Approach 2: Technical Profile InputClaims Mid-Journey

Idea: Add InputClaims and OutputClaims to technical profiles in the middle of the user journey to capture the query parameter.

<!-- In SelfAsserted-Signin-Email-With-Validation -->
<InputClaim ClaimTypeReferenceId="consumerAppReferrer" DefaultValue="unknown" />
<OutputClaim ClaimTypeReferenceId="consumerAppReferrer" DefaultValue="" />

Why it Failed:

Approach 3: PolicyProfile InputClaims with Standard Resolvers

Idea: Try capturing at the PolicyProfile level using various claim resolvers.

<InputClaims>
<InputClaim ClaimTypeReferenceId="consumerAppReferrer" PartnerClaimType="consumerAppReferrer" />
</InputClaims>

Why it Failed:

TL;DR

To capture custom OAuth query parameters in Azure AD B2C ID/access tokens, use the {OAUTH-KV:parameterName} claim resolver with AlwaysUseDefaultValue="true" in your relying party policy's OutputClaims. HTTP Referer headers and REST APIs are unnecessary—B2C has native support for this.

The Solution: {OAUTH-KV:parameterName}

Discovery: Azure AD B2C has a native claim resolver specifically for OAuth/OIDC query parameters: {OAUTH-KV:parameterName}

The working implementation has three components:

1. Define the Claim in ClaimsSchema

<ClaimType Id="consumerAppReferrer">
<DisplayName>Consumer App Referrer</DisplayName>
<DataType>string</DataType>
</ClaimType>

2. Use the OAUTH-KV Resolver in OutputClaims

<OutputClaim 
ClaimTypeReferenceId="consumerAppReferrer"
PartnerClaimType="consumerAppReferrer"
DefaultValue="{OAUTH-KV:consumerAppReferrer}"
AlwaysUseDefaultValue="true"
/>

Key attributes:

3. Pass the Query Parameter in Authorization URL

https://tenant.b2clogin.com/tenant.onmicrosoft.com/oauth2/v2.0/authorize?
p=B2C_1A_POLICY_NAME
&client_id=YOUR_CLIENT_ID
&redirect_uri=https://yourapp.com/callback
&response_type=id_token
&scope=openid
&consumerAppReferrer=https://your-origin-app.com/path

How It Works

1. Authorization Request Arrives

URL: ?...&consumerAppReferrer=https://your-app.com/portal

2. B2C Receives and Processes Request

PolicyProfile OutputClaim executes

3. OAUTH-KV Resolver Activates

Reads "consumerAppReferrer" from query parameters

4. Claim Added to Token

JWT payload: { "consumerAppReferrer": "https://your-app.com/portal" }

5. Client Receives Token

Application can now read the originating URL

Testing the Implementation

Test URL Format

https://your-tenant.b2clogin.com/your-tenant.onmicrosoft.com/oauth2/v2.0/authorize?p=B2C_1A_YOUR_POLICY&client_id=YOUR_CLIENT_ID&nonce=defaultNonce&redirect_uri=https%3A%2F%2Fjwt.ms&scope=openid&response_type=id_token&prompt=login&consumerAppReferrer=https%3A%2F%2Fyour-app.com%2Fpath

Verification Steps

  1. Open the authorization URL (with encoded consumerAppReferrer parameter)
  2. Complete authentication (enter credentials, TOTP, MFA, etc.)
  3. Arrive at https://jwt.ms
  4. Decode the ID token and verify the claim:
{
"iss": "https://your-tenant.b2clogin.com/...",
"sub": "user-object-id-guid",
"aud": "your-client-id",
"email": "[email protected]",
"consumerAppReferrer": "https://your-app.com/path",
"iat": 1704888000,
"auth_time": 1704888000
}

Key Learnings

1. B2C Has Native OAuth Support

Many developers jump to REST APIs or custom solutions, but B2C’s {OAUTH-KV:} resolver handles this natively. Check the documentation before building custom integrations.

2. Claim Resolvers Are Powerful

Beyond {OAUTH-KV:}, B2C supports various resolvers:

3. AlwaysUseDefaultValue Matters

Without AlwaysUseDefaultValue="true", the resolver might not execute properly. This attribute forces B2C to evaluate the resolver value.

4. Policy Hierarchy and Scope

5. Testing is Critical

The difference between "consumerAppReferrer": "unknown" (using DefaultValue) and a missing claim or empty string can indicate:

Production Considerations

1. URL Encoding

Custom query parameters must be properly URL-encoded:

Original: https://app.com/portal/s?param=value
Encoded: https%3A%2F%2Fapp.com%2Fportal%2Fs%3Fparam%3Dvalue

2. Parameter Size Limits

OAuth/OIDC URL parameters have practical size limits (typically 2KB). Validate your URL values don’t exceed this.

3. Security

4. Multiple Relying Party Policies

Apply the same pattern to all relying party policies:

5. Refresh Token Flow

To preserve the claim across token refreshes:

<!-- In the RedeemRefreshToken technical profile -->
<OutputClaim
ClaimTypeReferenceId="consumerAppReferrer"
DefaultValue="{OAUTH-KV:consumerAppReferrer}"
/>

Implementation Checklist

Common Pitfalls

ProblemCauseSolutionClaim missing from JWTPolicy not redeployedRedeploy to staging/productionClaim shows “unknown”Parameter not being readCheck {OAUTH-KV:} resolver syntaxClaim always emptyAlwaysUseDefaultValue="false"Change to "true"Claim definition errorMissing ClaimType in ClaimsSchemaAdd ClaimType definitionOld value in tokenBrowser cacheUse incognito/private mode

Conclusion

Capturing custom query parameters in Azure AD B2C doesn’t require complex REST APIs or workarounds. The {OAUTH-KV:parameterName} claim resolver provides native support for exactly this use case.

The winning formula:

  1. Define your claim type
  2. Use the OAUTH-KV resolver
  3. Set AlwaysUseDefaultValue=”true”
  4. Pass the parameter in the authorization URL

Simple, elegant, and B2C native.

Resources

Have you used custom query parameters in B2C? Share your experience in the comments!

This article is based on real-world implementation in a multi-tenant authentication system with Azure AD B2C. The journey from HTTP Referer headers through REST APIs to the native OAUTH-KV solution demonstrates the importance of understanding platform capabilities before building custom solutions.


Capturing Custom Query Parameters in Azure AD B2C: A Journey of Discovery was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.

This article was originally published on Level Up Coding and is republished here under RSS syndication for informational purposes. All rights and intellectual property remain with the original author. If you are the author and wish to have this article removed, please contact us at [email protected].

NexaPay — Accept Card Payments, Receive Crypto

No KYC · Instant Settlement · Visa, Mastercard, Apple Pay, Google Pay

Get Started →