left-icon

OWIN Succinctly®
by Simone Chiaretta and Ugo Lattanzi

Previous
Chapter

of
A
A
A

CHAPTER 5

Authentication with Katana

Authentication with Katana


Introduction

So far we have learned what OWIN is, what Katana is, the idea behind them, their approach, and also how to build custom middleware components.

In this chapter, we are going to apply what we learned until now, starting from one of the most useful middleware components available for Katana, the authentication process.

Given that the web is evolving quickly and many websites require different kinds of authentication, we will see how to use the classic form authentication, and also how to integrate social authentication with the most used social networks (Twitter, Facebook, and Google).

Authentication

Authentication is one of the topics that best fits with the idea of middleware, since it is something that has to be verified at each request and is the same in all applications.

As explained in the previous chapters, middleware is something that can handle a request, do something with it, and then forward it to the application, or stop the execution if something is wrong.

The authentication process is also one of the best real-life examples to understand how middleware works within OWIN.

What happens when someone requests a URL that requires authentication?

Figure 1

Sequence diagram of login process

As you can see in the sequence diagram in Figure 37, the middleware changes the 401 unauthorized response coming from the controller to a 302, redirecting the user to the login page.

Using Katana, you can choose from several packages for authentication. By using NuGet, you can choose from the following types of authentication:

  • Forms authentication
  • Twitter authentication
  • Facebook authentication
  • Google authentication
  • Windows Azure
  • Active Directory
  • OpenID
  • Microsoft account authentication
  • Many more

Form Authentication

Form authentication is the most widespread authentication and, in the .NET world, is most likely to be used with ASP.NET MVC because you will need to render HTML.

Before we go too deep into the code, it is important to understand the difference between the form authentication managed by OWIN and the form authentication managed by ASP.NET MVC and WebForms.

Features

The following table compares the form authentication features between ASP.NET MVC and OWIN.

Form Authenteication Features in ASP.NET MVC and OWIN

Features

MVC Authentication

OWIN Authentication

Cookie Authentication

Yes

Yes

Cookieless Authentication

Yes

No

Expiration

Yes

Yes

Sliding Expiration

Yes

Yes

Token Protection

Yes

Yes

Claims Support

No

Yes

Web Farm Support

Yes

Yes

Unauthorized Redirection

Yes

Yes

As you can see, Katana’s implementation covers almost all the features released by ASP.NET MVC plus claim authentication. This means that it is a good choice for your .NET web application. Beware though, if you need to keep cookieless authentication in your website, you have to create your own custom middleware (or do not use OWIN).

Tip: Form authentication with Katana requires ASP.NET Identity, so if you don't know it I recommend taking a look at the ASP.NET website: http://www.asp.net/identity.

Installation

There are two ways to create a project using OWIN for authentication. The first is to use the template included with ASP.NET MVC 5 and create your application on top of it.

The second is to install and configure the right packages manually, which is probably the best way if you want to add OWIN to an existing application.

MVC 5 Template

The absolute easiest way is to use an ASP.NET MVC 5 template. To do so, open Visual Studio and create a new web application project with the MVC template.

New ASP.NET MVC project

Before clicking OK, it is important to specify the authentication mode by clicking the Change Authentication button on the right side of the window.

Changing the authentication mode

For form authentication, we are going to use the Individual User Accounts option.

The result is a web application that supports form authentication and social authentication (Facebook, Google, Twitter, and so on), and uses Entity Framework to create and save credentials into a SQL database.

From Scratch or an Existing Application

Another way to implement form authentication is to manually add OWIN. This is probably the most useful approach if you’re adding the authentication to an existing project.

Adding NuGet package for OWIN implementation of ASP.NET Identity

The first step is to install the right packages: Microsoft.AspNet.Identity.Owin (as shown in Figure 40) and Microsoft.Owin.Host.SystemWeb.

The following figure shows what you should see installed in your project after installing the two packages and their dependencies.

Installed NuGet packages

The next step is to create the startup class needed by OWIN.

using Microsoft.Owin;

using Owin;

 

[assembly: OwinStartupAttribute(typeof(Syncfusion.OwinSuccinctly.FormsAuthentication.Startup))]

