3

I have a Web Api 2.0 running OAuth with RefreshTokens following the following link;

BitofTech Link Refresh Tokens

Locally, this is working fine and I can do the following;

  1. Login using credentials to get a JWT (30 min lifetime) and Refresh_Token (120hr lifetime).
  2. I Can then access my api using the JWT until it expires.
  3. 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;

invalid grant 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);

        }
Matthew Flynn
  • 3,661
  • 7
  • 40
  • 98
  • I am seeing the same behavior, did you find a solution for this? – Davy Dec 31 '16 at 06:50
  • 4
    Yes. In the end it turned out to be the iis app pools resettling itself. As the encryption is based on the key generated by this pool it was changing each time this happened. The solution was to generate and add a machine key to the web.config. – Matthew Flynn Dec 31 '16 at 06:51
  • I assume you mean iis pooL? :) – Davy Dec 31 '16 at 06:52
  • Could you give some more info about the problem? Did you manage to fix it? – Davy Dec 31 '16 at 06:57
  • 1
    Yes of course. I'm not at my machine this morning so I'll post a detailed solution later. But basically if you drill down to the serializeticket it encrypts using a machine key. When the pool resets this changes and so deserializeticket is failing as it cannot authenticate using the new key. Here's a good link http://stackoverflow.com/questions/33693386/machine-key-changes-when-app-pool-is-recycled – Matthew Flynn Dec 31 '16 at 07:02
  • 1
    It is very likely that this is the problem. I noticed before that if i keep using the application (thus preventing the iis app to go idle and die) then the token would keep working, and if enough time passed while not using the application, the refresh would fail. Im going to give this a try! – Davy Dec 31 '16 at 07:06
  • Yeps, that did it ... – Davy Dec 31 '16 at 11:12
  • Glad I could be of help. As I said I'll do a write up so hopefully it helps others. – Matthew Flynn Dec 31 '16 at 11:22
  • @MatthewFlynn i have tried same fix but it doesn't work for me, do i have to change something else tooo – MUHAMMAD MUBUSHER ASLAM Apr 17 '17 at 09:34
  • @MUHAMMADMUBUSHERASLAM so to confirm you generated and added a key to the web.config? – Matthew Flynn Apr 18 '17 at 09:52

0 Answers0