Azure Active Directory Authentication in Web Applications

I’ve previously used “Individual User Accounts” authentication for authenticating users in web applications but as the management of users in the underlying SQL databases isn’t that simple it seemed that using Azure Active Directory to manage users might be a better option.

The first step in the process is to create an “Azure Active Directory B2C” directory in your subscription.

Once the directory has finished deploying create a new ASP.NET Core Web Application and for Authentication choose “Work or School Accounts”, the domain of the B2C directory you just created will now be selectable under the “Domain” drop down, select it and then create your project.

Creating the project will also create a new Application in the “Azure Active Directory” section of your new directory, you can switch directory by clicking the account section in the top right of the Azure portal and choosing the desired directory.

Once in the directory go into the “Azure Active Directory” blade and select the “Enterprise applications” blade, within this select your application (to see all user created applications click on the “Total apps” text).

To allow users to use an application they need to be invited through the “Users and groups” blade. Select “Add user” and then “Users”, you can then invite any email that has a Windows Live login.

After the required user invitations have been sent, go back up to the created application in the “Enterprise Application” blade and select “Properties”. By default once a user has accepted an invitation they will have access to all applications in the directory, even if they weren’t added to any of the other applications, this seems like a terrible idea and in order to prevent users accessing applications you don’t want them to the “User assignment required?” option should be turned on.

If you now run the application localy you will be presented with the Microsoft login screen where you can login with an either the credentials of that you used to set this up in the Azure portal or those of an invited user.

Although this all now appears to work there’s a couple more things that need to be setup before the web application is ready to be deployed.

First off, when the application was created in “Azure Active Directory” the reply URL that a user is redirected to after login is set to be the local URL (e.g. https://localhost:44329/signin-oidc), if you actually want to deploy the application to Azure you’ll need to add a reply URL that points to your site. This can be done in “Azure Active Directory” > “<YOUR APPLICATION NAME>” > “Reply URL’s”.

Update

Authentication failures seem to now be taken care of in the MS login portal rather than being handed back to your application to deal with and the below files are no longer created as part of the scaffolding process in the project. This can probably be ignored unless you’re creating an application from an older version of Visual Studio.

Secondly, if a user trys to login and they haven’t been granted access to the application the login will fail as expected but they’ll be redirected back to the web application which will then trow an error as it doesn’t know what to do in the case of login failure events. This produces a rather unhelpful error like that below.


An unhandled exception occurred while processing the request.

OpenIdConnectProtocolException: Message contains error: 'access_denied', error_description: 'AADSTS50105: The signed in user is not assigned to a role for the application ''.
Trace ID: 8fa9c12f-f95a-422a-9545-0a5477a77c00
Correlation ID: 8ed28cbe-143a-4532-b2df-1a449b5e9690
Timestamp: 2017-12-13 17:21:04Z', error_uri: 'error_uri is null'.

In order to handle these “access_denied” exceptions you need to update the AddAzureAd method in the AzureAdAuthenticationBuilderExtensions class in the Extensions folder of your project to the following.


public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder, Action<AzureAdOptions> configureOptions)
{
	builder.Services.Configure(configureOptions);
	builder.Services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, ConfigureAzureOptions>();

	builder.AddOpenIdConnect(options =>
	{
		options.Events = new OpenIdConnectEvents
		{
			OnRemoteFailure = context =>
			{
				context.HandleResponse();
				context.Response.Redirect("Account/AccessDenied");

				return Task.FromResult(0);
			}
		};
	});

	return builder;
}

This handles any remote access failure from the login attempt and redirects it to the pre-created AccessDenied.cshtml page, unfortunatly this page has an error in it as well and the title header ViewData should be prefixed with an “@” symbol to ensure it is processed by the razor engine.


<h1 class="text-danger">@ViewData["Title"]</h1>

5 Comments

Abel Bolanos Martinez · 4th September 2018 at 3:37 pm

I’m kind new in .Net. Could you share the file where you updated the method?
I created a “Extensions” folder and inside I set a new file called AzureADAuthenticationBuilderExtensions.cs
But I don’t see any chage neither I can’t debug the file.

    Shinigami · 5th September 2018 at 9:37 am

    Hi Abel, I think this has changed in Visual Studio since I wrote this post. Initially the file AzureADAuthenticationBuilderExtensions.cs was created in the project as part of the scaffolding process when it was created, however it looks like this is now all taken care of in the MS login portal. If you’re not seeing this file on project creation then I’d suggest logging in to your application in an incognito browser window with an account without access and seeing if it works as expected.

      Abel Bolanos Martinez · 5th September 2018 at 9:41 pm

      Could you show me how you do it? Because I don’t see that is created.
      I tried today from Visual Studio Professional 2017 and from Visual Studio Code and nothing.
      Anyway, I could make it work but I had to make some changes:
      1. I found the source code in https://github.com/aspnet/AADIntegration/tree/master/src/Microsoft.AspNetCore.Authentication.AzureAD.UI
      2. Change the name of the function from ‘AddAzureAD’ to ‘AddAzureAd’.
      3. Source code has change a lot and I had to put almost everything in that *.cs because most of the classes where declared as internal.

        Shinigami · 6th September 2018 at 10:13 am

        Sorry, this doesn’t create the Extensions folder or the various AD class that were previously created within it. This all seems to be taken care of by the authentication service which is added in Startup.cs. I created my project in Visual Studio 2017 15.8.1 and it’s a .NET Core Web Application targeting dotnet 2.1, the authentication is set to “Work and School” as above. Once you’ve added your users to the app created in the Azure portal they should be able to login to your site.

          Abel Bolanos Martinez · 6th September 2018 at 2:08 pm

          Thank you so much for your help Shinigami. Your solutions works very well for me. But I created the Extensions/AzureADAuthenticationBuilderExtensions.cs with most of the AD classes inside, even with the AD controller class because all of them were declared as ‘internal’. It was not possible to only override the AddAzureAD function, I had to create a new one called AddAzureAd.

Leave a Reply

Your email address will not be published. Required fields are marked *