Click here to monitor SSC
  • Av rating:
  • Total votes: 17
  • Total comments: 3
Edward Charbeneau

Creating Custom OAuth Middleware for MVC 5

04 August 2014

Website visitors will have come to expect to be able to use OAuth authentication, rather than require yet another ID and password. Although MVC5 provides Google, LinkedIn, Facebook or Twitter authentication, you would need to write custom authentication middleware for any other provider. Ed Charbeneau shows you how to get started.

OAuth allows web users to prove their identity when using a web site without having to create a subscription or supply details or credentials, using instead their Google, LinkedIn, Facebook or Twitter accounts. If a Web site implements OAuth, then visitors can use the site without worrying about their access credentials being compromised.

ASP.Net MVC 5 enables OAuth2 authentication. Although Google, LinkedIn, Facebook or Twitter authentication providers ship ‘out of the box’, there are many others that are not included. In order to add an additional authentication provider to an application you will need custom authentication middleware. In this article we’ll learn about the processes and components required for custom authentication in MVC 5.

You can read more about MVC’s default providers in Dino Esposito’s Social Login in ASP.NET MVC article.

MVC 5 authentication changes

Because MVC 5 is built on Katana, an implementation of the OWIN specification, authentication has changed significantly and the authentication providers written for previous versions of MVC will not work. They will need to be rewritten as OWIN middleware. OWIN is a new modular interface for handling HTTP requests designed to decouple the server and application.

OWIN Middleware Components

OWIN Middleware Components or OMCs are modules written to work with Katana at a low level and are used to respond to HTTP requests. OMCs implement the IAppBuilder interface and are added to the OWIN pipeline using the I AppBuilder.Use method. The OWIN pipeline in the Katana runtime will process OMCs in the order they were registered in the application.

For more detailed information about OMCs in general, please refer to the Katana overview OWIN Middleware in the IIS integrated pipeline in the ASP.Net documentation

With MVC 5, authentication middleware are registered with the application when the Startup.ConfigAuth method is executed. When MVC executes the ConfigAuth method the applications instance of the IAppBuilder is exposed and passed to the authentication middleware.