namespace Syncfusion.OwinSuccinctly.FormsAuthentication

{

    using System;

 

    using Microsoft.AspNet.Identity;

    using Microsoft.AspNet.Identity.Owin;

    using Microsoft.Owin.Security;

    using Microsoft.Owin.Security.Cookies;

 

    public class Startup

    {

        public void Configuration(IAppBuilder app)

        {

            app.UseCookieAuthentication(

                new CookieAuthenticationOptions

                    {

                        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,

                        AuthenticationMode = AuthenticationMode.Active,

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

                    });

        }

    }

}

The code is pretty simple. The extension method UseCookieAuthentication enables the authentication and CookieAuthenticationOptions is its configuration.

The first important thing to notice is the two properties AuthenticationType and AuthenticationMode.

The first is part of ASP.NET Identity. The second one is part of OWIN, for which there are two possible values as shown in the following table. The descriptions come from the official MSDN site.

AuthenticationMode values

Value

Description

Active

In Active mode the authentication middleware will alter the user identity as the request arrives, and will also alter a plain 401 as the response leaves.

Passive

In Passive mode the authentication middleware will only provide user identity when asked, and will only alter 401 responses where the authentication type named in the extra challenge data.

Of course, there are other important settings we have to manage like authentication cookies, login URL, and so on. The following table shows all the available options you can manage with the CookieAuthenticationOptions class.

Cookie authentication options

Options

Description

CookieDomain

Defines the cookie domain.

CookieHttpOnly

True (default) or False defines whether the cookie is HttpOnly.

CookieName

The name of the cookie (e.g. AuthorizationCookie).

CookiePath

The path of the cookie. The default is /.

CookieSecure

An enum with three options: Always (HTTPS scenario), Never (HTTP), and SameAsRequest (hybrid HTTP/HTTPS).

ExpireTimeSpan

Defines the expiration of the cookie. The default is 14.

ReturnUrlParameter

The name of the return parameter used for the redirect after a successful login.

SlidingExpiration

Manages the expiration extension for active users.

As explained in the authentication section at the beginning of the chapter, the MVC controller is really important because it contains the authorize attribute necessary to prevent anonymous access.

Now that the OWIN part is complete, it is time to write some code on MVC.

Note: In this book, we are not going to explain ASP.NET MVC, so it is important to know what a controller, action, and routing is, or how to manage a POST request.

Because the login page specified in the OWIN configuration is /Account/Login, the first thing to do is to create the AccountController and the Login action.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Mvc;

 

namespace Syncfusion.OwinSuccinctly.FormsAuthentication.Controllers

{

    using System.Security.Claims;

    using System.Threading.Tasks;

 

    using Microsoft.AspNet.Identity;

    using Microsoft.Owin.Security;

 

    using Syncfusion.OwinSuccinctly.FormsAuthentication.Models;

 

    public class AccountController : Controller

    {

        //

        // GET: /Account/Login

        [AllowAnonymous]

        public ActionResult Login(string returnURL)

        {

            ViewBag.ReturnURL = returnURL;

            return View();

        }

 

 

        //

        // POST: /Account/Login

        [HttpPost]

        [AllowAnonymous]

        [ValidateAntiForgeryToken]

        public async Task<ActionResult> Login(LoginViewModel model, string returnURL)

        {

            if (ModelState.IsValid)

            {

                if (model.Email == "[email protected]" && model.Password == "Password1")

                {

                    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);

 

                    var user = new IdentityUser("1") { UserName = "user" };

 

                    var manager = new UserManager<IdentityUser>(new IdentityStore());

 

                    ClaimsIdentity identity = await manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);

                    AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = model.RememberMe }, identity);

                    return this.Redirect(returnURL);

                }

                else

                {

                    ModelState.AddModelError("", "Invalid username or password.");

                }

            }

 

            // If we got this far, something failed, redisplay form

            return View(model);

        }

 

        private IAuthenticationManager AuthenticationManager

        {

            get

            {

                return HttpContext.GetOwinContext().Authentication;

            }

        }

    }

}

