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,我也在使用它。

事实:

  1. Identity Server 3 在刷新访问令牌时请求客户端密码
  2. 不应将 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 库,因为它可以为您管理静默更新。