public static class FacebookAuthenticationExtensions

    {

        /// <summary>

        /// Authenticate users using Facebook

        /// </summary>

        /// <param name="app">The <see cref="IAppBuilder"/> passed to the configuration method</param>

        /// <param name="options">Middleware configuration options</param>

        /// <returns>The updated <see cref="IAppBuilder"/></returns>

        public static IAppBuilder UseFacebookAuthentication(this IAppBuilder app, FacebookAuthenticationOptions options)

        {

            if (app == null)

            {

                throw new ArgumentNullException("app");

            }

            if (options == null)

            {

                throw new ArgumentNullException("options");

            }

 

            app.Use(typeof(FacebookAuthenticationMiddleware), app, options);

            return app;

        }

In the Microsoft MVC source code for Facebook authentication; you can see the UseFacebookAuthentication helper used to register the middleware via app.Use.

Each authentication middleware provides an API for setting up the middleware options and invoking IAppBuilder.Use . The Use [ AuthType ] Authentication extension methods are primarily syntactic sugar designed for easy setup.

app.UseFacebookAuthentication(

               appId: "value",

               appSecret: "value");

 

public partial class Startup

    {

        // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864

        public void ConfigureAuth(IAppBuilder app)

        {

            // Enable the application to use a cookie to store information for the signed in user

            app.UseCookieAuthentication(new CookieAuthenticationOptions

            {

                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,

                LoginPath = new PathString("/Account/Login")

            });

            // Use a cookie to temporarily store information about a user logging in with a third party login provider

            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

 

            // Uncomment the following lines to enable logging in with third party login providers

            //app.UseMicrosoftAccountAuthentication(

            //    clientId: "",

            //    clientSecret: "");

 

            //app.UseTwitterAuthentication(

            //   consumerKey: "",

            //   consumerSecret: "");

 

            app.UseFacebookAuthentication(

               appId: "304043486424974",

               appSecret: "0aa12bfc9f6660e47658ace979c34f1f");

 

            //app.UseGoogleAuthentication();

This excerpt from a standard MVC application’s App_Start\Startup.Auth.cs file shows how OAuth providers are initialized.

OAuth Process

Overview

The OAuth process is complex and requires several interactions with the user, browser, application/middleware, and the OAuth service. Let’s look at an overview of the process grouped into five main steps:

  • A request requires user authentication (http 401 unauthorized)
  • The browser is redirected to the third party authorization page
  • The user clicks "Allow" and the service redirects the browser back to the application with an access code.
  • The middleware uses the access code to gain access to the user’s information and generates a Claims Identity containing basic user information.
  • The application receives the Claims Identity for creating a user profile, and login.

OAuth process details

There are many detailed sub processes that must occur in each of these steps. Since we are creating a custom authentication middleware we will be responsible for handling each detail of the entire authentication process.

The process begins when the user is required to authenticate with the application. In MVC this is when a user reaches an endpoint that has been marked [Authorize] . The application will redirect the user to the Account/Login action and the Login view will be displayed. All authentication providers registered with the application will be presented for the user to choose from.

When the user clicks on a provider, the application will respond with a 401 response containing the provider type (ex: “facebook”) in the AuthenticationResponseChallenge . At this point the ApplyResponseChallengeAsync method is invoked on the middleware to intercept the response. If the response is a (401 unauthorized) with the matching provider type then the response will be changed to a redirect to the authentication provider’s endpoint.

Once the user has reached the authentication provider they will prompted by the third party to allow the application access to user details such as: user name, email and ID (service APIs may vary). When the user chooses to allow the application access, the service will redirect the user to the applications callback path.

It’s important to differentiate the callback path of the middleware (ex: application/signin-authType) and application (ex: application/Account/ExternalLoginCallback). The callback path is not the ExternalLoginCallback action on the Account controller but instead a path used for the middleware to identify a request coming back from a third party service. The middleware is invoked before application routing occurs.

When the request reaches the application, the middleware will intercept the request. The request will contain the callback path, the authorization code needed for retrieving an authentication token, and other information required by the API such as: client id, client secret, and CSRF tokens.

After obtaining the authorization code the middleware will contact the authentication service again to request an authentication token. Once the middleware and application have the authentication token the third party API can be used to retrieve information about the user. A request will be sent to the AuthenticationEndpoint with any headers and values required by the API.

The service will respond with a success status and contain the authentication token. Depending on the API and addition request may be required to obtain detailed information about the user. Once the user’s information has been collected and ClaimsIdentity is created, the ClaimsIdentity will be returned to the application via the AccountController.ExternalLoginCallback action. The application now has the user’s information and can create a user profile and login the user.

The diagram shows the authentication process in reference to the middleware and application.

OAuth Components

OAuth middleware consists of several components that work together to complete the OAuth process. The following classes are used to configure and register the middleware, instantiate the provider, and handle authentication. Each component is described below in the order they are required by the authentication process.

AuthenticationExtensions

An authentication extensions class is used to create an API used for registering the middleware with the OWIN pipeline. The class Custom AuthenticationExtensions extends the IAppBuilder by providing a UseCustom Authentication method. The U seCustom Authentication method gives other developers an easy to use API for initializing the middleware and its options while registering the middleware with Katana.

AuthenticationOptions

CustomAuthentication Options specifies configuration for the authentication process and objects used throughout the authentication process. This includes service endpoints and API parameters such as client ID and client secret. CustomAuthentication Options inherits from the AuthenticationOptions base class. The authentication options associated with a custom middleware are often referenced by other components as TOptions .

AuthenticationMiddleware

CustomAuthenticationMiddleware inherits from AuthenticationMiddleware < TOptions > where TOptions is CustomAuthenticationOptions . CustomAuthenticationMiddleware initializes the CustomAuthenticationProvider , CustomAuthenticationHandler , and ILogger < CustomAuthenticationMiddleware > . The AuthenticationMiddleware itself is rather sparse because most of the work has been abstracted away into the AuthenticationHandler .

AuthenticationProvider

Custom AuthenticationProvider specifies the delegates that are called during authentication. OnAuthenticated is invoked when a user is successfully authenticated. OnReturnEndpoint , is invoked before the ClaimsIdentity is saved and the browser redirects to the originally requested URL.

Authenticated Context

CustomAuthenticationContenxt inherits from BaseContext . The AuthenticationContext receives and parses the user information retrieved from the authentication service. The AuthenticationContext properties contain the login session information as well as details about the user that logged in including the ClaimsIdentity and AuthenticationProperties .

ReturnEndpointContext

CustomReturnEndpointContext inherits from ReturnEndpointContext . ReturnEndpointContext provides information about the OWIN context and holds the authentication ticket information.

AuthenticationHandler

The CustomAuthenticationHandler is responsible for the bulk of the authentication process. CustomAuthenticationHandler inherits from AuthenticationHandler < CustomAuthenticationOptions > and has three methods that need to be overridden: AuthenticateCoreAsync , ApplyResponseChallengeAsync , and InvokeAsync .

ApplyResponseChallengeAsync

This method is invoked during an HTTP response. The method will look for a response that requires authentication (401 unauthorized) and a matching authentication type. When this criteria is met the method will be responsible for creating the CSFR token and redirecting the browser to the authentication endpoint.

InvokeAsync

The InvokeAsync method is used to detect a callback request from the authentication service. InvokeAsync will check the request for a path that matches callback path (ex: /signin-facebook). When the callback path is detected the method will invoke AuthenticateAsyncCore via AuthenticateAsnyc . Once AuthenticateAsyncCore is complete the method will create a ReturnEndpointContext , grant the ClaimsIdentity and complete the request by redirecting to the application’s ExternalLoginCallback action.

AuthenticateCoreAsync

AuthenticateCoreAsync performs several tasks. The method will validate the CSRF token insuring the security of the request. Next, the access token is request from the authentication service and if needed a second request is made for additional user information. Once the user’s information is collected the authentication context and ClaimsIdentity are generated. Finally, the OnAuthenticated method is called and given the AuthenticationContext .

Conclusion & Open Source

By understanding the processes and components involved in authentication using Katana, you will be able to create authentication middleware for any OAuth service provider. Although the authentication process is complex and has many components, there are several open source implementations available as a reference. The open source projects listed below are excellent references for jumpstarting development of your own middleware.

The Katana Project on Codeplex (Microsoft)

OwinOAuthProviders project on GitHub

Edward Charbeneau

Author profile:

As a Sr. Corporate Web Developer with Sypris Solutions, Inc., Ed Charbeneau designs and develops web based applications for business, manufacturing, systems integration as well as customer facing websites. Ed’s well rounded experience includes all aspects of web development from programming, database and ORM, to graphics design, and advertising/analytics. His diverse set of tools and skills includes C#, Asp.Net/MVC, HTML/CSS, Photoshop, and JavaScript.

Search for other articles by Edward Charbeneau

Rate this article:   Avg rating: from a total of 17 votes.


Poor

OK

Good

Great

Must read
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.


Subject: Nice article!
Posted by: Jayganesh (not signed in)
Posted on: Monday, August 18, 2014 at 10:27 PM
Message: Thanks!

Subject: Excellent post
Posted by: Rahul@RahulSharma.in (not signed in)
Posted on: Wednesday, August 20, 2014 at 11:58 PM
Message: Very informative and to the point.
I have a related question that I believe you are the right person to ask...
I want to keep the authentication mvc 5 website separate from my other mvc 5 website. In other words, how can I redirect all of my websites to the identity/authentication provider central website?
Same behavior like when you open mail.live.com it redirects you to the login.live.com for authentication. Any help or pointer to the right direction would be helpful.

Subject: RE: Rahul
Posted by: EdCharbeneau (view profile)
Posted on: Friday, August 22, 2014 at 11:17 AM
Message: Rahul, I'm not sure how that could be accomplished. There are authentication cookies associated with the domain name and other variables you would need to research. It sounds like heavy customization would be required.

Thanks for the feedback.

 

Top Rated

ASP.NET SignalR: Old-fashioned Polling, Just Done Better
 A website often needs to update a page as the underlying data changes. You can, of course, just poll... Read more...

Rethinking the Practicalities of Recursion
 We all love recursion right up to the point of actually using it in production code. Why? Recursion... Read more...

Acceptance Testing with FitNesse: Multiplicities and Comparisons
 FitNesse is one of the most popular tools for unit testing since it is designed with a Wiki-style... Read more...

Acceptance Testing with FitNesse: Documentation and Infrastructure
 FitNesse is a popular general-purpose wiki-based framework for writing acceptance tests for software... Read more...

Prototyping Desktop Deblector
 Deblector is an open-source debugging add-in for .NET Reflector; the Reflector team investigated... Read more...

Most Viewed

A Complete URL Rewriting Solution for ASP.NET 2.0
 Ever wondered whether it's possible to create neater URLS, free of bulky Query String parameters?... Read more...

Visual Studio Setup - projects and custom actions
 This article describes the kinds of custom actions that can be used in your Visual Studio setup project. Read more...

.NET Application Architecture: the Data Access Layer
 Find out how to design a robust data access layer for your .NET applications. Read more...

Calling Cross Domain Web Services in AJAX
 The latest craze for mashups involves making cross-domain calls to Web Services from APIs made publicly... Read more...

Build and Deploy a .NET COM Assembly
 Phil Wilson demonstrates how to build and deploy a .NET COM assembly using best practices, and how to... Read more...

Why Join

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.