【问题标题】:Refresh token expired as soon as access token访问令牌后刷新令牌已过期
【发布时间】:2018-06-05 00:31:59
【问题描述】:

我正在实现 JWT 刷新令牌,并为刷新令牌设置不同的过期时间,但它的过期时间与访问令牌相同

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

保存在数据库中

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

结束保存 Db

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

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

任何帮助我做错了什么?

【问题讨论】:

  • 您在提供的代码中哪里设置了不同的过期时间?我看到这段代码中有两个过期时间设置为相同的值。
  • 这是刷新令牌
  • 请为您的访问令牌添加逻辑。如果时间相同,我们需要查看两个令牌。
  • 您能否在您的问题中为 IAuthenticationTokenProvider 编写整个实现代码?
  • 你似乎在使用相同的refreshTokenLifeTime 两个令牌。

标签: c# oauth-2.0 jwt refresh-token


【解决方案1】:

刷新令牌不会延长到期时间,这称为滑动到期,您不能使用访问令牌来做到这一点。我使用刷新令牌来更新用户角色,而不是过期时间。 检查此Link 以了解 Slidingexpiration 我使用下面的代码来刷新令牌并持久化它

  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);
            }
        }
    }
}

现在请求上下文包含之前为该用户存储的所有声明,您需要添加允许您发出新声明或更新现有声明并将它们包含到之前生成的新访问令牌中的逻辑 您需要在您拥有的 AuthorizationServerProvider 类中添加以下代码。

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);
    }

【讨论】:

  • 我的代码有什么问题,同样的代码,我只粘贴了刷新令牌逻辑
  • 实现了同样的逻辑,所以每次生成访问令牌的时候也会生成刷新令牌,所以你在哪里使用刷新令牌的有效期更长
  • 请再次查看答案,我已经更新它更方便了
  • 哦,我想你错了,刷新令牌不是为了延长过期时间,这叫滑动过期,不能用访问令牌来做。我使用刷新令牌来更新用户角色,而不是过期时间。
  • 检查此链接可能会有所帮助stackoverflow.com/questions/42330013/…
【解决方案2】:

这是错误的

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

您正在读取生命周期,而不是将其设置为任何新值。

【讨论】:

  • context.Ticket.Properties.ExpiresUtc = refreshTokenLifeTime;... 这里我正在设置值
  • @Md.ParvezAlam,您刚刚从 Owin 上下文中读到了它。您没有在任何地方生成 av tokenvalue(在您提供的代码示例中)。
猜你喜欢
  • 2019-05-31
  • 2021-12-19
  • 2014-01-01
  • 2019-04-07
  • 1970-01-01
  • 2021-10-03
  • 2020-03-10
  • 1970-01-01
  • 2021-08-25
相关资源
最近更新 更多