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

ano*_*non 5 c# identityserver4 refresh-token

我正在使用 Identity Server 4 示例代码。特别是,对于客户端,我使用带有混合流的示例 MVC 客户端:https : //github.com/IdentityServer/IdentityServer4/tree/master/samples/Clients/src/MvcHybrid

对于服务器,我将 Identity Server 与内存客户端一起使用(没有实体框架,也没有 ASP.Net Identity):https : //github.com/IdentityServer/IdentityServer4/tree/master/samples/Quickstarts

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

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

http://docs.identityserver.io/en/latest/topics/refresh_tokens.html

刷新令牌的最长生命周期(以秒为单位)。默认为 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
});
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

我还搜索了 IdentityServer4单元/集成测试,但找不到内省刷新令牌的示例。

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

ano*_*non 2

access_token好的,所以答案是响应中没有数据表明refresh_token. 此外,没有可用于检查过期时间的端点。

OAuth 规范对此没有任何说明,因此我不想更改响应access_token。我最终创建了自己的端点,如果需要,它会返回过期时间。如果有人需要起点,这是我的控制器操作:

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
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 调用 GetRefreshTokenAsync() 时最好使用 async/await,而不是 .Result。 (3认同)