简体   繁体   中英

Google OAuth2 refresh expires & does not renew

I followed this tutorial EXACTLY, however

@app.route('/test')
def test_api_request():
  if 'credentials' not in flask.session:
    return flask.redirect('authorize')

  # Load credentials from the session.
  credentials = google.oauth2.credentials.Credentials(
      **flask.session['credentials'])

  drive = googleapiclient.discovery.build(
      API_SERVICE_NAME, API_VERSION, credentials=credentials)

  files = drive.files().list().execute()

  # Save credentials back to session in case access token was refreshed.
  # ACTION ITEM: In a production app, you likely want to save these
  #              credentials in a persistent database instead.
  flask.session['credentials'] = credentials_to_dict(credentials)

  return flask.jsonify(**files)

However in this part:

  credentials = google.oauth2.credentials.Credentials(
      **flask.session['credentials'])

The refresh token expires after an hour, with this error:

The credentials do not contain the necessary fields need to refresh the access token. You must specify refresh_token, token_uri, client_id, and client_secret.

But clearly in the flask session the dict object is there:

{'client_id': '<COMMENTED_OUT>.apps.googleusercontent.com',
 'client_secret': '<COMMENTED_OUT>',
 'refresh_token': None,
 'scopes': ['https://spreadsheets.google.com/feeds',
            'https://www.googleapis.com/auth/drive',
            'https://mail.google.com/'],
 'token': '<COMMENTED_OUT>',
 'token_uri': 'https://oauth2.googleapis.com/token'}

I believe the google tutorial auto-refreshes the token

Two questions 1) Do i need to manually "refresh" the refresh token? The comment in the tutorial says "Save credentials back to session in case access token was refreshed".. which implies that it's refreshed automatically

2) Is this because the app is still in unverified status?

Looking at the dict, the refresh token is missing:

'refresh_token': None,

You need this token in order to refresh your access token after it expires. The refresh token is only provided in the JSON response if the user saw a consent screen (the one that lists the scopes being requested). If the user has previously approved access, and the scopes haven't changed, the OAuth flow will skip that screen if the user is sent back into the flow, and therefore not return the refresh token.

What likely happened is that during your testing you approved access once, but didn't store the refresh token correctly. Further attempts to approve access didn't return the refresh token, hence your inability to refresh the access token.

To ensure a refresh token is always returned, set the URL parameter prompt=consent in the authorization URL:

authorization_url, state = flow.authorization_url(
    access_type='offline',
    include_granted_scopes='true'
    prompt='consent')

(It's documented in the "HTTP/REST" tab here ).

Alternatively, visit and revoke access to your application. The next time you go through the OAuth flow you should see the consent screen again, and get a new refresh token.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM