首页 > 解决方案 > 用于发布和验证 JWT 的自定义令牌服务

问题描述

我们需要开发一个“单点登录”服务(SSO)来为大量客户发布 JWT。这些客户端的开发人员还需要能够验证这些令牌。显然我们不能向他们提供我们用来生成这些令牌的密钥。因此,我们决定为他们提供具有两种方法的 API 服务。一个用于发布令牌,第二个用于验证它。

我在质疑自己,我们是否选择了正确的方法。这是一个基本方案,显示用户将如何与他们的客户(安全应用程序)一起工作

图 1 - 用户交互的基本方案

用户通过我们的服务使用他的凭据登录并获取他的访问令牌。然后他的令牌用于安全应用程序的请求标头中。SSO 客户端模块是 AuthenticationHandler,它向我们的服务发送 HTTP 请求以检查令牌的有效性。

这是我们用来验证令牌的 SSO 客户端模块的一些代码。我们使用自定义身份验证处理程序来调用远程 SSO 服务:

internal class SsoAuthenticationHandler : AuthenticationHandler<SsoAuthenticationOptions>
{
    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        if (!TryRetrieveToken(Request, out var token))
        {
            return AuthenticateResult.NoResult();
        }

        if (await _ssoClient.ValidateTokenAsync(token))
        {
            return AuthenticateResult.Success(...);
        }

        return AuthenticateResult.NoResult();
    }
}

和 SsoClient 自己:

public class SsoClient
{
    public async Task<bool> ValidateTokenAsync(string token)
    {
        const string validateUrl = "api/auth/validatetoken";

        var address = $"https://{_ssoHost}/{validateUrl}";
        using (var httpClient = new HttpClient())
        {
            httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
            var res = await httpClient.GetStringAsync(new Uri(address));
            reply = DeserializeSsoReply(res);
        }

        return reply.Succeeded;
    }
}

我找不到适合我们场景的最佳实践,所以我想知道这种方法是否会遇到任何可能的陷阱?

标签: c#asp.net-corejwt

解决方案


当我们遇到类似情况时,我们所做的就是为每个有效客户提供一个证书,他们可以使用该证书为目标(也称为我们)服务创建 JWT。在对其来源进行验证后,他们的凭据被重新打包并使用我们与他们共享的证书重新签名。对于有限数量的有效调用者,这有助于我们跟踪真实来源(基于签名证书)以及为我们使用提供标准化的有效负载。

收到后,我们验证受众是否正确(也就是我们),并且签名者是配置的签名者之一。

每个人都保守自己的秘密,任何你想相信你就是你的人,你提供你的公钥。密钥的所有者(又名您)始终控制您的秘密,但每个人都必须就端到端协议达成一致。

我不认为这种重新发明更多的是保护流行路径并限制一组已知用户的进入。


推荐阅读