【问题标题】:.AddOpenIdConnect() Middleware Clarification.AddOpenIdConnect() 中间件说明
【发布时间】:2021-03-29 15:10:00
【问题描述】:

所以,我正在尝试使用 ASP.NET Core 3.1 实现 OIDC 客户端应用程序。我正在尝试利用 .AddOpenIdConnect().AddJswtBearer() 中间件。但是,我需要澄清一下这个中间件在做什么。

这是我目前的中间件配置:

.AddOpenIdConnect(options =>
{
    options.Authority = Configuration["auth:oidc:authority"];
    options.ClientId = Configuration["auth:oidc:clientid"];
    options.ClientSecret = Configuration["auth:oidc:clientsecret"];
    options.ResponseType = OpenIdConnectResponseType.Code;
    options.GetClaimsFromUserInfoEndpoint = true;
    options.SaveTokens = true;
})
.AddJwtBearer(options =>
{
    options.Authority = Configuration["auth:oidc:authority"];
    options.Audience = Configuration["auth:oidc:clientid"];
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidIssuer = Configuration["auth:oidc:authority"],
        ValidAudience = Configuration["auth:oidc:clientid"],
        ValidateIssuerSigningKey = true,
        ClockSkew = TimeSpan.Zero
     };
}

我注意到,根据我在下面的 Fiddler 捕获,首次启动应用程序时会请求授权服务器的 /.well-known/oidc-configuration/.well-known/keys 端点

它在哪里做的?

我也在尝试验证从授权服务器收到的 JWT 是否有效(在服务器发送它到客户端收到它的时间之间它没有被篡改)。当我在.AddJwtBearer() 中间件中添加TokenValidationParameters 对象时,我明白会发生这种情况。为了测试这一点,我尝试将TokenValidationParameters 中的Valid Audience 更改为asdkwewrj 之类的东西,我知道这不是我的令牌的有效受众。但是,我从来没有收到客户说观众无效的错误。身份验证仍然有效,我仍然能够访问我的安全仪表板。

我正在尝试实现的另一件事是使用此 OIDC 客户端的 refresh_token grant_type。我认为.AddOpenIdConnect() 中间件中的options.saveTokens 可以让我保存令牌。看起来它们保存为 cookie,但这些 cookie 看起来不像我的令牌值(我的访问令牌是 JWT,但在我看到的 cookie 中,它们都不是以 ey 开头)。

简而言之,我试图理解以下内容:

  1. 如果我定义了正确的JwtBearerOptions(就像我上面所做的那样),这个.AddJwtBearer() 中间件是否会为我验证ID 令牌?或者我是否需要根据 JWK URI 中的 JWK 手动验证 ID 令牌?
  2. 如果我必须使用 JWKs URI 中的 JWK 手动验证 ID 令牌,当中间件向 /.well-known/keys 端点发出请求时,如何存储这些 JWK?
  3. 如何获取访问令牌和刷新令牌对应的cookie,然后将刷新令牌发送到我的授权服务器?
  4. 我注意到我可以在这两个中间件中使用 options.Events。这些中的任何一个都可以解决我想要完成的任何项目吗?
  5. 总体而言,这两个中间件为我处理了哪些我不需要手动执行的操作(即令牌验证和/或令牌更新)?

谢谢!对于像这样深入的 ASP.NET 开发,我还是很陌生,所以我很感激任何回应。

