3
votes

We want to authenticate users for our web application using OAuth 2.0 via Azure B2C AD. Users managed the B2C AD will come from different sources, some we create ourselves but most will sign up themselves and we want to enable other identity providers such as Github or Google, hence Azure B2C AD instead of Azure Active Directory. We also want to put these users (including some of the self-signed-up ones) into groups.

The basic authentication workflow (including the the signup process) works: We created an app in a B2C tenant, enabled Web API access, generated a client secret and a user flow for signing in and signing up and set up our 3rd party identity providers.

We initiate the user authentication on https://<tenant>.b2clogin.com/tfp/<tenant>.onmicrosoft.com/<user-flow>/oauth2/v2.0/authorize?client_id=<client-id>&redirect_uri=<redirect-uri>&scope=<client-id>&response_type=code

The user returns with a valid authorization code and we use that to request an access token from https://<tenant>.b2clogin.com/tfp/<tenant>.onmicrosoft.com/<user-flow>/oauth2/v2.0/token using the following POST data:

{
    "code":"<authorization-code>",
    "client_id":"<client-id>",
    "client_secret":"<client-secret>",
    "redirect_uri":"<redirect-uri>",
    "grant_type":"authorization_code"
}

We then want to use this access token to fetch the user's profile data (including username, email and group memberships) from Azure AD Graph API (https://graph.windows.net//me?api-version=1.6). The docs explicitly say that B2C directories must not use the new Microsoft Graph API https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-devquickstarts-graph-dotnet

The API responds that the token is expired:

<?xml version="1.0" encoding="utf-8"?><error
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><code>Authentication_ExpiredToken</code><message
xml:lang="en">Your access token has expired. Please renew it before
submitting the request.</message></error>

But the timestamp in the token decoded by https://jwt.ms/ says otherwise:

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "X5eXk4xyojNFum1kl2Ytv8dlNP4-c57dO6QGTVBwaNk"
}.{
  "iss": "https://<tenant>.b2clogin.com/<id>/v2.0/",
  "exp": 1553689573,
  "nbf": 1553685973,
  "aud": "<client-id>",
  "idp": "github.com",
  "name": "<username>",
  "oid": "<oid>",
  "sub": "<sub>",
  "emails": [
    "<email>"
  ],
  "tfp": "B2C_1_SignupAndSignin",
  "azp": "<client-id>",
  "ver": "1.0",
  "iat": 1553685973
}.[Signature]

However, the aud in the token is our app only, not the Azure AD Graph API. That suggests that the token issued by Azure B2C AD is simply not valid for the Graph API.

So our question is, what is the proper way to:

  • obtain an access token for a B2C AD User which will allow us to fetch user info
  • read profile and group memberships for an authenticated B2C AD User

Some answers to Secure API with Azure AD/B2C users suggest creating a second app to query the Graph API. Is that the only way to achieve our goals?

1

1 Answers

1
votes

I don't think you will be able to use a B2C token to access the Azure AD Graph API.

You could use a B2C token to access some resource secured with B2C, e.g. an Azure Function or your app.

In this case I think you will need to use a service account to connect to Azure AD Graph API on behalf of your user. Your app, on the server side, will need to implement the neccessary role based access control - e.g. only fetching the current user info. You could use the B2C token (after it has been validated) in your app to discover who the current user is.

Azure AD B2C: Use the Azure AD Graph API

For B2C tenants, there are two primary modes of communicating with the Graph API.

  • For interactive, run-once tasks, you should act as an administrator account in the B2C tenant when you perform the tasks. This mode requires an administrator to sign in with credentials before that admin can perform any calls to the Graph API.
  • For automated, continuous tasks, you should use some type of service account that you provide with the necessary privileges to perform management tasks. In Azure AD, you can do this by registering an application and authenticating to Azure AD. This is done by using an Application ID that uses the OAuth 2.0 client credentials grant. In this case, the application acts as itself, not as a user, to call the Graph API.