Differently-formatted issuerUserId when using Microsoft Account provider in Azure AD B2C - azure

We're investigating a migration of our existing authentication system to Azure AD B2C. Our current system accepts both MSA and Google logins, and we use an in-house developed service based on IdentityServer, which stores the IDs from the third-party IdPs in Azure Table storage.
I've followed the instructions for setting up MSA as an ID provider and for migrating users with a social account, and have converted my existing MSA IDs to base64 when posting them as userIdentities to the AD Graph API (in line with the sample code from the second link above). But when I sign in with an MSA, instead of recognizing my account, it directs me to the sign-up page (as part of the Sign-in/Sign-up policy I have defined).
If I follow through with creating the user, and then inspect the newly created user with the /users/<new-user-id> endpoint in the Graph API, I get back a strange-looking issuerUserId when compared to what I have stored for my Microsoft users currently.
My existing users have ids that look something like 1234ab56789cde01, and the IDs being sent to me via B2C are formatted as something like AAAAAAAAAAAAAAAAAAAAAAbCdEF12GhIj_KlM34nOPQwhen base64 decoded. (Values altered to avoid any potential privacy issues.) The capital 'A's are always there at the beginning, and I get characters from the full range of alphanumeric values in the new format as compared to the original IDs that only have a range of hexadecimal characters.
I've managed to get the Google accounts working just fine. All that's necessary there is to convert them to base64 and they just work. But I'm struggling to figure out how to migrate the MSAs. Either I'm doing something wrong on the app registration side, or there's another step to generating the AAAAAAAA-prefixed IDs that I'm just missing. Any help is appreciated. Thanks!

The built-in identity provider for Microsoft Account maps from the sub (subject) claim for the Microsoft account to the issuerUserId property of the userIdentity object.
If you are wanting to migrate identities that are mapped from a different claim (such as the oid (object identifier) claim) of a Microsoft account, then you must use custom policies and then add a custom identity provider for Microsoft Account with the following modification:
<ClaimsProvider>
<Domain>live.com</Domain>
<DisplayName>Microsoft Account</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="MSA-OIDC">
<DisplayName>Microsoft Account</DisplayName>
<Protocol Name="OpenIdConnect" />
<Metadata>
<Item Key="ProviderName">https://login.live.com</Item>
<Item Key="METADATA">https://login.live.com/.well-known/openid-configuration</Item>
<Item Key="response_types">code</Item>
<Item Key="response_mode">form_post</Item>
<Item Key="scope">openid profile email</Item>
<Item Key="HttpBinding">POST</Item>
<Item Key="UsePolicyInRedirectUri">0</Item>
<Item Key="client_id">Your Microsoft application client id</Item>
</Metadata>
<CryptographicKeys>
<Key Id="client_secret" StorageReferenceId="B2C_1A_MSASecret" />
</CryptographicKeys>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="identityProvider" DefaultValue="live.com" />
<OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="socialIdpAuthentication" />
<!-- ORIGINAL: The following output claims maps from the "sub" claim to the "issuerUserId" property. -->
<!--<OutputClaim ClaimTypeReferenceId="socialIdpUserId" PartnerClaimType="sub" />-->
<!-- MODIFICATION: The following output claims maps from the "oid" claim to the "issuerUserId" property. -->
<OutputClaim ClaimTypeReferenceId="socialIdpUserId" PartnerClaimType="oid" />
<OutputClaim ClaimTypeReferenceId="displayName" PartnerClaimType="name" />
<OutputClaim ClaimTypeReferenceId="email" />
</OutputClaims>
<OutputClaimsTransformations>
<OutputClaimsTransformation ReferenceId="CreateRandomUPNUserName" />
<OutputClaimsTransformation ReferenceId="CreateUserPrincipalName" />
<OutputClaimsTransformation ReferenceId="CreateAlternativeSecurityId" />
<OutputClaimsTransformation ReferenceId="CreateSubjectClaimFromAlternativeSecurityId" />
</OutputClaimsTransformations>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-SocialLogin" />
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
For information about getting started with custom policies, see Azure Active Directory B2C: Get started with custom policies.

Related

Azure B2C custom policy Microsoft Live.com Account - Get Picture

