Azure Active Directory B2C: Build an ASP.NET Core MVC web API


Hello everyone,

[Update]: I shared a sample solution on GitHub: https://github.com/helgemahrt/aspnetcore-api-with-b2c

 
The Azure Active Directory B2C documentation features a list of awesome quick-start guides for different scenarios: https://docs.microsoft.com/en-us/azure/active-directory-b2c/
Unfortunately, there are only guides for good old .NET - but none about .NET Core yet (at least not at the time of writing). If you search the internet for B2C and aspnetcore, you'll find plenty of articles covering ASP.NET Core web apps (basically the equivalent to this guide: https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-devquickstarts-web-dotnet) but only very little on ASP.NET Core web APIs.

 
I spent a lot of time in the past couple of days trying to find the right combination of libraries and settings to make the OAuth Bearer authentication against B2C work in an ASP.NET Core web API. To save you that effort, here are the equivalents to the classic ASP.NET web API quick start guide, https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-devquickstarts-api-dotnet. Once you know what you have to do, it's actually pretty straight-forward. πŸ™‚

 
The only library you'll need is the following:

    "Microsoft.AspNetCore.Authentication.JwtBearer": "1.0.0",

 
In your Startup.cs, add the following lines to your Configure function:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    ...

    app.UseJwtBearerAuthentication(new JwtBearerOptions()
    {
        MetadataAddress = string.Format(AadInstance, Tenant, Policy),
        Audience = ClientId,
    });

    ...
}

 
In my case, I only added my B2C SignIn policy and it worked like a charm. I hope this saved you a headache searching for the right way to set this up.

Cheers,
Helge Mahrt

Comments (13)

  1. Thanks for this – worked well for me – one question – what OAuth flow are you working with? I’ve tried to get Hybrid flow working but can only seem to get the id flow (OpenIdConnectResponseType.IdToken) – I don’t get a code token back from B2C (only an IdToken) when I try to use Hybrid flow (OpenIdConnectResponseType.CodeIdToken).

    1. Helge Mahrt says:

      I’m glad to hear that! πŸ™‚
      Well, I’m working with a mobile client. As the API doesn’t have an UI itself, all I want it to do is to validate the access tokens against B2C, which is why I only added the SignIn policy.
      I haven’t implemented the mobile client yet. For now – for testing purposes – I created a simple tool to generate tokens using the Microsoft Authentication Library, which takes care of everything. (https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-devquickstarts-native-dotnet)

  2. bill says:

    Thanks for your help.

    I guess the trick will be to add handlers for a web MVC that redirects to a login page and returning a 401 for native clients when authentication fails. Know anyone that’s done that?

    1. whnoel says:

      OK, there is a way to do this, but it became complicated. I just separated my MVC from my API into two different sites, and this solution worked like a charm. Do you know how (in Asp.Net Core) to access the incoming token in the MVC site so it can be sent along as a bearer token to the API site? I’ve got it all working except that. I’ve seen examples on BootstrapContext, but none of them actually work in Asp.Net Core as the BootstrapContext is always null (despite setting the SaveSigninToken flag).

      1. Helge Mahrt says:

        After setting SaveSignInToken to true, I was able to get to the token like this:

        (HttpContext.User.Identity as System.Security.Claims.ClaimsIdentity).BootstrapContext as string;
        

        Does this work for you?

        1. Frank Chen says:

          When I check the value of BootstrapContext from User.Identity, it always showed null. It doesn’t matter if you set SaveToken=true inside your JwtBearerOptions setting. I also found out http://www.cloudidentity.com/blog/2012/11/30/using-the-bootstrapcontext-property-in-net-4-5-2/ which talked to change in your web.config file. However, since we are talking about ASP.Net Core, system.identityModel doesn’t work in web.config file. do you have other suggestion I can try? thanks

          1. Helge Mahrt says:

            IIRC, what you need to do is set the SaveSigninToken to true on the TokenValidationParameters, not set the SaveToken to true. (Just create a new object and set only that value) They sound similar but are not the same πŸ™‚

  3. Wouter says:

    Hi Helge, do you mind providing your full boilerplate code? Spent 4+ hours trying to make it work without any luck πŸ™

    1. Wouter says:

      (I started off with the Web API with Work or School accounts template in VS, and used the code for Configure you referenced above. I looked through the sample at devquickstarts but in the end i’m stuck without a tokenvalidator)

    2. Helge Mahrt says:

      I shared a minimal sample solution here: https://github.com/helgemahrt/aspnetcore-api-with-b2c πŸ™‚ Just fill in your B2C values and it should work.

      1. Wouter says:

        Thanks! Works like a charm!!

        1. Helge Mahrt says:

          Glad to hear that! πŸ™‚

  4. PG says:

    Thanks, worked perfectly fine, saved my hours!

Skip to main content