Azure AAD B2C integration with Web and Mobile platforms


Recently, as part of re-architecting a suite of applications to Azure, we migrated Web and Mobile applications to Azure AAD B2C for the purpose of user registration and authentication. This migration included various tech stacks like ASP.NET Webforms, APIs and MVC for web applications and native mobile applications built on iOS, Android, UWP platforms. We wanted to use social IDPs like Google, Facebook and Microsoft login along with local AAD accounts.

This post isn’t to take you through how to integrate Azure AAD B2C with different stacks. The official documentation does good justice on that front. This post is focused on some the architectural decisions and solutions to challenges you may face while integrating B2C with different stacks.

 

Why Azure AAD B2C?

Azure AAD B2C simplifies registration and login process through social accounts like Facebook, Google or Microsoft or traditional username/password. It is highly scalable identity management service for consumer facing applications that provides an easy integration with applications using OAuth APIs and allows branding customization for sign-up and sign-in pages. Based on the configuration done in Azure AAD B2C tenant, the application can get user information in tokens without implementing user registration and login process. This reduces the identity management overload on the application built on any platform.

With this mind, Azure AAD B2C service was chosen as the right fit for both registration and login process. You can learn more about at Azure AAD B2C

 

Web Stack Integration

Integration with ASP.NET MVC or WebAPI stack is really easy. You can add Microsoft’s Open Web Interface for .NET (OWIN) middleware NuGet packages in the bootstrap process. Your web app communicates with Azure AD B2C by sending authentication messages that specify the policy they want to execute as part of the HTTP request. In case of WebAPI, your API can accept and validate bearer tokens by using OWIN library as middleware.

Bearer Token in HTTP Handlers

If your API layer is behind a façade of HTTP Handlers (legacy), you are entrusted with an additional task to validate the bearer token in your HTTP Handler. This becomes a bit tricky because you are trying to implement something similar to what has been implemented in OpenIdConnectAuthenticationHandler in OWIN. If feasible, consider migrating to standard WebAPI implementation using OWIN middleware – that would make things easier to implement, manage and upgrade. If, however, you choose to implement a custom validation process, you’ll have to follow the process outlined below.

Every Azure AAD B2C tenant has a OpenID configuration endpoint that looks like,

https://login.microsoftonline.com/myownb2ctenant.onmicrosoft.com/discovery/v2.0/keys?p=b2c_1_signin

This OpenID configuration endpoint provides vital information like discovery endpoint, valid audience, issuer, configured claims, refresh token, etc. This OpenID configuration can be used in custom JWT Security Token Handler (derived from class JwtSecurityTokenHandler) to validate issuers, audience and keys.

// Get tenant information that's used to validate incoming jwt tokens
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint);

// Get Config from AAD:
var config = await configManager.GetConfigurationAsync();
var validationParameters = new TokenValidationParameters
{
    ValidAudience = validAudience,
    ValidIssuer = config.Issuer,
    IssuerSigningTokens = config.SigningTokens,
    CertificateValidator = System.IdentityModel.Selectors.X509CertificateValidator.None,
};

Based on the level of security you would like to have, you can override the ValidateToken method. I would recommend implementing IssuerSigningKeyValidator, SignatureValidator and AudienceValidator if you choose to adopt a Custom JWT Security Token Handler. You can also have a look at OpenIdConnectAuthenticationHandler in OWIN for reference implementation.

 

Mobile Stack Integration

Azure AAD B2C has excellent integration with native iOS, UWP and Android stacks and also with Xamarin. The integration code has been very well documented on Azure Samples website. With the sample code on GitHub, you’ll be able to quickly integrate Azure AAD B2C with your line of business app.

Universal Windows Platform and Custom UI

If you are not using the standard B2C branding for sign-in and sign-up pages, i.e. you have modified Page UI customization to have your own branding, you may have to be careful when you integrate MSAL (currently in alpha release) with UWP application.
b2c-customized-policy
When you select a custom UI instead of default UI, Azure AAD B2C appends additional information to the token after the authentication is completed. The length of redirect URL that has the token may exceed 2082 characters. When the length of token is lesser than 2082 characters, WebAuthenticationBroker (inside UWP) redirects back to the application. When the length of token exceeds 2082 characters, WebAuthenticationBroker throws an exception “the specified protocol is unknown” error and on the UI an error is displayed “We can’t connect to the service you need right now. Check your network connection or try this again later”
b2c-claims

The easy (yet undiscoverable) fix to this is to reduce the number of claims you have configured in the B2C tenant and retrieve the required information using Graph API. If possible, you can keep bare minimum 2-3 claims and test your UWP application with custom UI. Based on my experience, you can select Object Id, Is New and Email Address as 3 claims and retrieve the other claims from Graph API. Graph API will require you to first register a service account as directed in this post.

The Graph API provides us rich information about the user. For local accounts, Graph API does not necessarily provide Email Address so it is essential that you capture Email Address in the claims if email address is mandatory requirement in your application. A sample response from Graph API looks like,
{
  "odata.metadata": "https://graph.windows.net/myownb2ctenant.onmicrosoft.com/$metadata#directoryObjects/Microsoft.DirectoryServices.User/@Element",
  "odata.type": "Microsoft.DirectoryServices.User",
  "objectType": "User",
  "objectId": "57d0cb6a-5fce-497e-8967-7f4f23960992",
  "deletionTimestamp": null,
  "accountEnabled": false,
  "signInNames": [],
  "assignedLicenses": [],
  "assignedPlans": [],
  "city": null,
  "companyName": null,
  "country": null,
  "creationType": null,
  "department": null,
  "dirSyncEnabled": null,
  "displayName": "Your Display Name",
  "facsimileTelephoneNumber": null,
  "givenName": "Given Name",
  "immutableId": null,
  "isCompromised": null,
  "jobTitle": null,
  "lastDirSyncTime": null,
  "mail": null,
  "mailNickname": "unknown",
  "mobile": null,
  "onPremisesSecurityIdentifier": null,
  "otherMails": [ "registeredemailaddress@hostname.com" ],
  "passwordPolicies": "DisablePasswordExpiration",
  "passwordProfile": {
    "password": null,
    "forceChangePasswordNextLogin": true,
    "enforceChangePasswordPolicy": false
  },
  "physicalDeliveryOfficeName": null,
  "postalCode": null,
  "preferredLanguage": null,
  "provisionedPlans": [],
  "provisioningErrors": [],
  "proxyAddresses": [],
  "refreshTokensValidFromDateTime": "2016-11-21T09:21:44Z",
  "showInAddressList": null,
  "sipProxyAddress": null,
  "state": null,
  "streetAddress": null,
  "surname": "Your Last Name",
  "telephoneNumber": null,
  "usageLocation": null,
  "userPrincipalName": "cpim_825fbf28-bdfe-4ab4-84f2-acfb79b279c6@myownb2ctenant.onmicrosoft.com",
  "userType": "Member"
}

This strategy can not only be applied to UWP applications but can also be applied to other platforms to create a Principal object by collating the data retrieved from B2C Claims and Graph API.

If you have any other observations that must be added to this article, please post it as comment.

UPDATE: March 2017: Please note change for Google and MSAL
https://azure.microsoft.com/en-us/blog/azure-ad-b2c-google-signin-issue/

UPDATE: May 2017: Please note new MSAL version for Windows Store, UWP, NetCore, Xamarin Android and iOS is available at:
https://github.com/AzureAD/microsoft-authentication-library-for-dotnet

 

Happy coding!
Comments (0)

Skip to main content