If you have never used ASP.NET Identity, this code probably seems complex, but it is really powerful. In fact, we will see later how to combine different kinds of authentication using the same approach.

The most important method of the previous code block is AuthenticationManager.SignIn. It creates the authentication cookie used to check credentials across the requests. The other methods (CreateIdentityAsync and UserManager<IdentityUser>) are needed by ASP.NET Identity.

Testing

If you did everything right, running the app and typing [email protected] as the username and Password1 as the password in the login form should log you in.

Social Authentication

As we have just seen, using form authentication with OWIN and ASP.NET Identity is really simple. Now we will see how to extend the authentication, allowing users to log into the application using social networks like Twitter, Facebook, Google, and so on.

A Brief of Social Authentication

Before looking at how to implement social authentication in our application, it is important to know that all the most famous social networks use OAuth 1.x/2.x as their authentication workflow.

OAuth was not designed for authentication but for authorization decisions across a network of web-enabled applications and APIs. In fact, you can use OAuth to authenticate a user or an application that needs to use external APIs.

Another important authentication protocol (not explained in this book) is OpenID which is a simple identity layer, designed on top of OAuth 2.0 protocol, that offers the basic profile information about the end-user in an interoperable and REST-like manner.

Introducing OAuth

In this book, we are not going to explain how OAuth works or how to implement an OAuth server, but we need to know what it is.

Here is a good description from the OAuth website:

An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications.

OAuth is really helpful because users don’t have to complete another registration process, but can simply login via one of the social networks they already use.

In addition, no user credentials are shared with the third-party application because all the communication between the client app (your website in this case) and the authorization server (Facebook, Twitter, Google and so on) is token-based.

The next figure shows the sequence diagram of an OAuth authorization flow.

Figure 7

OAuth sequence diagram

Even though this workflow may seem complex, in fact it is not. We are already used to this kind of workflow when we log into an application using a social network like Facebook. In fact, we have seen this screen thousands of times.

.

Facebook authorization request

This screen is the Authenticate and Authorize Client step in the diagram in Figure 42.

Setting Up OWIN

Now that it is clear what OAuth is and how it works, it is time to set up your OWIN application.

Note: The code for the rest of the explanation is built on top of the sample created in the Form Authentication section of this chapter.

Because the authentication comes from an external application (the social network), it is important to configure our middleware to accept external cookies for authentication.

app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

Now the application is almost ready, and we need to configure the desired social media and the right endpoint (MVC actions) to manage communication between our application and the authentication server.

The last part is the same for all social authentications because all of them are based on the same protocol (OAuth precisely). We will explain this final part further in the OAuth Token Validation section.

Note: Twitter, Facebook, and Google sections are very similar. If you don't need to implement all these providers, you can choose your favorite and jump to the OAuth Token Validation section.

Twitter Authentication

Twitter, along with Facebook, is one of the most popular social networks, especially if you are a developer. As such, it offers the opportunity to use its authentication in your application.

Register Your Application

As we saw in the previous section, OAuth requires registering with the authorization server. To use Twitter’s authentication, we need to go to the Twitter application management site at apps.twitter.com and follow the steps to register an application.

Create new application

With OWIN, you don't have to specify the Callback URL because it uses the default value signin-twitter.

Register application form

To complete the integration with Twitter, we need the API key and the API secret for the application we just registered. Open the Keys and Access Tokens tab.

Registered application summary

Register application API

Note: By default, a Twitter app is read-only. This means your application can't tweet for the user but can only read data. If you want to do more, you can change this by clicking the Change App Permissions button.

Now that we have all the ingredients ready, we can go back to writing code on our application and add the OWIN Twitter package, Microsoft.Owin.Security.Twitter.

NuGet Package Manager with Twitter-related OWIN package

Finally, paste your API keys in the OWIN configuration file.

app.UseTwitterAuthentication(

    consumerKey: "my-api-key",

    consumerSecret: "my-api-secret");

Now the OWIN part is complete. We don't have to write more code here (that's why OWIN is so cool). The next step is to write the necessary code to manage tokens, cookies, and all the other stuff required by OAuth. We will cover this part in the OAuth Token Validation section.