I try to get user image for MSA-OIDC TechnicalProfiles, but it's not working.
Somebody will help me? This is my Claims Provider.
For google and facebook this solution working perfectly. I will add that in Azure Ad Application I added permission for User.Read, email, profile. It's enough?
<ClaimsProvider>
<Domain>live.com</Domain>
<DisplayName>Microsoft</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="MSA-OIDC">
<DisplayName>Sign in with Microsoft</DisplayName>
<Protocol Name="OpenIdConnect" />
<Metadata>
<Item Key="ProviderName">https://login.live.com</Item>
<Item Key="METADATA">https://login.live.com/.well-known/openid-configuration</Item>
<Item Key="response_types">code</Item>
<Item Key="response_mode">form_post</Item>
<Item Key="scope">openid profile email</Item>
<Item Key="HttpBinding">POST</Item>
<Item Key="UsePolicyInRedirectUri">false</Item>
<Item Key="client_id">************************</Item>
</Metadata>
<CryptographicKeys>
<Key Id="client_secret" StorageReferenceId="B2C_1A_MSASecret" />
</CryptographicKeys>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="issuerUserId" PartnerClaimType="oid" />
<OutputClaim ClaimTypeReferenceId="givenName" PartnerClaimType="given_name" />
<OutputClaim ClaimTypeReferenceId="surName" PartnerClaimType="family_name" />
<OutputClaim ClaimTypeReferenceId="displayName" PartnerClaimType="name" />
<OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="socialIdpAuthentication" />
<OutputClaim ClaimTypeReferenceId="identityProvider" PartnerClaimType="iss" />
<OutputClaim ClaimTypeReferenceId="email" />
<OutputClaim ClaimTypeReferenceId="picture" PartnerClaimType="picture" />
</OutputClaims>
<OutputClaimsTransformations>
<OutputClaimsTransformation ReferenceId="CreateRandomUPNUserName" />
<OutputClaimsTransformation ReferenceId="CreateUserPrincipalName" />
<OutputClaimsTransformation ReferenceId="CreateAlternativeSecurityId" />
</OutputClaimsTransformations>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-SocialLogin" />
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
• I didn’t use the claims provider class as posted by you in the question, but I followed the Github solution as given below in the link and I successfully signed with the Microsoft account through the ‘Signin or Signup’ userflow. Also, I tried to signup using the Identity Experience Framework also through the custom policy and was successful in creating a Microsoft account in Azure AD B2C during signup. Please find the link below for your reference: -
https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/active-directory-b2c/identity-provider-microsoft-account.md
Microsoft account signup option through custom policy used from the above link: -
Also, for getting the profile picture image of Microsoft account in Azure B2C, you will have to already import the profile picture of that user in Azure B2C because there is no way to get the profile photo of a Microsoft account in Azure B2C even through custom policy. Also, please take note of the points in the link below: -
https://learn.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0#to-retrieve-the-profile-photo-of-a-contact
The community thread link below states some probable steps that you can carry out in case of getting the profile user image: -
Get User profile pic using custom policy with azure B2C

Azure B2C federated sign out is not complete (identity token is not passed to third party end session endpoint)

