如何从单个服务端点发出和验证 jwt?

Posted

技术标签:

【中文标题】如何从单个服务端点发出和验证 jwt?【英文标题】:How to issue and validate jwt from single service endpoint? 【发布时间】:2019-03-03 20:35:51 【问题描述】:

我已在 Angular 前端 Web 应用程序和 .Net Core Web API 后端(用于获取数据)之间成功连接了一个基于令牌的授权系统。

现在,我想将 JWT Logic(生成和验证)整合到第三个 Web API .Net Core 项目中。

如何将以下逻辑“移动”到单独的 Web API 中以进行令牌验证?

在 Startup.cs 中:

  public void ConfigureServices(IServiceCollection services)
                
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        
            options.TokenValidationParameters = new TokenValidationParameters
            
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,

                ValidateIssuer = true,
                ValidateAudience = true,

                ValidAudiences = new List<string>  "Audience1", "Audience2" ,
                ValidIssuer = "Credit Card oAuth Web API",
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("superSecretKey@345"))

            ;
        );                        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    

在控制器中:

        [Authorize (Roles = "Credit Card Administrator")]
    public ActionResult<string> Get(int id)
    
        return "value";
    

我想保留 Roles 的逻辑(因为在 JWT 中设置了这样的声明,所以它正在工作):

var userClaims = new List<Claim>()
            
                new Claim(JwtRegisteredClaimNames.Sub, name),
                new Claim(JwtRegisteredClaimNames.Email, "user.name@company.com"),
                new Claim(JwtRegisteredClaimNames.GivenName, "User Name"),
                new Claim(ClaimTypes.Role, "Customer Administrator"),
                new Claim(ClaimTypes.Role, "Credit Card Administrator"),
                new Claim(ClaimTypes.Role, "Counter Administrator")
            ;

            // TODO: Refactor The Following: Get token from oAuth Service (pass in Audience and Claims)
            var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("superSecretKey@345"));
            var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);

            var tokenOptions = new JwtSecurityToken(
                issuer: "http://localhost:58726",
                audience: "http://localhost:58726",
                claims: userClaims,
                expires: DateTime.Now.AddMinutes(20),
                signingCredentials: signinCredentials
            );

            var tokenString = new JwtSecurityTokenHandler().WriteToken(tokenOptions);

我希望这是有道理的,并感谢任何帮助。

【问题讨论】:

不确定“想要将 JWT 逻辑(生成和验证)整合到第三个 Web API .Net Core 项目中”是什么意思。 .您是想设置一个作为不同 Web 服务器运行的 OpenAuth,还是创建另一个在同一个网站上运行的解决方案子项目? 这正是 IdentityServer4 所做的。它将您的身份验证服务器分开。 @itminus 我认为你是正确的,我正在尝试创建一个将在另一台服务器上运行的 oauth 项目。我想将发送到数据控制器的 JWT 传递给 oath 服务进行验证。 @Sasan 谢谢。我会看看 Identity Server 4。它是一个框架还是一个 3rd 方服务? 【参考方案1】:

如何将以下逻辑“移动”到单独的 Web API 中以进行令牌验证?

您要移动的逻辑是 ASP.NET Core 身份验证中间件的一部分,其中包括这些职责。

    从 HTTP 请求的 Authorize 标头中读取访问令牌(不记名令牌), 验证访问令牌, 将访问令牌的声明显示为Authorize 属性。

在这种情况下,访问令牌被编码为 JWT。

听起来您想在单独的服务器上执行步骤 (2)。如果是这种情况,您可能正在寻找 OAuth Introspection。

GitHub 上有一些extensions for that here。此外,AspNet.Security.OAuth.Extensions Error while introspection 问题和答案将帮助您为 OAuth Introspection 配置这些扩展。

【讨论】:

谢谢肖恩。这似乎是我想要做的。我希望 OAth 服务将接受 JWT 令牌进行验证,并且我现有的“数据”Web api 项目将能够传递它。我快速检查了链接(还没有完全消化其中的内容),我没有看到任何对 JWT 的引用......但我保证我会很快完整阅读它们。 “秘密”应该存储在哪里?它应该存储在两个地方吗?我有三个“项目”:oAuth Web 服务、Web 应用程序(客户端)和 Web API(数据的来源)。秘密是否应该只存储在 oAuth Web 服务器中?还是应该同时存储在客户端和 oAuth 项目中? 你具体指的是什么秘密? 有一个秘密用于加密 JWT 中的凭证。它也是客户端和认证服务器之间共享的秘密。但是,就我而言,因为我可以控制所有三个项目,所以我不确定该密钥是否应该仅存储在 oAuth 服务或客户端中。 据我所知,如果我们使用自省,那么只有授权服务器需要 JWT 密码。验证/解密/解析 JWT 成为自省端点的工作。确认我在这里说的话oauth.com/oauth2-servers/token-introspection-endpoint不要相信我的话,因为我有一段时间没有深入研究内省了。

以上是关于如何从单个服务端点发出和验证 jwt?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JwtSecurityTokenHandler 和 JWKS 端点验证 JWT?

来自 C# HttpClient 针对 Spring 服务器 JWT 令牌的身份验证

为啥 JWT 是无状态认证?

向 Google 进行身份验证时,从 Spring OAuth2 授权服务器发出 JWT 令牌

使用 php 进行 jwt 服务器端身份验证

Spring Cloud - 如何仅允许访问特定微服务的端点?