Token Authentication is a very popular method to secure a web api from unwanted visitors.
The basic process flow is as follows:
- The Angular website sends credentials (username and password) to the web api.
- The web api validates that the login is accurate and returns a token to the web application.
- The web application stores this token and uses it every time it makes a subsequent call to the web api.
Obviously is not the only way to authenticate a user to the web api.
There are other methods like using cookies, online authorization services like Auth0 (which I hope will be testing next).
For this step by step token authentication in web api 2 via OWIN, I will be using the following:
- Visual Studio 2017.
- Net Framework 4.6.1
- Postman 7.1.1
- ASP.NET Web API 2 (C#)
Let’s start.
Web API Token Authentication using OWIN
1. Create a Web Api 2 project in Visual Studio 2017
- Open your Visual Studio 2017 (or the version you have installed).
- New Project → Visual C# → Web → ASP.NET Web Application (.NET Framework)
- I am not using Net Core just yet, this is a simple ASP.Net Web API 2.
- Choose any name for your Web API application.
- I am choosing .Net Framework 4.6.1
- Choosing MVC + Web API to create the web api with controllers.
- (Optional) You can create unit tests.
Here is the screen capture for the Web Api 2 creation:
After clicking OK we are rewarded with a Web API solution filled with wonderful C# code.
2. Install the Required NuGet Packages
To be able to use Token Authentication via OWIN, you need to install 3 NuGet packages:
- Microsoft.AspNet.Identity.Owin (installed version 2.2.2)
- Microsoft.Owin.Host.SystemWeb (installed version 4.0.1)
- Microsoft.Owin.Cors (installed version 4.0.1)
You can install these packages from:
- Right click the project → Manage NuGet Packages…
- or running the Install0-Package command for each of the packages from the Package Manager Console, like this:
Install-Package Microsoft.AspNet.Identity.Owin -Version 2.2.2 Install-Package Microsoft.Owin.Host.SystemWeb -Version 4.0.1 Install-Package Microsoft.Owin.Cors -Version 4.0.1
Once you have the packages in place, is time to start writing some code.
I am going to start creating the auxiliary classes like the User model, the UserService class , then we can add the token authentication, hopefully this process will be less complicated.
3. Create a User Model
Let’s start by the simplest class, our User model.
- Inside the “Models” folder, create a new class: “User.cs”
- BTW, my solution and project are called: “OwinAuthenticationWebApi”.
Here is the code for User.cs:
using System; namespace OwinAuthenticationWebApi.Models { public class User { public string Username { get; set; } public string Email { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public DateTime LoggedOn { get; set; } public int NumberOfCars { get; set; } } }
Very basic, the last property “NumberOfCars” will be used to test the Token Authorization part.
Let’s create the service now.
4. Create a Service to Fake a Database Authentication
If you are used to writing your service and repository or data layers, then this follows that pattern.
The controller calls the UserService to validate the user, in turn, the service makes a call to the database to match the username and password and validate or not a correct login.
In this basic example, we are just going to fake a call to the Db, and just return a mock user to the caller.
using System.Threading.Tasks; using OwinAuthenticationWebApi.Models; namespace OwinAuthenticationWebApi.Service { public class UserService { public async Task<User> GetUser(string username, string password) { // Match the username and password with a database repository // Return user found User user = new User { FirstName = "John", LastName = "Smith", Username = "johnsmith", Email = "john.smith@email.com" }; return user; } } }
You can very easily extend this step-by-step example to use a database back-end modifying the “GetUser” method.
Finally, it’s time to add the Token Authentication via OWIN to our Web API 2.
5. Add the OWIN Startup class
We need to create an OWIN Startup class to specify each of the components we will be using for the application pipeline.
We are going to use the OwinStartup attribute to setup our class detection. This is the most used convention, but you can also configure the startup class just based on naming convention or in the Configuration file.
Steps to create the startup class:
- Right-click the main project → Add → New Item
- Search for the “OWIN startup class”.
- Name the class “Startup.cs”
After adding some code, here is the complete startup class:
using System; using Microsoft.Owin; using Microsoft.Owin.Cors; using Microsoft.Owin.Security.OAuth; using Owin; [assembly: OwinStartup(typeof(OwinAuthenticationWebApi.Startup))] namespace OwinAuthenticationWebApi { public class Startup { public void Configuration(IAppBuilder app) { // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888 app.UseCors(CorsOptions.AllowAll); OAuthAuthorizationServerOptions option = new OAuthAuthorizationServerOptions { TokenEndpointPath = new PathString("/token"), Provider = new ApplicationOAuthProvider(), AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(60), AllowInsecureHttp = true }; app.UseOAuthAuthorizationServer(option); app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); } } }
OWIN Benefits
- You can see the attribute mentioned above: [assembly: OwinStartup(typeof(OwinAuthenticationWebApi.Startup))]
- OWIN stands for “Open Web Interface for .NET” and that is what it is, an abstraction between the web servers and the .Net web applications.
- Because the dependency between applications and web servers has been abstracted, you can easily convert your web application from IIS hosting to a self hosting environment.
UseCors
- CORS stands for “Cross Origin Resource Sharing”.
- Modern browsers do not allow the execution of scripts from different origins. CORS allows for an exception to this rule by using additional HTTP headers to let the browser run scripts from another domain.
- This is by far the best article about CORS: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
- Being that this is an example and don’t need to be particular about this protection, I am allowing any domain to call the web api: app.UseCors(CorsOptions.AllowAll).
OAuthAuthorizationServerOptions
- TokenEndpointPath: The request path client web applications used to communicate directly with the GrantResourceOwnerCredentials method.
- Provider: the object provided by the application to process events raised by the Authorization Server.
- AccessTokenExpireTimeSpan: the period of time the authentication token remains valid after being issued. The client application is expected to refresh or acquire a new access token after the token has expired.
- AllowInsecureHttp: Setting this property to true allows token requests delivered over HTTP.
- You can find the complete list of OAuthAuthorizationServerOptions properties here: https://docs.microsoft.com/en-us/previous-versions/aspnet/dn308223(v%3Dvs.113)
I really hate those Microsoft links, I know it will come back with a 404 in the future.
UseOAuthAuthorizationServer
- The next couple of lines are just setting up the authorization server.
6. Create a Class to Provide Authorization (ApplicationOAuthProvider)
Follow these steps to create a new class for OWIN authentication:
- Right-click on the main project → Add → New Class
- Name the class: “ApplicationOAuthProvider.cs”
- Inherit “OAuthAuthorizationServerProvider” (using Microsoft.Owin.Security.OAuth)
This is where all the fun happens!
In this class we call the service (UserService) to start the validation of the user and return a validation identity (ClaimsIdentity).
using Microsoft.Owin.Security.OAuth; using OwinAuthenticationWebApi.Models; using OwinAuthenticationWebApi.Service; using System; using System.Security.Claims; using System.Threading.Tasks; namespace OwinAuthenticationWebApi { public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider { public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { // connect to service to validate user User user = await new UserService().GetUser(context.UserName, context.Password); // Create ClaimsIdentity if (user != null) { var identity = new ClaimsIdentity(context.Options.AuthenticationType); identity.AddClaim(new Claim("Username", user.Username)); identity.AddClaim(new Claim("Email", user.Email)); identity.AddClaim(new Claim("FirstName", user.FirstName)); identity.AddClaim(new Claim("LastName", user.LastName)); identity.AddClaim(new Claim("LoggedOn", DateTime.Now.ToString())); context.Validated(identity); } else { context.Rejected(); context.SetError("invalid_login", "Add here your custom login error"); } } public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { context.Validated(); } } }
Few tips here:
- You can see we are adding few properties to ClaimsIdentity like Username, Email, FirstName, LastName, and LoggedOn.
- If you want to send an error message back to the front-end, remember to SetError(…) after calling Rejected(), otherwise the Error property gets reset.
- I had seen other code using the ValidateClientAuthentication method to make the user validation, not sure if I will have the time to research that, and\or which is the preferred way. If you know, please add a comment below.
7. Create a Simple Class to Test Token Authentication
Here is a simple class to test the [Authorize] attribute allowing access only with a token:
using OwinAuthenticationWebApi.Models; using System; using System.Collections.Generic; using System.Security.Claims; using System.Web.Http; namespace OwinAuthenticationWebApi.Controllers { public class CarController : ApiController { [HttpPost] [Route("api/GetNumberOfCars")] [Authorize] public User GetNumberOfCars() { // Get Cars belonging to the user // You can use the ClaimsIdentity to get info about the authenticated user. var identityClaims = (ClaimsIdentity)User.Identity; IEnumerable<Claim> claims = identityClaims.Claims; // Or do some Db operation to retrieve data User user = new User { FirstName = identityClaims.FindFirst("FirstName").Value, LastName = identityClaims.FindFirst("LastName").Value, Username = identityClaims.FindFirst("Username").Value, Email = identityClaims.FindFirst("Email").Value, LoggedOn = DateTime.Now, NumberOfCars = new Random().Next(0, 5) }; return user; } } }
Nothing really complicated here.
This basic class returns the User information (extracted from ClaimsIdentity – token) and a random number as the NumberOfCars for this user.
Notice the use of the [Authorize] attribute.
8. Testing the Token Authentication
Here we are going to make 3 simple test calls to the web api using Postman.
Compile and run the web api project.
1. Get the Token
- Here is the call to URL: http://localhost:61736/token
- Sending the user information as x-www-form-urlencoded.
- grant_type = “password” (very important)
- Returns the “access_token” and the token_type (“bearer”) and the expiration time.
2. Make a call without passing the token
- Let’s try to make a call to our test [Authorize] class, but without passing the token.
3. Finally, let’s pass the token and get the result.
- Under Authentication, you need to select the type: “Bearer Token”.
- Next to token, copy and paste the token return on the first authentication call. (In my case, it expired while I was writing this email so I had to get a new one).
- Returns the user information and the random number of cars (2).
Last Words
Protecting your web api using OWIN TOKEN AUTHENTICATION is an effective way to secure your calls from Angular or any other front-end.
This was a very simple example, hopefully enough for you to start and create your own implementation.
And when you do, I hope to hear about it, please leave your experience using our comments section.
If you like the article, please share it with your friends. Helps me a lot.