Why we need multiple token requests:
We're using implicit flow for our SPA to get access tokens from Azure AD B2C to access APIs that are protected by the B2C. We need to access multiple APIs and those are all registered as different applications in B2C, hence different audience for each. Since they are all different audience, B2C doesn't support a single token request for multiple audiences, so we'd have to make multiple token requests.
Background on B2C setup
We support local account login, as well as social login which is using our other Azure AD identity provider. We're also using custom policies for our B2C (identity experience framework)
The issue
The issue happens for user using the Azure AD login social login. The user has logged in before.
When multiple requests are made, we noticed the following network trace in google chrome:
- Line 1 & 2 are the token request to B2C authorize endpoint for 2 different api/scope/audience.
- Line 3+4 & line 5+6, those are redirects to login.windows.net and login.microsoftonline.com both as 1 set for a particular api/scope/audience.
- Line 7 & 8 are both the the response (id token) form post back to B2C. The line 7 returns a bad request response from the form post.
The questions
- Why the need to redirect back to login.windows.net or login.microsoftonline.com? Since the user has logged in before, shouldn't he has a valid session and thus B2C can just return the token requested?
- Can B2C support concurrent token request (or login) from the same browser for social login identity? We're suspecting this is due to the auth state that B2C expect from social login is only one and unique, so concurrent login causes this to override each other which then cause the other request to be invalid. There is no details at all on the bad request response. It just shows a blank page with "Bad request" text.
-- Update March 5th, 2019 --
After some tinkering on B2C custom policies, I've managed to suppress the redirects, after having logged in once, by changing the following:
<TechnicalProfile Id="SM-SocialLogin">
<DisplayName>Session Mananagement Provider</DisplayName>
<!--Changed to this provider instead of ExternalLoginSSOSessionProvider-->
<Protocol Name="Proprietary" Handler="Web.TPEngine.SSO.DefaultSSOSessionProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<PersistedClaims>
<PersistedClaim ClaimTypeReferenceId="alternativeSecurityId" />
<PersistedClaim ClaimTypeReferenceId="objectId" />
... removed for brevity ...
<PersistedClaim ClaimTypeReferenceId="groups" />
</PersistedClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="objectIdFromSession" DefaultValue="true"/>
</OutputClaims>
</TechnicalProfile>
Changes made is to use default session provider.
Why the external session provider would not suppress re-authenticating though? The metadata AlwaysFetchClaimsFromProvider
set to false would not suppress re-authenticating as well.
But going with this workaround cause us another problem which is asked in a separate question.