Tutorial: Protect and grant access to a Node.js web API from a single-page application with Azure AD B2C

This tutorial shows you how to call an Azure Active Directory B2C (Azure AD B2C)-protected Node.js web API from a single-page application.

In this tutorial, the second in a two-part series:

  • Create a web API application registration in your Azure AD B2C tenant
  • Configure scopes for the web API
  • Grant permissions to the web API
  • Modify a web API code sample to work with your tenant

In the first tutorial in this series, you downloaded the code sample and modified it to sign in users with a user flow in your Azure AD B2C tenant.

If you don't have an Azure subscription, create a free account before you begin.

Prerequisites

Add a web API application

Web API resources need to be registered in your tenant before they can accept and respond to protected resource requests by client applications that present an access token.

To register an application in your Azure AD B2C tenant, you can use our new unified App registrations experience or our legacy Applications (Legacy) experience. Learn more about the new experience.

  1. Sign in to the Azure portal.
  2. Select the Directory + subscription filter in the top menu, and then select the directory that contains your Azure AD B2C tenant.
  3. In the left menu, select Azure AD B2C. Or, select All services and search for and select Azure AD B2C.
  4. Select App registrations, and then select New registration.
  5. Enter a Name for the application. For example, webapi1.
  6. Under Redirect URI, select Web, and then enter an endpoint where Azure AD B2C should return any tokens that your application requests. In this tutorial, the sample runs locally and listens at http://localhost:5000.
  7. Select Register.
  8. Record the Application (client) ID for use in a later step.

Next, enable the implicit grant flow:

  1. Under Manage, select Authentication.
  2. Select Try out the new experience (if shown).
  3. Under Implicit grant, select both the Access tokens and ID tokens check boxes.
  4. Select Save.

Configure scopes

Scopes provide a way to govern access to protected resources. Scopes are used by the web API to implement scope-based access control. For example, some users could have both read and write access, whereas other users might have read-only permissions. In this tutorial, you define both read and write permissions for the web API.

  1. Select App registrations.
  2. Select the webapi1 application to open its Overview page.
  3. Under Manage, select Expose an API.
  4. Next to Application ID URI, select the Set link.
  5. Replace the default value (a GUID) with api, and then select Save. The full URI is shown, and should be in the format https://your-tenant-name.onmicrosoft.com/api. When your web application requests an access token for the API, it should add this URI as the prefix for each scope that you define for the API.
  6. Under Scopes defined by this API, select Add a scope.
  7. Enter the following values to create a scope that defines read access to the API, then select Add scope:
    1. Scope name: demo.read
    2. Admin consent display name: Read access to demo API
    3. Admin consent description: Allows read access to the demo API
  8. Select Add a scope, enter the following values to add a scope that defines write access to the API, and then select Add scope:
    1. Scope name: demo.write
    2. Admin consent display name: Write access to demo API
    3. Admin consent description: Allows write access to the demo API

Record the value under Scopes for the demo.read scope to use in a later step when you configure the single-page application. The full scope value is similar to https://contosob2c.onmicrosoft.com/api/demo.read.

Grant permissions

To call a protected web API from another application, you need to grant that application permissions to the web API.

In the prerequisite tutorial, you created a web application named webapp1. In this tutorial, you configure that application to call the web API you created in a previous section, webapi1.

  1. Select App registrations, and then select the web application that should have access to the API. For example, webapp1.
  2. Under Manage, select API permissions.
  3. Under Configured permissions, select Add a permission.
  4. Select the My APIs tab.
  5. Select the API to which the web application should be granted access. For example, webapi1.
  6. Under Permission, expand demo, and then select the scopes that you defined earlier. For example, demo.read and demo.write.
  7. Select Add permissions.
  8. Select Grant admin consent for (your tenant name).
  9. If you're prompted to select an account, select your currently signed-in administrator account, or sign in with an account in your Azure AD B2C tenant that's been assigned at least the Cloud application administrator role.
  10. Select Yes.
  11. Select Refresh, and then verify that "Granted for ..." appears under Status for both scopes.

Your single-page web application has now been granted permissions to the protected web API for the scopes specified. A user authenticates with Azure AD B2C to use the single-page application. The single-page app uses the authorization grant flow to access the protected web API with an access token returned by Azure AD B2C.

Configure the sample

Now that the web API is registered and you've defined scopes, configure the web API code to work with your Azure AD B2C tenant. In this tutorial, you configure a sample Node.js web API you download from GitHub.

