Quickstart: Protect a web API with the Microsoft identity platform

In this quickstart, you download and run a code sample that demonstrates how to protect an ASP.NET web API by restricting access to its resources to authorized accounts only. The sample supports authorization of personal Microsoft accounts and accounts in any Azure Active Directory (Azure AD) organization.

The article also uses a Windows Presentation Foundation (WPF) app to demonstrate how you can request an access token to access a web API.

Prerequisites

Clone or download the sample

You can obtain the sample in either of two ways:

  • Clone it from your shell or command line:

    git clone https://github.com/AzureADQuickStarts/AppModelv2-NativeClient-DotNet.git
    
  • Download it as a ZIP file.

Tip

To avoid errors caused by path length limitations in Windows, we recommend extracting the archive or cloning the repository into a directory near the root of your drive.

Register the web API (TodoListService)

Register your web API in App registrations in the Azure portal.

  1. Sign in to the Azure portal.

  2. If you have access to multiple tenants, use the Directory + subscription filter in the top menu to select the tenant in which you want to register an application.

  3. Find and select Azure Active Directory.

  4. Under Manage, select App registrations > New registration.

  5. Enter a Name for your application, for example AppModelv2-NativeClient-DotNet-TodoListService. Users of your app might see this name, and you can change it later.

  6. For Supported account types, select Accounts in any organizational directory.

  7. Select Register to create the application.

  8. On the app Overview page, look for the Application (client) ID value, and then record it for later use. You'll need it to configure the Visual Studio configuration file for this project (that is, ClientId in the TodoListService\Web.config file).

  9. Under Manage, select Expose an API > Add a scope. Accept the proposed Application ID URI (api://{clientId}) by selecting Save and continue, and then enter the following information:

    1. For Scope name, enter access_as_user.
    2. For Who can consent, ensure that the Admins and users option is selected.
    3. In the Admin consent display name box, enter Access TodoListService as a user.
    4. In the Admin consent description box, enter Accesses the TodoListService web API as a user.
    5. In the User consent display name box, enter Access TodoListService as a user.
    6. In the User consent description box, enter Accesses the TodoListService web API as a user.
    7. For State, keep Enabled.
  10. Select Add scope.

Configure the service project

Configure the service project to match the registered web API.

  1. Open the solution in Visual Studio, and then open the Web.config file under the root of the TodoListService project.

  2. Replace the value of the ida:ClientId parameter with the Client ID (Application ID) value from the application you registered in the App registrations portal.

Add the new scope to the app.config file

To add the new scope to the TodoListClient app.config file, follow these steps:

  1. In the TodoListClient project root folder, open the app.config file.

  2. Paste the Application ID from the application that you registered for your TodoListService project in the TodoListServiceScope parameter, replacing the {Enter the Application ID of your TodoListService from the app registration portal} string.

Note

Make sure that the Application ID uses the following format: api://{TodoListService-Application-ID}/access_as_user (where {TodoListService-Application-ID} is the GUID representing the Application ID for your TodoListService app).

Register the web app (TodoListClient)

Register your TodoListClient app in App registrations in the Azure portal, and then configure the code in the TodoListClient project. If the client and server are considered the same application, you can reuse the application that's registered in step 2. Use the same application if you want users to sign in with a personal Microsoft account.

Register the app

To register the TodoListClient app, follow these steps:

  1. Go to the Microsoft identity platform for developers App registrations portal.

  2. Select New registration.

  3. When the Register an application page opens, enter your application's registration information:

    1. In the Name section, enter a meaningful application name that will be displayed to users of the app (for example, NativeClient-DotNet-TodoListClient).
    2. For Supported account types, select Accounts in any organizational directory.
    3. Select Register to create the application.

    Note

    In the TodoListClient project app.config file, the default value of ida:Tenant is set to common. The possible values are:

    • common: You can sign in by using a work or school account or a personal Microsoft account (because you selected Accounts in any organizational directory in a previous step).
    • organizations: You can sign in by using a work or school account.
    • consumers: You can sign in only by using a Microsoft personal account.
  4. On the app Overview page, select Authentication, and then complete these steps to add a platform:

    1. Under Platform configurations, select the Add a platform button.
    2. For Mobile and desktop applications, select Mobile and desktop applications.
    3. For Redirect URIs, select the https://login.microsoftonline.com/common/oauth2/nativeclient check box.
    4. Select Configure.
  5. Select API permissions, and then complete these steps to add permissions:

    1. Select the Add a permission button.
    2. Select the My APIs tab.
    3. In the list of APIs, select AppModelv2-NativeClient-DotNet-TodoListService API or the name you entered for the web API.
    4. Select the access_as_user permission check box if it's not already selected. Use the Search box if necessary.
    5. Select the Add permissions button.

Configure your project

Configure your TodoListClient project by adding the Application ID to the app.config file.

  1. In the App registrations portal, on the Overview page, copy the value of the Application (client) ID.

  2. From the TodoListClient project root folder, open the app.config file, and then paste the Application ID value in the ida:ClientId parameter.

Run your projects

Start both projects. If you are using Visual Studio:

  1. Right click on the Visual Studio solution and select Properties

  2. In the Common Properties select Startup Project and then Multiple startup projects.

  3. For both projects choose Start as the action

  4. Ensure the TodoListService service starts first by moving it to the fist position in the list, using the up arrow.

Sign in to run your TodoListClient project.

  1. Press F5 to start the projects. The service page opens, as well as the desktop application.

  2. In the TodoListClient, at the upper right, select Sign in, and then sign in with the same credentials you used to register your application, or sign in as a user in the same directory.

    If you're signing in for the first time, you might be prompted to consent to the TodoListService web API.

    To help you access the TodoListService web API and manipulate the To-Do list, the sign-in also requests an access token to the access_as_user scope.

Pre-authorize your client application

You can allow users from other directories to access your web API by pre-authorizing the client application to access your web API. You do this by adding the Application ID from the client app to the list of pre-authorized applications for your web API. By adding a pre-authorized client, you're allowing users to access your web API without having to provide consent.

  1. In the App registrations portal, open the properties of your TodoListService app.
  2. In the Expose an API section, under Authorized client applications, select Add a client application.
  3. In the Client ID box, paste the Application ID of the TodoListClient app.
  4. In the Authorized scopes section, select the scope for the api://<Application ID>/access_as_user web API.
  5. Select Add application.

Run your project

  1. Press F5 to run your project. Your TodoListClient app opens.
  2. At the upper right, select Sign in, and then sign in by using a personal Microsoft account, such as a live.com or hotmail.com account, or a work or school account.

Optional: Limit sign-in access to certain users

By default, any personal accounts, such as outlook.com or live.com accounts, or work or school accounts from organizations that are integrated with Azure AD can request tokens and access your web API.

To specify who can sign in to your application, use one of the following options:

Option 1: Limit access to a single organization (single tenant)

You can limit sign-in access to your application to user accounts that are in a single Azure AD tenant, including guest accounts of that tenant. This scenario is common for line-of-business applications.

  1. Open the App_Start\Startup.Auth file, and then change the value of the metadata endpoint that's passed into the OpenIdConnectSecurityTokenProvider to https://login.microsoftonline.com/{Tenant ID}/v2.0/.well-known/openid-configuration. You can also use the tenant name, such as contoso.onmicrosoft.com.
  2. In the same file, set the ValidIssuer property on the TokenValidationParameters to https://sts.windows.net/{Tenant ID}/, and set the ValidateIssuer argument to true.

Option 2: Use a custom method to validate issuers

You can implement a custom method to validate issuers by using the IssuerValidator parameter. For more information about this parameter, see TokenValidationParameters class.

Help and support

If you need help, want to report an issue, or want to learn about your support options, see Help and support for developers.

Next steps

Learn more about the protected web API scenario that the Microsoft identity platform supports.

In this quickstart, you download an ASP.NET Core web API code sample and review the way it restricts resource access to authorized accounts only. The sample supports authorization of personal Microsoft accounts and accounts in any Azure Active Directory (Azure AD) organization.

Prerequisites

Step 1: Register the application

First, register the web API in your Azure AD tenant and add a scope by following these steps:

  1. Sign in to the Azure portal.
  2. If you have access to multiple tenants, use the Directories + subscriptions filter in the top menu to switch to the tenant in which you want to register the application.
  3. Search for and select Azure Active Directory.
  4. Under Manage, select App registrations > New registration.
  5. For Name, enter a name for your application. For example, enter AspNetCoreWebApi-Quickstart. Users of your app will see this name, and you can change it later.
  6. Select Register.
  7. Under Manage, select Expose an API > Add a scope. For Application ID URI, accept the default by selecting Save and continue, and then enter the following details:
    • Scope name: access_as_user
    • Who can consent?: Admins and users
    • Admin consent display name: Access AspNetCoreWebApi-Quickstart
    • Admin consent description: Allows the app to access AspNetCoreWebApi-Quickstart as the signed-in user.
    • User consent display name: Access AspNetCoreWebApi-Quickstart
    • User consent description: Allow the application to access AspNetCoreWebApi-Quickstart on your behalf.
    • State: Enabled
  8. Select Add scope to complete the scope addition.

Step 2: Download the ASP.NET Core project

Download the ASP.NET Core solution from GitHub.

Tip

To avoid errors caused by path length limitations in Windows, we recommend extracting the archive or cloning the repository into a directory near the root of your drive.

Step 3: Configure the ASP.NET Core project

In this step, configure the sample code to work with the app registration that you created earlier.

  1. Extract the .zip archive into a folder near the root of your drive. For example, extract into C:\Azure-Samples.

    We recommend extracting the archive into a directory near the root of your drive to avoid errors caused by path length limitations on Windows.

  2. Open the solution in the webapi folder in your code editor.

  3. Open the appsettings.json file and modify the following code:

    "ClientId": "Enter_the_Application_Id_here",
    "TenantId": "Enter_the_Tenant_Info_Here"
    
    • Replace Enter_the_Application_Id_here with the application (client) ID of the application that you registered in the Azure portal. You can find the application (client) ID on the app's Overview page.
    • Replace Enter_the_Tenant_Info_Here with one of the following:
      • If your application supports Accounts in this organizational directory only, replace this value with the directory (tenant) ID (a GUID) or tenant name (for example, contoso.onmicrosoft.com). You can find the directory (tenant) ID on the app's Overview page.
      • If your application supports Accounts in any organizational directory, replace this value with organizations.
      • If your application supports All Microsoft account users, leave this value as common.

For this quickstart, don't change any other values in the appsettings.json file.

How the sample works

The web API receives a token from a client application, and the code in the web API validates the token. This scenario is explained in more detail in Scenario: Protected web API.

Startup class

The Microsoft.AspNetCore.Authentication middleware uses a Startup class that's executed when the hosting process starts. In its ConfigureServices method, the AddMicrosoftIdentityWebApi extension method provided by Microsoft.Identity.Web is called.

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddMicrosoftIdentityWebApi(Configuration, "AzureAd");
    }

