C# 如何使用';刷新令牌';在IdentityServer 4中?

C# 如何使用';刷新令牌';在IdentityServer 4中?,c#,identityserver4,C#,Identityserver4,我正在使用带有IdentityServer 4的.net core。我有一个Web api和一个MVC应用程序,可以访问api上的安全端点。它的设置与IdentityServer quickstart非常相似: 我发现我的access\u令牌即将过期,我想了解如何重新协商refresh\u令牌 以以下代码为例(摘自quickstart): public异步任务CallApiUsingUserAccessToken() { var accessToken=await-HttpContext.Au

我正在使用带有IdentityServer 4的.net core。我有一个Web api和一个MVC应用程序,可以访问api上的安全端点。它的设置与IdentityServer quickstart非常相似:

我发现我的
access\u令牌
即将过期,我想了解如何重新协商
refresh\u令牌

以以下代码为例(摘自quickstart):

public异步任务CallApiUsingUserAccessToken()
{
var accessToken=await-HttpContext.Authentication.GetTokenAsync(“访问令牌”);
var client=新的HttpClient();
client.SetBearerToken(accessToken);
var content=await client.GetStringAsync(“http://localhost:5001/identity");
Json=JArray.Parse(content.ToString();
返回视图(“json”);
}

如果
access\u令牌
已过期,它将失败并响应401。是否有使用
刷新\u令牌重新协商
访问\u令牌的内置机制?

没有用于刷新
访问\u令牌的内置系统。但是,您可以使用
IdentityModel
包请求使用
refresh\u令牌的新
access\u令牌

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


  • 在调用受保护资源之前,始终刷新access_令牌
  • 通过检查当前的
    access\u令牌的生存期并使用
    refresh\u令牌请求一个新的
    access\u令牌
    (个人偏好),检查当前的
    access\u令牌
    是否即将过期
  • 等待API返回401AD请求一个新的
    access\u令牌
    refresh\u令牌
在此代码之前,您可以检查
access\u令牌
生存期和/或在请求新的
access\u令牌

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);
var discoveryResponse=wait DiscoveryClient.GetAsync(“IdentityServer url”);
如果(发现响应IsError)
{
抛出新异常(discoveryResponse.Error);
}
var tokenClient=new tokenClient(discoveryResponse.TokenEndpoint,“ClientId”,“ClientSecret”);
//这将请求一个新的访问令牌和一个新的刷新令牌。
var-tokenResponse=await-tokenClient.RequestRefreshTokenAsync(await-httpContext.Authentication.GetTokenAsync(“刷新令牌”);
if(tokenResponse.IsError)
{
//处理错误。
}
var oldIdToken=await-httpContext.Authentication.GetTokenAsync(“id_-token”);

var tokens=new List

“在调用受保护的资源之前始终刷新访问令牌”-这并不总是必要的,而且通过消除对每个请求进行重新身份验证的需要,有点挫败了刷新令牌的一个要点(即,减少身份验证服务器的负担)。TokenClient已过时,你能举一个新方法的例子吗?@JuanPablo现在你可以这样使用
var response=wait client.RequestRefreshTokenAsync(新的RefreshTokenRequest{Address=discoveryResponse.TokenEndpoint,ClientId=“mvc”,ClientSecret=“secret”,Scope=“my api”,RefreshToken=RefreshToken})var discoveryResponse=wait client.GetDiscoveryDocumentAsync(“http://localhost:5500");
对于任何想知道如何获取实际刷新令牌的人,当您第一次进行身份验证时,您需要在发出请求时将
脱机访问
添加到您的作用域中。执行此操作时,刷新令牌将与
访问令牌
到期令牌
令牌类型
一起返回。
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);