In my ADB2C custom policy setup I have a technical profile which authenticates with an external IDP and uses an ExternalLoginSSOSessionProvider. This works as expected for the first login; the user is redirected to the external IDP, enters their credentials, and are redirected back to the ADB2C which concludes the flow. However immediate subsequent logins still navigate to the user to the external IDP, despite I am already logged in. As far as I can tell the external IDP should have been skipped according to the docs: https://learn.microsoft.com/en-us/azure/active-directory-b2c/custom-policy-reference-sso#externalloginssosessionprovider, specifically:
"When a technical profile, which references a session management technical profile, contains an OutputClaim
, which has been persisted into the session cookie, then this technical profile will be skipped." I output multiple claims in the technical profile for the external IDP and I persist all those claims in the session provider.
What do I need to do such that ADB2C does not redirect to the external IDP on subsequent logins?
Below is the extensions policy file containing the technical profiles:
<TrustFrameworkPolicy [removed]>
<BasePolicy>
<TenantId>[removed]</TenantId>
<PolicyId>[removed]/PolicyId>
</BasePolicy>
<BuildingBlocks>
<ClaimsSchema>
<ClaimType Id="mitid_accesstoken">
<DisplayName>Identity Provider Access Token</DisplayName>
<DataType>string</DataType>
<AdminHelpText>Stores the access token of the identity provider.</AdminHelpText>
</ClaimType>
<ClaimType Id="idp_values">
<DisplayName>[removed]</DisplayName>
<DataType>string</DataType>
<AdminHelpText>Used for setting static values to query string</AdminHelpText>
</ClaimType>
</ClaimsSchema>
<ContentDefinitions>
<ContentDefinition Id="api.selfasserted">
<LoadUri>[removed]</LoadUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:contract:selfasserted:2.1.26</DataUri>
</ContentDefinition>
</ContentDefinitions>
</BuildingBlocks>
<ClaimsProviders>
<ClaimsProvider>
<Domain>[removed]</Domain>
<DisplayName>MitID</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="MitID-oidc">
<DisplayName>MitID</DisplayName>
<Protocol Name="OpenIdConnect" />
<Metadata>
<Item Key="ProviderName">MitID</Item>
<Item Key="METADATA">[removed]</Item>
<Item Key="client_id">[removed]</Item>
<Item Key="response_types">code</Item>
<Item Key="scope">openid mitid userinfo_token</Item>
<Item Key="response_mode">form_post</Item>
<Item Key="HttpBinding">POST</Item>
<Item Key="UsePolicyInRedirectUri">false</Item>
<Item Key="issuer">[removed]</Item>
</Metadata>
<CryptographicKeys>
<Key Id="client_secret" StorageReferenceId="B2C_1A_MitIdSecret" />
</CryptographicKeys>
<InputClaims>
<InputClaim ClaimTypeReferenceId="idp_values" DefaultValue="mitid" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="issuerUserId" DefaultValue=[removed] />
<OutputClaim ClaimTypeReferenceId="identityProvider" DefaultValue=[removed] />
<OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="socialIdpAuthentication" AlwaysUseDefaultValue="true" />
<OutputClaim ClaimTypeReferenceId="mitid_accesstoken" PartnerClaimType="{oauth2:access_token}" />
<OutputClaim ClaimTypeReferenceId="sub" PartnerClaimType="sub" />
</OutputClaims>
<OutputClaimsTransformations>
<OutputClaimsTransformation ReferenceId="CreateAlternativeSecurityId" />
</OutputClaimsTransformations>
<UseTechnicalProfileForSessionManagement ReferenceId="Custom-SocialLogin" />
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
<ClaimsProvider>
<DisplayName>Session Management</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="Custom-SocialLogin">
<DisplayName>Session Mananagement Provider</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.SSO.ExternalLoginSSOSessionProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="AlwaysFetchClaimsFromProvider">false</Item>
</Metadata>
<PersistedClaims>
<PersistedClaim ClaimTypeReferenceId="alternativeSecurityId" />
<PersistedClaim ClaimTypeReferenceId="issuerUserId"/>
<PersistedClaim ClaimTypeReferenceId="identityProvider"/>
<PersistedClaim ClaimTypeReferenceId="authenticationSource" />
<PersistedClaim ClaimTypeReferenceId="mitid_accesstoken"/>
<PersistedClaim ClaimTypeReferenceId="sub"/>
</PersistedClaims>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
</ClaimsProviders>
<UserJourneys>
<UserJourney Id="SignUpOrSignIn">
<OrchestrationSteps>
<OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin">
<ClaimsProviderSelections>
<ClaimsProviderSelection TargetClaimsExchangeId="mitid_Exchange" />
</ClaimsProviderSelections>
</OrchestrationStep>
<OrchestrationStep Order="2" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="mitid_Exchange" TechnicalProfileReferenceId="MitID-oidc" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="3" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
</OrchestrationSteps>
<ClientDefinition ReferenceId="DefaultWeb" />
</UserJourney>
</UserJourneys>
</TrustFrameworkPolicy>