Issue with Azure AD B2C Custom Policy: "Basic credentials specified for 'REST-fetchUserProfile-APAC' are invalid

Ray Garg 20 Reputation points
2025-01-13T02:44:31.7266667+00:00

Description

I am working on an Azure AD B2C custom policy for the Global Identity Framework, designed to support traveling user sign-ins across multiple regions. This setup involves two major components Right now im only working on region tenant artifact, but this traveling user sign in case applies and has the same logic to both meaning the technical profiles used for both artifacts would be the same:

Funnel Tenant: Handles the initial user sign-in and routes the request based on the user's region.

Regional Tenant: Processes sign-ins for users registered in specific regions.

For users in the EMEA tenant, the sign-in process works as expected. However, when users registered in the APAC tenant attempt to sign in, the policy correctly identifies their region and routes the request to the REST-login-NonInteractive-APAC and REST-fetchUserProfile-APAC technical profiles. Unfortunately, it fails with the error: "Basic credentials specified for 'REST-fetchUserProfile-APAC' are invalid. Check that the credentials are correct and that access has been granted by the resource."

Custom Policy - Self-Asserted Local Account Sign-In Profile The first step in the user journey always begins with the SelfAsserted-LocalAccountSignin-Email profile, which includes the following configuration:




Below are the two key technical profiles for APAC users. Microsoft has provided these 2 profiles in their proof of concept documentations and i am following them exactly how they are listed. https://learn.microsoft.com/en-us/azure/active-directory-b2c/b2c-global-identity-proof-of-concept-funnel:

REST-login-NonInteractive-APAC: Responsible for authenticating the user in the APAC tenant via ROPC.




REST-fetchUserProfile-APAC: Fetches user profile details using a Graph API call.




Issue Details When an APAC user attempts to sign in:

The policy correctly identifies the user's region as "APAC" using the REST-regionLookup technical profile. The REST-login-NonInteractive-APAC profile successfully generates an access token (graph_bearerToken) using the ROPC flow. However, when the REST-fetchUserProfile-APAC technical profile attempts to use the graph_bearerToken to call the Graph API, it fails with the error: "Basic credentials specified for 'REST-fetchUserProfile-APAC' are invalid. Check that the credentials are correct and that access has been granted by the resource."

one thing additionally (not sure if this helps) is that i ran a curl command to obtain the access token so i can decode it in jwt.io. this is the test user in my apac tenant that i am attempting to login with in the emea tenant. here is the curl command:

curl -X POST "https://login.microsoftonline.com/zappsecincAdB2Capac.onmicrosoft.com/oauth2/v2.0/token"-H "Content-Type: application/x-www-form-urlencoded"-d "client_id=

Developer technologies | ASP.NET | ASP.NET Core
{count} votes

1 answer

