Secure an Aurelia Single Page App with Azure Active Directory B2C / MSAL

If you create a modern web application with an API / REST backend and a Single Page Application (SPA) as your frontend, that you want to run in the internet, you definitely don’t want to handle security / user management on your own. You will want to use a service like Auth0 or Azure Active Directory to handle authentication and/or authorization.

In this example, we will develop a basic Aurelia frontend application, that will be secured via Microsoft Authentication Library (MSAL) for JavaScript backed by a custom Azure Active Directory (B2C). The B2C directory is the identity store where users of our application will be stored. The Aurelia app will login to the B2C directory via MSAL and use an ID token provided after a successful login to call the web API (authorization token in the request header).

23

Implicit Flow

Let’s start by creating the directory…

Create a B2C Directory

The creation of an Azure Active Directory is quite simple. Log in to your Azure account and select “New”. Search for “Azure Active Directory B2C” and select “Create” –> “Create a new Azure AD B2C Tenant”. Enter your desired organization and domain name and select the country/region you want the directory to be located. In my example, the configuration looks like that:

2

After the tenant is created, we have to add an application that can access the directory. Therefore, go to the newly created B2C directory and select “Applications” in the settings blade. Click “Add” and enter a name for the application. Also, be sure to select “Include web app / web API”, because we want to use the “implicit flow” as shown in the intro section above. In the reply URL enter “http://localhost:9000“, because this is the URL our Aurelia app will be running on. After a successful login, Azure AD will redirect the browser to that given URL.

4

B2C Application Settings

