- by gowthamk91
Introduction:
In my previous article, I showed how to enrich tokens in Azure AD B2C by calling an Azure Function App during sign-in:
https://gowthamcbe.com/2023/12/20/azure-ad-b2c-custom-policy-custom-claim-token-enrichment/
In this follow-up post, I’ll extend that solution so the claims-enrichment step (the Technical Profile that calls the Function App — in my case, GetUserAppRoleAssignment) runs only when the request originates from a particular client (OIDC client ID). All other clients skip the step. This limits calls to the function app to the intended application, avoiding unnecessary latency and extra calls for other apps.
This article covers:
- Why conditional execution is useful
- The exact OrchestrationStep precondition to use
- A full example orchestration step and technical profile reference
Use Case:
You have multiple client applications using the same B2C tenant and custom policies. One of them needs extra claim enrichment (for example, to get roles and app-role assignments from a backend), but the others don’t. You want the enrichment to run only for the target client ID (Example: 54f3c2f9-026c-49fb-3414-03476788db9e.)
Step-by-step instructions
STEP 1: How preconditions work?
B2C OrchestrationStep supports <Preconditions> that evaluate claims and optionally run actions such as SkipThisOrchestrationStep. The first <Value> in ClaimEquals must be a claim reference or claim name (e.g. {OIDC:ClientId}), not a literal string. If that referenced claim does not exist at the step, the condition will fail.
We want the enrichment step to run only when {OIDC:ClientId} equals 54f3c2f9-026c-49fb-3414-03476788db9e.
The easiest, most reliable pattern is:
- Use a ClaimEquals precondition with ExecuteActionsIf=”false”.
- Put {OIDC:ClientId} as the first <Value>.
- Put your target GUID as the second <Value>.
- Use the <Action>SkipThisOrchestrationStep</Action> to skip the step when the precondition triggers (note: because we use ExecuteActionsIf=”false” the action runs when the comparison is false — see explanation below).
Why ExecuteActionsIf=”false”?
- If {OIDC:ClientId} == GUID → ClaimEquals evaluates to true. Since ExecuteActionsIf=”false”, the action is not executed → step runs.
- If {OIDC:ClientId} != GUID → ClaimEquals evaluates to false. Since ExecuteActionsIf=”false”, the action is executed → step skipped.
This pattern is easy to reason about and avoids common mistakes involving inverted logic.
STEP 2:
Define a Claim Type inside ClaimsSchema
<ClaimType Id="AppClientId">
<DisplayName>AppClientId</DisplayName>
<DataType>string</DataType>
</ClaimType>Add an output claim in AAD-UserReadUsingObjectId Technical profile
<OutputClaim ClaimTypeReferenceId="AppClientId" DefaultValue="{OIDC:ClientId}" AlwaysUseDefaultValue="true" />STEP 3: Apply the pre-condition in the user journey
Place this inside the orchestration step that performs the ClaimsExchange for the token enrichment :
<OrchestrationStep Order="4" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimEquals" ExecuteActionsIf="false">
<Value>{OIDC:ClientId}</Value>
<Value>54f3c2f9-026c-49fb-3414-03476788db9e</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="GetUserAppRoleAssignmentExchange" TechnicalProfileReferenceId="GetUserAppRoleAssignment" />
</ClaimsExchanges>
</OrchestrationStep>Replace Order=”4″ with the correct order number for your flow.
Summary
- Use an OrchestrationStep precondition with <Precondition Type=”ClaimEquals”> and ExecuteActionsIf=”false” to run a claims-enrichment step only for a specific {OIDC:ClientId}.
- Make sure the first <Value> is a claim reference (e.g. {OIDC:ClientId}); otherwise the comparison will always fail.
Please check my GitHub repo, which includes:
- TrustFrameworkExtensions.xml (with the updated user journey)
- TrustFrameworkBase.xml (unchanged, but included for reference)
- GetUserAppRoleAssignment Technical Profile (in Extensions file or your TP file)