Facebook Authentication

Facebook authentication is not so different from Twitter because it is based on the same protocol, so we’ll follow the same steps for Twitter but on the Facebook website.

Register your Application

Because OAuth requires registering with the authorization server, we need to go to the Facebook Developer Website at developers.facebook.com/apps and register our application to obtain the necessary keys to integrate the login between the two applications.

Register a new Facebook app

Creating a new application

Registered application summary

Now that we have created our application, we have to specify the allowed domains. In our case it will be localhost, but you also need to specify your production domain. The steps are demonstrated in the following figures.

After creating the app on the Facebook developer site, click Settings on the left side of the page and then click the Add Platform button.

Application settings

Select the Website option.

Adding a new platform

Specify localhost as the App Domain and the Site URL.

Application settings

Finally, everything is ready and we can register the App ID and App Secret into OWIN, but first, it is necessary to install the right OWIN Facebook package from NuGet, Microsoft.Owin.Security.Facebook.

Manage NuGet packages with Facebook-related OWIN package

As you did for Twitter authentication, specify the appId and appSecret in the OWIN Startup class.

app.UseFacebookAuthentication(

    appId: "my-app-id",

    appSecret: "my-app-secret");

We are done. Facebook integration with OWIN is now complete, but it is necessary to manage the cookies between the requests. We will cover that part in the OAuth Token Validation section.

Google Authentication

Until a few months ago, Google was offering the opportunity to use its authentication base on different protocols:

  • Open ID 2.0
  • OAuth 1.0
  • OAuth 2.0

For security reasons, it is no longer possible to use the first two types of authentication, so we have to do the same thing we did with Facebook and Twitter but on the Google Developers Console.

Create Your Project

Google uses a different naming for the registration process. In fact, here you are not registering your application, but instead creating a project.

Go to the Google Developers Console at console.developers.google.com/project and create a new project.

Create Project

New Project form

After a few seconds, the project should be created and we can manage our client credentials. Click the Credentials option on the left side of the screen.

Credentials settings

Under the OAuth header, click the Create new Client ID button.

Create new client ID

Specify /signin-google as the redirect URI. OWIN manages callback URLs automatically, with different callbacks per social authentication.

Create Client ID form

Credentials

Now that your project is registered for Google authentication, install the Google authentication provider package via NuGet.

Google Security NuGet package

Finally, copy the Client ID and Client Secret values into the OWIN Startup class.

app.UseGoogleAuthentication(

    clientId: "my-client-id",

    clientSecret: "my-client-secret");

The OWIN Google integration is done, but let's see how to let your users log in via their social network accounts.

OAuth Token Validation

Now that all social media sites are ready to communicate with our application, it is important to correctly configure the application to accept their callbacks.

Note: The code we are going to see in this section is part ASP.NET MVC code and ASP.NET Identity. Nothing here is OWIN, but it is necessary to complete the integration. Moreover, there are several ways to create this part. ASP.NET Identity is not the only one, but it is suggested.

Show Login Buttons on Login Page

Of course, we have to show the right login buttons on the login page. This means not only the classic login form, but also our social authentication integration. The goal here is to create a “Log in with…” button for each social network we registered in our application.

To do that, we have to retrieve all registered social authentications using a specific extension method for the HttpContextBase class that returns an OwinContext with all we need.

In our Login.cshtml file, we have to retrieve all the registered social authentications using the following code.

@{

    var loginProviders = Context.GetOwinContext()

        .Authentication.GetExternalAuthenticationTypes();

}

Now we have to iterate over them and create the login button, but before doing it, it is important to understand why we can't simply put a link in our page.

When a user clicks on an authentication link on Twitter, for example, we have to send a set of information to specify to Twitter which application it is calling, the redirect URL, and other info. Part of this info must be specified in HTTP request headers, so we have to create a POST form, submit the provider info to our MVC action, and then redirect the user to the social network for the authentication.

Still working with our Login.cshtml file, the following code does just that.

@using (Html.BeginForm("ExternalLogin", "Account"))

