In Azure B2C custom policy, the Verified.strongAuthenticationPhoneNumber only gets saved to the Old Authentication Method Experience

Kevin Guan 30 Reputation points
2024-04-05T16:06:51.52+00:00

I have a Microsoft Azure Custom Policy in the Identity Experience Framework that runs through the User's MFA experience. After the initial User Login, the User Flow next asks the User to set up their MFA if they have not yet done so. If the User select the phone number option as their preferred MFA experience, they can enter their phone number to be persisted into Azure's Authentication Method.

The issue that I am facing arises here because the old and new user authentication experiences in Azure AD B2C does not both capture the phone number for MFA, as the number isn't being persist in the new Authentication Method experience. It is in the old Authentication Method Experience.

This is generally not a big issue if it weren't for the fact that the Microsoft Graph API that I am using to update the MFA Phone Number only checks the New Authentication Method Experience and not the old. Example code, using Microsoft Graph SDK 5:

patientGraphClient
        .users(azureId)
        .authentication()
        .phoneMethods(azureB2cProperties.getPhoneTypeMobile())
        .buildRequest();
phoneAuthenticationMethodRequest.patch(phoneAuthenticationMethod);

This is the code that is recommended on Microsoft's page in Java. This checks the New Authentication Method Experience to see if the number is there and if not, return a Not Found error message back. The problem here is that the User DOES have a MFA number saved, but in the Old Authentication Method Experience.

What I would like to do is that in the Custom Policies, when persisting the MFA Phone Number, I would like to make sure that the number gets saved in both the Old and New experience. I would also like to make sure that when the Microsoft's Graph API update the user's MFA number, it checks both experience and update both experience.

Here is some code from my Custom Policy on how I set up the MFA Phone number field.

<TechnicalProfiles>
<TechnicalProfile Id="PhoneFactor-InputOrVerify">	
<DisplayName>PhoneFactor</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.PhoneFactorProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="ContentDefinitionReferenceId">api.phonefactor</Item>
<Item Key="ManualPhoneNumberEntryAllowed">true</Item>
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
</CryptographicKeys>
<InputClaimsTransformations>
<InputClaimsTransformation ReferenceId="CreateUserIdForMFA" />
</InputClaimsTransformations>
<InputClaims>
<InputClaim ClaimTypeReferenceId="userIdForMFA" PartnerClaimType="UserId" />
<InputClaim ClaimTypeReferenceId="strongAuthenticationPhoneNumber" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="Verified.strongAuthenticationPhoneNumber" PartnerClaimType="Verified.OfficePhone" />
<OutputClaim ClaimTypeReferenceId="newPhoneNumberEntered" PartnerClaimType="newPhoneNumberEntered" />
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-MFA" />
</TechnicalProfile>


        <TechnicalProfile Id="AAD-UserWritePhoneNumberUsingObjectId">
          <Metadata>
            <Item Key="Operation">Write</Item>
            <Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">false</Item>
            <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item>
          </Metadata>
          <IncludeInSso>false</IncludeInSso>
          <InputClaims>
            <InputClaim ClaimTypeReferenceId="objectId" Required="true" />
          </InputClaims>
          <PersistedClaims>
            <PersistedClaim ClaimTypeReferenceId="objectId" />
            <PersistedClaim ClaimTypeReferenceId="Verified.strongAuthenticationPhoneNumber" PartnerClaimType="strongAuthenticationPhoneNumber" />
          </PersistedClaims>
          <IncludeTechnicalProfile ReferenceId="AAD-Common" />
        </TechnicalProfile>

      </TechnicalProfiles>

        <TechnicalProfile Id="SM-MFA">
<DisplayName>Session Mananagement Provider</DisplayName><Protocol Name="Proprietary" Handler="Web.TPEngine.SSO.DefaultSSOSessionProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<PersistedClaims>
	<PersistedClaim ClaimTypeReferenceId="Verified.strongAuthenticationPhoneNumber" /></PersistedClaims>
	<OutputClaims><OutputClaim ClaimTypeReferenceId="isActiveMFASession" DefaultValue="true" >
</OutputClaims>
</TechnicalProfile>


