如何使用' refresh_token'在IdentityServer 4中?

时间:2017-05-25 07:47:45

标签: c# identityserver4

我使用.net核心与IdentityServer 4.我有一个Web api,以及一个访问api上安全端点的MVC应用程序。它与IdentityServer快速入门的设置非常相似:

https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/Quickstarts/6_AspNetIdentity

我发现我的access_tokens即将到期,并且我想了解如何重新协商refresh_tokens

以下面的代码为例(取自快速入门here):

public async Task<IActionResult> CallApiUsingUserAccessToken()
    {
        var accessToken = await HttpContext.Authentication.GetTokenAsync("access_token");

        var client = new HttpClient();
        client.SetBearerToken(accessToken);
        var content = await client.GetStringAsync("http://localhost:5001/identity");

        ViewBag.Json = JArray.Parse(content).ToString();
        return View("json");
    }

如果access_token已过期,则会因401响应而失败。是否有使用access_token重新协商refresh_token的内置机制?

1 个答案:

答案 0 :(得分:6)

系统中没有用于刷新access_token的内置版本。不过,您可以使用IdentityModel包来申请access_token个新refresh_token

Client有一个属性AllowOfflineAccess,您应该在IdentityServer中将其设置为true。请注意,对隐式/客户端凭据流有效。

  • 在调用受保护资源之前始终刷新access_token
  • 检查当前access_token是否即将过期,方法是检查其生命周期并申请新的access_token refresh_token(个人偏好)
  • 等待API返回401广告请求,使用access_token
  • 返回新的refresh_token

在此代码之前,您可以检查access_token生命周期和/或在请求新的access_token

之前将此代码包装在服务中
var discoveryResponse = await DiscoveryClient.GetAsync("IdentityServer url");
if (discoveryResponse.IsError)
{
    throw new Exception(discoveryResponse.Error);
}

var tokenClient = new TokenClient(discoveryResponse.TokenEndpoint, "ClientId", "ClientSecret");
// This will request a new access_token and a new refresh token.
var tokenResponse = await tokenClient.RequestRefreshTokenAsync(await httpContext.Authentication.GetTokenAsync("refresh_token"));

if (tokenResponse.IsError)
{
    // Handle error.
}

var oldIdToken = await httpContext.Authentication.GetTokenAsync("id_token");

var tokens = new List<AuthenticationToken>
{
    new AuthenticationToken
    {
        Name = OpenIdConnectParameterNames.IdToken,
        Value = oldIdToken
    },
    new AuthenticationToken
    {
        Name = OpenIdConnectParameterNames.AccessToken,
        Value = tokenResult.AccessToken
    },
    new AuthenticationToken
    {
        Name = OpenIdConnectParameterNames.RefreshToken,
        Value = tokenResult.RefreshToken
    }
};

var expiresAt = DateTime.UtcNow.AddSeconds(tokenResult.ExpiresIn);
tokens.Add(new AuthenticationToken
{
    Name = "expires_at",
    Value = expiresAt.ToString("o", CultureInfo.InvariantCulture)
});

// Sign in the user with a new refresh_token and new access_token.
var info = await httpContext.Authentication.GetAuthenticateInfoAsync("Cookies");
info.Properties.StoreTokens(tokens);
await httpContext.Authentication.SignInAsync("Cookies", info.Principal, info.Properties);

取自并略微修改:Source