Search code examples
pythonflaskoauth-2.0google-oauth

Getting invalid_token & Token expired or revoked while trying to revoke OAuth2 access token (Google Sign in)


I am using Flask & Oauth 2 to authenticate the user into my system. Login with Google works fine, but if I keep the user logged in for a long amount of time, logout issues this error.

{
  "error": "invalid_token",
  "error_description": "Token expired or revoked"
}

I am new to Flask and web development and unable to understand why this happens. If I try to login again, it says user already connected.

My Sign in button HTML

<div id="signinButton">
  <span class="g-signin" 
        data-scope="openid email" 
        data-clientid="<ClientID>.apps.googleusercontent.com" 
        data-redirecturi="postmessage" 
        data-accesstype="offline" 
        data-cookiepolicy="single_host_origin" 
        data-callback="signInCallback" 
        data-approvalprompt="force">
  </span>
</div>

My disconnect method: code jumps to 400 error

# Google Sign out method
@app.route('/gdisconnect')
def gdisconnect():
    access_token = login_session.get('access_token')
    if access_token is None:
        print 'Access Token is None'
        response = make_response(
            json.dumps('Current user not connected.'), 401
        )
        response.headers['Content-Type'] = 'application/json'
        return response
    print 'In gdisconnect access token is %s' % access_token
    print 'User name is: '
    print login_session['username']
    url = 'https://accounts.google.com/o/oauth2/revoke?token=%s' % login_session['access_token']
    print url
    h = httplib2.Http()
    result = h.request(url, 'GET')[0]
    print 'result is '
    print result
    if result['status'] == '200':
        del login_session['access_token']
        del login_session['gplus_id']
        del login_session['username']
        del login_session['email']
        del login_session['picture']
        response = make_response(json.dumps('Successfully disconnected.'), 200)
        response.headers['Content-Type'] = 'application/json'
        return response
    else:
        response = make_response(
            json.dumps('Failed to revoke token for given user.',
                       400)
        )
        response.headers['Content-Type'] = 'application/json'
        return response

Solution

  • Your OAuth Access Token is expired. You do not need to revoke an expired access token.

    The solution is to process the Access Token's exp (expires at) value. If the token is expired just deleted it from the user session. Your code can either save this value at the time the token is created or refreshed or you can call the Google endpoint: https://www.googleapis.com/oauth2/v3/tokeninfo to obtain information on the token which includes which includes the exp and expires_in values. Note: this endpoint will also return an error for an expired token so call it at creation or refresh.

    Another option is to continue calling revoke but if an error occurs, check if the token is expired. If true, then ignore the error, delete the token from the session and continue on without reporting a problem.

    If you really want to terminate the client's OAuth session you can revoke the Refresh Token (which normally does not expire). This will revoke all Access Tokens.