The AddAuthentication() method configures the service to add JwtBearer-based authentication.

The line that contains .AddMicrosoftIdentityWebApi adds the Microsoft identity platform authorization to your web API. It's then configured to validate access tokens issued by the Microsoft identity platform based on the information in the AzureAD section of the appsettings.json configuration file:

appsettings.json key Description
ClientId Application (client) ID of the application registered in the Azure portal.
Instance Security token service (STS) endpoint for the user to authenticate. This value is typically https://login.microsoftonline.com/, indicating the Azure public cloud.
TenantId Name of your tenant or its tenant ID (a GUID), or common to sign in users with work or school accounts or Microsoft personal accounts.

The Configure() method contains two important methods, app.UseAuthentication() and app.UseAuthorization(), that enable their named functionality:

// The runtime calls this method. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // more code
    app.UseAuthentication();
    app.UseAuthorization();
    // more code
}

Protecting a controller, a controller's method, or a Razor page

You can protect a controller or controller methods by using the [Authorize] attribute. This attribute restricts access to the controller or methods by allowing only authenticated users. An authentication challenge can be started to access the controller if the user isn't authenticated.

namespace webapi.Controllers
{
    [Authorize]
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase

Validation of scope in the controller

The code in the API verifies that the required scopes are in the token by using HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);:

namespace webapi.Controllers
{
    [Authorize]
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        // The web API will only accept tokens 1) for users, and 2) having the "access_as_user" scope for this API
        static readonly string[] scopeRequiredByApi = new string[] { "access_as_user" };

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);

            // some code here
        }
    }
}

Help and support

If you need help, want to report an issue, or want to learn about your support options, see Help and support for developers.

Next steps

The GitHub repository that contains this ASP.NET Core web API code sample includes instructions and more code samples that show you how to:

  • Add authentication to a new ASP.NET Core web API.
  • Call the web API from a desktop application.
  • Call downstream APIs like Microsoft Graph and other Microsoft APIs.