当在 jwt 承载处理程序中配置的不同别名下到达站点时,验证颁发者失败

Validating issuer fails when site is reached under different alias as configured in the jwt bearer handler

我有使用 jwt 承载身份验证的网络 api。创建 jwt 的实现 (openiddict) 使用当前 url 作为发行者。

services
    .AddOpenIddict()
    .UseJsonWebTokens();

我将 jwt 身份验证处理程序配置为使用有效的颁发者。

services
    .AddAuthentication()
    .AddJwtBearer(options =>
    {
        options.Authority = "http://test/";
        ...
    });

当我到达 http://test/ 下的站点时,我得到了一个访问令牌,其中发行者设置为 http://test/。由于 Authority 与发行者匹配,请求将被验证。

当我到达 http://125.124.35.21/ 下的站点时,我得到了一个访问令牌,其中发行者设置为 http://125.124.35.21/。由于 Authority 与颁发者不匹配,请求将不会被验证。

I want in both cases to be able to authenticate the request.

现在我看到根据 the jwt rfciss 声明是可选的。

我的问题是我是否可以为此目的将 ValidateIssuer 设置为 false,如果我这样做会打开一个安全漏洞,是否有更推荐的替代方案?

services
    .AddAuthentication()
    .AddJwtBearer(options =>
    {
        options.Authority = "http://test/";
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = false,
            ...
        }
    });

哪个配置用于解析.well-known/openid-configurationAuthority?希望不是发行者,因为这意味着每个人都可以发行令牌并将其与我的 api.

一起使用

我查看了生成访问令牌的代码,发现它仅在未设置配置值时采用当前 uri。

https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/blob/120a7ea9a14a33fad292cf4a11b4077118fab21f/src/AspNet.Security.OpenIdConnect.Server/OpenIdConnectServerHelpers.cs#L198

public static string GetIssuer(this HttpContext context, OpenIdConnectServerOptions options)
{
    var issuer = options.Issuer;
    if (issuer == null)
    {
        if (!Uri.TryCreate(context.Request.Scheme + "://" + context.Request.Host +
                               context.Request.PathBase, UriKind.Absolute, out issuer))
        {
            throw new InvalidOperationException("The issuer address cannot be inferred from the current request");
        }
    }

    return issuer.AbsoluteUri;
}

所以当我配置 openiddict 时,我可以设置 Issuer 属性.

services.AddOpenIddict()
    ...
    .Configure(options =>
    {
        options.Issuer = "http://test/";
        ...
    });

当我添加身份验证服务时,我也可以只设置 Authority 属性.

services
    .AddAuthentication()
    .AddJwtBearer(options =>
    {
        options.Authority = "http://test/";
        ...
    });

似乎当没有配置有效的颁发者时,Authority 被用来验证颁发者。但是我没有找到支持该声明的代码。

也许它隐藏在 Microsoft.IdentityModel.Protocols.OpenIdConnect.dll

另一种选择是将 ValidateIssuer 设置为 false


正如 JWT RFC 所说,iss(发行人)声明是可选的。

The "iss" (issuer) claim identifies the principal that issued the JWT. The processing of this claim is generally application specific. The "iss" value is a case-sensitive string containing a StringOrURI value. Use of this claim is OPTIONAL.


OAuth 2.0 RFC 根本没有提及发行者或代币的格式。


解析 .well-known/openid-configuration 的 uri 由 MetadataAddress 属性 配置。如果此 属性 未设置,则似乎 Authority 属性 用于构建 uri。

https://github.com/aspnet/Security/blob/b3e4bf382c9676e2d912636b7ee0255cad244e11/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerPostConfigureOptions.cs#L37

if (string.IsNullOrEmpty(options.MetadataAddress) && !string.IsNullOrEmpty(options.Authority))
{
    options.MetadataAddress = options.Authority;
    if (!options.MetadataAddress.EndsWith("/", StringComparison.Ordinal))
    {
        options.MetadataAddress += "/";
    }

    options.MetadataAddress += ".well-known/openid-configuration";
}

并且由于用于验证令牌的 public 密钥存储在以 MetadataAddress 为前缀的 .well-known/jwks 文件中,因此应该保存以忽略此声明,如果您不要排除某些共享相同配置文件的发行者。但是我想不到这样的情况。

另一种解决方案是将所有已知别名包含在 TokenValidationParametersValidIssuers 属性 中。但我认为这不是一个好主意,因为您可能会忘记一些别名。

例如,在不同的子网中,您可能可以在不同的 ips 或不同的 dns 别名下访问该服务。