0
votes

I have integrated Azure AD multitenant with B2C using custom policies and i dont want to have a signup page for the Azure AD user when he tries to sign in for the first time. Since that using Preconditions im trying to skip signup page for AD login users. But it gives me the following error AADB2C90037: An error occurred while processing the request. Please contact administrator of the site you are trying to access. But if the second precondition removed from the 4th step it won't give me the error and will bring the signup page which is not my requirement.My claim provider and preconditions in user journey have been mentioned below.

signin_signup policy file

 <RelyingParty>
    <DefaultUserJourney ReferenceId="SignUpOrSignInAD" />

    <UserJourneyBehaviors>
      <JourneyInsights TelemetryEngine="ApplicationInsights" InstrumentationKey="xxxxxxxxx" DeveloperMode="true" ClientEnabled="false" ServerEnabled="true" TelemetryVersion="1.0.0" />
    </UserJourneyBehaviors>
    <TechnicalProfile Id="PolicyProfile">
      <DisplayName>PolicyProfile</DisplayName>
      <Protocol Name="OpenIdConnect" />
      <OutputClaims>
     <OutputClaim ClaimTypeReferenceId="displayName" />
        <OutputClaim ClaimTypeReferenceId="givenName" />
        <OutputClaim ClaimTypeReferenceId="surname" />
        <OutputClaim ClaimTypeReferenceId="signInNames.emailAddress" />
        <OutputClaim ClaimTypeReferenceId="otherMails" PartnerClaimType="emails" />
        <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub" />
        <!-- <OutputClaim ClaimTypeReferenceId="identityProvider" /> -->
        <OutputClaim ClaimTypeReferenceId="tenantId" AlwaysUseDefaultValue="true" DefaultValue="{Policy:TenantObjectId}" />
        <OutputClaim ClaimTypeReferenceId="TnCs" />
        <OutputClaim ClaimTypeReferenceId="signInNames.emailAddress" PartnerClaimType="SignInemails" />
        <OutputClaim ClaimTypeReferenceId="signInName" />
        <OutputClaim ClaimTypeReferenceId="userPrincipalName" />
        <OutputClaim ClaimTypeReferenceId="upnUserName" />
        <OutputClaim ClaimTypeReferenceId="authenticationSource" />
      </OutputClaims>
      <SubjectNamingInfo ClaimType="sub" />
    </TechnicalProfile>
  </RelyingParty>

Claims Provider for AD

  <ClaimsProvider>
  <Domain>commonaad</Domain>
  <DisplayName>Common AAD</DisplayName>
  <TechnicalProfiles>
    <TechnicalProfile Id="Common-AAD">
      <DisplayName>Multi-Tenant AAD</DisplayName>
      <Description>Login with your Contoso account</Description>
      <Protocol Name="OAuth2"/>
      <Metadata>
    <Item Key="AccessTokenEndpoint">https://login.microsoftonline.com/organizations/oauth2/v2.0/token</Item>
    <Item Key="authorization_endpoint">https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize</Item>
    <Item Key="BearerTokenTransmissionMethod">AuthorizationHeader</Item>
    <Item Key="ClaimsEndpoint">https://graph.microsoft.com/v1.0/me</Item>
    <Item Key="client_id">xxxxxxxxxxxxxxxxxxxxxxxxxxx</Item>
    <Item Key="DiscoverMetadataByTokenIssuer">true</Item>
    <Item Key="HttpBinding">POST</Item>
    <Item Key="IdTokenAudience">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</Item>
    <Item Key="response_types">code</Item>
    <Item Key="scope">https://graph.microsoft.com/user.read</Item>
    <Item Key="UsePolicyInRedirectUri">false</Item>
    <Item Key="ValidTokenIssuerPrefixes">https://login.microsoftonline.com/</Item>
      </Metadata>

      <CryptographicKeys>
        <Key Id="client_secret" StorageReferenceId="B2C_1A_AADAppSecret"/>
      </CryptographicKeys>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="objectId" />
        <OutputClaim ClaimTypeReferenceId="tenantId" PartnerClaimType="tid"/>
        <OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="ExternalAD" AlwaysUseDefaultValue="true" />
        <OutputClaim ClaimTypeReferenceId="identityProvider" PartnerClaimType="idp" />
        <OutputClaim ClaimTypeReferenceId="displayName" PartnerClaimType="displayName" />
        <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="mail" />
        <OutputClaim ClaimTypeReferenceId="givenName" PartnerClaimType="givenName" />
        <OutputClaim ClaimTypeReferenceId="surname" PartnerClaimType="surname" />
        <OutputClaim ClaimTypeReferenceId="issuerUserId" PartnerClaimType="id"/>
        <OutputClaim ClaimTypeReferenceId="userPrincipalName" PartnerClaimType="userPrincipalName" />
      </OutputClaims>
      <OutputClaimsTransformations>
        <OutputClaimsTransformation ReferenceId="CreateRandomUPNUserName"/>
        <OutputClaimsTransformation ReferenceId="CreateUserPrincipalName"/>
        <OutputClaimsTransformation ReferenceId="CreateAzureADIdentityProvider" />
        <OutputClaimsTransformation ReferenceId="CreateAlternativeSecurityId"/>
        <OutputClaimsTransformation ReferenceId="CreateSubjectClaimFromAlternativeSecurityId"/>
      </OutputClaimsTransformations>
      <UseTechnicalProfileForSessionManagement ReferenceId="SM-SocialLogin"/>
    </TechnicalProfile>
  </TechnicalProfiles>