Note down the Application ID and the domain name (https://{yourtenantname}.onmicrosoft.com – in my case https://aureliab2c.onmicrosoft.com), as we will need the values when we configure the authentication of our Web API.

Next, to give users the ability to register for the application, you have to create a policy within the directory that allows users to create an account. You also need a policy to sign in and – if you want to – a policy to reset the password for a user.

In this example, we will only use “local accounts” (login with username and password). You can also add further identity providers like Google or Facebook to add social login capabilities to your application. To keep it simple, we only support local accounts at the moment.

Fortunately, we can create a policy that allows users to add an account and configure the login process in one single configuration. It’s called “Sign-up or sign-in policy”.

Click on the corresponding entry in the configuration blade and add a new one.

Next, you have to enter information about the identity provider to use (in our case “Local Account”, the signup attributes (fields a user can enter during signup like “Given Name” and “Surname”) and application claims (information that will be sent with the identity token after login). In our application, the configuration is as follows:

5

Identity Provider

6

Signup Attributes

7

Application Claims

Of course, you can adjust a lot more settings, but for our case, this is enough in the first place.

After you have created the policy, you can test it by clicking on the “Run Now” button and create a user for yourself.

19

Login Page / B2C

20

Signup Page

As a last step, note down the name of the policy you have just created – in our case: B2C_1_signupin. We need it later on…

Our directory is now ready to go, so let’s head over to the API…

Create REST API

The REST API we want to develop is based on ASP.NET Core 2.0 and will be secured by the Azure AD we just created. To achieve this in a very convenient way, you can enter the connection to the Azure AD during project setup.

In Visual Studio, open “File –> New — Project” and select “ASP.NET Core Web Application” and in the following wizard, select “Web API”.

Create Web API

Create Web API

To enter the B2C data you noted down in the last steps, click on the “Change Authentication” button, select “Individual User Accounts” and enter the following details:

  • the domain name of your B2C tenant
  • the application ID that corresponds to the API
  • the policy to use
11

Auth Configuration

The wizard adds settings to you appsettings.json file and configures you startup class to use the B2C information you just entered.

While we want to focus on the authentication process and securing the backend, the API will only provide one controller that can be called on the path “people“. The GET request on that path will return a list of characters (from StarWars 😉 – well, just sample data). As the controller is annotated with the Authorize attribute, requests will only be successful, if the caller adds the Authorization header with a valid ID / Bearer token. The token will be provided by the AAD B2C directory after a successful login. More one that later when we implement the Aurelia app.

So, as I said…if you want to call the people controller without a valid token, you will receive a 401 status code (Unauthorized) – the way we want it. To test that behavior, we can use Postman.

13

401 Unauthorized / Call API without a Bearer Token

The backend is now secured by the Azure B2C directory…so let’s add the frontend.

Create the Aurelia SPA

Before we can start developing the frontend application with Aurelia, we have to install the command line interface (CLI). To do this, open a command prompt an enter the following command:

npm install -g aurelia-cli@latest

This command will install the Aurelia CLI globally on your machine. After the command returns, we can create a new Aurelia application via

au new frontend

The command (btw. frontend is the name of our application) will start a wizard where you can select different options, e.g. if you want to use plain JavaScript or TypeScript.

15

Start the wizard

16

Select Options

We will use TypeScript for our application.

After you have entered all the necessary information, you can finish the wizard and install the dependencies (you will be ask by the wizard) afterwards.

The result will be an Aurelia application with minimal dependencies, built with TypeScript. You can test the application by running…

au run --watch

and opening the browser, pointing to http://localhost:9000.

To be able to call the API, request an ID token at the B2C directory and display the results from the people controller, we need a few more dependencies.

First, we need the current version of the MSAL JS library, which is – at the time of writing – still in preview for JavaScript. You can install it via NPM, but the current version available (0.11) has a few bugs. Therefore, we will take the current dev version directly from the GitHub repository 🙂

You can download the version from https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/out/msal.js and save it in a “lib” folder in the root directory of the Aurelia app.

Next, we need the Aurelia fetch library and jwt_decode (to decode the ID token we receive after login from the B2C directory). Install both dependencies via

npm install aurelia-fetch-client@latest jwt_decode@latest --save

Because we are “compiling” the application via the Aurelia CLI, we also need to add these additional libraries to the aurelia.json file located in the “aurelia_project” folder. Insert entries for the MSAL lib (line 4), aurelia-fetch-client (line 12) and jwt_decode (starting line 47) in the dependencies section of the JSON file.

Now we are ready to implement the application. As we want to focus on the authentication process, I will concentrate on the pieces that are important for our case.

  1. Create a settings file, where we can access the B2C settings during runtime.
  2. Add a class (in auth.ts file) that is responsible for handling the authentication process
    1. Check, if user is already authenticated
    2. Get the current ID / JWT token
    3. Login via B2C directory
    4. Logout
  3. Add a class (HttpConfig) that will configure the Aurelia HttpClient class to intercept each request and insert the Authentication header (Bearer token)

The Auth class is the “main actor” in our frontend example. It uses the MSAL class UserAgentApplication to login & logout…as well as getting the ID token after a successful login attempt.

As we want to secure the complete frontend application and not only a few path/routes, we use the Auth class in the bootstrapping process of the Aurelia app – in the main.ts file.

As you can see, after loading the Aurelia framework, we check if the user is already logged in (by calling isAuthenticated on the auth object). If the promise is rejected (user is not logged in), we redirect to the AAD login page by invoking auth.login. After entering the username and password and submitting the form, we will be redirected with an ID token as URL parameter (id_token) to our app. The MSAL library picks up the id_token and handles expiration checking and storing all the necessary data for us. If everything is ok, the next call to isAuthenticated will successfully resolve and the app loads the main class App (in app.ts). While loading the view and view-model, a call to the web API is invoked (in method activate, line 4 – one of the lifecycle methods of an Aurelia view. activate is called before the view is visible/attached to the DOM).

In the .NET Core application, the request headers are checked for a valid Bearer token. If the token provided is valid, the call is routed to the people controller and the results are sent to the Aurelia app, which in turn displays the list of…StarWars characters 🙂

To see the contents of the ID token in the frontend, we decode the token in the App class (see above) and display the results (given name, surname, email and token expiration date) in a message box.

22

Final Application

If the Logout button in the top menu is clicked, auth.logout is called, the MSAL library clears stored data about the ID token and endpoints and redirects to http://localhost:9000/#.

Wrap Up

As you have seen, it is possible to secure a REST API and a corresponding Single Page Application – in our case an Aurelia app – with Azure Active Direct B2C. Of course, the app is far away from “production-ready”, but it is a good example to get an impression of how you can integrate an OpenID Connect flow in your own application and secure a SPA in a very simple way.

You can find the complete sample on GitHub: https://github.com/cdennig/azure-b2c-aurelia-example

Have fun with it…

Cheers!

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s

%d bloggers like this: