Why CORS error "Response to preflight request doesn't pass access control check"?
Solution 1
In case anyone wondered, this is how I solved this problem:
It was not about not setting the cors policy in asp.net web api (as I have mentioned that I did what Microsoft docs website was suggesting.)
The problem was that the IIS was not configured to handle OPTION verb methods! and because the pre-flight request was using OPTION method, It was always getting 404 not found (rejection from the web server), hence the error.
I should mention that to this day I still do not know why "/token" worked before the configuration of the web server and why controllers did not have the same reaction!
but anyhow, the problem just solved like that. Hope that helps!
Solution 2
Maybe a bit old but worth to mention that you need to add the cors headers in global.asax
protected void Application_BeginRequest(object sender, EventArgs e)
{
var context = System.Web.HttpContext.Current;
var origins = System.Configuration.ConfigurationManager.AppSettings["AllowedCorsDomain"]?.TrimEnd('/');
context.Response.AddHeader("Access-Control-Allow-Origin", origins);
if (context.Request.HttpMethod == "OPTIONS")
{
//These headers are handling the "pre-flight" OPTIONS call sent by the browser
context.Response.AddHeader("Access-Control-Allow-credentials", "true");
context.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, POST, DELETE, OPTIONS");
context.Response.AddHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type, origin, authorization, Accepts, accept, client-security-token, access-control-allow-headers");
context.Response.AddHeader("Access-Control-Max-Age", "86400");
context.Response.End();
}
}
aRasH
I am an experienced software developer. I’ve been developing software for almost 10 years. I have experience in managing software projects from the ground up and I’m really hoping to expand my network and be a part of awesome development teams.
Updated on June 04, 2022Comments
-
aRasH almost 2 years
I'm using ASP.NET Web API with OAuth authorization in my project.
I have tried to decouple every tier in the solution using best practices. I have a web project which contains AngularJS files and other resources which is uploaded on www.example.com and I have another project which is protected backend web api controllers and server side stuff which is uploaded on api.example.com
It all works fine in localhost. when I publish this to production server request for "/token" is successful but requesting any action in any controller in the back-end api returns this error: "Access to XMLHttpRequest at 'http://api.example.com/someRoute' from origin 'http://www.example.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.".
I searched almost any active link for similar error on the internet and no answers yet for me!
I paste some of my code here from the back-end API so you can understand my approach better.
public partial class Startup { public void Configuration(IAppBuilder app) { HttpConfiguration httpConfig = new HttpConfiguration(); UnityConfig.Register(httpConfig); ConfigureAuth(app); WebApiConfig.Register(httpConfig); app.UseWebApi(httpConfig); #region AutoMapper Init DtoMapping.Map(); #endregion } } public void ConfigureAuth(IAppBuilder app) { // Configure the auth context, user manager and signin manager to use a single instance per request app.CreatePerOwinContext(AuthContext.Create); app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create); app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create); OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions() { //remove this line on production AllowInsecureHttp = true, TokenEndpointPath = new PathString("/token"), AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30), Provider = new SimpleAuthorizationServerProvider() }; // Token Generation app.UseOAuthBearerTokens(OAuthServerOptions); app.UseOAuthAuthorizationServer(OAuthServerOptions); app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); } public class WebApiConfig { public static void Register(HttpConfiguration config) { EnableCorsAttribute cors = new EnableCorsAttribute("*", "*", "*"); config.EnableCors(cors); config.MapHttpAttributeRoutes(); //... } } [EnableCors("*", "*", "*")] public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider { public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { context.Validated(); return Task.FromResult<object>(null); } public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { var identity = new ClaimsIdentity(context.Options.AuthenticationType); context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); IList<string> roleNames; using (var _repo = new IdentityRepository()) { var user = await _repo.FindUserAsync(context.UserName, context.Password); if (user == null) { context.SetError("invalid_grant", "username or password is invalid."); context.Rejected(); return; } roleNames = await _repo.GetRolesForUserAsync(user.Id); } identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); foreach (var roleName in roleNames) { identity.AddClaim(new Claim(ClaimTypes.Role, roleName)); } var props = new AuthenticationProperties(new Dictionary<string, string> { { "userName", context.UserName } }); var ticket = new AuthenticationTicket(identity, props); context.Validated(ticket); } }
So, Can anyone please help me?
Thank you for your time.
-
SNO over 5 yearsI think it doesn't work for you because you set "Cors" in WebApiConfig globally and additional as attribute in
SimpleAuthorizationServerProvider
. Try to remove the attribute inSimpleAuthorizationServerProvider
and try again. As far as I can imagine I had the same issue and this worked for me. -
SNO over 5 yearsAdditionaly I recommend to set CORS only for DEBUG (/Development) and not for release. It's a security mechanism that shouldn't be always disabled. Using the subdomain you should set cors at least for the subdomain and not as wildcard.
-
aRasH over 5 yearsThanks for your answer, but removing the attribute does not solve the problem. I think the only reason that "/token" works for generating access token is this attribute available on the authorization provider class. If I remove it, POST request to "/token" returns the cors error same as requesting any other route so the login process won't work. I even tried to put this attribute on web api controllers to see if it works, despite using the global cors setting, but the result was still the same.
-
aRasH over 5 yearsFor security reason that you have mentioned , I will definitely remove the star and restrict cors to some domains in production but now I just need to see if it works for any setting.
-
-
Bel over 2 yearsThank you. CORS has always been fiddly as hell. Since I only need it for DEV, I wrapped this in a #if DEBUG and got on with my work. One change I had to make for Windows Authentication was to move Access-Control-Allow-credentials outside the conditional.