C# IdentityServer4刷新令牌:如何确定过期时间?

C# IdentityServer4刷新令牌:如何确定过期时间?,c#,identityserver4,refresh-token,C#,Identityserver4,Refresh Token,我正在使用Identity Server 4示例代码。特别是,对于客户端,我使用混合流的示例MVC客户端: 对于服务器,我将Identity server与内存中的客户端一起使用(没有实体框架,也没有ASP.Net标识): 客户机和服务器都有非常普通的开箱即用配置 我试图了解刷新令牌如何过期,以及本机应用程序如何主动确定过期时间(在被API拒绝之前)。我的理解是,刷新令牌的默认过期时间很长: : 刷新令牌的最长生存期(秒)。默认值为2592000秒/30天 但是,当示例代码请求刷新令牌时,我没有

我正在使用Identity Server 4示例代码。特别是,对于客户端,我使用混合流的示例MVC客户端:

对于服务器,我将Identity server与内存中的客户端一起使用(没有实体框架,也没有ASP.Net标识):

客户机和服务器都有非常普通的开箱即用配置

我试图了解刷新令牌如何过期,以及本机应用程序如何主动确定过期时间(在被API拒绝之前)。我的理解是,刷新令牌的默认过期时间很长:

:

刷新令牌的最长生存期(秒)。默认值为2592000秒/30天

但是,当示例代码请求刷新令牌时,我没有得到预期的过期时间。以下是示例代码:

var disco = await _discoveryCache.GetAsync();
if (disco.IsError) throw new Exception(disco.Error);

var rt = await HttpContext.GetTokenAsync("refresh_token");
var tokenClient = _httpClientFactory.CreateClient();

var tokenResult = await tokenClient.RequestRefreshTokenAsync(new RefreshTokenRequest
{
    Address = disco.TokenEndpoint,

    ClientId = "mvc.hybrid",
    ClientSecret = "secret",
    RefreshToken = rt
});
tokenResult.ExpiresIn
是3600秒,实际上是访问令牌的过期时间。我原以为是2592000秒。所以问题1是:为什么会这样

但更重要的是,我知道当我使用SQL Server作为数据存储时,刷新令牌的过期时间实际上是默认的30天。有一个表
PersistedGrants
,其中包含刷新令牌,有效期显然是从发布日期起30天。因此,问题2是:应用程序如何以编程方式确定其收到的刷新令牌的过期日期

我试图解析RefreshToken本身,但它实际上不是完整的JWT,因此这会抛出一个错误:

var jwt = new JwtSecurityTokenHandler().ReadJwtToken(accessTokenResponse.RefreshToken);
var diff = jwt.ValidTo - jwt.ValidFrom;
我还搜索了IdentityServer4,但找不到内省刷新令牌的示例


据推测,该信息要么需要位于初始令牌响应中的某个位置,要么需要在Identity Server中内置一个端点。但是我找不到这些东西。

好的,所以答案是,
访问\u令牌
响应中没有指示
刷新\u令牌
过期时间的数据。此外,没有可用于检查过期的端点

OAuth规范没有对此做任何说明,因此我不想更改
access\u令牌
响应。最后,我创建了自己的端点,如果需要,它将返回过期时间。以下是我的控制器操作,如果有人需要一个起点:

private readonly IRefreshTokenStore _refreshTokenStore; // inject this into your controller

...

[Route("[controller]/GetRefreshTokenExpiration")]
[Authorize(...YOUR SCOPE...)]
public async Task<IActionResult> GetRefreshTokenExpiration(string refreshTokenKey)
{
    var refreshToken = await this._refreshTokenStore.GetRefreshTokenAsync(refreshTokenKey);
    if (refreshToken == null)
    {
        return NotFound(new { message = "Refresh token not found" });
    }
    return Ok(new {
        message = "Refresh token found",
        lifetime_seconds = refreshToken.Lifetime
    });
}
专用只读IRefreshTokenStore\u refreshTokenStore;//将其注入控制器
...
[路由(“[controller]/GetRefreshTokenExpiration”)]
[授权(…您的范围…)
公共异步任务GetRefreshTokenExpiration(字符串refreshTokenKey)
{
var refreshttoken=等待此消息。\u refreshttokenstore.getrefreshttokenasync(refreshttokenkey);
if(refreshttoken==null)
{
return NotFound(new{message=“Refresh token not found”});
}
返回Ok(新的{
message=“找到刷新令牌”,
生命周期\秒=刷新令牌。生命周期
});
}

到期时间来自访问令牌,因为您正在请求访问令牌。刷新令牌仅用作密钥。如果已将刷新令牌配置为仅用于一次tim使用,则还将返回一个新的刷新令牌,从而撤销当前的刷新令牌。我怀疑您可以使用以下内容读取过期时间:
newjwtsecuritytokenhandler().ReadJwtToken(tokenResult.refreshttoken).ValidTo@RuardvanElburg-谢谢你的回复。不幸的是,我已经尝试使用
JwtSecurityTokenHandler
来计算
TimeSpan
。但是正如您所说,刷新“令牌”似乎不是完整的JWT,因此读取方法失败。我将把这个添加到主帖子中。我正试图解决与你相同的问题。我们采取的策略是,如果出于任何原因,使用刷新令牌请求新访问令牌失败,我们将请求用户再次登录。在实践中,这对我们很有效。会话cookie和访问令牌的过期时间都比刷新令牌小得多。因此,无论哪个先到期,最终都会请求一个新的刷新令牌。我们将刷新令牌到期视为一种特殊情况。您最好在调用GETPrimeToKeNasyCyc()时使用AsiNc/Acess,而不是.REST。