IdentityServer3 - 無効な CORS パスのため拒否されました 質問する

IdentityServer3 - 無効な CORS パスのため拒否されました 質問する

IdentityServer3 に対して問題なく認証される ASP.NET MVC アプリケーションがありますが、ユーザーが約 3 分後に AJAX 機能を続行する前に待機すると、ApiController を使用するアプリケーションの Web API 部分が失敗し始めます (3 分前はすべて正常に見えます)。

Chrome に表示されるエラーは次のとおりです。

XMLHttpRequest を読み込めませんhttps://test-auth.myauthapp.com/auth/connect/authorize?client_id=ecan-farmda…gwLTk5ZjMtN2QxZjUyMjgxNGE4MDg2NjFhZTAtOTEzNi00MDE3LTkzNGQtNTc5ODAzZTE1Mzgw。要求されたリソースには「Access-Control-Allow-Origin」ヘッダーが存在しません。Origin 'http://test.myapp.comしたがって、アクセスは許可されません。

IE では次のエラーが発生します。

SCRIPT7002: XMLHttpRequest: ネットワーク エラー 0x4c7、操作はユーザーによってキャンセルされました。

IdentityServer3 のログを見ると、次のようなエントリが見つかります。

2015-08-10 16:42 [警告] (Thinktecture.IdentityServer.Core.Configuration.Hosting.CorsPolicyProvider) パス: /connect/authorize に対して、オリジンからの CORS 要求が行われました:http://test.myapp.comしかし、CORSパスが無効であるため拒否されました

IdentityServer3 Web アプリケーションでは、クライアントに AllowedCorsOrigins を提供しています。

Thinktecture.IdentityServer.Core.Models.Client client = new Thinktecture.IdentityServer.Core.Models.Client()
{
    Enabled = configClient.Enabled,
    ClientId = configClient.Id,
    ClientName = configClient.Name,
    RedirectUris = new List<string>(),
    PostLogoutRedirectUris = new List<string>(),
    AllowedCorsOrigins = new List<string>(),
    RequireConsent = false, // Don't show consents screen to user
    RefreshTokenExpiration = Thinktecture.IdentityServer.Core.Models.TokenExpiration.Sliding
};

foreach (Configuration.RegisteredUri uri in configClient.RedirectUris)
{
    client.RedirectUris.Add(uri.Uri);
}

foreach (Configuration.RegisteredUri uri in configClient.PostLogoutRedirectUris)
{
    client.PostLogoutRedirectUris.Add(uri.Uri);
}

// Quick hack to try and get CORS working
client.AllowedCorsOrigins.Add("http://test.myapp.com");
client.AllowedCorsOrigins.Add("http://test.myapp.com/"); // Don't think trailing / needed, but added just in case

clients.Add(client);

サービスを登録するときに、InMemoryCorsPolicyService を追加します。

app.Map("/auth", idsrvApp =>
{
    var factory = new IdentityServerServiceFactory();

    factory.Register(new Registration<AuthContext>(resolver => AuthObjects.AuthContext));
    factory.Register(new Registration<AuthUserStore>());
    factory.Register(new Registration<AuthRoleStore>());
    factory.Register(new Registration<AuthUserManager>());
    factory.Register(new Registration<AuthRoleManager>());

    // Custom user service used to inject custom registration workflow
    factory.UserService = new Registration<IUserService>(resolver => AuthObjects.AuthUserService);

    var scopeStore = new InMemoryScopeStore(Scopes.Get());
    factory.ScopeStore = new Registration<IScopeStore>(scopeStore);
    var clientStore = new InMemoryClientStore(Clients.Get());
    factory.ClientStore = new Registration<IClientStore>(clientStore);

    var cors = new InMemoryCorsPolicyService(Clients.Get());
    factory.CorsPolicyService = new Registration<ICorsPolicyService>(cors);

    ...

    var options = new IdentityServerOptions
    {
        SiteName = "Authentication",
        SigningCertificate = LoadCertificate(),
        Factory = factory,
        AuthenticationOptions = authOptions
    };

    ...
});

IdentityServer3のログエントリには、「CORS request made for path: /connect/authorize」ではなく「CORS request made for path: /認証/connect/authorize" ですが、IdentityServer3 のソース コードを調べると、おそらくこれは問題ではないことがわかります。

InMemoryCorsPolicyService が選択されていない可能性があります。

ApiController と呼ばれる AJAX が動作しない理由について何かご存知ですか?

Thinktecture.IdevtityServer3 v1.6.2 が NuGet を使用してインストールされました。

アップデート

IdentityServer3 の開発者と話し合い中ですが、まだ解決に至っていません。参考になれば幸いです:

https://github.com/IdentityServer/IdentityServer3/issues/1697

ベストアンサー1

CORS は悪夢です。これはブラウザの問題であり、IE と Chrome で異なる動作が発生するのはそのためです。

サーバー上で CORS を構成する方法は (少なくとも) 2 つあります。クライアントがヘッダー付きのリクエストを行うときは、それを受け入れるかどうかをサーバーに伝える必要があります。受け入れた場合、サーバーはブラウザーへの応答にヘッダーOriginを追加します。Access-Control-Allow-Origin

MVC / webAPI では、CORS サービスを追加し、CORS ポリシーを設定して、.UseCors次のようにする必要があります。

builder.Services.AddCors((options =>
            {
                if (settings.AllowedCorsOrigins.Length > 0)
                {
                    options.AddDefaultPolicy(builder => 
                    { 
                        builder.SetIsOriginAllowedToAllowWildcardSubdomains();
                        builder.AllowAnyHeader().AllowAnyMethod().WithOrigins(settings.AllowedCorsOrigins); 
                    });
                }
                if (isDevelopment)
                {
                    options.AddPolicy("localhost", builder => 
                    {
                        builder.SetIsOriginAllowedToAllowWildcardSubdomains();
                        builder.AllowAnyHeader().AllowAnyMethod().SetIsOriginAllowed((string origin) => { return origin.Contains("localhost"); }); });
                    }
            });

そして

            app.UseCors();
            if (app.Environment.IsDevelopment())
            {
                app.UseCors("localhost");
            }

通常、許可されたホストのリストは、 内の文字列の配列として必要ですappsettings.json。また、 の罠には注意してくださいSetIsOriginAllowedToAllowWildcardSubdomains

これに加えて、IdentityServerには独自の追加のCORS設定があり、加えて標準のMVC/webAPI設定に。これらは表に記載されており、ワイルドカードサブドメインはサポートされていません。このようなものを実装して、同じ設定を使用することで、ClientCorsOriginこの罠を回避することができます。ICorsPolicyServiceappsettings.json

    public class CorsPolicyService : ICorsPolicyService
    {
        private readonly CorsOptions _options;

        public CorsPolicyService(IOptions<CorsOptions> options)
        {
            _options = options.Value;
        }

        private bool CheckHost(string host)
        {
            foreach (string p in _options.AllowedCorsOrigins)
            {
                if (Regex.IsMatch(host, Regex.Escape(p).Replace("\\*", "[a-zA-Z0-9]+"))) // Hyphen?
                {
                    return true;
                }
            }
            return false;
        }

        public Task<bool> IsOriginAllowedAsync(string origin)
        {
            return Task.FromResult(CheckHost(origin));
        }
    }

おすすめ記事