Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a refresh_token to get a new access_token (using Flask-OAuthLib)?

I'm building a website + backend with the FLask Framework in which I use Flask-OAuthlib to authenticate with google. After authentication, the backend needs to regularly scan the user his Gmail. So currently users can authenticate my app and I store the access_token and the refresh_token. The access_token expires after one hour, so within that one hour I can get the userinfo like so:

google = oauthManager.remote_app(
        'google',
        consumer_key='xxxxxxxxx.apps.googleusercontent.com',
        consumer_secret='xxxxxxxxx',
        request_token_params={
            'scope': ['https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/gmail.readonly'],
            'access_type': 'offline'
        },
        base_url='https://www.googleapis.com/oauth2/v1/',
        request_token_url=None,
        access_token_method='POST',
        access_token_url='https://accounts.google.com/o/oauth2/token',
        authorize_url='https://accounts.google.com/o/oauth2/auth'
    )

token = (the_stored_access_token, '')
userinfoObj = google.get('userinfo', token=token).data
userinfoObj['id']  # Prints out my google id

Once the hour is over, I need to use the refresh_token (which I've got stored in my database) to request a new access_token. I tried replacing the_stored_access_token with the_stored_refresh_token, but this simply gives me an Invalid Credentials-error.

In this github issue I read the following:

regardless of how you obtained the access token / refresh token (whether through an authorization code grant or resource owner password credentials), you exchange them the same way, by passing the refresh token as refresh_token and grant_type set to 'refresh_token'.

From this I understood I had to create a remote app like so:

google = oauthManager.remote_app(
        'google',
        #  also the consumer_key, secret, request_token_params, etc..
        grant_type='refresh_token',
        refresh_token=u'1/xK_ZIeFn9quwvk4t5VRtE2oYe5yxkRDbP9BQ99NcJT0'
    )

But this leads to a TypeError: __init__() got an unexpected keyword argument 'refresh_token'. So from here I'm kinda lost.

Does anybody know how I can use the refresh_token to get a new access_token? All tips are welcome!

like image 913
kramer65 Avatar asked Nov 26 '14 10:11

kramer65


1 Answers

This is how I get a new access_token for google:

from urllib2 import Request, urlopen, URLError
from webapp2_extras import json
import mimetools
BOUNDARY = mimetools.choose_boundary()
def refresh_token()
    url = google_config['access_token_url']
    headers = [
             ("grant_type", "refresh_token"),
             ("client_id", <client_id>),
             ("client_secret", <client_secret>),
             ("refresh_token", <refresh_token>),
             ]

    files = []
    edata = EncodeMultiPart(headers, files, file_type='text/plain')
    headers = {}
    request = Request(url, headers=headers)
    request.add_data(edata)

    request.add_header('Content-Length', str(len(edata)))
    request.add_header('Content-Type', 'multipart/form-data;boundary=%s' % BOUNDARY)
    try:
        response = urlopen(request).read()
        response = json.decode(response)
    except URLError, e:
        ...

EncodeMultipart function is taken from here: https://developers.google.com/cloud-print/docs/pythonCode

Be sure to use the same BOUNDARY

like image 52
JaredM Avatar answered Oct 04 '22 10:10

JaredM