Download a *.zip archive or clone the sample web API project from GitHub. You can also browse directly to the Azure-Samples/active-directory-b2c-javascript-nodejs-webapi project on GitHub.

git clone https://github.com/Azure-Samples/active-directory-b2c-javascript-nodejs-webapi.git

Configure the web API

  1. Open the config.js file in your code editor.

  2. Modify the variable values to reflect those of the application registration you created earlier. Also update the policyName with the user flow you created as part of the prerequisites. For example, B2C_1_signupsignin1.

    const clientID = "<your-webapi-application-ID>"; // Application (client) ID
    const b2cDomainHost = "<your-tenant-name>.b2clogin.com";
    const tenantId = "<your-tenant-ID>.onmicrosoft.com"; // Alternatively, you can use your Directory (tenant) ID (a GUID)
    const policyName = "B2C_1_signupsignin1";
    

Enable CORS

To allow your single-page application to call the Node.js web API, you need to enable CORS in the web API. In a production application you should be careful about which domain is making the request, but for this tutorial, allow requests from any domain.

To enable CORS, use the following middleware. In the Node.js web API code sample in this tutorial, it's already been added to the index.js file.

app.use((req, res, next) => {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Authorization, Origin, X-Requested-With, Content-Type, Accept");
    next();
});

Configure the single-page application

The single-page application (SPA) from the previous tutorial in the series uses Azure AD B2C for user sign-up and sign-in, and by default, calls the Node.js web API protected by the fabrikamb2c demo tenant.

In this section, you update the single-page web application to call the Node.js web API protected by your Azure AD B2C tenant (and which you run on your local machine).

To change the settings in the SPA:

  1. In the active-directory-b2c-javascript-msal-singlepageapp project you downloaded or cloned in the previous tutorial, open the apiConfig.js file inside the JavaScriptSPA folder.

  2. Configure the sample with the URI for the demo.read scope you created earlier and the URL of the web API.

    1. In the apiConfig definition, replace the b2cScopes value with the full URI for the demo.read scope (the Scope value you recorded earlier).
    2. Change the domain in the webApi value to the redirect URI you added when you registered the web API application in an earlier step.

    Because the API is accessible at the /hello endpoint, leave /hello in the URI.

    The apiConfig definition should look similar to the following code block, but with your B2C tenant's name in the place of <your-tenant-name>:

    // The current application coordinates were pre-registered in a B2C tenant.
    const apiConfig = {
      b2cScopes: ["https://<your-tenant-name>.onmicrosoft.com/api/demo.read"],
      webApi: "http://localhost:5000/hello" // '/hello' should remain in the URI
    };
    

Run the SPA and web API

You're now ready to test the single-page application's scoped access to the API. Run both the Node.js web API and the sample JavaScript single-page application on your local machine. Then, sign in to the single-page application and select the Call API button to initiate a request to the protected API.

Although both applications are running locally when you follow this tutorial, you've configured them to use Azure AD B2C for secure sign-up/sign-in and to grant access to the protected web API.

Run the Node.js web API

  1. Open a console window and change to the directory containing the Node.js web API sample. For example:

    cd active-directory-b2c-javascript-nodejs-webapi
    
  2. Run the following commands:

    npm install && npm update
    node index.js
    

    The console window displays the port number where the application is hosted.

    Listening on port 5000...
    

Run the single-page app

  1. Open another console window and change to the directory containing the JavaScript SPA sample. For example:

    cd active-directory-b2c-javascript-msal-singlepageapp
    
  2. Run the following commands:

    npm install && npm update
    npm start
    

    The console window displays the port number of where the application is hosted.

    Listening on port 6420...
    
  3. Navigate to http://localhost:6420 in your browser to view the application.

    Single-page application sample app shown in browser

  4. Sign in using the email address and password you used in the previous tutorial. Upon successful login, you should see the User 'Your Username' logged-in message.

  5. Select the Call API button. The SPA obtains an authorization grant from Azure AD B2C, then accesses the protected web API to display the name of the logged-in user:

    Single-page application in browser showing username JSON result returned by API

Next steps

In this tutorial, you:

  • Created a web API application registration in your Azure AD B2C tenant
  • Configured scopes for the web API
  • Granted permissions to the web API
  • Modified a web API code sample to work with your tenant

Now that you've seen an SPA request a resource from a protected web API, gain a deeper understanding of how these application types interact with each other and with Azure AD B2C.