IdentityServer 3 使用刷新令牌刷新用户
IdentityServer 3 refresh user with refresh token
我们正在尝试以正确的方式设置 Identity Server 3。
我们的身份验证工作正常,我们设法检索了刷新令牌。
客户端应用程序正在使用 Angular。
现在,当 acces_token 过期时,对其余 api 的任何调用都会失败(我们设法将其转到 return 401),但我们想知道如何重新验证用户.
在我们的测试中,从 Javascript 发出的任何 api 调用都会失败 (401),但是一旦页面刷新,整个机制就会启动。我们确实看到我们被重定向了到身份服务器,但它没有显示登录页面,我们显然被发送回带有新令牌的客户端应用程序。
我想做的是刷新访问令牌,而不必强制用户刷新页面。
但我不确定这是谁的责任?是客户端应用程序(网站)还是 angular 应用程序?换句话说,应用程序应该为 Angular 透明地处理这个问题,还是应该 angular 在收到 401 时做一些事情,在这种情况下,我不太确定信息将如何流回网络应用
有线索吗?
其他信息:我们正在使用 OpenId Connect
我成功了!
正如我在评论中所说,我使用了 this article. The writer is referencing a very nice lib,我也在使用它。
事实:
- Identity Server 3 在刷新访问令牌时请求客户端密码
- 不应将 refresh_token 或 client_secret 存储在 javascript 应用程序中,因为它们被认为是不安全的(参见 the article)
所以我选择将 refresh_token 作为加密 cookie 发送到 class 中(发现 ST 顺便说一句,只是找不到 link,抱歉... )
public static class StringEncryptor
{
public static string Encrypt(string plaintextValue)
{
var plaintextBytes = plaintextValue.Select(c => (byte) c).ToArray();
var encryptedBytes = MachineKey.Protect(plaintextBytes);
return Convert.ToBase64String(encryptedBytes);
}
public static string Decrypt(string encryptedValue)
{
try
{
var encryptedBytes = Convert.FromBase64String(encryptedValue);
var decryptedBytes = MachineKey.Unprotect(encryptedBytes);
return new string(decryptedBytes.Select(b => (char)b).ToArray());
}
catch
{
return null;
}
}
}
javascript 应用程序正在从 cookie 中获取值。然后它删除cookie以避免那个东西被一遍又一遍地发送,这是没有意义的。
当access_token失效后,我向应用服务器发送一个http请求,加密refresh_token。那是一个匿名电话。
服务器联系身份服务器并获得一个新的 access_token 并发送回 Javascript。 awesome library 将所有其他请求排入队列,所以当我带着我的新令牌回来时,我可以告诉它继续 authService.loginConfirmed();
。
刷新实际上非常简单,因为您只需使用 IdentityServer3 中的 TokenClient
。完整方法代码:
[HttpPost]
[AllowAnonymous]
public async Task<JsonResult> RefreshToken(string refreshToken)
{
var tokenClient = new TokenClient(IdentityServerConstants.IdentityServerUrl + "/connect/token", "my-application-id", "my-application-secret");
var response = await tokenClient.RequestRefreshTokenAsync(StringEncryptor.Decrypt(refreshToken));
return Json(new {response.AccessToken});
}
欢迎发表评论,这可能是最好的方法。
供将来参考 - 在 angular(或其他 JS)应用程序中使用刷新令牌不是正确的方法,因为刷新令牌过于敏感而无法存储在浏览器中。您应该使用基于身份服务器 cookie 的静默更新来获取新的访问令牌。另请参阅 oidc-client-js javascript 库,因为它可以为您管理静默更新。
我们正在尝试以正确的方式设置 Identity Server 3。 我们的身份验证工作正常,我们设法检索了刷新令牌。
客户端应用程序正在使用 Angular。
现在,当 acces_token 过期时,对其余 api 的任何调用都会失败(我们设法将其转到 return 401),但我们想知道如何重新验证用户.
在我们的测试中,从 Javascript 发出的任何 api 调用都会失败 (401),但是一旦页面刷新,整个机制就会启动。我们确实看到我们被重定向了到身份服务器,但它没有显示登录页面,我们显然被发送回带有新令牌的客户端应用程序。
我想做的是刷新访问令牌,而不必强制用户刷新页面。
但我不确定这是谁的责任?是客户端应用程序(网站)还是 angular 应用程序?换句话说,应用程序应该为 Angular 透明地处理这个问题,还是应该 angular 在收到 401 时做一些事情,在这种情况下,我不太确定信息将如何流回网络应用
有线索吗?
其他信息:我们正在使用 OpenId Connect
我成功了!
正如我在评论中所说,我使用了 this article. The writer is referencing a very nice lib,我也在使用它。
事实:
- Identity Server 3 在刷新访问令牌时请求客户端密码
- 不应将 refresh_token 或 client_secret 存储在 javascript 应用程序中,因为它们被认为是不安全的(参见 the article)
所以我选择将 refresh_token 作为加密 cookie 发送到 class 中(发现 ST 顺便说一句,只是找不到 link,抱歉... )
public static class StringEncryptor
{
public static string Encrypt(string plaintextValue)
{
var plaintextBytes = plaintextValue.Select(c => (byte) c).ToArray();
var encryptedBytes = MachineKey.Protect(plaintextBytes);
return Convert.ToBase64String(encryptedBytes);
}
public static string Decrypt(string encryptedValue)
{
try
{
var encryptedBytes = Convert.FromBase64String(encryptedValue);
var decryptedBytes = MachineKey.Unprotect(encryptedBytes);
return new string(decryptedBytes.Select(b => (char)b).ToArray());
}
catch
{
return null;
}
}
}
javascript 应用程序正在从 cookie 中获取值。然后它删除cookie以避免那个东西被一遍又一遍地发送,这是没有意义的。
当access_token失效后,我向应用服务器发送一个http请求,加密refresh_token。那是一个匿名电话。
服务器联系身份服务器并获得一个新的 access_token 并发送回 Javascript。 awesome library 将所有其他请求排入队列,所以当我带着我的新令牌回来时,我可以告诉它继续 authService.loginConfirmed();
。
刷新实际上非常简单,因为您只需使用 IdentityServer3 中的 TokenClient
。完整方法代码:
[HttpPost]
[AllowAnonymous]
public async Task<JsonResult> RefreshToken(string refreshToken)
{
var tokenClient = new TokenClient(IdentityServerConstants.IdentityServerUrl + "/connect/token", "my-application-id", "my-application-secret");
var response = await tokenClient.RequestRefreshTokenAsync(StringEncryptor.Decrypt(refreshToken));
return Json(new {response.AccessToken});
}
欢迎发表评论,这可能是最好的方法。
供将来参考 - 在 angular(或其他 JS)应用程序中使用刷新令牌不是正确的方法,因为刷新令牌过于敏感而无法存储在浏览器中。您应该使用基于身份服务器 cookie 的静默更新来获取新的访问令牌。另请参阅 oidc-client-js javascript 库,因为它可以为您管理静默更新。