</ClaimsProvider>

Orchestrator step for skipping the signup

<OrchestrationStep Order="4" Type="ClaimsExchange">
          <Preconditions>
            <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
              <Value>objectId</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
           <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
             <Value>authenticationSource</Value>
              <Value>ExternalAD</Value>
              <Action>SkipThisOrchestrationStep</Action>
            </Precondition>
          </Preconditions>
          <ClaimsExchanges>
            <ClaimsExchange Id="SelfAsserted-Social" TechnicalProfileReferenceId="SelfAsserted-Social" />
          </ClaimsExchanges>
        </OrchestrationStep>
3
Any one who got the same business scenario?SINFER

3 Answers

2
votes

Your approach is correct, in the sense you are skipping the step to make this happen. But, i do not think Azure AD issues a claim called "objectId", so it is null. So when B2C tries issue a token it cannot. Check your app insight logs to see the AAD token that comes back and map the claims properly into B2C's claimId's.

See the AAD Token reference here: https://docs.microsoft.com/en-us/azure/active-directory/develop/id-tokens

In your Common-AAD technical profile, it should be like this:

<OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="oid"/>
1
votes

@SINFER: You may want to take another deep dive into making this work. I'm assuming you want to actually eliminate the sign-up, as opposed to just hiding the option and automating it in the background. If you want the latter, that's a different answer.

First consider if the consequences of skipping the sign-up flow really fits your requirements. The sign-up creates a stub account in the B2C directory so that it can perform identity operations and persist identity attributes. If you don't need the identity controls (i.e. you're depending on the IdPs for this entirely) and can guarantee that the claims you flow to the relying party will come only from (or can be calculated/referenced-via-API from) the identity provider claims, then you certainly don't need that stub account i.e. you don't need a sign-up flow.

Furthermore, looking at it in the opposite direction, by skipping sign-up flow, you lose the stub account, and therefore also lose the objectId that is automatically generated by B2C when it creates a user account in its directory. And it's this missing objectId that causes your problem. If your policies are based on the templates from Microsoft, you should generate the objectId yourself before it needs to get used elsewhere, particuarly before your claims provider issues its token.

However you choose to generate your objectId, make sure it's globally unique and immutable. A combination of the identity provider identifier and the user's identifier as issued by the IdP is sufficient, as long as the user's identifier is immutable. This allows downstream processes to ensure that the objectId always refers to the same user regardless of the sign-in session (i.e. if they sign in days later, it's still the same objectId).

A longer explanation is on github, Walkthrough: Add a sign-in-only custom policy in Azure Active Directory B2C.

Also note that you may get undesirable behaviour if your user journey (for whatever specific criteria you choose; I think you said if the user comes from a partner AAD) makes any writes or unhandled reads to the B2C directory, which I think is implemented by the "Azure Active Directory" claims provider. You really should try to skip/suppress calls to technical profiles that read or write to AAD. Inspecting the user journey is not sufficient - you have to dig deep and follow all the calls via the IncludeTechnicalProfile element.

And finally, I'm surprised the app insights logs wasn't more verbose - you'll want both EVENTS and TRACES configured for a good picture.

0
votes

Signing-in to an Azure AD tenant requires that the user performing the sign-in flow already has an attribute such as object ID that will identify them on the Azure AD tenant they are signing-in to. Object IDs of every user is different on every Azure AD tenant irrespective of their root Azure AD tenant, this attribute is not transferred from directory to directory and only a sign-up process will create this attribute for users on Azure AD.

As i have been able to configure custom policy file to bypass this step, i will not be able to get an access token as users are required to go through the signup process before they will get attributes such as object IDs that uniquely identifies every user on different Azure AD tenants.

Existing users on an Azure AD B2C tenant will not have to pass through the sign-up process, they could simply proceed to sign-in to your Azure AD B2C tenant as they would already have attributes identifying them on your Azure AD tenant.