Getting the scopes and audiences correct when calling an API in Azure AD B2C

Rory Braybrook
The new control plane
3 min readNov 19, 2018

This is a typical use case within B2C. You have a client application (web or native) and this application needs to call an API.

The API is protected i.e. it requires an OAuth Bearer token and the functionality that the API can perform is controlled by scopes (permissions).

You set this all up and when you call the API you get “Not authorised” and you proceed to spend the rest of the day banging your head against a wall 😃

We have two applications, B2CTest (the client) and B2CAPI (the API that the client calls).

B2C Test — Application ID = 47840c35-e986–468b-8d2c-e25aa02d3d08

B2C API — Application ID = ecfb57af-c76a-49a0-b48f-37311846956f

Creating the API:

Note the “App ID URI”. We set this to “b2capi”.

Under “API access”, we select “openid” (use OpenID Connect and return a JWT token) and “offline_access” (return a refresh token).

Under “Published scopes”, we create two new scopes viz. “read” and “write”.

Note the generated full scope value:

https://tenant/b2capi/write

where “b2capi” is the “App ID URI” above.

On the client side under “API Access”, we add the B2CAPI API and then we select the scopes.

We don’t need to add any new scopes here.

Now let’s test it.

I use jwt.ms as the reply URL as this will display the JWT for us — a neat debugging tool.

Under “Access Tokens”, select the API and then select all the scopes.

B2C then generates the following URL for the “Run now endpoint”:

https://tenant.b2clogin.com/tenant.onmicrosoft.com/oauth2/v2.0/authorize?p=B2C_1_Tenant-SignUpIn&client_id=47840c35-e986-468b-8d2c-e25aa02d3d08&nonce=defaultNonce&redirect_uri=https%3A%2F%2Fjwt.ms&scope=openid%20https%3A%2F%2Ftenant.onmicrosoft.com%2Fb2capi%2Fwrite%20https%3A%2F%2Ftenant.onmicrosoft.com%2Fb2capi%2Fread%20https%3A%2F%2Ftenant.onmicrosoft.com%2Fb2capi%2Fuser_impersonation&response_type=id_token%20token&prompt=login

Note that the client_id (Application ID) is the ID of the application (B2CTest) not the API.

URL decoded:

https://tenant.b2clogin.com/tenant.onmicrosoft.com/oauth2/v2.0/authorize?p=B2C_1_Tenant-SignUpIn&client_id=47840c35-e986-468b-8d2c-e25aa02d3d08&nonce=defaultNonce&redirect_uri=https://jwt.ms

&scope=openid https://tenant.onmicrosoft.com/b2capi/write https://tenant.onmicrosoft.com/b2capi/read https://tenant.onmicrosoft.com/b2capi/user_impersonation

&response_type=id_token token&prompt=login

Note the full scope value.

When we run the policy and authenticate we get the JWT:

Note the “aud” (audience) is the application ID of the API which is exactly what we want.

The “scp” (scope) contains the three scopes we asked for.

The “”azp” (authorised party) contains the application ID of the client.

There’s a good overview here.

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