asp.net web api - optionsverbhandler - Habilitar CORS para Web Api 2 y autenticación de token OWIN
microsoft owin cors (2)
Tengo un proyecto web ASP.NET MVC 5 (localhost: 81) que llama a las funciones de mi proyecto WebApi 2 (localhost: 82) usando Knockoutjs, para establecer la comunicación entre los dos proyectos que habilito CORS. Todo funciona hasta ahora, hasta que intenté implementar la autenticación de token OWIN en WebApi.
Para usar el punto final / token en WebApi, también necesito habilitar CORS en el punto final, pero después de horas de intentar y buscar soluciones, todavía está funcionando y el api / token aún genera:
XMLHttpRequest cannot load http://localhost:82/token. No ''Access-Control-Allow-Origin'' header is present on the requested resource.
public void Configuration(IAppBuilder app)
{
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
TokenConfig.ConfigureOAuth(app);
...
}
TokenConfig
public static void ConfigureOAuth(IAppBuilder app)
{
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<AppUserManager>(AppUserManager.Create);
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider()
};
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
Proveedor de Autorizacion
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
var appUserManager = context.OwinContext.GetUserManager<AppUserManager>();
IdentityUser user = await appUserManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
... claims
}
IdentityConfig
public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext context)
{
// Tried to enable it again without success.
//context.Response.Headers.Add("Access-Control-Allow-Origin", new[] {"*"});
var manager = new AppUserManager(new UserStore<AppUser>(context.Get<ApplicationDbContect>()));
...
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider =
new DataProtectorTokenProvider<AppUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
EDITAR:
1. Nota importante: la apertura directa del punto final (localhost: 82 / token) funciona.
2. Llamar a Api (localhost: 82 / api / ..) desde el proyecto web también funciona, por lo que CORS está habilitado para WebApi.
Sé que su problema se resolvió con comentarios, pero creo que es importante entender qué lo causó y cómo resolver toda esta clase de problemas.
Observando su código, puedo ver que está configurando el encabezado Access-Control-Allow-Origin
más de una vez para el punto final del token:
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
Y dentro del método GrantResourceOwnerCredentials
:
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
Esto, considerando las especificaciones CORS , es en sí mismo un problema porque:
Si la respuesta incluye cero o más de un valor de encabezado Access-Control-Allow-Origin, devuelva fail y finalice este algoritmo.
En su escenario, el marco está configurando este encabezado dos veces, y al comprender cómo se debe implementar CORS, esto provocará que se elimine el encabezado en ciertas circunstancias (posiblemente relacionado con el cliente).
Esto también se confirma con la siguiente respuesta de la pregunta: Duplicar acceso-control-permitir-origen: * ¿causando un error de COR?
Por esta razón, mover la llamada a app.UseCors
después de la llamada a ConfigureOAuth
permite que su encabezado CORS se establezca solo una vez (porque la tubería de Owin se interrumpe en el middleware OAuth, y nunca llega al middleware Microsoft CORS para el punto final de Token
) y hace tu llamada Ajax funcionando.
Para una solución mejor y global, puede intentar volver a poner app.UseCors
antes de la llamada de middleware OAuth, y eliminar la segunda inserción de Access-Control-Allow-Origin
dentro de GrantResourceOwnerCredentials
.
Sigue los pasos a continuación y tendrás tu API funcionando:
- Elimine cualquier código como
config.EnableCors(), [EnableCors(header:"*"....)]
de su API. Ir a startup.cs y agregar debajo de la línea
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
antes de
ConfigureAuth(app);
Uou también necesitará instalar el paquete Microsoft.owin.cors para usar esta funcionalidad