Sort by: Most helpful
  1. Jack Dang (WICLOUD CORPORATION) 1,020 Reputation points Microsoft External Staff
    2025-08-13T07:20:06.8733333+00:00

    Hi @Ray Garg ,

    Thanks for the additional details and for clarifying your setup with the REST-login-NonInteractive-APAC and REST-fetchUserProfile-APAC technical profiles. I understand you're using the bearer token output from REST-login-NonInteractive-APAC to authenticate the REST-fetchUserProfile-APAC profile, which fetches user profile details via the Microsoft Graph API. Your question about integrating an API connector and whether to change the AuthenticationType to Basic is a great point to address. Let’s resolve this step-by-step.

    Solution

    1. Using an API Connector in REST-fetchUserProfile-APAC
      • Currently, your REST-fetchUserProfile-APAC profile is set up to use a bearer token (graph_bearerToken) to call the Microsoft Graph API (https://graph.microsoft.com/beta/me). This doesn’t require an API connector unless you intend to replace the Graph API call with a custom REST API endpoint.
      • If you want to continue using the Graph API, no API connector is needed—your existing bearer token configuration with UseClaimAsBearerToken is sufficient.
      • If you meant to use an API connector to call a custom REST service (e.g., to fetch additional user data), you can modify the REST-fetchUserProfile-APAC profile as follows:
    <TechnicalProfile Id="REST-fetchUserProfile-APAC">
      <DisplayName>Fetch user profile cross tenant</DisplayName>
      <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      <Metadata>
        <Item Key="ServiceUrl">https://your-custom-api-endpoint.com/userprofile</Item> <!-- Replace with your API URL -->
        <Item Key="AuthenticationType">Bearer</Item>
        <Item Key="UseClaimAsBearerToken">graph_bearerToken</Item>
        <Item Key="SendClaimsIn">Body</Item> <!-- Adjust based on your API's requirements -->
        <Item Key="DebugMode">true</Item>
      </Metadata>
      <InputClaims>
        <InputClaim ClaimTypeReferenceId="graph_bearerToken" />
        <!-- Add other input claims if your API requires them, e.g., user ID -->
      </InputClaims>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="id" />
        <OutputClaim ClaimTypeReferenceId="userPrincipalName" PartnerClaimType="upn" />
        <!-- Add other output claims based on your API response -->
      </OutputClaims>
      <UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
    </TechnicalProfile>
    
    • Replace https://your-custom-api-endpoint.com/userprofile with the URL of your custom REST API.
    • Ensure your API is configured to accept a bearer token in the Authorization header and returns the expected claims.
    1. Do You Need to Change AuthenticationType to Basic?
      • No, you should not change the AuthenticationType to Basic. The error "Basic credentials specified for 'REST-fetchUserProfile-APAC' are invalid" suggests the policy might have been misconfigured to use Basic authentication (e.g., username/password) at some point. Since REST-login-NonInteractive-APAC provides a bearer token via the ROPC flow, and you’ve confirmed the app registration is set up correctly in the APAC tenant, keep AuthenticationType="Bearer" and UseClaimAsBearerToken="graph_bearerToken".
      • Switching to Basic would require adding a client ID and secret in the metadata, which isn’t applicable here given your token-based approach.
    2. Verification of Current Setup
      • You mentioned the app registration in your APAC tenant has the necessary permissions and public client flows enabled. Ensure the REST-login-NonInteractive-APAC profile requests the correct scope (e.g., https://graph.microsoft.com/.default) to include the required Graph API permissions.
      • Check the bearer token’s scp and aud claims (using a tool like jwt.io) to confirm they include the expected permissions (e.g., User.Read.All) and audience (e.g., https://graph.microsoft.com).
      • If the call fails, test the stable Graph API endpoint (https://graph.microsoft.com/v1.0/me) instead of the beta endpoint to rule out API-specific issues.
    3. Final Configuration
      • If you’re sticking with the Graph API (no custom API connector), your REST-fetchUserProfile-APAC profile should remain as is, with verification of the token:
    <TechnicalProfile Id="REST-fetchUserProfile-APAC">
      <DisplayName>Fetch user profile cross tenant</DisplayName>
      <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      <Metadata>
        <Item Key="ServiceUrl">https://graph.microsoft.com/beta/me</Item>
        <Item Key="AuthenticationType">Bearer</Item>
        <Item Key="UseClaimAsBearerToken">graph_bearerToken</Item>
        <Item Key="SendClaimsIn">Url</Item>
        <Item Key="DebugMode">true</Item>
      </Metadata>
      <InputClaims>
        <InputClaim ClaimTypeReferenceId="graph_bearerToken" />
      </InputClaims>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="id" />
        <OutputClaim ClaimTypeReferenceId="userPrincipalName" PartnerClaimType="upn" />
      </OutputClaims>
      <UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
    </TechnicalProfile>
    

    Hope this helps! If you agree with my suggestion, feel free to interact with the system accordingly!

    0 comments No comments

Your answer

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