Free Customer Identity Access Management with Azure AD B2C
Published: 2021-10-08 16:43:20

---
title: Free Customer Identity Access Management with Azure AD B2C
published: true
description: This article describes how to configure Azure AD B2C to manage identities and access to an application. Thanks to [AAD B2C](https://docs.microsoft.com/en-us/azure/active-directory-b2c/overview) you can allow users to sign-up/sign-in to your application and leverage capabilities like SSO, MFA and email verification without a single line of code. You can also modify users flow to add customized steps on sign-up.
tags: 
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9i7pasynxxi42a0xeoz2.jpg
---
*Image by <a href="https://pixabay.com/fr/users/thedigitalway-3008341/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=1590455">TheDigitalWay</a> from <a href="https://pixabay.com/fr/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=1590455">Pixabay</a>*

This article describes how to configure Azure AD B2C to manage identities and access to an application. Thanks to [AAD B2C](https://docs.microsoft.com/en-us/azure/active-directory-b2c/overview) you can allow users to sign-up/sign-in to your application and leverage capabilities like SSO, MFA and email verification without a single line of code. You can also modify users flow to add customized steps on self-service customer registration.

## What is a Customer Identity Access Management solution ?

According to [Wikipedia](https://en.wikipedia.org/wiki/Customer_identity_access_management), a CIAM is

> a subset of the larger concept of identity access management (IAM) and is focused specifically on managing the identities of customers who need access to corporate websites, web portals and webshops. Instead of managing user accounts in every instance of a software application of a company, the identity is managed in a CIAM component, making reuse of the identity possible. The biggest differentiator between CIAM and regular (internal) IAM is that in CIAM the consumers of the service manage their own accounts and profile data.

Main advantages of using a CIAM are:

* No need to create and maintain an custom identity server
* Customers repository reuse accross multiple applications
* Advanced scenarios like MFA, SSO
* Last standard compliance in terms of security
* Compatibility with many identity providers (Azure AD, Facebook, ...)
* User monitoring to detect fraudulent access
* [GDPR](https://en.wikipedia.org/wiki/General_Data_Protection_Regulation) compliance

## Create an Azure Active Directory B2C tenant

The first step is to create a new tenant in which we'll register our application. If you don't have an Azure subscription yet, you can create a new one for free. Simply follow steps from [this tutorial](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-tenant). Following a little summary:

Don't forget to make sure *Microsoft.AzureActiveDirectory* is registered as a resource provider in your subscription before creating the resource.

![Microsoft.AzureActiveDirectory subscription screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xvxrm2gq6qbjffra71no.png)

Then go to the home page, click on "Create a resource", find "Azure Active Directory B2C", click on "Create" and "Create a new Azure AD B2C Tenant". Fill the fields and click on "Create".

![Create Azure Active Directory B2C screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/476pxsio7t4620prfl0q.png) 
 
> Once you clicked on the final "create" button, go grab a ☕ because it will take a while ;-)

> It would appear quite weird but it seems that the tenant creation is synchronous. So after clicking on "Create", do not leave the page until the creation is finished. Otherwise the creation will be cancelled.

![Create tenant event screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/88qrg4ztdy0swrtibq43.png)
 
## Register a web application

Next we need to register a web application. The registration process will generate an application ID (also known as "client ID") that'll use to uniquely identify our application. 

Follow [these steps](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-register-applications?tabs=app-reg-ga#register-a-web-application) to register a web application. During the process you will create a client secret. Keep it somewhere because we'll need it later.

> Client secrets are useful during the development phase or for server-to-server communication when the server storing the secret is in a trusted private place. Please do not store client secrets on the client side (users computer, smartphone, etc.). If you do so, the secret would be exposed and from then should be considered public.

## Create user flows and custom policies in Azure Active Directory B2C

Now we will create a user flow to enables a user to sign up and sign in with Facebook. To do this, I'm going to follow [this tutorial](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-custom-policy) from Microsoft. The first thing to do is to choose between a standard user flow and a custom policy. With a standard policy you can select a predefined flow. With The custom policy you can go further and personalize the flow as you wish. Let's choose the second option and follow the instructions.

![custom policy button screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bg6l4ma7su8va084f50c.png)

At the time I'm writing this article, there is a certificate issue on www.contoso.com. The certificate is registered for *.oneroute.microsoft.com so it is considered invalid. Since Facebook check the certificate validity of the user data deletion URL, it is not possible to use the URL provided in the tutorial.

![invalid url screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/92rorp8u2fpo1rsb21o3.png)

![invalid certificate screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tpmumacnkmv5wkedwmb2.png)

I didn't found any useful information concerning this issue on the web, so I created a new issue on [azure-docs repo](https://github.com/MicrosoftDocs/azure-docs/issues/81763). I hope they will transmit the information to the team in charge of maintaining contoso.com

You can use any valid https URL instead, it doesn't matter for purpose of this tutorial because that URL is only here for legal reasons. For instance you could use `https://httpbin.org/`. 

### Tip: setup XML validation in VSCode

At one point of the tutorial, we have to get the custom policy starter pack and modify some XML files in it. In order to prevent dumb errors like typos, we could check the validity of the XML according to the corresponding schema (XSD file). It can be done automatically in VSCode IDE.

Install the [XML extension from Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-xml)

Open command palette (CTRL+SHIFT+P) and search "Open Settings (JSON)".

![open settings menu screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/701u3d8tp2eqn2z67xf4.png)
 
In the *settings.json* file opened, add the following sections:

```json
"xml.symbols.showReferencedGrammars": true,
"xml.fileAssociations": [
{
    "pattern": "TrustFrameworkExtensions.xml",
    "systemId": "TrustFrameworkPolicy_0.3.0.0.xsd"
}
```

Now if you make a typo, VSCode will tell it to you:

![Oops screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bkopda9o87v4awhziekf.png) 

## Play with policies

Once you finished the tutorial, you should be able to sign-up using an (email, password) or using Facebook. It is now time to play with policies to see what we can get out of it.

Personaly I'm interested in user migration from a legacy system. After some research over the web I found a very interesting github repository containing dozens of [Azure AD B2C samples](https://github.com/azure-ad-b2c/samples). And in the list the one I'm interested in: [User migration](https://github.com/azure-ad-b2c/user-migration). 

Clone the above repository on your computer. To deploy and run this sample we'll need 2 things:

1) An Azure Blob Storage account.
2) A docker image to host the application on Azure. Because the sample is under aspnetcore 2.0.

If you don't have an Azure account yet, your can [create one for free and get 200 USD of Azure credits](https://azure.microsoft.com/en-us/free).

### Create a storage account

Connect to your Azure account and create a new storage account. Go to "Access keys" menu, click on "Show keys" and copy one of the connection strings.

![Azure storage account access keys](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1u9ctzxa1pxhnrnmprtp.png)

Open *appsettings.json* and paste the connection string in the appropriate AppSettings:

```json
"AppSettings": {
    "BlobStorageConnectionString": "<Your connection string to Azure Table that stores your identities to be migrated>"

  }
```

### Create a docker image to publish the sample to Azure

The sample application won't work if you publish it as-is to an Azure Web App because the minimum runtime version is aspnetcore 3.1 and the sample targets 2.0. Hopefully there is Docker to the rescue.

Open the sample in Visual Studio 2019, right-click on the project name in solution explorer and click on "Add docker support". Visual Studio then scaffold a Dockerfile for your project, but there is a little issue. You should see this error message when building the image:

```
ERROR: pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
```

This is because the aspnetcore images have been renamed, so the names of the "base" and "build" image are wrong in *Dockerfile*. Open *Dockerfile* and replace `microsoft/aspnetcore:2.0` with `mcr.microsoft.com/dotnet/core/aspnet:2.2` and `microsoft/aspnetcore-build:2.0` with `mcr.microsoft.com/dotnet/core/sdk:2.2`

Now the image should build normally. If not, check you run the `docker build` command in the parent folder of the *.csproj* file. For instance:

```bash
~/user-migration/jit-migration-v2/source-code $ docker build -f "AADB2C.JITUserMigration/Dockerfile" .
```

Right-click on the project in solution explorer and select "Publish...". 

Create a new profile targetting Azure App Service Container.

Create a new webapp and a new registry container.

Then click "Publish" and after a few minutes your application is online.

You can now populate the fake database by calling `api/test/PopulateMigrationTable` on you freshly published API. The endpoint respond with 200 OK and a JSON body content containing the list of users with passwords.

### Modify and publish the custom policy

As stated in the sample instructions: 

> Open the policies files, change the tenant name, client_id and IdTokenAudience for Local Account sign-in, and upload the policies to Azure portal.

There is a little omission here: we also need to modify the URL to the REST API in order to use the webapp we just published instead of the default one.

Open "TrustFrameworkExtensions.xml" and replace `http://aadb2cjitusermigrationv2.azurewebsites.net` with the URL of your webapp. You can find the URL on the *Overview* page of your *App Service* on [the Azure portal](portal.azure.com).

You also have to remove the Google provider from "TrustFrameworkBase.xml" because we do not have registered a Google App, we only have registered a Facebook App.

Switch to your AAD B2C account, go to "Identity Experience Framework" and delete the custom policies we created earlier. Then upload the new ones. The order in which you add them matters because some files depends on the others. So add them in [this](https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-custom-policy#upload-the-policies) order.

### Test the sign-up/sign-in policy

Select "B2C_1A_JITMIGRAION_SIGNUP_SIGNIN" and click on "Execute now". Enter one of the email address contained in the Azure Table, for instance `jeff@contoso.com`. Enter the associated password (1234 by default). Then click on "Sign-in".

Our REST API is called to validate the user identity and if it is OK the user is migrated to AAD B2C

![migrated user](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0lh0g4nzyg8gxfjgqi3g.png)

and removed from Azure Table.

![no more jeff](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/noie2iet85krx1aiod6w.png)

## Request for additional information on sign-up screen

It is not possible to request for additional information on the sign-in screen because SSO requires only 2 informations:

* A user unique ID (can be a unique user name, an email or a phone number)
* A password

But it is possible to request for additional information during the sign-up process. Imagine you want to add a nickname on the sign-up page. First we have to declare a new claim. Open *SocialAndLocalAccounts/TrustFrameworkExtensions.xml* and add the following declaration in `BuildingBlocks/ClaimsSchema`:

```xml
<ClaimType Id="nickname">
  <DisplayName>Your nickname</DisplayName>
  <DataType>string</DataType>
  <UserInputType>TextBox</UserInputType>
</ClaimType>
```

In the same file, find the *LocalAccountSignUpWithLogonEmail* technical profile and add the following *OutputClaim*:

```xml
<OutputClaim ClaimTypeReferenceId="nickname"/>
```

If you want to include the nickname in the token's claims, open *SocialAndLocalAccounts/SignUpOrSignIn.xml* and add the following output claim:

```xml
<OutputClaim ClaimTypeReferenceId="nickname" />
```

Upload the 2 modified policies in IEF and execute the sign-in/sign-up policy. Click on "sign-up" button. You should see a new field "nickname". Fill the fields and create a new account. Once the local account created, you should see the nickname in the returned token claims:

![decoded token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aia8xjiskbsab9pfj8yg.png)
 
Problem: if you re-execute the sign-in/sign-up policy and now sign-in using your new account, the nickname is not present anymore in the token's claims because it has not been persisted. The question is: how can I make the nickname persistent so it would be added automatically on each sign-in?

You have 2 solutions to handle this:

* Store the nickname on you own during sign-up and [enrich tokens with claims from external sources using API connectors](https://docs.microsoft.com/en-us/azure/active-directory-b2c/add-api-connector-token-enrichment?pivots=b2c-custom-policy) during sign-in.
* [Define custom attributes in Azure Active Directory B2C](https://docs.microsoft.com/en-us/azure/active-directory-b2c/user-flow-custom-attributes?pivots=b2c-custom-policy) and let AAD B2C store the custom attribute for you.

Just follow the steps described in one of the above article, sign-up a new user, then sign-in and now you should see the nickname in the claims.
 
## Conclusion

AAD B2C is a comprehensive CIAM solution and can allow you to save a lot of time by avoiding you to implement your own identity and SSO provider. Thanks to this, you can focus on your business and deliver more functionalities to your customers while still offering a premium authentication experience.

I am discovering AAD B2C and wrote this article at the same time I was learning about it. I found they were some omission or imprecision in the official documentation. Moreover, the documentation is very intimidating because it is huge. So I thought it could be useful for someone to have a summary of a few AAD B2C features with tips to avoid pitfalls. I barely scratched the surface of what it has to offer and have yet many things to learn. Maybe It'll be worth it to write a second article on this subject when I'll be more experimented on it.