Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CORS issue with Google Oauth2 for server side webapps

I referred this question on SO: Google oauth 400 response: No 'Access-Control-Allow-Origin' header is present on the requested resource but the solution suggested is for Javascript web app using implicit grant flow.

My setup is such that my front end is built on angular 4 but I package it and deploy it alongwith rest api on the same server. Si I am following the server side web app flow: https://developers.google.com/identity/protocols/OAuth2WebServer (In the below example the server port is 8300)

I have authorized http://localhost:8300 as Javascript origin and making a request from an angular app to a rest api residing on http://localhost:8300/auth/oauth/test but I am still getting CORS error:

Failed to load https://accounts.google.com/o/oauth2/v2/auth?client_id=568176070083-1lc20949a0q58l0rhmq93n95kvu8s5o6.apps.googleusercontent.com&redirect_uri=http://localhost:8300/auth/myauth/oauth/callback&response_type=code&scope=https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile&state=EUTZF8: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8300' is therefore not allowed access.

enter image description here

My questions are :

  1. Is the solution suggested here, the only way out?
  2. Is there some config on the Google APIs page which I missed?
  3. If I access the rest api directly http://localhost:8300/auth/oauth/test directly from the browser, everything works great. But if I am making a get request from browser to this url (since it is secured, redirection to google api should happen, after authentication, at least this rest api breakpoint should be hit). Because in both the cases, it's access to
    Is my last assumption wrong?

If this is of relevance, I am doing angular get request like:

loginWithGoogle(){
    console.log(" Login with oauth2 ");
    let oauthUrl = "http://localhost:8300/auth/oauth/test";
    return this.http.get(oauthUrl)                                
      .subscribe(
        res => {                    
          this.onSuccess(res);
        }, error => {
          this.onFailure(error);
        });

}

EDIT

Actually my 3rd point is why is CORS thrown when rest api is accessed through XHR from angular app which is also on same domain as rest api and not when rest api is accessed directly fron browser.

like image 660
tryingToLearn Avatar asked Feb 22 '18 10:02

tryingToLearn


1 Answers

When you use the Authorization code grant (OAuth2 for backend apps - &response_type=code), you must redirect the browser to the /auth endpoint - you cannot use XHR for that. The user will be redirected back after authentication.

After redirecting to the /auth endpoint, user needs to see in an address bar that the page is from Google (trusted source) and Google may need to do some more redirects in order to authenticate the user and present the consent page. So using XHR is not possible.

Update: For the third point, your backend API should return the HTTP 401 if the request doesn't contain valid credentials (not HTTP 30x redirect as it does now). Then, your Angular application needs an HTTP error handler which redirects the browser on HTTP 401 response.

But if you want to keep the token in your Angular application, it's better to use the Implicit grant, which is designed for applications running in a browser. Because using the Authorization code grant, your backend has the role of client (in OAuth2 scheme), but you want the Angular application to be the client (since it holds the token).

like image 79
Ján Halaša Avatar answered Nov 09 '22 00:11

Ján Halaša