AngularJS CRUD Application With ASP.NET Core Web API Secured By Azure AD

AngularJS CRUD Application With ASP.NET Core Web API Secured By Azure AD

This is a simple overview about how to create an Azure AD secured sample AngularJS application that also saves and retrieves data from an Azure AD authenticated ASP.NET Core Web API. The sample application that will be used is a simple Contacts application that allows an authenticated user to create, read, update and delete their contacts. A link to the source code will be provided at the end of this post.

Azure AD Application Configuration

Before diving into the code, you need to securely setup the AngularJS application and the ASP.NET Core Web API for authentication in Azure AD. This has been demonstrated before in some of my previous posts, however, I am including this step here for completeness.

Azure AD Configuration

In order to configure the sample application, several configuration steps are required for the setup to succeed. However, keep in mind that the current UI functionality for completing the configuration exists only in the 'legacy' Azure AD portal. This functionality will soon be migrated to the new portal, thus I will only enumerate the steps needed for the configuration to succeed as I expect the UI to change quite dramatically from what is currently there.
Here are the steps:

  1. Log into the 'legacy' management portal, located at: manage.windowsazure.com/
  2. Access the Active Directory section on the left side menu and access your default Azure AD instance or create a new one just for testing this or any other sample apps.
  3. Once you have chosen your Azure AD Domain to use, select it from your list and click on it to expand on its details.
  4. Inside of your Azure AD Domain of choice, locate the Applications tab and click on it.
  5. Locate the ADD button on that section and click on it to bring the modal wizard.
  6. Select Add an application my organization is developing and proceed to the next screen in the wizard.
  7. Give your application a Name suited to your liking and select Web Application and/or Web API for the Type, click next.
  8. Now for the Sign-On URL you will need the address URL where you are hosting the application. In the case of the sample application that this post refers to the URL is : https://localhost:44306/. And the App ID URI can be anything you like as long as it is unique, such as https://sampleapps.onmicrosoft.com/MySecureApp. Once you click next, your application will be configured, with the given settings, in Azure AD. However, there is one last step that is very important.
  9. In order for a Single Page Application to authenticate with a Web API using Azure AD, you need to utilize the OAuth 2.0 implicit authorization grant to secure the ASP.NET Core Web API back end. This setting is off by default so you will have to locate the Manage Manifest link in the Configure page section and select the Download Manifest file.
  10. Inside the manifest file locate the setting for oauth2AllowImplicitFlow and set its value to true, save the file.
  11. From the Configure tab section under the application you are setting up, locate the Manage Manifest link and from within that link locate the Upload Manifest and click on it, choose the manifest file you just edited and upload it back into the Azure portal.
  12. Now from the same Configure page section, locate the CLIENT ID and copy it to the clipboard, you will need this setting to paste it in your configurations later on.

AngularJS Client Configuration

The AngularJS application's configuration resides within the app/app.config.js file. Note that this file allows for setting up different routes that should be secured by Azure AD, this is possible thanks to the Azure Active Directory Library for JavaScript, also known as ADAL JS. This library also utilizes an 'interceptor' that captures http calls to the ASP.NET Core Web API and adds an authorization header and a Bearer token signed by Azure AD. This is what allows the AngularJS application to securely connect to the Web API. Here is the snippet from that configuration file:

angular
.module('contactApp')
.config(function ($stateProvider, $httpProvider, adalAuthenticationServiceProvider) {
    $stateProvider.state('contacts', {
        url: '/contacts',
        templateUrl: 'app/contact/contact-list.html',
        controller: 'ContactListController',
        requiredADLogin: true,
    }).state('viewContact', {
        url: '/contacts/:id/view',
        templateUrl: 'app/contact/contact-view.html',
        controller: 'ContactViewController',
        requiredADLogin: true,
    }).state('newContact', {
        url: '/contacts/new',
        templateUrl: 'app/contact/contact-create.html',
        controller: 'ContactCreateController',
        requiredADLogin: true,
    }).state('editContact', {
        url: '/contacts/:id/edit',
        templateUrl: 'app/contact/contact-edit.html',
        controller: 'ContactEditController',
        requiredADLogin: true,
    });

    adalAuthenticationServiceProvider.init(
        {
            instance: 'https://login.microsoftonline.com/',
            tenant: 'This is your Azure AD tenant, e.g. sampleapps.onmicrosoft.com',
            clientId: 'This is your client id from Azure AD, e.g. d1d425ce-28f4-4181-a351-982e2c3f41b2',
            extraQueryParameter: 'nux=1',
        },
        $httpProvider
        );

}).run(function ($state) {
    $state.go('contacts');
});

That is all that is needed to configure the client application.

ASP.NET Core Web API Configuration

The ASP.NET Core Web API application's configuration with Azure AD utilizes Bearer tokens for its authentication. As mentioned earlier, this is accomplished by ADAL JS which adds an Authorization header to the API call which is validated by the Web API and if it succeeds then access to the specified resource is allowed.
In order for the Web API to authenticate service calls with Azure AD, the following settings are added in the appsettings.json file:

"Authentication": {
"AzureAd": {
    "AADInstance": "https://login.microsoftonline.com/",
    "ClientId": "This is your client id from Azure AD, e.g. d1d425ce-28f4-4181-a351-982e2c3f41b2",
    "TenantId": "This is your tenant id from Azure AD, e.g. b4c6f7f9-e288-4370-89ed-71b9b89cb949"
}}

The simplest way to find your Tenant Id is to look at the URL in the Azure Portal that displays in the Azure AD configuration section for your application. The URL contains your Tenant Id at the end of it:

https://manage.windowsazure.com/../ActiveDirectoryExtension/Directory/b4c6f7f9-e288-4370-89ed-71b9b89cb949/RegisteredApp/..

Now, the Startup.cs file will reference those settings in order to setup the JWT Bearer Options, which is the settings needed to authenticate the Bearer token:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        app.UseDefaultFiles();
        app.UseStaticFiles();

        app.UseJwtBearerAuthentication(new JwtBearerOptions
        {
            Authority = Configuration["Authentication:AzureAd:AADInstance"]
                        + Configuration["Authentication:AzureAd:TenantId"],
            Audience = Configuration["Authentication:AzureAd:ClientID"]
        });

        app.UseMvc();
    }

The last thing needed for the ASP.NET Core Web API authentiaction to succeed is to make sure the controller is decorated with an Authorize attribute:

[Route("api/[controller]")]
[Authorize]
public class ContactsController : Controller {...}

Running The Sample Application

After these settings have been updated/configured, the project can be run from within Visual Studio 2015 by simply starting a new debugging session.
In order to validate that your API is being authenticated, you can set a break point on the contact creation API endpoint and add the following code:

 bool isUserAuthenticated = User.Identity.IsAuthenticated;

Then exercise the client application by adding a contact and observe that the **IsAuthenticated property's value is true.

The source code for this sample can be found on GitHub: https://github.com/jpvelasco/angularjs-aspnet-web-api-core-azure-ad

Hope this helps.