services | platforms | author |
---|---|---|
active-directory-b2c |
dotnet |
dstrockis |
This sample shows how to build a web API with Azure AD B2C using the ASP.Net Core JWT Bearer middleware. It assumes you have some familiarity with Azure AD B2C. If you'd like to learn all that B2C has to offer, start with our documentation at aka.ms/aadb2c.
The app is a simple web API that exposes standard CRUD operations via /api/Values through standard GET, PUT, POST and DELETE.
Getting started is simple! To run this sample you will need:
- To install .NET Core 2.0 for Windows by following the instructions at dot.net/core, which will include Visual Studio 2017.
- An Internet connection
- An Azure subscription (a free trial is sufficient)
From your shell or command line:
git clone https://github.com/Azure-Samples/active-directory-b2c-dotnetcore-webapi.git
You can also modify the sample to use your own Azure AD B2C tenant. First, you'll need to create an Azure AD B2C tenant by following these instructions.
IMPORTANT: if you choose to perform one of the optional steps, you have to perform ALL of them for the sample to work as expected.
This sample is configured with a single policy. Which policy is configured is not relevant as it is only used to obtain the metadata to validate the token. By default, this metadata is the same for all policies. Create a policy by following the instructions here.
If you already have an existing policy in your Azure AD B2C tenant, feel free to re-use it. No need to create a new one just for this sample.
You will need to register your Web API with Azure AD B2C and define the scopes that client applications can request access tokens for.
Your web API registration should include the following information:
- Enable the Web App/Web API setting for your application.
- Enter any Reply URL, as indicated previously, because the web API only does token validation and does not obtain token. To get this sample to work, you will want to use the reply url :
https://jwt.ms
. - Make sure you also provide a AppID URI, for example
demoapi
, this is used to construct the scopes that are configured in you single page application's code. - (Optional) Once you're app is created, open the app's Published Scopes blade and add any extra scopes you want.
- Copy the Application ID generated for your application and Published Scopes values, so you can input them in your application's code.
- Open the solution in Visual Studio.
- Open the
appsettings.json
file.
(1) Find the assignment for Tenant
and replace the value with your tenant name.
(2) Find the assignment for ClientID
and replace the value with the Application ID from Step 4.
(3) Find the assignment for Policy
and replace the value with the name of the policy from Step 3.
- Open the
Index.cshtml
file in the views folder. Find the url in this file at location : https://github.com/FrankHu-MSFT/active-directory-b2c-dotnetcore-webapi/blob/master/B2C-WebApi/Views/Home/Index.cshtml#L8
(1) Find the assignment for Tenant
and replace the value with your tenant name.
(2) Find the assignment for ClientID
and replace the value with the Application ID from Step 4.
(3) Find the assignment for Policy
and replace the value with the name of the policy from Step 3.
(4) Find the assignment for Scope
and replace the value with the name of the policy from Step 3.
Clean the solution, rebuild the solution, and run it. You can now sign up & sign in to your application using the accounts you configured in your respective policies.
Here there's a quick guide to the most interesting authentication related bits of the sample.
As it is standard practice for ASP.NET Core Web APIs, the token validation functionality is implemented with the JWT Bearer middleware. Here there's a relevant snippet from the middleware initialization:
services.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(jwtOptions =>
{
jwtOptions.Authority = $"https://login.microsoftonline.com/tfp/{Configuration["AzureAdB2C:Tenant"]}/{Configuration["AzureAdB2C:Policy"]}/v2.0/";
jwtOptions.Audience = Configuration["AzureAdB2C:ClientId"];
jwtOptions.Events = new JwtBearerEvents
{
OnAuthenticationFailed = AuthenticationFailed
};
});
Important things to notice:
- The Authority points is constructed using the tfp path, the tenant name and the policy.
- The OnAuthenticationFailed notification is to print better error messages if you have issues configuring this sample. You should not use this handler in production.
Optionally, you can enforce more granular access control via scopes.
You can access codes via:
var scopes = HttpContext.User.FindFirst("http://schemas.microsoft.com/identity/claims/scope")?.Value;
if (!string.IsNullOrEmpty(TheScope) && scopes != null && scopes.Split(' ').Any(s => s.Equals(TheScope)))
// Do stuff
else
// Unauthorized
Scopes are space delimited, so use a string split and check that the scope you are want is present via a .Equals. Beware of using .Contains as that will cause issues if you have two scopes like: read
and denyread
. Contains on read will also match denyread.