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
この罠を回避することができます。ICorsPolicyService
appsettings.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));
}
}