Search code examples
pythonyoutube-apigoogle-oauthflask

FlowExchangeError: invalid_grant in flask application


I am creating an API to wrap google oauth. I am using google python client library.

Code in api.py

from flask import request, g
from ..helpers import config_helper
from ..adapters.youtube.oauth_adapter import OauthAdapter
from ..api import api_blueprint as api


@api.before_app_request
def before_request():
    client_id, client_secret, scope, callback = config_helper.get_config()
    g.auth = OauthAdapter(client_id, client_secret, scope, callback)


@api.route('/authorisation_url/')
def authorisation_url():
    auth = g.get('auth', None)
    return auth.get_authorisation_url()


@api.route('/oauth2callback/')
def callback():
    authorisation_code = request.args.get('code')
    return authorisation_code


@api.route('/save_oauth2credential/', methods=['POST'])
def oauth2_credentials():
   auth = g.get('auth', None)
   user = request.form.get('user')
   authorisation_code = request.form.get('authorisation_code')
   auth.save_credentials(user, authorisation_code)


@api.teardown_app_request
def after_request(response):
    g.auth = None
    return response

Code in oauth_adapter.py

from oauth2client.client import OAuth2WebServerFlow
from ..repositories import oauth_credentials_repository


class OauthAdapter:
    def __init__(self, client_id, client_secret, scope, callback):
        self.flow = OAuth2WebServerFlow(client_id=client_id,
                                    client_secret=client_secret,
                                    scope=scope,
                                    redirect_uri=callback)

    def get_authorisation_url(self):
        return self.flow.step1_get_authorize_url()

    def save_credentials(self, user, authorisation_code):
        credentials = self.flow.step2_exchange(authorisation_code)
        oauth_credentials_repository.save(user, credentials, 'Google')

I need to save the credentials object against the logged in user so I can use it later to make call to other google api's on behalf of this user.

When I call @api.route('/save_oauth2credential/', methods=['POST']) to retrieve the credentials using the authorisation_code retrieved in @api.route('/oauth2callback/') step. I keep getting FlowExchangeError: invalid_grant

Any ideas?


Solution

  • Have a look at the network dialogue in Chrome Devtools and see what is going over the wire. I'm guessing that there is a 403 invalid grant response in there somewhere. So you need to figure out the cause of the invalid grant. I just posted some possible explanations at Getting 'invalid_grant' error with google oauth from second time

    In general, there are two things you need to do.

    Firstly, check that your code is correct, that your scopes and client id are solid, and that you are correctly saving the refresh token.

    Once you've done all of that, you need to deal with invalid grant as an occupational hazard, and reprompt the user for for authorisation in order to get a new refresh token.