OAuth “Implicit Grant” flow with OWIN/Katana

Today we will implement the Implict Grant Flow with OWIN.If you are not familiar with this OAuth flow then please refer here .

First let’s see what the request from client looks like

URL:
http://localhost:1234/api/auth?client_id=123456&redirect_uri=http://localhost:4321/TokenReciever.html&response_type=token
Method:
GET

Unlike the Resource Owner grant flow the parameters here are specified in request URL itself and not POSTed through body of request.

Now on to server side :

1. Required Packages

Same as in previous post on Resource Owner grant flow

2. OWIN Startup Class

Setup is same as stated in previous post but due to how implict flow works,we will not point to token endpoint.We will now point to authorization end point.

Code :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Owin;
using Microsoft.Owin.Security.OAuth;
using Owin;

[assembly: OwinStartup(typeof(ImplictOAuthFlow.StartUp))]
namespace ImplictOAuthFlow
{

public class StartUp
 {

public void Configuration(IAppBuilder app)
 {
 app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
 {
 // the endpoint path which will be consumed via HTTP. e.g. http://website[:port]/api/auth

 AuthorizeEndpointPath = new PathString("/api/auth"),
 //Provider is a class which inherits from OAuthAuthorizationServerProvider.Will be covered next.
 Provider = new CustomAuthServer(),
 // mark true if you are not on https channel
 AllowInsecureHttp = true,

});
 // indicate our intent to use bearer authentication
 app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
 {
 AuthenticationType = "Bearer",
 AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,

});
 }
 }
}

3. Provider class
For Implicit Grant flow we need to override different set of methods.

code :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Microsoft.Owin.Security.OAuth;

namespace ImplictOAuthFlow
{
 class CustomAuthServer : OAuthAuthorizationServerProvider
 {

public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
 {
 //We validated that Client Id and Reditect Uri are indeed what we expect
 if (context.ClientId == "123456" && context.RedirectUri.Contains("localhost"))
 context.Validated();
 else
 context.Rejected();

return Task.FromResult<object>(null);
 }

public override Task AuthorizeEndpoint(OAuthAuthorizeEndpointContext context)
 {
 // The authentication types should be set to "Bearer" while setting up the ClaimsIdentity
// I have set up basic mandatory ClaimsIdentity. You can add the necessary claims if required.
 System.Security.Claims.ClaimsIdentity ci = new System.Security.Claims.ClaimsIdentity("Bearer");
 context.OwinContext.Authentication.SignIn(ci);
 context.RequestCompleted();
 return Task.FromResult<object>(null);
 }

}
}

4. Receiving Token

Token is received in a redirect to the URL mentioned in “redirect_uri” parameter in request URL.So the response we get is :

http://localhost:4321/TokenReciever.html#access_token=wl8LNcbvgSF2BFMgYTn6Qt9x2cO-XTMBRBty200m_pFMsts9YW8Ydyj2I7b8ThTAZLMg6GtLuJcGOm8dl0AAxRXcOde6Jk8RPva_tqjRmR8vCbEkiUoEaJsybyjYenZkifl3mRJsEZwPTbtu0wusn_dPB1dVlFcI0-wivyVwzCQNE1vZTnJdIUA2Z5LSvzpflvl6zgSX45LbRj3uH7i58A&token_type=bearer&expires_in=1200

OAuth “Resource Owner Password Credentials Grant” flow with OWIN/Katana

Security is an essential component of any web application worth its salt. .Net has always offered many mechanisms to this end.But now we see OAuth ,the open security protocol, is being adopted very fast due to its simple and standardized approach.

Microsoft now has provided support for OAuth via OWIN/Katana.

OAuth offers many authorization flows.

Today we will cover the “Resource Owner Password Credentials Grant” http://tools.ietf.org/html/rfc6749#section-4.3

Below is a sample client request for this flow

URL: http://somesite/api/token

Header: Content-Type: application/x-www-form-urlencoded

Body: client_id=123456&grant_type=password&username=user&password=pwd

Method: POST Now on to code :

1. Required Packages

  1. Owin
  2. Microsoft.Owin
  3. Microsoft.Owin.Security
  4. Microsoft.Owin.Security.OAuth
  5. Microsoft.Owin.Host.SystemWeb

2. OWIN Startup Class

If you are not aware of the essential OWIN Startup class,please refer here http://www.asp.net/aspnet/overview/owin-and-katana/owin-startup-class-detection Below is the bare essential startup code :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Owin;
using Microsoft.Owin.Security.OAuth;
using Owin;

[assembly: OwinStartup(typeof(TestOAuth.StartUp))]
namespace TestOAuth
{

public class StartUp
{

public void Configuration(IAppBuilder app)
{
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
// the endpoint path which will be consumed via HTTP. e.g. http://website[:port]/api/token
// it should begin with a leading slash so /token is also ok but I have kept it /api/token to match my default route in Web-API
TokenEndpointPath = new PathString("/api/token"),
//Provider is a class which inherits from OAuthAuthorizationServerProvider.Will be covered next.
Provider = new CustomAuthServer(),
// mark true if you are not on https channel
AllowInsecureHttp=true
});
// indicate our intent to use bearer authentication
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
AuthenticationType = "Bearer",
AuthenticationMode=Microsoft.Owin.Security.AuthenticationMode.Active

});

}
}
}

3. Provider class

As mentioned in code above,we have implemented a custom provider named as “CustomAuthServer”. The provider is where the action takes place.It has methods which authenticates the request as received by token end point and if all is well, returns the access token. Lets jump to the code (again bare essential )

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Owin;
using Microsoft.Owin.Security.OAuth;
using Owin;

namespace TestOAuth
{
class CustomAuthServer : OAuthAuthorizationServerProvider
{
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId, clientSecret;
//gets the clientid and client secret from request body.If you are providing it in header as basic authentication then use
//context.TryGetBasicCredentials
context.TryGetFormCredentials(out clientId, out clientSecret);
// validate clientid and clientsecret. You can omit validating client secret if none is provided in your request (as in sample client request above)
if (clientId == "123456" )
context.Validated();
else
context.Rejected();
return Task.FromResult(0);

}
public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
//we check if the passed username and password are correct.

if (context.UserName == "user" && context.Password == "pwd")
{
System.Security.Claims.ClaimsIdentity ci = new System.Security.Claims.ClaimsIdentity("ci");
//this indicates that user is valid one and can be issued a token.
//it has several overloads ,you can take what fits for you.I have used it with ClaimsIdentity
context.Validated(ci);
}
else
{
// a custom error message can be returned to client before rejecting the request.
context.SetError("Incorrect Credentials");
context.Rejected();
}
return Task.FromResult(0);
}

public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
// This is called last in pipeline when token is about to be issued successfully.

}
}
}

The overriden methods above are the ones required for Resource Owner Password Grant Flow. For other flows,other methods are required to be overriden. We will cover other flows in later posts.

4. Receiving Token

A typical token reply is : {“access_token”:”09E5QzjmV5Tk1PNlCgCZPMMLM4SsyNnHRIxF-XbwEAnGwwlLrYjQKEyLvmDsk7-1LcdDhNzyK1SQdxkFAr3Gq2n3rJZuBfqa-svAuEeKFLqhevHX0mwuqav_7kj_rARNKPi6laph3a1VRHPWTqdI91KwdYoweLGhsMZvRG6tXPSi5jd_p-vqlrGPXp6lzl4S”, “token_type”:”bearer”, “expires_in”:1199}

This completes the flow for issuing token.