{

@Html.AntiForgeryToken()

<div id="socialLoginList">

    <p>

        @foreach (AuthenticationDescription p in loginProviders)

        {

            <button type="submit" class="btn btn-default"

                    id="@p.AuthenticationType" name="provider"

                    value="@p.AuthenticationType"

                    title="Log in using your @p.Caption account">

                    @p.AuthenticationType

            </button>

        }

    </p>

</div>

}

Until now, it hasn’t been anything complex; we retrieved the registered providers, iterated the collection, and created a button. Each button submits to an action called ExternalLogin in the AccountController sending the authentication provider.

Now we have to get this information and redirect it to the social authentication. Open the AccountController we created in the Form Authentication section and add the following code.

[HttpPost]

[ValidateAntiForgeryToken]

public ActionResult ExternalLogin(string provider, string returnURL)

{

    // Request a redirect to the external login provider

    return new ChallengeResult(

        provider,

        URL.Action(

            "ExternalLoginCallback",

            "Account",

            new { ReturnURL = returnURL }

            )

        );

}

The code is really simple. The action gets the provider and redirects the user to the login page, sending the callback URL (ExternalLoginCallback).

The unusual code for MVC developers is the class ChallengeResult that's not a part of MVC, Identity, or OWIN, so we have to create it.

internal class ChallengeResult : HttpUnauthorizedResult

{

    public ChallengeResult(string provider, string redirectUri)

        : this(provider, redirectUri, null)

    {

    }

 

    public ChallengeResult(string provider, string redirectUri, string userId)

    {

        LoginProvider = provider;

        RedirectUri = redirectUri;

        UserId = userId;

    }

 

    public string LoginProvider { get; set; }

    public string RedirectUri { get; set; }

    public string UserId { get; set; }

 

    public override void ExecuteResult(ControllerContext context)

    {

        var properties = new AuthenticationProperties() { RedirectUri = RedirectUri };

        if (UserId != null)

        {

            properties.Dictionary["XsrfId"] = UserId;

        }

        context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);

    }

}

All this is necessary to create the right redirect request. Now that we have the action ready, let's try the application.

If we did everything right, the login layout should result in the following in our application.

C:\Users\user\Documents\GitHub\Syncfusion-OwinSuccintly\markdown\Authentication\Assets\Social Authentication\Login-Page.png

Login page

Clicking the Twitter button should redirect to Twitter page that asks to authorize the app.

C:\Users\user\Documents\GitHub\Syncfusion-OwinSuccintly\markdown\Authentication\Assets\Social Authentication\Login-Page-Twitter.png

Twitter authorize app page

Next, after providing the right credentials, we should be sent back to our application where we will get an error.

C:\Users\user\Documents\GitHub\Syncfusion-OwinSuccintly\markdown\Authentication\Assets\Social Authentication\Login-Page-404.png

404 error on calling callback page

No worries. That's okay. The social login is redirecting the user to Account/ExternalLoginCallback because we specified it before. Now we have to create the action to process the callback.

[AllowAnonymous]

public async Task<ActionResult> ExternalLoginCallback(string returnURL)

{

    var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();

    if (loginInfo == null)

    {

        return RedirectToAction("Login");

    }

 

           

    //Verify if a user with loginInfo.Login exists in your database

    var user = new IdentityUser("1") { UserName = "imperugo" };

 

    if (user != null)

    {

        AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);

 

        var manager = new UserManager<IdentityUser>(new IdentityStore());

 

        ClaimsIdentity identity = await manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);

        AuthenticationManager.SignIn(new AuthenticationProperties(), identity);

        return this.RedirectToAction("Index", "Home");

    }

    else

    {

        // If the user does not have an account, then prompt the user to create an account

        return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email });

    }

}

By running the demo application again and logging in using one of the registered social networks, you should be able to see the protected page.

Of course, this code is only a demo. In a final application you have to implement your login persistence, but the demo works and allows you to test the login integration easily.

Conclusions

In this chapter, you have learned how to manage authentication using OWIN and Katana with different providers, starting with the classic form authentication and trying the most common social networks like Twitter, Facebook, and Google.

NuGet offers other providers for Microsoft, Yahoo, and many others, so browse NuGet to see what else is out there.

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.