Use OpenId in a ASP.NET 5 (vNext) application to authenticate with Azure active directory

Use OpenId in a ASP.NET 5 (vNext) application to authenticate with Azure active directory

ASP.NET 5 (vNext) is, at the moment of writing, in RC1. Since it is still a release candidate a lot of things are unclear. One of those things is authentication using OpenId.

In this article I will write about how to authenticate with an Azure Active Directory (AAD) using Microsofts OpenIdConnect library – a library still in pre release which can be downloaded from Nuget (https://www.nuget.org/packages/Microsoft.AspNet.Authentication.OpenIdConnect/). I will use cookies to store the authentication tokens retrieved by Azure (https://www.nuget.org/packages/Microsoft.AspNet.Authentication.Cookies/).

I’ll get right to it.
The libs we need are Cookies and OpenIdConnect. In our Startup.cs class, which is the starting point of the application, we will need to add these namespaces.

using Microsoft.AspNet.Authentication.Cookies;
using Microsoft.AspNet.Authentication.OpenIdConnect;

Then we need to configure our services to use authentication.

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication();
}

Then, in our Startup method, we need to setup our application to use Cookies (UseCookieAuthentication) and then configure OpenId. The notable thing here is that we need to set correct information to ClientId and Authority to make this work, these values can be retrieved from your Azure AD. In addition we need to specify that the Cookie authentication should authenticate automatically (unless you want to alter the request manually).

public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
    app.UseCookieAuthentication(options => { options.AutomaticAuthentication = true; });
    app.UseOpenIdConnectAuthentication(options =>
    {
        options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.ClientId = "3cc10d4f-d825-4ffd-ab1a-f18846b53134"; //This is the Id of your application in AAD.
        options.Authority = "https://login.microsoftonline.com/{Your TenantId}"; //The authoritys logon url, for Azure this is the logon base url with the TenantId appended to it
    });
}

Okay, now OpenId is setup for use. The last thing we need to do is to add a middleware that performs the authentication. We will have to write our own, don’t worry, it is really slim. Let’s add it at the bottom of our Startup method.

//Code mentioned above omitted.
app.UseMiddleware<AuthenticateMiddleware>();

The implementation is straight forward, create a class that contains a constructor that accepts a RequestDelegate and an Invoke method that accepts a HttpContext. We do not need to inherit from any middleware base class, the Invoke method and the constructor is invoked by .NET at runtime using dynamics.

In our Invoke method we need to check whether or not the user already is authenticated and if so use the RequestDelegate to pass control over to the next middleware in the pipeline. If the user is not authenticated we will issue a challenge to the client using the authentication scheme “OpenIdConnect”. Pay notice to the fact that we are not passing control over to the next middleware (using the RequestDelegate), this will have the effect that the request is terminated and the challenge is sent as response.

public class AuthenticateMiddleware
{
    private readonly RequestDelegate _next;
    public AuthenticateMiddleware(RequestDelegate next)
    {
        _next = next;
    }
    public async Task Invoke(HttpContext context)
    {
        if (context.User.Identity.IsAuthenticated)
        {
            await _next(context);
            return;
        }
        await context.Authentication.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme);
    }
}

That should be it, any request to our application is now authenticated. The current implementation will continue to challenge the user after a failed attempt, which might be desired behaviour, but we might want to redirect to our own page or do something else.

There are several events that we can listen to and act upon, one of these events is “OnAuthenticationFailed”. We can do this by assigning a new “OpenIdConnectionEvents” to the Events property of the OpenIdConnectOptions class sent into our OpenId configuration.

app.UseOpenIdConnectAuthentication(options =>
    options.Events = new OpenIdConnectEvents
    {
        //Other settings are omitted
        OnAuthenticationFailed = failedContext =>
        {
            failedContext.HandleResponse();
            //Whatever you need to do when authentication fails.
        }
    }
);