Search code examples
oauth-2.0corsgoogle-oauthcross-domainflask-dance

Why google oauth flow is failing when initiated from frontend, but seems to work if I initiate from backend directly?


I have a Flash backend using flask-dance in order to allow a web app to authenticate users with Google provider.

In my local dev environment, the backend runs from https://localhost:5000, while my local frontend is at https://local.mydomain.com

I have a backend endpoint at https://localhost:5000/login/google which redirects the user to the Google OAuth flow:

    @app.route('/login/<provider>')
    def login(provider: str):
        # here we store the page the user has come from with the referrer value
        session["return_to"] = request.referrer

        if provider == 'google':
            return redirect(url_for("google.login"))

        return False

If I access this URL directly in the browser, I'm redirected to Google and the OAuth flow completes successfully.

If, however, I add a button on the frontend that redirects to that URL, the OAuth flow fails midway and the browser prints the following errore:

Access to XMLHttpRequest at 'https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=580945975384-0mqduo9k8dchc0ho7tnd7g6ejo70jrlb.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Flocalhost%3A5000%2Fauth%2Fgoogle%2Fauthorized&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+openid&state=tWt5b2pkp0jfjxtXD8aHlMwsKyuCJw' (redirected from 'https://localhost:5000/login/google') from origin 'https://local.mydomain.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

index.js:1 Error: Network Error
    at createError (createError.js:16)
    at XMLHttpRequest.handleError (xhr.js:117)

xhr.js:210 GET https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=580945975384-0mqduo9k8dchc0ho7tnd7g6ejo70jrlb.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Flocalhost%3A5000%2Fauth%2Fgoogle%2Fauthorized&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+openid&state=tWt5b2pkp0jfjxtXD8aHlMwsKyuCJw net::ERR_FAILED 200

This is the failed request:

enter image description here

The Flask backend app has CORS enabled.

Why is this happening?

I suspect that running the backend locally from a different domain has something to do with it, but I couldn't quite figure out exactly what is going on and how to fix this.


Solution

  • The Google OAuth URL you request (https://accounts.google.com/o/oauth2/auth) is the starting point for their authentication process - it requires a full browser - it needs to display a credentials form, consent and then to redirect the browser back to your application. That's why you cannot use XMLHttpRequest for accessing it.

    Your backend CORS settings cannot help it - Google would have to enable it on their endpoint, but it still would not work for the reasons mentioned before.