Using the userinfo endpoint in Azure AD B2C

Rory Braybrook
The new control plane
3 min readMar 10, 2021

This endpoint is part of the OAuth2 specification.

The base article is here.

Following the article, I created a Web application as follows:

I then got the custom policy here.

This has two policies:

  • One for the Relying Party (RP)
  • One for the extensions

These need to be uploaded after changing the tenant name etc.

Then log into the app. you created above (using the IEF “Run now” button) and look at the JWT returned:

{   "exp": 1615324444,
"nbf": 1615320844,
"ver": "1.0",
"iss": "https://tenant.b2clogin.com/65f7...2316/v2.0/",
"sub": "10b2...c7c1",
"aud": "7bd3...4760",
"acr": "b2c_1a_userinfo_signup_signin",
"nonce": "defaultNonce",
"iat": 1615320844,
"auth_time": 1615320844,
"name": "Cond Access",
"given_name": "Cond",
"family_name": "Access",
"tid": "65f7...2316" }

The important fields are the issuer (iss) and audience (aud).

Use these to update the metadata in the custom policy:

<Metadata>
<!-- Update the Issuer and Audience below -->
<!-- Audience is optional, Issuer is required-->
<Item Key="issuer">https://tenant.b2clogin.com/65f7...2316/v2.0/</Item>
<Item Key="audience">[ "7bd3...4760" ]</Item>
<Item Key="client_assertion_type">urn:ietf:params:oauth:client-assertion-type:jwt-bearer</Item>
</Metadata>

Note that the audience is actually a string collection to allow for many applications registered in this tenant to use this endpoint.

I used Postman to test this:

It’s a GET to:

https://tenant.b2clogin.com/tenant.onmicrosoft.com/b2c_1a_userinfo_signup_signin/openid/v2.0/userinfo

Note that the policy name in the call is the policy name of the RP xml file (i.e. UserInfo_SignUpOrSignin.xml).

PolicyId=”B2C_1A_UserInfo_signup_signin”
PublicPolicyUri=”http://tenant.onmicrosoft.com/B2C_1A_UserInfo_signup_signin"

You can also get it from the “acr” in the JWT.

Set Postman up like:

Take the encoded version of the JWT returned when you authenticated that looks like:

eyJ0eX...ywc_NbA

and then insert this under the Authorization tab with Type=Bearer Token

Then when you click “Send”, you should see:

{
"objectId": "10b2...c7c1",
"givenName": "Joe",
"surname": "Bloggs",
"displayName": "Joe Bloggs",
"signInNames.emailAddress": "JoeB@gmail.com"
}

If you have issues, you can use AppInsights but note the format of the RP XML:

<DefaultUserJourney ReferenceId="SignUpOrSignIn"/>
<Endpoints>
<Endpoint Id="UserInfo" UserJourneyReferenceId="UserInfoJourney"/>
</Endpoints>
<UserJourneyBehaviors>
<JourneyInsights TelemetryEngine="ApplicationInsights" InstrumentationKey="1e17...a138" DeveloperMode="true" ClientEnabled="false" ServerEnabled="true" TelemetryVersion="1.0.0"/>
</UserJourneyBehaviors>

“Endpoints” needs to come first.

If you want to add more claims to be returned e.g. UPN, then add them in the Technical Profile with Id=”UserInfoIssuer”.

<!-- The Below claims are what will be returned on the UserInfo Endpoint if in the Claims Bag-->
<InputClaims>
<InputClaim ClaimTypeReferenceId="objectId"/>
<InputClaim ClaimTypeReferenceId="givenName"/>
<InputClaim ClaimTypeReferenceId="surname"/>
<InputClaim ClaimTypeReferenceId="displayName"/>
<InputClaim ClaimTypeReferenceId="signInNames.emailAddress"/>
<InputClaim ClaimTypeReferenceId="userPrincipalName"/>
</InputClaims>

and in the Technical Profile with Id=”UserInfoAuthorization”.

The user journey calls “AAD-UserReadUsingObjectId” so you need to add it as an output claim there and in the RP.

The result is:

{
"objectId": "10b2...c7c1",
"givenName": "Joe",
"surname": "Bloggs",
"displayName": "Joe Bloggs",
"signInNames.emailAddress": "JoeB@gmail.com",
"userPrincipalName": "10b2...c7c1@tenant.onmicrosoft.com"
}

All good!

--

--

Rory Braybrook
The new control plane

NZ Microsoft Identity dude and MVP. Azure AD/B2C/ADFS/Auth0/identityserver. StackOverflow: https://bit.ly/2XU4yvJ Presentations: http://bit.ly/334ZPt5