質問

(I'm sorry for both posting this issue here and at github, but I really need help with this..)

I cannot enable CORS (System.Web.Http.Cors), when using authentication with Thinktecture.IdentityModel.45.

I have a problem with the endpoint for token, and I'm using the default "/token".

What happens is that when calling /token (from a javascript client) the browser issues 2 calls, the "OPTION" call and the "GET" call for the "/token" resource. I'm using a simple PolicyProviderFactory just to be able to check that requests get the correct CORS policy and it just returns

        new EnableCorsAttribute("*", "*", "*");

The first OPTION call works, and the GetCorsPolicyProvider gets hit. The other call works, but the GetCorsPolicyProvider doesn't get hit and the result is that the server returns a 200 OK with all the correct headers etc, but, the content response is empty.

I needed to add the following for the token resource in the route configuration otherwise I would get a "NOT FOUND".

        config.Routes.MapHttpRoute(
            name: "SecurityToken",
            routeTemplate: "api/token");

On all other requests both the OPTIONS and the GET invokes the CORS Policy provider and everything works. I've debugged into thinktecture.identitymodel and the corrent response, the correct token is returned.

The GET method of /token resource doesn't invoke the CORS Policy provider.. but why? The CorsMessageHandler is loaded but never gets invoked. How can one tell if the request will trigger CORS/CorsMessageHandler?

The diagnostics trace:

w3wp.exe Information: 0 : Request, Method=OPTIONS, Url=https://localhost/myapp/api/token, Message='https://localhost/myapp/api/token'
w3wp.exe Information: 0 : Message='CorsPolicyProvider selected: 'System.Web.Http.Cors.EnableCorsAttribute'', Operation=MyPolicyProviderFactory.GetCorsPolicyProvider
w3wp.exe Information: 0 : Message='CorsPolicy selected: 'AllowAnyHeader: True, AllowAnyMethod: True, AllowAnyOrigin: True, PreflightMaxAge: null, SupportsCredentials: True, Origins: {}, Methods: {}, Headers: {}, ExposedHeaders: {}'', Operation=EnableCorsAttribute.GetCorsPolicyAsync
w3wp.exe Information: 0 : Message='CorsResult returned: 'IsValid: True, AllowCredentials: True, PreflightMaxAge: null, AllowOrigin: https://localhost:4433, AllowExposedHeaders: {}, AllowHeaders: {access-key,authorization}, AllowMethods: {GET}, ErrorMessages: {}'', Operation=CorsEngine.EvaluatePolicy
w3wp.exe Information: 0 : Operation=CorsMessageHandler.SendAsync, Status=200 (OK)
w3wp.exe Information: 0 : Operation=AuthenticationHandler.SendAsync, Status=200 (OK)
w3wp.exe Information: 0 : Response, Status=200 (OK), Method=OPTIONS, Url=https://localhost/myapp/api/token, Message='Content-type='none', content-length=unknown'
w3wp.exe Information: 0 : Request, Method=GET, Url=https://localhost/myapp/api/token, Message='https://localhost/myapp/api/token'
w3wp.exe Information: 0 : Operation=AuthenticationHandler.SendAsync, Status=200 (OK)
w3wp.exe Information: 0 : Response, Status=200 (OK), Method=GET, Url=https://localhost/myapp/api/token, Message='Content-type='application/json; charset=utf-8', content-length=851'

The authentication configuration looks like:

var authentication = new AuthenticationConfiguration
    {
         ClaimsAuthenticationManager = new ClaimsTransformer(),
         RequireSsl = false, 
         EnableSessionToken = true,
         SendWwwAuthenticateResponseHeaders = true
     };

     var accessKeyHandler = new SimpleSecurityTokenHandler(
            "accessKey", 
            AccessKey.Validate);

        authentication.AddAccessKey(
            accessKeyHandler,
            AuthenticationOptions.ForHeader("access-key"));

        authentication.AddBasicAuthentication(UserCredentials.Validate, retainPassword: true);
        PassiveSessionConfiguration.ConfigureMackineKeyProtectionForSessionTokens();
役に立ちましたか?

解決 2

The problem was that the CorsHandler needed to be added Before the AuthenticationHandler. But I did that:

config.EnableCors();
// ...
config.MessageHandlers.Add(new AuthenticationHandler(authentication));

But that will make the CorsHandler come after the AuthenticationHandler in config.MessageHandlers. Because .EnableCors adds the handler via a LazyInitializer.

To fix it I did:

config.EnableCors();
config.EnsureInitialized(); // this will add the handler to the .MessageHandlers
config.MessageHandlers.Add(new AuthenticationHandler(authentication));

This proved to be instable.. the stable solution was to add the CorsMessageHandler "manually":

AttributeBasedPolicyProviderFactory corsPolicyProviderFactory = new AttributeBasedPolicyProviderFactory
{
     DefaultPolicyProvider = corsAttribute
};
config.SetCorsPolicyProviderFactory(corsPolicyProviderFactory);
config.MessageHandlers.Add(new CorsMessageHandler(config));

他のヒント

To get CORS to play nicely with the OWIN Token endpoint, I had to install the Microsoft.Owin.Cors Nuget package and then add this line of code:

Startup.Auth.cs

using Microsoft.Owin.Cors;
// ...

public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        // ...
        app.UseCors(CorsOptions.AllowAll);

After adding the package and configuring CORS in code, it worked just fine.

The above did not solve my problem with /token not setting Allow headers. I found the solution to this problem on:

ASP.NET WEB API 2 OWIN Authentication unsuported grant_Type

Aparently Token runs in Owin Request context and is separate from the rest...

A suitable answer has already been accepted but when I ran into this issue, I found that I had to add a line to Providers > ApplicaitonOAuthProvider class. As I was attempting to access the WebApi from a remote website in Azure.

enter image description here

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top