I have application which uses Azure B2C as IDP. Azure B2C provides a possible to use local account or federation via OpenIdConnect to third party IDP (Identity Server). I'm using custom policies in B2C. Login works fine but I have issues with sign out. Sign out from federated identity provider is executed but identity token of third party IDP is not passed to the end session endpoint and sign out is not properly executed.
Sign out requests:
GET https://xxxxx.b2clogin.com/xxxxx.onmicrosoft.com/b2c_1a_signup_signin/oauth2/v2.0/logout?post_logout_redirect_uri=https%3A%2F%2Flocalhost%3A44317%2Fsignout-callback-oidc&id_token_hint=xxxxx
GET https://thirdpartyidp.com/idp/connect/endsession <- id_token_hint querystring parameter is missing from here
GET https://thirdpartyidp.com/idp/logout?id=xxxxx
GET https://localhost:44317/signout-callback-oidc?state=xxxxx
I have tested this also with out of box user flow but same problem occurs.
I'm using this technical profile configuration:
<ClaimsProvider>
<Domain>thirdpartyidp</Domain>
<DisplayName>thirdpartyidp</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="thirdpartyidp-OAUTH">
<DisplayName>thirdpartyidp</DisplayName>
<Protocol Name="OpenIdConnect" />
<Metadata>
<Item Key="ProviderName">thirdpartyidp</Item>
<Item Key="METADATA">https://thirdpartyidp.com/idp/.well-known/openid-configuration</Item>
<Item Key="ValidTokenIssuerPrefixes">https://thirdpartyidp.com</Item>
<Item Key="IdTokenAudience">app</Item>
<Item Key="DiscoverMetadataByTokenIssuer">true</Item>
<Item Key="response_types">code</Item>
<Item Key="response_mode">form_post</Item>
<Item Key="scope">openid profile</Item>
<Item Key="HttpBinding">POST</Item>
<Item Key="UsePolicyInRedirectUri">false</Item>
<Item Key="client_id">app</Item>
<Item Key="SingleLogoutEnabled">true</Item>
</Metadata>
<CryptographicKeys>
<Key Id="client_secret" StorageReferenceId="B2C_1A_thirdpartyidp" />
</CryptographicKeys>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="issuerUserId" PartnerClaimType="sub" />
<OutputClaim ClaimTypeReferenceId="givenName" PartnerClaimType="sub" />
<OutputClaim ClaimTypeReferenceId="surName" PartnerClaimType="sub" />
<OutputClaim ClaimTypeReferenceId="displayName" PartnerClaimType="sub" />
<OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="socialIdpAuthentication" />
<OutputClaim ClaimTypeReferenceId="identityProvider" PartnerClaimType="iss" />
<OutputClaim ClaimTypeReferenceId="identityProviderAccessToken" PartnerClaimType="{oauth2:access_token}" />
</OutputClaims>
<OutputClaimsTransformations>
<OutputClaimsTransformation ReferenceId="CreateRandomUPNUserName"/>
<OutputClaimsTransformation ReferenceId="CreateUserPrincipalName"/>
<OutputClaimsTransformation ReferenceId="CreateAlternativeSecurityId"/>
</OutputClaimsTransformations>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-SocialLogin"/>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
I found two-three year old articles that Azure AD B2C does not support signing you out from the external identity provider. According this pretty new article (https://learn.microsoft.com/en-us/azure/active-directory-b2c/session-behavior?pivots=b2c-custom-policy#sign-out) it should be possible if I understood correctly. Azure B2C definitely attempts federated sign out but it's not complete.
Do I have some kind of custom policy configuration problem or what could be the issue?
You need to configure your relying party to send the Id token during signout.
<UserJourneyBehaviors>
<SingleSignOn Scope="Tenant" EnforceIdTokenHintOnLogout="true"/>
</UserJourneyBehaviors>
I got answer from MS support that passing identity token to third party IDP end session endpoint is not currently supported.

How to add Slack as an Identity Provider in AAD B2C?

I'd like to add Slack as an Identity Provider to my app using AAD B2C. Is there any example of how to build the Technical Profile for that?
I was able to create a Technical profile to connect to Slack, but I'm having a problem with sending a user_scope parameter instead of the scope parameter. The OAuth2 technical profile only supports "scope" parameter and I'm not able to find a way of sending "user_scope" instead.
I was also able to connect using endpoints that didn't include "v2" in them, but I'm not sure that's the right approach
This is the technical profile I'm using in the ClaimsProvider now. I have anothe ClaimsProvider for AAD multitenant. Didn't modify the relying party at all for Slack.
<TechnicalProfile Id="Slack-OAUTH">
<DisplayName>Slack</DisplayName>
<Protocol Name="OAuth2" />
<Metadata>
<Item Key="ProviderName">slack</Item>
<Item Key="authorization_endpoint">https://slack.com/oauth/v2/authorize</Item>
<Item Key="AccessTokenEndpoint">https://slack.com/api/oauth.v2.access</Item>
<Item Key="ClaimsEndpoint">https://slack.com/api/users.identity</Item>
<Item Key="HttpBinding">POST</Item>
<Item Key="UsePolicyInRedirectUri">0</Item>
<Item Key="client_id">ClientID</Item>
</Metadata>
<CryptographicKeys>
<Key Id="client_secret" StorageReferenceId="REFERENCE_TO_SECRET_IN_B2C_KEYS" />
</CryptographicKeys>
<InputClaims>
<InputClaim ClaimTypeReferenceId="user_scope" DefaultValue="identity.basic" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="identityProvider" DefaultValue="slack" />
<OutputClaim ClaimTypeReferenceId="user" />
<OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="socialIdpAuthentication" />
</OutputClaims>
<OutputClaimsTransformations>
<OutputClaimsTransformation ReferenceId="GetIdClaimFromJson" />
<OutputClaimsTransformation ReferenceId="GetNameClaimFromJson" />
<OutputClaimsTransformation ReferenceId="CreateRandomUPNUserName" />
<OutputClaimsTransformation ReferenceId="CreateUserPrincipalName" />
<OutputClaimsTransformation ReferenceId="CreateAlternativeSecurityId" />
<OutputClaimsTransformation ReferenceId="CreateSubjectClaimFromAlternativeSecurityId" />
</OutputClaimsTransformations>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-SocialLogin" />
</TechnicalProfile>
The call to slack works and I'm getting a code back and being redirected to aadb2c, but then I get an exception back. Put the policy in development mode to drop logs into App Insights and got an exception saying: An invalid OAuth response was received: '{0}'.
'Message':'The given key was not present in the dictionary.','Data':{}​
To enable sign-in for users from a Slack account, you need to create a Slack application project.
Sign in to the Slack API with your account credentials.
Select Create New App.
Enter an App Name and select a Development Slack Workspace.
Select Create App.
Under App Credentials, copy the values of Client ID and Client secret. You will need both of them to configure Slack as an identity provider in your tenant. Client secret is an important security credential.
Under Features, select OAuth and Permissions.
Add a new Redirect URL, enter https:/your-tenant-name.b2clogin.com/your-tenant-name.onmicrosoft.com/oauth2/authresp.
Replace your-tenant-name with the name of your tenant. You need to use all lowercase letters when entering your tenant name even if the tenant is defined with uppercase letters in Azure AD B2C.
Click Save URLs.
Create a policy key
You need to store the client secret that you previously recorded in your Azure AD B2C tenant.
Sign in to the Azure portal.
Make sure you're using the directory that contains your Azure AD B2C tenant by clicking the Directory and subscription filter in the top menu and choosing the directory that contains your tenant.
Choose All services in the top-left corner of the Azure portal, and then search for and select Azure AD B2C.
On the Overview page, select Identity Experience Framework - PREVIEW.
Select Policy Keys and then select Add.
For Options, choose Manual.
Enter a Name for the policy key. For example, SlackSecret. The prefix B2C_1A_ is added automatically to the name of your key.
In Secret, enter your client secret that you previously recorded.
For Key usage, select Signature.
Click Create.
Slack claims provider as follows:
<TechnicalProfile Id="Slack-OAUTH">
<DisplayName>Log in with your Slack account</DisplayName>
<Protocol Name="OAuth2"/>
<OutputTokenFormat>JWT</OutputTokenFormat>
<Metadata>
<Item Key="AccessTokenEndpoint">https://slack.com/api/oauth.access</Item>
<Item Key="authorization_endpoint">https://slack.com/oauth/authorize</Item>
<Item Key="BearerTokenTransmissionMethod">AuthorizationHeader</Item>
<Item Key="ClaimsEndpoint">https://slack.com/api/users.identity</Item>
<Item Key="client_id">Your Slack App Registration Client ID</Item>
<Item Key="HttpBinding">POST</Item>
<Item Key="response_types">code</Item>
<Item Key="scope">identity.basic</Item>
<Item Key="UsePolicyInRedirectUri">false</Item>
</Metadata>
<CryptographicKeys>
<Key Id="client_secret" StorageReferenceId="B2C_1A_slackfederation"/>
</CryptographicKeys>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="slackAuthentication" />
<OutputClaim ClaimTypeReferenceId="user" />
<OutputClaim ClaimTypeReferenceId="identityProvider" DefaultValue="slack" />
</OutputClaims>
<OutputClaimsTransformations>
<OutputClaimsTransformation ReferenceId="GetIdClaimFromJson" />
<OutputClaimsTransformation ReferenceId="GetNameClaimFromJson" />
<OutputClaimsTransformation ReferenceId="CreateAlternativeSecurityId" />
<OutputClaimsTransformation ReferenceId="CreateRandomUPNUserName" />
<OutputClaimsTransformation ReferenceId="CreateUserPrincipalName" />
</OutputClaimsTransformations>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
And supporting claims transforms:
<ClaimsTransformation Id="GetIdClaimFromJson" TransformationMethod="GetClaimFromJson">
<InputClaims>
<InputClaim ClaimTypeReferenceId="slackOAuthResponse" TransformationClaimType="inputJson" />
</InputClaims>
<InputParameters>
<InputParameter Id="claimToExtract" DataType="string" Value="id" />
</InputParameters>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="socialIdpUserId" TransformationClaimType="extractedClaim" />
</OutputClaims>
</ClaimsTransformation>
<ClaimsTransformation Id="GetNameClaimFromJson" TransformationMethod="GetClaimFromJson">
<InputClaims>
<InputClaim ClaimTypeReferenceId="slackOAuthResponse" TransformationClaimType="inputJson" />
</InputClaims>
<InputParameters>
<InputParameter Id="claimToExtract" DataType="string" Value="name" />
</InputParameters>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="displayName" TransformationClaimType="extractedClaim" />
</OutputClaims>
</ClaimsTransformation>
I have been struggling with this same situation where user_scope isn't a valid parameter in my .net core web app.
I tried setting the auth endpoint to:
https://slack.com/oauth/v2/authorize?user_scope=identity.basic+identity.email+identity.team
and that did get past one hurdle, but after I sign in and am redirected back to my web app, it fails to process the claims. I'll update this partial answer if I can get it working, but hopefully, it will help someone figure this out.

How can I read the mobile value from a B2C user record and transform it to a strongAuthenticationPhoneNumber?

I have the need to create Azure B2C user accounts programmatically. In a separate user data store I hold pertinent information about the users I need to set up in B2C including their mobile phone number, which we've already been communicating with them on.
My business requirement is that this mobile phone number is used as a secondary factor during the user's first-time login/password reset experience. I have an initial login experience which uses an externally-created JWT token to take the user to a custom User Journey where they can set a password for the first time.
I understand that it is not yet possible to set the Azure MFA mobile number via Graph API or PowerShell. (Is this still true?). Therefore B2C asks the user to enter their mobile number in the exemplar PhoneFactor-InputOrVerify Technical Profile. This is a security hole as you can just enter any mobile number in there and verify that number.
I can easily programmatically add the user's number to some other field - e.g. the mobile field on the user record.
Question 1.
Is there a way to read the user account mobile value and present it to a Technical Profile as if it is the strongAuthenticationPhoneNumber value or Verified.strongAuthenticationPhoneNumber?
Question 2.
Is this even a good idea? I imagine there are good reasons not to do this, but I can't fathom what they might be.
I've tried creating new ClaimTypes, reading the 'mobile' field value, creating ClaimsTranfromations to try to make the mobile claim appear to be the strongAuthenticationPhoneNumber claim, and trying generally to 'spoof' B2C into thinking this is the actual number as stored in the MFA data store.
This is the the standard PhoneFactor-InputOrVerify Technical Profile from the starterpack:
<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>
I can provide more code samples of the custom User Journey I mentioned earlier but I don't think this will help with this problem.
You have a few options:
You can add the strongAuthenticationPhoneNumber claim to the same JWT that is used for the onboarding flow and prompt for verification of this phone number during this onboarding flow.
You can map to the strongAuthenticationPhoneNumber claim for the PhoneFactor-InputOrVerify technical profile from the mobile property (or an extension property) of the user object.
For option 1, the onboarding user journey should write the verified phone number to the user object, without the newPhoneNumberEntered-based precondition:
<OrchestrationStep Order="8" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="AADUserWriteWithObjectId" TechnicalProfileReferenceId="AAD-UserWritePhoneNumberUsingObjectId" />
</ClaimsExchanges>
</OrchestrationStep>
For option 2, you can map to the strongAuthenticationPhoneNumber claim from the mobile property, as follows:
<InputClaims>
<InputClaim ClaimTypeReferenceId="userIdForMFA" PartnerClaimType="UserId" />
<InputClaim ClaimTypeReferenceId="mobile" PartnerClaimType="strongAuthenticationPhoneNumber" />
</InputClaims>

How to get claims from OpenID Connect provider in Azure AD B2C

I am having some issues getting claims from an OpenID Connect provider with an Azure AD B2C custom policy.
My OIDC provider does not return any claims in the id_token, it has a separate endpoint for claims called userInfo_endpoint where you send a GET request with Bearer authentication and the access_token go get user claims in json format. I understand this is pretty standard OIDC functionality.
Most examples I see use the ClaimsEndpoint to get claims and it seems to me the claims are added to the user as part of the signin_signup user journey.
Everything up to this point works as expected, testClaim is returned from b2c as part of the id_token, but no other claims are set. I have Application Insights set up for the policy, but the endpoint /userinfo is never called by B2C, and I see no trace of it in the logs. Are OIDC /userinfo endpoints even supported?
Below is my claims provider section.
<ClaimsProvider>
<DisplayName>Provider</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="provider-oidc">
<DisplayName>Providerprofile</DisplayName>
<Protocol Name="OpenIdConnect" />
<OutputTokenFormat>JWT</OutputTokenFormat>
<Metadata>
<Item Key="client_id">preprod-provider</Item>
<Item Key="scope">openid profile</Item>
<Item Key="response_types">code</Item>
<Item Key="METADATA">https://preprod.provider.com/oidc/.well-known/openid-configuration</Item>
<Item Key="ProviderName">https://preprod.provider.com/oidc</Item>
<Item Key="state">123abc</Item>
<Item Key="HttpBinding">POST</Item>
<Item Key="UsePolicyInRedirectUri">true</Item>
<Item Key="authorization_endpoint">https://preprod.provider.com/oidc/authorize</Item>
<Item Key="token_endpoint">https://preprod.provider.com/oidc/token</Item>
<Item Key="ClaimsEndpoint">https://preprod.provider.com/oidc/userinfo</Item>
<Item Key="ClaimsEndpointAccessTokenName">oauth2_access_token</Item>
<Item Key="ClaimsResponseFormat">json</Item>
<!--Item Key="userinfo_endpoint">https://preprod.provider.com/oidc/userinfo</Item-->
</Metadata>
<CryptographicKeys>
<Key Id="client_secret" StorageReferenceId="B2C_1A_ProviderClientSecret" />
</CryptographicKeys>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="socialIdpUserId" PartnerClaimType="sub"/>
<OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="providerAuthentication" />
<OutputClaim ClaimTypeReferenceId="identityProvider" DefaultValue="provider" />
<OutputClaim ClaimTypeReferenceId="displayName" PartnerClaimType="name" />
<OutputClaim ClaimTypeReferenceId="givenName" PartnerClaimType="given_name" />
<OutputClaim ClaimTypeReferenceId="surName" PartnerClaimType="family_name" />
<OutputClaim ClaimTypeReferenceId="testClaim" DefaultValue="testValue" />
</OutputClaims>
<OutputClaimsTransformations>
<OutputClaimsTransformation ReferenceId="CreateRandomUPNUserName"/>
<OutputClaimsTransformation ReferenceId="CreateUserPrincipalName"/>
<OutputClaimsTransformation ReferenceId="CreateAlternativeSecurityId"/>
<OutputClaimsTransformation ReferenceId="CreateSubjectClaimFromAlternativeSecurityId"/>
</OutputClaimsTransformations>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
Azure AD B2C does not support the userinfo_endpoint. You can request this feature in the Azure AD B2C feedback forum.
There are two workarounds for this:
At the application level - add code that, after obtaining the id_token, calls out to this userinfo_endpoint to obtain those extra claims and add them to the token for the rest of the application to leverage
At the B2C custom policy level - add a callout to a Rest API to retrieve the extra claims and add them in the token. Note that you won't be able to call the userinfo_endpoint, rather you'll need to write an in-between service that transforms the call REST call from B2C (which doesn't yet support sending an Authorization: Bearer X header) into a call to your userinfo_endpoint or to the underlying user store with the extra claims.
While the OpenIdConnect Technical Profile doesn't seem to support a userinfo endpoint, you should be able to use the OAuth2 Technical Profile together with the ClaimsEndpoint to get claims from the userinfo endpoint
The user_info endpoint is now supported in ADB2C. Please see https://learn.microsoft.com/en-us/azure/active-directory-b2c/userinfo-endpoint?pivots=b2c-custom-policy for more information.

Resources