如何在服务器端交换授权令牌

时间:2018-10-03 07:51:58

标签: asp.net-core oauth-2.0 asp.net-core-2.1

我有一个使用OAuth身份验证的ASP.Net Core 2.1 Web API。另外,我们正在使用基于声明的身份验证,其中的声明编码在auth令牌中。

这已经运行了一段时间,但是最近出现了一个新要求,该要求从根本上使必须存储在令牌中的索取数量成倍增加,因此事情变得一发不可收拾。长话短说,现在我们处于auth令牌太长的地步,以至于我们不得不重新配置服务器以允许超过128k的标头。

这显然是站不住脚的;仅从网络流量的角度来看,必须发送100k的标头以及最简单的GET请求是荒谬的。因此,现在我在考虑以下几行:不用编码令牌中的声明,只需使用Guid令牌并将声明与令牌一起存储在 database 中,因此当我们验证令牌时我们可以同时提取索偿并在本地交换索偿。

从理论上讲,这应该一口气解决我们的整个问题,但是我只是停留在实现细节上,特别是:由于基于声明的身份验证期望找到auth令牌中编码的声明,因此我该如何交换排除包含所有声明的那个的Guid auth令牌?

现有代码:

public class MyAuthenticationEvents : OAuthValidationEvents
{
    public override async Task ValidateToken(ValidateTokenContext context)
    {
        if (context.Properties.ExpiresUtc < DateTime.UtcNow)
        {
            context.Fail("Access Token has expired.");
            return;
        }
        if (!await TokenIsValidAsync(context)) // code to validate the auth token against the database, could be modified to return claims
        {
            context.Fail("Access Token has not been properly set or has been invalidated.");
            return;
        }
        // Here I would expect to do some skullduggery to switch the compact Guid token for a large token containing claims
        context.Success();
    }
}

正确的语法是什么?还是我在错误地树上吠叫,有一种完全更好的方法可以实现我的目标?

2 个答案:

答案 0 :(得分:2)

您现有的身份验证中间件正在基于JWT的内容填充ClaimsPrincipal上的声明,但是到您的授权处理程序检查声明时,它们并没有直接从令牌中读取,因此无需修改令牌本身。

您应该能够从中间件访问和修改当前用户(HttpContext.User)声明,因此您可以使custom middleware在身份验证中间件之后执行,并根据数据库的结果添加声明查找。

编辑:正如Shaul在他的回答中指出的那样,这也可以在身份验证组件的Validate方法中完成。在这种情况下,这实际上是个好地方。如果您希望将声明对数据库中声明的“转换”与身份验证过程脱钩,则可以使用单独的中间件(如我所述)。关键是ASP.NET Core将用户声明存储在ClaimsPrincipal对象中,您只需要更新它,而不必担心令牌本身。

答案 1 :(得分:2)

结果非常简单。我需要在repoToken方法中做的就是使用一个ValidateToken()创建一个新的ClaimsPrincipal,它是根据我存储在数据库中的序列化声明重新构建的:

ClaimsIdentity

仅需注意一件事:首次登录时,必须返回 ... // create claimsIdentity from serialized claims context.Principal = new ClaimsPrincipal(claimsIdentity); context.Success(); } 声明,因此在Subject方法中,我们仍然需要:

HandleTokenRequest()