繁体   English   中英

使用包含多个 CN 或域名的 SSL 托管 asp.net core + ReactJS web 应用程序导致无效的发行者错误

[英]Hosting asp.net core + ReactJS web app with SSL containing multiple CN or domain names is causing invalid issuer error

我在托管使用 asp.net core 3.1 和 React 构建的 Web 应用程序时遇到以下问题。

我们为 React 使用了默认的 Visual Studio 模板。 ASP.NET Identity 用于身份验证和授权。

只要我们使用为单个域或 CN 颁发的 SSL 证书托管网站,身份验证和授权就会按预期工作。 (例如example.com)

如果我们使用带有多个 CN(例如 example.com、sub1.example.com、sub2.example.com)的 SSL 托管他的网站,则它适用于任何一个域。 对于其余域,我们得到以下行为:

登录按预期工作。 /connect/token 路径发出有效的令牌。 登录后,当我们尝试调用任何 api(所有 api 都托管在 /api 路由下)时,我们会收到 401 未经授权的错误。 标题中的错误描述:

WWW-Authenticate: Bearer error="invalid_token", error_description="颁发者 ' https://sub1.example.com ' 无效"。

我还尝试在 jwt.io 上解析发布的令牌。 iss 字段(颁发者)是https://sub1.example.com ,它与错误描述完全匹配。 我无法理解为什么身份引擎拒绝识别为其颁发令牌的发行者。

这是来自 Startup.cs 的相关片段

public void ConfigureServices(IServiceCollection services)
{
    services.AddIdentityServer()
            .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
    services.AddAuthentication()
            .AddIdentityServerJwt();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseAuthentication();
    app.UseIdentityServer();
    app.UseAuthorization();
}

有任何想法吗?

新的 .Net(.net 核心)是高度可配置和模块化的。 通常扩展方法采用一个委托,我们可以使用它来配置选项。 但是, AddIdentityServerJwt方法不遵循该约定。

我注意到很久以前,有一个叫做财产ValidIssuersTokenValidationParameters可与AddJwtBearer扩展方法来配置。 但是, AddIdentityServerJwt扩展方法不接受任何选项委托作为参数。

事实证明,有一种特殊的方式来配置选项。

services.AddAuthentication()
    .AddIdentityServerJwt();

services.Configure<JwtBearerOptions>(IdentityServerJwtConstants.IdentityServerJwtBearerScheme, options =>
{
    options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
    {
        ValidIssuers = new string[] { "https://sub1.example.com", "https://sub2.example.com", "https://sub3.example.com" }
    };
});

添加了此代码并解决了问题。 配置也可以移动到 appsettings.json。

这可能是因为从一个 CN 上的 IdentityServer4 实例接收令牌,并尝试使用另一个 CN 向 IdentityServer4 发出请求来验证它。 拒绝令牌的 IdentityServer 组件是 TokenValidator 的ValidateJwtAsync方法。 此方法将在发行人进入JwtSecurityTokenHandler的ValidateToken作为一个属性TokenValidationParameters 颁发者是从在“AddIdentityServer”扩展方法中的IdentityServerOptions上配置的颁发者中检索的,或者是从请求动态生成

我可以想到一种解决验证问题的方法,那就是使用传递给AddIdentityServer的委托在 IdentityServerOptions 上设置颁发 这将导致为所有发行的令牌设置相同的发行者,而不管它是从哪个 CN 访问的。 这将使 IdentityServer 成为颁发者信息的单一真实来源,并允许 IdentityServer 在令牌进入验证时知道要验证哪个颁发者。

其他试图维护发行者的解决方案受到 TokenValidator 是一个内部类的严重限制,该类不能被继承,并且很容易被替换为将针对有效发行者列表进行验证的实现。 此外,配置为具有颁发者 uri 的 IdentityServerOptions 注册为单例,并且不能更改其值。 可以设计其他人为的实现,例如尝试使用中间件动态更改 HttpContext 上的主机值(我不确定是否可能,因为我从未尝试过),但不建议任何违反 IdentityServer4 设计决策的内容。

请检查网址 http://{url}/.well-known/openid-configuration

这个网址应该是真的

以下代码适用于不同的领域。 验证启动

 services.AddIdentityServer(options =>
        {
            options.IssuerUri = Configuration["ServerSettings:Authority"].ToString();
            options.PublicOrigin = Configuration["ServerSettings:Authority"].ToString();
        })
            .AddDeveloperSigningCredential()
            .AddInMemoryApiResources(Config.GetApiResources())
            .AddInMemoryIdentityResources(Config.GetIdentityResources())
            .AddInMemoryClients(Config.GetClients())
            .AddProfileService<ProfileService>();

api启动

services.AddAuthentication("Bearer")
        .AddIdentityServerAuthentication(options =>
        {
            options.Authority = Configuration["ServerSettings:Authority"].ToString(); //"http://localhost:31864";
            options.RequireHttpsMetadata = false;
            options.ApiName = "api";
        });

在同一个域中工作,但如果域不同,则应指定此项

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM