1

I am implementing JWT refresh token, and setting different time expire for refresh token, but it is taking expire time same as access token

var refreshTokenId = Guid.NewGuid().ToString("n");
DateTime refreshTokenLifeTime = context.OwinContext.Get<DateTime>("as:clientRefreshTokenLifeTime");

To save in database

RefreshToken refreshToken = new RefreshToken();
refreshToken.Token = refreshTokenId;
refreshToken.PrivateKey = context.SerializeTicket();
refreshToken.ExpiryDate = refreshTokenLifeTime;

End saving Db

context.Ticket.Properties.IssuedUtc = DateTime.Now;
context.Ticket.Properties.ExpiresUtc = refreshTokenLifeTime;

context.SetToken(refreshTokenId);
context.SetToken(context.SerializeTicket());

Any help what I am doing wrong?

Md. Parvez Alam
  • 4,326
  • 5
  • 48
  • 108

2 Answers2

4

The refresh token does not extend the time of expiration, this is called sliding expiration and you cannot do it with access tokens. I have used the refresh token to update user Roles, not the expiration time. Check this Link for Slidingexpiration I used the below code to refresh token and persisting it

  public class SimpleRefreshTokenProvider : IAuthenticationTokenProvider
{

    public async Task CreateAsync(AuthenticationTokenCreateContext context)
    {
        var clientid = context.Ticket.Properties.Dictionary["as:client_id"];

        if (string.IsNullOrEmpty(clientid))
        {
            return;
        }

        var refreshTokenId = Guid.NewGuid().ToString("n");

        using (AuthRepository _repo = new AuthRepository())
        {
            var refreshTokenLifeTime = context.OwinContext.Get<string>("as:clientRefreshTokenLifeTime"); 

            var token = new RefreshToken() 
            { 
                Id = Helper.GetHash(refreshTokenId),
                ClientId = clientid, 
                Subject = context.Ticket.Identity.Name,
                IssuedUtc = DateTime.UtcNow,
                ExpiresUtc = DateTime.UtcNow.AddMinutes(Convert.ToDouble(refreshTokenLifeTime)) 
            };

            context.Ticket.Properties.IssuedUtc = token.IssuedUtc;
            context.Ticket.Properties.ExpiresUtc = token.ExpiresUtc;

            token.ProtectedTicket = context.SerializeTicket();

            var result = await _repo.AddRefreshToken(token);

            if (result)
            {
                context.SetToken(refreshTokenId);
            }

        }
    }

    public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
    {

        var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin");
        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });

        string hashedTokenId = Helper.GetHash(context.Token);

        using (AuthRepository _repo = new AuthRepository())
        {
            var refreshToken = await _repo.FindRefreshToken(hashedTokenId);

            if (refreshToken != null )
            {
                //Get protectedTicket from refreshToken class
                context.DeserializeTicket(refreshToken.ProtectedTicket);
                var result = await _repo.RemoveRefreshToken(hashedTokenId);
            }
        }
    }
}

Now the request context contains all the claims stored previously for this user, and you need to add the logic which allows you to issue new claims or update the existing claims and contain them into the new access token generated before you need the add the below code in the AuthorizationServerProvider Class you have.

public override Task GrantRefreshToken(OAuthGrantRefreshTokenContext context)
    {
        var originalClient = context.Ticket.Properties.Dictionary["as:client_id"];
        var currentClient = context.ClientId;

        if (originalClient != currentClient)
        {
            context.SetError("invalid_clientId", "Refresh token is issued to a different clientId.");
            return Task.FromResult<object>(null);
        }

        // Change auth ticket for refresh token requests
        var newIdentity = new ClaimsIdentity(context.Ticket.Identity);
        newIdentity.AddClaim(new Claim("newClaim", "newValue"));

        var newTicket = new AuthenticationTicket(newIdentity, context.Ticket.Properties);
        context.Validated(newTicket);

        return Task.FromResult<object>(null);
    }
Hussein Khalil
  • 1,395
  • 11
  • 29
  • What is wrong with my code, the same code, I have pasted only refresh token logic – Md. Parvez Alam Dec 27 '17 at 10:30
  • The same logic implemented so each time you generate access token refresh token will also be generated, so where you are using longer validity of refresh token – Md. Parvez Alam Dec 27 '17 at 10:31
  • please check the answer again, I have updated it to be more convenient – Hussein Khalil Dec 27 '17 at 11:28
  • This is same I have implemented. Have you checked that your refresh token stay longer than access token, per your code and mine code also, when access token suppose to expire we use refresh token to regenerate access token, at that point refresh token also get refreshed and generate new refresh token – Md. Parvez Alam Dec 28 '17 at 06:20
  • 1
    Oh, I think you got it wrong, the refresh token is not to extend the time of expiration, this is called sliding expiration and you cannot do it with access tokens. I have used the refresh token to update user Roles, not the expiration time. – Hussein Khalil Dec 28 '17 at 07:13
  • 1
    check this link might help https://stackoverflow.com/questions/42330013/jwt-token-refresh-sliding-sessions-and-signout – Hussein Khalil Dec 28 '17 at 07:14
1

This is wrong

DateTime refreshTokenLifeTime = context.OwinContext.Get<DateTime>("as:clientRefreshTokenLifeTime");

you are reading the lifetime, not setting it to any new value.

Frode Nilsen
  • 167
  • 2
  • 11