Why does Azure AD B2C fail with AADB2C99002 for ExternalAzureAD/EntraID guest users after successful login?

Chris Cotter 0 Reputation points
2025-10-23T14:50:28.8866667+00:00

We are trying to use Azure AD B2C Identity Experience Framework with custom policies for sign-in. Our users are guest accounts created via invitation in Azure AD (Identity type: ExternalAzureAD, Creation type: Invitation).

Problem:

  • These users authenticate successfully using their corporate credentials.
  • After login, they are redirected back to the sign-in page.
  • Browser console shows:

ERROR ServerError: server_error: AADB2C99002: This user does not exist and profile 'AAD-UserReadUsingObjectId' requires the user to have already been created.

What we tried:

  • Replacing AAD-UserReadUsingObjectId with AAD-UserReadUsingEmailAddress → validation errors.
  • Attempting to use email claim → not supported.
  • Tried FormatString transformation → not supported.
  • Using objectId fails because guest users aren’t found.

Question: What is the correct way to configure a custom policy so that ExternalAzureAD guest users can sign in successfully? Should we use alternativeSecurityId with AAD-UserReadUsingAlternativeSecurityId? If so, how do we generate alternativeSecurityId without unsupported transformations? We are using Azure AD B2C with custom policies for sign-in.

We are trying to use Azure AD B2C Identity Experience Framework with custom policies for sign-in. Our users are guest accounts created via invitation in Azure AD (Identity type: ExternalAzureAD, Creation type: Invitation).

Azure App Configuration
Azure App Configuration
An Azure service that provides hosted, universal storage for Azure app configurations.
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Jerald Felix 9,840 Reputation points
    2025-11-28T10:34:14.79+00:00

    Hello Chris Cotter,

    Thanks for raising this question in Q&A forum.

    I understand that you are encountering the error AADB2C99002 ("The resource you are attempting to access does not exist") when users sign in via an External Identity Provider (IDP) in Azure AD B2C.

    This is a common error in Custom Policies (Identity Experience Framework). It occurs when the policy tries to look up a user in the B2C directory using the external IDP's credentials, but fails to find them, and the policy is not correctly configured to handle this "User Not Found" scenario.

    Here is the breakdown and the fix:

    1. The Cause:
      • When a user signs in with an external IDP (e.g., Google or Azure AD), B2C executes a Technical Profile (usually AAD-UserReadUsingAlternativeSecurityId) to check: "Do I already have a user with this external ID?"
      • For a new user, this check returns "User does not exist" (which is technically error AADB2C99002).
      • If your User Journey treats this as a fatal error instead of a signal to create a new account, the flow breaks.
    2. The Fix (Check Orchestration Steps):
      • Open your UserJourney XML (usually in TrustFrameworkBase.xml or TrustFrameworkExtensions.xml).
      • Locate the step that calls AAD-UserReadUsingAlternativeSecurityId.
      • Verify Preconditions: Ensure there is a subsequent step (usually SelfAsserted-Social) that writes the user to the directory. Crucially, verify that the read step is not blocking execution.
      • Correction strategy: Often, the issue is actually in the ClaimsExchange. If you are using the starter pack, ensure you haven't accidentally removed the write step or the precondition that checks objectId.
      Example of correct logic:
      
          <OrchestrationStep Order="2" Type="ClaimsExchange">
      
            <ClaimsExchanges>
      
              <ClaimsExchange Id="AADUserReadUsingAlternativeSecurityId" TechnicalProfileReferenceId="AAD-UserReadUsingAlternativeSecurityId" />
      
            </ClaimsExchanges>
      
          </OrchestrationStep>
      
          <OrchestrationStep Order="3" Type="ClaimsExchange">
      
            <Preconditions>
      
              <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
      
                <Value>objectId</Value>
      
                <Action>SkipThisOrchestrationStep</Action> </Precondition>
      
            </Preconditions>
      
            <ClaimsExchanges>
      
              <ClaimsExchange Id="SelfAsserted-Social" TechnicalProfileReferenceId="SelfAsserted-Social" />
      
            </ClaimsExchanges>
      
          </OrchestrationStep>
      
      
    3. Check Partner Claim Type:
      • Ensure that the AlternativeSecurityId mapping in your Technical Profile matches what the IDP is actually sending (e.g., sub, oid, or id).

    If helps, approve the answer.

    Best Regards,

    Jerald Felix

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.