An Azure service that provides hosted, universal storage for Azure app configurations.
Hi @Divyata Jadhav - Pls see the response to your questions below inline
1. Is it valid to have two App Registrations for the same physical API?
Yes. B2C runs in its own tenant with its own token issuer, so a registration sitting in your workforce tenant has no practical way to represent the API to B2C users. Two registrations is just how you express one API to two identity systems.
2. What should I select for Supported account types?
These come out differently for each one, so they're under 3 and 4.
3. Should the Clerk Policy API App Registration be Single tenant?
Yes, if only your own staff use the Clerk Portal. That's the "Accounts in this organizational directory only" option. Go multi-tenant only if people from other organizations need access.
4. Should the Customer Policy API be registered in the B2C tenant, and what account type?
Yes, it has to live there, for the same reason as above. The account type is "Accounts in any identity provider or organizational directory," which is what B2C user flows need.
5. Is this recommended for production, or is there a better approach?
Yes, this is standard when you have two identity systems. The bigger job is on the API side. It now has to accept tokens from two issuers, each with a different authority, audience and claim shape.
ASP.NET Core has a mechanism for exactly this. You register both JWT bearer handlers and let a policy scheme decide per request which one applies, based on the issuer in the incoming token:
services.AddAuthentication(options =>
{
options.DefaultScheme = MY_POLICY_SCHEME;
options.DefaultChallengeScheme = MY_POLICY_SCHEME;
})
.AddJwtBearer(CLERK_SCHEME, o => { /* workforce authority + audience */ })
.AddJwtBearer(CUSTOMER_SCHEME, o => { /* B2C authority + audience */ })
.AddPolicyScheme(MY_POLICY_SCHEME, null, options =>
{
options.ForwardDefaultSelector = context =>
{
// read the bearer token, check its issuer, return the matching scheme
};
});
That skeleton is off Policy schemes in ASP.NET Core. The full example there routes between an Entra issuer and a third-party one, which is close enough to your situation to be worth reading.
Three things worth knowing before you build it.
- Each scheme needs its own
Audience, set to the client ID of the registration it belongs to. Getting those crossed is why a token validates in one portal and fails in the other. - Be explicit about which scheme your authorization policies apply to. If you aren't, a clerk scope and a customer scope become interchangeable.
- The two issuers won't produce identical claims, so check what your code reads off the token before assuming it works for both.
There is one alternative. B2C can federate to Entra ID, so clerks could sign in through B2C with their work accounts, which gets you down to one registration and one issuer. It's a big change though, and I wouldn't do it unless you're still designing rather than building.
Either way, check you already have a B2C tenant. It closed to new customers on 1 May 2025, so you can't create a new one, and Entra External ID is the replacement. Existing tenants are supported to at least May 2030.
Help make this community better for everyone: if this answer resolved your issue, please accept it or leave an upvote. If not, share more details in a comment so we can continue the discussion and find the right solution.