【问题讨论】:

    标签: c# asp.net-core authentication oauth-2.0 openid-connect


    【解决方案1】:

    如果我,这个 .AddJwtBearer() 中间件是否会为我验证 ID 令牌 是否定义了正确的 JwtBearerOptions(就像我在上面所做的那样)?还是我 需要针对 JWK 中的 JWK 手动验证 ID 令牌 网址?

    AddJwtBearer 仅由 API 用于验证访问令牌并从中创建用户 (ClaimsPrincipal)。这就是它所做的一切。它不处理 id 令牌。

    一般来说,将 API 放在单独的服务上更容易,这样可以更清楚地知道谁在做什么。当您在同一个服务中混合使用客户端和 API 时,可能会更难推理。

    如果我必须使用来自 JWKs URI,当中间件生成时,我如何存储这些 JWKs 请求 /.well-known/keys 端点?我如何获得饼干 对应访问令牌和刷新令牌,然后发送 我的授权服务器的刷新令牌?

    ID 令牌由 AddOpenIdConnect 为您验证和处理。您不需要自己验证 ID-token。 AddOpenIdConnect 将创建 cookie,并可选择将令牌存储在 cookie 中。

    总的来说,这两个中间件为我处理了什么,我不应该 需要手动执行(即令牌验证和/或令牌更新)?

    总结一下:

    为客户端使用 .AddOpenIdConnect(),允许用户登录。

    将 .AddJswtBearer() 用于后端 API。

    令牌更新是一个不同的故事,他们都没有开箱即用。为此,您可以考虑使用IdentityModel.AspNetCore 或自己做点什么。

    【讨论】:

    • 好的,太好了。这开始有些意义了。因此,如果我希望使用 .AddOpenIdConnect() 中间件验证所有 ID 令牌参数,我仍然可以使用 TokenValidationParameters?另外,我在哪里可以查看我的应用程序中有关经过身份验证的用户的所有声明数据?
    • 用户通过身份验证后,您可以访问HttpContext.User 或整个框架中的许多User 属性之一(例如,在控制器、Razor 视图或 Razor 页面上)。
    • TokenValidator 用于验证访问权和 ID-token。
    【解决方案2】:

    首先,OIDC认证方案和JWT承载认证方案是相互独立的。 OIDC 主要用于服务器端身份验证,几乎不会单独使用,但始终与 cookie 方案一起使用。这样做的原因是 OIDC 方案将仅用于身份验证,但不能自行持久化信息。我已经详细介绍了in a different answer of mine,它还解释了身份验证流程如何与 OIDC 一起使用。

    对于 JWT 承载,此身份验证方案将在 每个 请求上运行,因为它是完全无状态的,并且希望客户端始终使用 Authorization 标头进行身份验证。这使得它主要用于保护 API,因为浏览器无法为正常的浏览器请求提供 JWT。

    因此,您应该首先问自己是否在保护您的服务器端 Web 应用程序(例如,使用 Razor 视图或 Razor 页面),在这种情况下您想要使用 OIDC 和 cookie 身份验证方案,或者您是否在保护您的 API。当然,答案可能是“两者”,在这种情况下,您需要所有这三种方案,但如果没有进一步配置,ASP.NET Core 将不支持这一点。


    在澄清之后,让我们来回答你的问题:

    1. /.well-known/oidc-configuration/.well-known/keys 的请求由 OIDC 和 JWT 承载方案完成,以便从您的身份提供者那里检索信息。他们将定期这样做以更新他们的数据,包括有关他们将用于验证令牌的签名密钥的信息。这发生在方案处理程序中,您通常看不到。

    2. 正确设置,JWT 不记名身份验证将为您验证令牌。它将通过使用检索到的签名密钥验证签名来做到这一点,然后它可能会检查其他属性,例如指定的受众或其生命周期。

    3. 您永远不需要手动验证令牌。这就是身份验证方案的工作。您正在使用身份验证堆栈,因此您无需执行任何操作即可访问应用程序中的用户主体。

    4. Cookie 使用data protection 进行保护,以防伪造。为了检索存储在 SaveTokens = true 中的令牌,您可以在 HTTP 上下文中使用 GetTokenAsync 方法。

    5. 您可以使用身份验证事件来添加身份验证方案的默认行为。但是,如果要使用标准机制验证您的令牌,则不需要这样做。

    6. 只有一个中间件:身份验证中间件。它使用配置的身份验证方案来执行用户身份验证,因此一旦正确设置,经过身份验证的用户在整个应用程序中都可用,例如在控制器、MVC 过滤器、Razor 视图等中。

    【讨论】:

    • 感谢您的所有澄清。它有很大帮助。但是,只是几个后续问题: 1. 我不需要担心客户端的 ID 令牌验证,这意味着我不需要 .AddJwtBearer() 中间件? 2. 在请求/.well-known/keys 端点时,是否可以查看中间件将JWK 存储在哪里?
    • 另一个跟进:我问是否有办法查看 JWK,因为我在 TokenValidationParameters 中注意到 .AddOpenIdConnect() 中间件,有一个选项可以设置 ValidateIssuerSigningKey 和还有一个设置IssuerSigningKey(s)的选项,但也有一个IssuerSigningKeyValidator。如果没有这些设置,中间件仍然可以正确验证 JWK?
    • 默认情况下,JwtBearerOptions.ConfigurationManager 用于从元数据端点(.well-known/openid-configuration 和签名密钥)请求配置。但是,您也可以通过设置 JwtBearerOptions.Configuration 直接配置身份验证配置。
    • 该配置管理器还将存储密钥(和配置),直到它再次刷新(定期发生)。您可以加载它(从选项中)并调用其GetConfigurationAsync 方法,以便从元数据端点访问配置。通常,没有必要这样做,因为身份验证方案会为您完成。
    • 好的,太好了。似乎最好让身份验证方案为我处理所有事情。
    猜你喜欢
    • 1970-01-01
    • 2018-02-09
    • 2020-05-14
    • 2018-01-10
    • 2016-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    相关资源
    最近更新 更多