<ClaimsProvider>
      <DisplayName>PhoneFactor</DisplayName>
      <TechnicalProfiles>
        <TechnicalProfile Id="PhoneFactor-InputOrVerify">
          <DisplayName>PhoneFactor</DisplayName>
          <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.PhoneFactorProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
          <Metadata>
            <Item Key="ContentDefinitionReferenceId">api.phonefactor</Item>
            <Item Key="ManualPhoneNumberEntryAllowed">true</Item>
          </Metadata>
          <CryptographicKeys>
            <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
          </CryptographicKeys>
          <InputClaimsTransformations>
            <InputClaimsTransformation ReferenceId="CreateUserIdForMFA" />
          </InputClaimsTransformations>
          <InputClaims>
            <InputClaim ClaimTypeReferenceId="userIdForMFA" PartnerClaimType="UserId" />
            <InputClaim ClaimTypeReferenceId="strongAuthenticationPhoneNumber" />
          </InputClaims>
          <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="Verified.strongAuthenticationPhoneNumber" PartnerClaimType="Verified.OfficePhone" />
            <OutputClaim ClaimTypeReferenceId="newPhoneNumberEntered" PartnerClaimType="newPhoneNumberEntered" />
          </OutputClaims>
          <UseTechnicalProfileForSessionManagement ReferenceId="SM-MFA" />
        </TechnicalProfile>

      </TechnicalProfiles>
    </ClaimsProvider>

Microsoft Identity Manager
Microsoft Identity Manager
A family of Microsoft products that manage a user's digital identity using identity synchronization, certificate management, and user provisioning.
728 questions
{count} votes

Accepted answer
  1. Shweta Mathur 30,181 Reputation points Microsoft Employee
    2024-04-08T06:14:41.9933333+00:00

    Hi @Kevin Guan ,

    Thanks for reaching out.

    Your understanding is correct here, MS Graph API cannot access the MFA phone numbers of the users that are stored either using the default user flows or using the custom policies in azure ad b2c.

    This is a known issue however, the timeframe for the fix is not available at this point.

    An alternative and reliable option in B2C is to use an extension attribute for the phone number and make MFA work with that custom attribute instead of strongAuthenticationPhoneNumber.

    Make sure to update all references from strongAuthenticationPhoneNumber to your extension attribute.

    Hope this will help.

    Thanks,

    Shweta

    Please remember to "Accept Answer" if answer helped you.


3 additional answers

Sort by: Most helpful
  1. John Flick 10 Reputation points
    2024-09-12T21:32:03.53+00:00
    1. Our team has also experienced similar issues with Azure AD B2C, Custom Workflows, and Microsoft Graph API. There are definitely some significant incompatibilities, including the format of the phone number string.
    2. Old authentication method allowed phone number to be stored without a space between country code and national number.
    3. New authentication method requires a space between country code and national number.
    4. When viewing in Azure portal, a B2C User's authentication is listed only under Old authentication method when using custom workflows, regardless of how number is formatted.
    5. In Azure portal, if a B2C User's authentication method is saved in the Old experience with the format where a space is between country code and national number, the authentication method will then appear in both Old and New experiences. However, once the authentication method has been updated and is in the New authentication method experience, B2C custom workflows no longer recognize the authentication method for MFA. Users, when they log in, are prompted to enter and validate a new phone number.

    The previous response from @Shweta Mathur is quite dated. It would be nice to get an update. Not sure why Graph API was updated to only see authentication methods with the new format. Seems quite premature, especially for B2C customers.

    1 person found this answer helpful.
    0 comments No comments

  2. John Flick 10 Reputation points
    2024-09-12T21:42:16.9+00:00

    An alternative and reliable option in B2C is to use an extension attribute for the phone number and make MFA work with that custom attribute instead of strongAuthenticationPhoneNumber.

    Also, unless I am missing something, this suggestion to use an extension attribute invalidates any ability to manage a User's Authentication Methods in the Azure portal. Seems like a Band-Aid at best.

    1 person found this answer helpful.
    0 comments No comments

  3. Palani, Logesh C 0 Reputation points
    2024-09-30T03:05:43.2333333+00:00

    We are facing the same issue as well. I am storing MFA number in strongAuthenticationPhoneNumber so that it can be changed by the admin, if required, in azure portal. But this variable cannot be accessed, updated or deleted by graph API. It can be accessed and updated by custom policy but cannot be deleted or removed.

    May I know if there is fix to this issue yet at least to delete/remove this via custom policy.
    It will be highly helpful if this can be accessed and managed by graph API as well.

    Please provide us at least the timeline of a fix for the above.

    Regards.


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.