ASP.NET Core Web API + Angular Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request

Viewed 1591

I have a backend on ASP.NET Core Web API and frontend on Angular 9. I am implementing google authentication. In postman It works fine, but in my angular app when I try to authorize via google I get error:

Access to XMLHttpRequest at 'https://accounts.google.com/o/oauth2/v2/... 
(redirected from 'https://localhost:44340/api/auth/googlelogin')
from origin 'http://localhost:4200' has been blocked by CORS policy: 
Response to preflight request doesn't pass access control check:
Redirect is not allowed for a preflight request.

CORS configuration on backend:

            services.AddCors(options =>
            {
                options.AddPolicy("MyPolicy",
                      builder =>
                      {
                          builder
                          .WithOrigins(Configuration["ApplicationSettings:Client_URL"].ToString())
                          .AllowAnyOrigin()
                          .AllowAnyHeader()
                          .AllowAnyMethod();
                      });
            });
            app.UseCors("MyPolicy");

Method in my service

        public ChallengeResult LoginViaGoogle()
        {
            var provider = "Google";
            var redirectUrl = "/api/auth/ExternalLoginCallBack";
            var properties = Database.SignInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
            return new ChallengeResult(provider, properties);
        }

Method in my controller

        [HttpGet("GoogleLogin")]
        public IActionResult GoogleLogin()
        {
            ChallengeResult result;
            try
            {
                result = _authService.LoginViaGoogle();
            }
            catch(Exception ex)
            {
                throw ex;
            }
            return result;
        }

My method in Angular:

  googleLogin(){
    const httpOptions = {
      headers: new HttpHeaders({
        "Access-Control-Allow-Origin": "*"
      })
    };
    return this.http.get("https://localhost:44340/api/auth/googlelogin", httpOptions);
  }

I have tried a lot of solutions from this website, but none helped.

I think that the problem may be that I incorrectly registered the URL in google oauth. enter image description here

2 Answers

The problem is that you are returning a redirect on this get request, which is not allowed when using CORS.

I would definitely recommend looking at the MDN documentation if you're having troubles with such things, they're very useful and pretty near complete.

To fix this, you could return a payload with the correct auth url and follow that using your front end code.

I don't specifically know angular but I would imagine it would look something like:

googleLogin(){
  // This header options was not doing anything, the request cannot tell the server how to do CORS.
  const authUrl = this.http.get("https://localhost:44340/api/auth/googlelogin");
  return this.http.get(authUrl);
}

When you make your ajax call to your backend and it returns a redirect to Google, your initial request will follow that redirect. This means you are trying to make an ajax call to Google, which is not allowed.

In order to solve this issue, you need to make an actual, full "postback" to your backend, either by some form submission or doing a window.location='yourdomain.page/path'. This is why is works when you drop the url in your browser and press Enter.

My suggestion is to have and endpoint that just returns the google oauth url that you can hit with ajax, then do a redirect i.e.

const url = await httpClient.get<GoogleAuth>('/oauth/google').toPromise(); //replace with your google auth returning endpoint
window.location = url;
Related