Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google API Scope Changed

edit: I solved it easily by adding "https://www.googleapis.com/auth/plus.me" to my scopes, but I wanted to start a discussion on this topic and see if anyone else experienced the same issue.

I have a service running on GCP, an app engine that uses Google API. This morning, I've received this "warning" message which threw an 500 error. It has been working fine for the past month and only threw this error today (5 hours prior to this post).

Does anyone know why Google returned an additional scope at the oauth2callback? Any additional insight is very much appreciated. Please let me know if you've seen this before or not. I couldn't find it anywhere.

Exception Type: Warning at /oauth2callback

Exception Value: Scope has changed from "https://www.googleapis.com/auth/userinfo.email" to "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/plus.me".

This line threw the error:

flow.fetch_token(
        authorization_response=authorization_response,
        code=request.session["code"])

The return url is https://my_website.com/oauth2callback?state=SECRET_STATE&scope=https://www.googleapis.com/auth/userinfo.email+https://www.googleapis.com/auth/plus.me#

instead of the usual https://my_website.com/oauth2callback?state=SECRET_STATE&scope=https://www.googleapis.com/auth/userinfo.email#

edit: sample code

import the required things

SCOPES = ['https://www.googleapis.com/auth/userinfo.email',
          'https://www.googleapis.com/auth/calendar',
          # 'https://www.googleapis.com/auth/plus.me' <-- without this, it throws the error stated above. adding it, fixes the problem. Google returns an additional scope (.../plus.me) which causes an error.
          ]

def auth(request):
    flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
        CLIENT_SECRETS_FILE, scopes=SCOPES)
    flow.redirect_uri = website_url + '/oauth2callback'
    authorization_url, state = flow.authorization_url(
        access_type='offline', include_granted_scopes='true', 
prompt='consent')
    request.session["state"] = state
    return redirect(authorization_url)

def oauth2callback(request):
    ...
    # request.session["code"] = code in url
    authorization_response = website_url + '/oauth2callback' + parsed.query
    flow.fetch_token(
    authorization_response=authorization_response,
    code=request.session["code"])
    ...
like image 912
Julius Ting Avatar asked Jul 19 '18 05:07

Julius Ting


People also ask

How do I add a scope to Google API?

Go to the Google API Console OAuth consent screen page. Add required information like a product name and support email address. Click Add Scope. On the dialog that appears, select the scopes your project uses.

What is the scope of an API?

The scope constrains the endpoints to which a client has access, and whether a client has read or write access to an endpoint. Scopes are defined in the Merchant Center or with the API Clients endpoint for a single project when creating an API Client. Once you create an API Client, you cannot redefine the scopes.

What is Gmail scope?

Gmail scopesCreate, read, update, and delete labels only. Recommended. https://www.googleapis.com/auth/gmail.send. Send messages only. No read or modify privileges on mailbox.


1 Answers

We discovered the same issue today. Our solution has been working without any hiccups for the last couple of months.

We solved the issue by updating our original scopes 'profile email' to https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile and by doing some minor changes to the code.

When initiating the google_auth_oauthlib.flow client, we previously passed in the scopes in a list with only one item which contained a string in which the scopes were separated by spaces.

google_scopes = 'email profile'
self.flow = Flow.from_client_secrets_file(secret_file, scopes=[google_scopes], state=state)

Now, with the updated scopes, we send in a list where each element is a separate scope.

google_scopes = 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile'    
self.flow = Flow.from_client_secrets_file(secret_file, scopes=google_scopes.split(' '), state=state)

Hope it helps, good luck!

like image 176
Rickard Bergeling Avatar answered Sep 28 '22 01:09

Rickard Bergeling