簡體   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