I have a Web Api 2.0 running OAuth with RefreshTokens following the following link;
Locally, this is working fine and I can do the following;
- Login using credentials to get a JWT (30 min lifetime) and Refresh_Token (120hr lifetime).
- I Can then access my api using the JWT until it expires.
- when the JWT expires after 30mins request a new one using the Refresh_Token.
However, I am finding something strange happening when I publish the api to my server. I can login and get a new 30 minute JWT and use this to access the api, but when I try to use the Refresh_Token grant type to get a new JWT it sends an error;
"error" "invalid_grant"
Now, interestingly if I request a new JWT within about 10 minutes of logging in (whilst the JWT is valid) then a new one is generated. (Note I am not including the expired JWT in the header data of the request). See my screenshot of the post for a new JWT with the error;
From debug logs on the server I can see that when I call the above it is triggering the RefreshTokenProviders ReceiveAsync method but its failing to deserialize the ticket;
context.DeserializeTicket(token.ProtectedTicket);
(I have confirmed the token.ProtectedTicket is being returned from the db.) As when log out context.Ticket its showing null?
Can anyone shed any light on how the DeserializeTicket functions?
For completness please see the RecevieAsync code below;
public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
{
this.Log().Fatal(() => "In ReceiveAsync");
var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin");
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });
string hashedTokenId = new Hash(context.Token).Value();
var container = (IUnityContainer)Startup.HttpConfiguration.DependencyResolver.GetService(typeof(IUnityContainer));
var _service = new RefreshTokenService(() => container.Resolve<IGPFocusDataContext>());
var refreshToken = _service.Find(
new RefreshTokenSearchCriteria
{
Hash = hashedTokenId
});
if (refreshToken.Result != null && refreshToken.Result.Count > 0)
{
var token = refreshToken.Result.SingleOrDefault();
context.DeserializeTicket(token.ProtectedTicket);
this.Log().Fatal(() => "deserialised context.Ticket :" + context.Ticket);
this.Log().Fatal(() => "deserialised context.Ticket :" + context.Ticket.Identity.Name);
this.Log().Fatal(() => "deserialised context.Ticket.Properties.IssuedUtc: " + context.Ticket.Properties.IssuedUtc);
this.Log().Fatal(() => "deserialised context.Ticket.Properties.Expires: " + context.Ticket.Properties.ExpiresUtc);
var result = _service.Remove(token.Id);
}