当在 jwt 承载处理程序中配置的不同别名下到达站点时,验证颁发者失败
Posted
技术标签:
【中文标题】当在 jwt 承载处理程序中配置的不同别名下到达站点时,验证颁发者失败【英文标题】:Validating issuer fails when site is reached under different alias as configured in the jwt bearer handler 【发布时间】:2018-09-25 23:37:10 【问题描述】:我有使用 jwt 不记名身份验证的 web 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
与颁发者不匹配,因此不会对请求进行身份验证。
我希望在这两种情况下都能够验证请求。
现在我看到,根据the jwt rfc,iss
声明是可选的。
我的问题是我是否可以为此目的将ValidateIssuer
设置为 false,如果我这样做时会打开一个安全漏洞,以及是否有更推荐的替代方法?
services
.AddAuthentication()
.AddJwtBearer(options =>
options.Authority = "http://test/";
options.TokenValidationParameters = new TokenValidationParameters
ValidateIssuer = false,
...
);
使用哪个配置来解析.well-known/openid-configuration
?Authority
?希望不是发行者,因为这意味着每个人都可以发行令牌并将其与我的 api 一起使用。
【问题讨论】:
【参考方案1】:我查看了生成访问令牌的代码,发现它仅在未设置配置值时才采用当前 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
【讨论】:
【参考方案2】:另一种选择是将ValidateIssuer
设置为false
。
正如JWT RFC 所说,iss
(颁发者)声明是可选的。
“iss”(颁发者)声明标识了颁发 智威汤逊。此声明的处理通常是特定于应用程序的。 "iss" 值是包含 StringOrURI 的区分大小写的字符串 价值。 此声明的使用是可选的。
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";
并且由于验证令牌的公钥存储在以MetadataAddress
为前缀的.well-known/jwks
文件中,如果您不想排除某些发行者,则应保存以忽略此声明其中所有共享相同的配置文件。但是我想不出这样的情况。
【讨论】:
【参考方案3】:另一个解决方案是在TokenValidationParameters
的ValidIssuers
属性中包含所有已知别名。但我认为这不是一个好主意,因为您可能会忘记一些别名。
例如,在不同的子网中,您可能可以使用不同的 ips 或不同的 dns 别名访问服务。
【讨论】:
以上是关于当在 jwt 承载处理程序中配置的不同别名下到达站点时,验证颁发者失败的主要内容,如果未能解决你的问题,请参考以下文章
在 ASP.Net 应用程序上结合 ADFS 身份验证和 JWT 承载