Using Azure AD B2C with Angular 8

Azure Active Directory (Azure AD) B2C is a popular business-to-consumer identity management service from Microsoft that enables you to customize and control how users sign up and sign in to your application.
While there are many examples out there how to use Azure B2C with an ASP.NET Core web application, it’s hard to find examples that performs identity management with Azure AD B2C using an Angular application.

In this article we will create an Angular 8 web application that authenticate against an Azure AD B2C and calls a secured ASP.NET Core-Web-API.

Prerequisites

Configure Azure AD B2C

For our example we need to create two applications. The first one will represent our middleware (ASP.NET Core-Web-API). The second one represents our web app (Angular).

Register the middleware application

To register the middleware application, go to the Application blade within your Azure AD B2C and click on Add:

add-b2c-app

Enter a name that describes your middleware and turn the Include web app / web API switch to YES. We don’t need the Reply URL for our middleware since we will obtain the token with an angular application. However, we have to enter any valid URI here (I choosed https://localhost). Finally we need to specify the APP ID URI that we will use later to grant the web app access to the middleware:

b2c-middleware-app

Register the web application

Now we have to register the web application. Again, enter a name that describes your web application and turn the Include web app / web API switch to YES. This time we do care about the reply URL. For local testing purpose we can enter http://localhost:4200/index.html here. We don’t need to specify an App ID URI. This is how the configuration should look like:

b2c-web-app

Grant API access

Since the web application needs to communicate with the secured middleware, we will also have to grant the web application access to the API.

Go back to your Azure B2C web application registration and inside the API access blade, click on the Add button. On the new dialog select your previous created middleware application and click on the Ok button (leave the scopes as they are):

API access

Create a sign up and sign in user flow

The last thing we have to configure inside the Azure AD B2C is the user flow. Learn more about user flow types.

Open the User flows (policies) blade and click on the New user flow button. In the following view click on Sign up and sign in.

Enter susi in the Name input and select Email signup for the Identity provider. Leave Multifactor authentication disabled and check both checkboxes for the given name claim:

createsusi

Create and secure the middleware

We will scaffold our ASP.NET Core Web API middleware using the .NET Core CLI. The command we are looking for is dotnet new.

Using the following parameters, we can create the middleware with preconfigured Azure AD B2C authentication:

  • –auth IndividualB2C (Individual authentication with Azure AD B2C)
  • –aad-b2c-instance The Azure Active Directory B2C instance to connect to
  • –susi-policy-id The sign-in and sign-up policy ID for the middleware we have created earlier
  • –client-id The Application ID of the middleware
  • –domain The domain for the directory tenant
  • –name The name for the middleware

Here an example with the values for my setup:

dotnet new webapi `
--auth IndividualB2C `
--aad-b2c-instance https://aboutazure.b2clogin.com/ `
--susi-policy-id B2C_1_susi `
--client-id 1d1cfeca-1fb2-4bf8-9d6b-4d5ac15ad7b3 `
--domain aboutazure.onmicrosoft.com `
--name foo.api

Before we run the application, lets change the ValuesController.cs to return “Hello World”:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace foo.api.Controllers
{
    [Authorize]
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        // GET api/values
        [HttpGet]
        public IActionResult GetAsync() => Ok("Hello, World!");
    }
}

We can now start the application using the dotnet run command. Our site will be available at http://localhost:5000.
If we perform a GET request on https://localhost:5001/api/values, we will get a 401 UNAUTHORIZED error – as expected since we are not passing an access token:

invalid-token

Create the web application

To create the Angular web application, we can use the ng new command from the Angular CLI. The name of our app will be foo.web. I also added some additional parameters to scaffold a minimal project without any testing frameworks and without routing:

ng new foo.web --minimal=true --skipGit=true --routing=false --style=css

Now it is time to choose a library that supports OpenID Connect (OIDC) authentication. For this demo project, we will use the angular-oauth2-oidc npm module from Manfred Steyer. It is OpendID certified and has lot of handy features like automatically adding the access token to certain URLs when calling a Web API.

You can install the module using npm:

npm i angular-oauth2-oidc --save

Then we need to import the module inside the app.module.ts. I also configured the module to include the access token in the request when calling our Web API:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { OAuthModule } from 'angular-oauth2-oidc';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    OAuthModule.forRoot({
      resourceServer: {
          allowedUrls: ['https://localhost:5001/api'],
          sendAccessToken: true
      }
    })
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

To configure the library, we need to create a class that implements AuthConfig. We will do this in a new file called auth.config.ts:

import { AuthConfig } from 'angular-oauth2-oidc';

export const DiscoveryDocumentConfig = {
  url : "https://aboutazure.b2clogin.com/aboutazure.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=b2c_1_susi"
}

export const authConfig: AuthConfig = {
  redirectUri: window.location.origin + '/index.html',
  responseType: 'token id_token',
  issuer: 'https://aboutazure.b2clogin.com/b88448e7-64f3-497b-a7aa-73ae0cc6e9ce/v2.0/',
  strictDiscoveryDocumentValidation: false,
  tokenEndpoint: 'https://aboutazure.b2clogin.com/aboutazure.onmicrosoft.com/oauth2/v2.0/token?p=b2c_1_susi',
  loginUrl: 'https://aboutazure.b2clogin.com/aboutazure.onmicrosoft.com/oauth2/v2.0/token?p=b2c_1_susi',
  clientId: '0c295dee-8904-4546-92b7-dc64dd14bf58',
  scope: 'openid profile https://aboutazure.onmicrosoft.com/foo-api/user_impersonation',
  skipIssuerCheck: true,
  clearHashAfterLogin: true,
  oidc: true,
}

We can get most of the values from the discovery document which is always located under:
https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/v2.0/.well-known/openid-configuration?p={policy}.

Here is how the values are mapped:
discoverytoauth.png

The clientId is the Application Id of our foo.web Azure AD application. The scope for our API can be found under Published scopes inside the Azure AD foo.api application:
publishedscopes

Finally, to test the application, I modified the app.component.ts to list the claims for a logged in user and added a button to invoke our secured API and to Sign out.

Test the sign up and sign in

Now its time to test our application. This is how our web app looks like when we browse it:
initial.png

If we click on the Login button, we get redirected to our b2c_1_susi Azure AD B2C flow:

b2cflow.png

I already created an account. This is how the site looks like after I signed in with that account:

martin.png

We can now invoke our secured foo.api service using the API Call button. We will see the response at the end of the page:

hello.png

I published the whole source code in my GitHub repository. I also deployed both the web application and the API on Azure. You can test it live here.
Please note, that you inital have to create an account using the “Sign up now” link after you clicked on the Login button.

2 thoughts on “Using Azure AD B2C with Angular 8”

  1. This is a great article, thanks a lot.
    question.
    – when you call the api, I don’t see a bearer token is explicitly added to html header. and the secured api call is still successful, what is the magic?

    thanks.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s