6

I am creating a simple authentication server using the default owin oauth server. After supplying the correct credentials a bearer token is generated and returned to the client. I used among others this tutorial by Taiseer

I would like to store the token in a database before the token is send to the client. Maybe I completely overlooked it, but where can I get the token before it is send? As far as I know the token is generated after the ticket is validated in the GrantResourceOwnerCredentials method. I am guessing the token is stored in the context. How can I get it out?

Startup.cs

private void ConfigureAuthServer(IAppBuilder app) {
  // Configure the application for OAuth based flow
  var oAuthServerOptions = new OAuthAuthorizationServerOptions {
    //For Dev enviroment only (on production should be AllowInsecureHttp = false)
    AllowInsecureHttp = true,
    TokenEndpointPath = new PathString("/oauth/token"),
    Provider = new ApplicationOAuthProvider(),
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(14)
  };

  // Enable the application to use bearer tokens to authenticate users
  app.UseOAuthAuthorizationServer(oAuthServerOptions);
  app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}

ApplicationOAuthProvider

public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) {
  //Dummy check here
  if (context.UserName != context.Password) {
    context.SetError("invalid_grant", "The user name or password is incorrect");
    return Task.FromResult<object>(null);
  }

  var claims = new List<Claim> {
    new Claim(ClaimTypes.NameIdentifier, context.UserName),
    new Claim(ClaimTypes.Name, context.UserName)
  };

  var oAuthIdentity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);

  AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties());
  context.Validated(ticket);
  return Task.FromResult<object>(null);
}

public override Task TokenEndpoint(OAuthTokenEndpointContext context) {
  foreach (KeyValuePair<string, string> property in context.Properties.Dictionary) {
    context.AdditionalResponseParameters.Add(property.Key, property.Value);
  }

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

Note: for those who wonder why I want to store the tokens.. it is a requirement I have to fulfill.

David K
  • 333
  • 2
  • 12

1 Answers1

12

To fetch the token before it is sent to the client you must override TokenEndpointResponse:

public override Task TokenEndpointResponse(OAuthTokenEndpointResponseContext context)
{
    return base.TokenEndpointResponse(context);
}

the context object has a property AccessToken which will contains the representation of the token as a string.

enter image description here

OAuthTokenEndpointResponseContext contains a dictionary of objects
IDictionary<string, object> in AdditionalResponseParameters which allows us to find all the claims for the indentity.

If we wanted to fetch the expiration of the token we would find the claim .expires in the dictionary:

context.AdditionalResponseParameters[".expires"]

There's a github repository if someone is interested to play with a simple integration of client and server interaction.

LeftyX
  • 35,328
  • 21
  • 132
  • 193
  • Glad I've helped, David K. Cheers. – LeftyX Oct 19 '15 at 14:47
  • how to validate access token from database for each api request? – Saad Khan Jan 24 '17 at 17:28
  • @SaadKhan: `GrantResourceOwnerCredentials` is the entry point where the request for a resource is validated. `OAuthGrantResourceOwnerCredentialsContext` will provide you 2 properties: `UserName` & `Password`. – LeftyX Jan 24 '17 at 19:15
  • @LeftyX that's true. I am already validating those from database and if validated then access token is generated. I want to store access token in database, which is I am doing using **TokenEndpointResponse**. Now I want to validate this access token for each API Request. Let suppose I have a endpoint name **abc.com/api/search** and user is passing access token in request header. I want to match that access token from my database before processing this request. How can I do that? – Saad Khan Jan 24 '17 at 20:16
  • @SaadKhan: The whole idea of the bearer token is, once validated, it's valid and your handler (api) will be called only if there's a valid (validated) token with the right claims, scopes and authorizations. The token can be invalidated. A few [articles](http://bitoftech.net/2015/01/21/asp-net-identity-2-with-asp-net-web-api-2-accounts-management/) have been written on the subject. When your handler is called you can fetch the user info using `var identity = User.Identity as ClaimsIdentity;`. – LeftyX Jan 25 '17 at 09:01
  • So once user email and password is validated there is no need to store accesstoken in database and then validate it on each subsequent request to my other api methods? – I Love Stackoverflow Oct 24 '17 at 12:09
  • @Learning: The token must be stored in the client for each subsequent request. The validation won't happen again. – LeftyX Oct 24 '17 at 14:04
  • So consider after login i want to redirect user to a page to show list of employee right.So now again i will make an api call to get employee list passing access token with that employee list call but then in order to validate that authorize user want to see list of employee how i will validate this if validation wont happen again? – I Love Stackoverflow Oct 24 '17 at 14:44
  • Can you please clear my above doubt please as i am trying to understand the implementation of this token based in owin framework – I Love Stackoverflow Oct 25 '17 at 10:01
  • @Learning: I wrote a [response](https://stackoverflow.com/a/26369622/219406) some time ago with some more details. There are some links to articles which would explain a lot more. Every secured api endpoint needs to be accessed with a valid token. The token is validated by the framework itself; it is decrypted and validated using the machineKey (web.config) to extract the authentication ticket. [Here](http://bitoftech.net/2014/09/24/decouple-owin-authorization-server-resource-server-oauth-2-0-web-api/) you can find a good explanation. – LeftyX Oct 25 '17 at 11:19
  • Thank you so much sir for the link and for the info.Owin framework works only with sql server or it can work with different RDBMS like MYSQL or ORACLE also? – I Love Stackoverflow Oct 25 '17 at 14:01
  • 1
    @Learning: `Owin` doesn't have any dependencies on a database, nor the api or the oauth integration. Most solutions you will find on the web use `asp.net identity`, `Entity Framework` and `sql server` for the `UserStore`. That can be customized to use other storage systems. This [answer](https://stackoverflow.com/a/31322732/219406) will help you to dig into the matter. At the bottom you will find an link to a github repo which uses a custom db. Cheers. – LeftyX Oct 25 '17 at 14:20
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/157488/discussion-between-learning-and-leftyx). – I Love Stackoverflow Oct 25 '17 at 14:29
  • @LeftyX want to get expiry date of token. so what i need to add in above code – A.Goutam Mar 19 '20 at 13:45
  • @A.Goutam: I have updated my answer. `context.AdditionalResponseParameters[".expires"]` would contain the expiration of the token. Hope it helps. – LeftyX Mar 19 '20 at 16:37