ASP.NET MVC OAuth2.0 Simple Example

In this article, we will make an example project on how to do a Token Based Authentication while developing a RESTful service with ASP.NET Web API


OAuth20.png

When we want to look at the life cycle of the Token Based Authentication process;


- Client enters its own credential information and this information is sent to Authorization Server.


- If this information is verified by the Authorization Server, an Access Token Http Response is returned to the client.


- The client now provides access to the services it wants to access by adding the Access Token to the Authorization Header of the HTTP Request.


In our example, we will provide authentication with the OAuth 2.0 protocol and we will use Microsoft's Owin library for this.


We will demonstrate OAuth 2.0 mechanism to authorize an ASP.NET MVC Web API via OWIN security layer.


Access token is generated automatically based on user's credential.


Access token is activated for a specific time period.


Username/Password is encrypted in base64 format. So, hackers can easily decrypt the request headers.


Create ASP.NET Web API Project


- Select New > Project > ASP.NET Web Application and Name it "OAuth20"


- Select the Empty Template and the Web API core reference from the coming dialog


- Right click the project and select the "Manage NuGet packages..." option


OAuth20_1.png

OAuth20_2.png

OAuth20_3.png

OAuth20_4.png

Install Microsoft.Owin.Security.OAuth, Microsoft.Owin, Microsoft.Owin.Host.SystemWeb and Microsoft.Owin.Cors


Create a new folder named "OAuth" into the project root directory. Add two new class Startup.cs and OAuthProvider.cs in the OAuth folder


using Microsoft.Owin.Security.OAuth;
using System.Security.Claims;
using System.Threading.Tasks;

namespace OAuth20.OAuth
{
    public class OAuthProvider : OAuthAuthorizationServerProvider
    {
        //We override the ValidateClientAuthentication method to allow client access to the OAuthAuthorizationServerProvider class
        public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            context.Validated();
        }
        //We override the GrantResourceOwnerCredentials method to allow the OAuthGrantResourceOwnerCredentialsContext class to have resource access.
        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
            //We are doing the necessary validation process for the user to get access_token
            if (context.UserName == "Mike" && context.Password == "123456")
            {
                var identity = new ClaimsIdentity(context.Options.AuthenticationType);

                identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
                identity.AddClaim(new Claim(ClaimTypes.Role, "User"));

                context.Validated(identity);
            }
            else
            {
                context.SetError("invalid_grant", "Username or password is incorrect.");
            }
        }
    }
}

using Microsoft.Owin;
using Microsoft.Owin.Security.OAuth;
using Owin;
using System;
using System.Web.Http;
[assembly:OwinStartup(typeof(OAuth20.OAuth.Startup))]
namespace OAuth20.OAuth
{
    
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            //Enable CORS for making request using browser from different domains
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
            OAuthAuthorizationServerOptions options = new OAuthAuthorizationServerOptions
            {
                AllowInsecureHttp = true,

                //The path for generating the token
                TokenEndpointPath = new PathString("/token"),

                //Setting the token expired time (24 hours)
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),

                //OAuthProvider class will validate the user credentials
                Provider = new OAuthProvider()
            };
            app.UseOAuthAuthorizationServer(options);
            app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

            HttpConfiguration config = new HttpConfiguration();
            WebApiConfig.Register(config);
        }
    }
}

Although all operations will be carried out over an access token, data security between client and server should be ensured with SSL.


We will use Bearer Authentication as the Authentication type.


Add a Web API Controller


using System.Security.Claims;
using System.Web.Http;

namespace OAuth20.Controllers
{
    public class TestController : ApiController
    {

        [Authorize(Roles = "User")]
        [HttpGet]
        [Route("api/test/user")]
        public IHttpActionResult GetUser()
        {
            var identity = (ClaimsIdentity)User.Identity;
            return Ok("Hello: " + identity.Name);
        }

    }
}

We have implemented OAuth 2.0 for Owin. Now let's use it on the controller. Add TestController in the Controllers folder.


OAuth20_5.png

As you can remember from Form Authentication, we were adding the [Authorize] attribute. We use the same attribute in Owin


Now that everything's ready on the API side, we can test our project.


OAuth20_6.png

As expected we got 401 unauthorized response.


Create Access Token


For this, we need to go to the POST type and the /token url by setting a few parameters to Headers and Body


OAuth20_7.png

OAuth20_8.png

In the returning JSON data, we see that the access_token has been created and it comes with expires_in duration.


We have given it with the AccessTokenExpireTimeSpan property in the Configuration method in the Startup.cs file.


Now let's make a GET request to the api/test/user url using this token.


OAuth20_9.png

Since our token type is Bearer, we add the Bearer tag before entering the access_token to the Authorization part in the Header, and then add the access_token


We see that we have successfully received the information from the service.


Download the source code.