Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Calendar API v3 - How to obtain a refresh token (Python)

I am trying to write a Django app which creates events in a specific Google calendar. So far I have been successful. There is only a little problem:

I don't know how to obtain a refresh token with the google python client.

The result is that after my token expires the app does not work and I have to create a new token. If I understand the documentation correct that's where the refresh token comes in.

Access tokens have a limited lifetime and, in some cases, an application needs access to a Google API beyond the lifetime of a single access token. When this is the case, your application can obtain what is called a refresh token. A refresh token allows your application to obtain new access tokens.

Google Documentation (see "Basic Steps", Section 4)

My code

import gflags
import httplib2

from apiclient.discovery import build
from oauth2client.file import Storage
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.tools import run

FLAGS = gflags.FLAGS

FLOW = OAuth2WebServerFlow(
    client_id=GOOGLE_API_CLIENT_ID,
    client_secret=GOOGLE_API_CLIENT_SECRET,
    scope=GOOGLE_API_CALENDAR_SCOPE,
    user_agent=GOOGLE_API_USER_AGENT)

storage = Storage(GOOGLE_API_CREDENTIAL_PATH)
credentials = storage.get()
if credentials is None or credentials.invalid == True:
  credentials = run(FLOW, storage)

http = httplib2.Http()
http = credentials.authorize(http)

service = build(serviceName='calendar', version='v3', http=http,
   developerKey=GOOGLE_API_DEVELOPER_KEY)

event = {
    [... Dictionary with all the necessary data here ...]
}

created_event = service.events().insert(calendarId=GOOGLE_API_CALENDAR_ID, body=event).execute()

This is pretty much the example from the Google documentation. The interesting bit is the Storage. It's a file where some credential data is saved.

Content of my storage file:

{
    "_module": "oauth2client.client", 
    "_class": "OAuth2Credentials", 
    "access_token": [redacted], 
    "token_uri": "https://accounts.google.com/o/oauth2/token", 
    "invalid": true, 
    "client_id": [redacted], 
    "client_secret": [redacted], 
    "token_expiry": "2011-12-17T16:44:15Z", 
    "refresh_token": null, 
    "user_agent": [redacted]
}

There should be a refresh token in there, but instead it's null. So I figure I can somehow request a refresh token.

I would appreciate any help on how I can get this to work. If you need more information, please tell me.

like image 716
Jens Avatar asked Dec 17 '11 18:12

Jens


People also ask

How do you make a python refresh token?

client_secret() tokens = b64encode(f"{client_id}:{client_secret}". encode("ascii")). decode("utf8") header = { "Authorization": "Basic {0}". format(tokens), "Content-Type": "application/x-www-form-urlencoded", } refresh_token = await self.

How do I get Google Calendar credentials?

Search for the Google Calendar API and enable it. On the main menu, select "APIs & Services" then "Credentials" Now create credentials with the "OAuth client ID" method. If you don't have one, you'll have to configure an OAuth consent screen.


1 Answers

I don't know how to do this with the Python Client or the Calendar API (I'm just using a ruby OAuth2 library for access to the Contacts API), but I found I needed to request "offline" access from the user.

This is done by adding the an "access_type" parameter with the value "offline" to the authorization url (the one you redirect the user to to click "I want to allow this application to get at my data").

If you do this, you get a refresh_token back in your JSON response when you ask google for access tokens. Otherwise you only get the access token (which is valid for an hour).

This requirement was apparently added recently (and may not be wonderfully documented).

You used to get a refresh token without having to get specific "offline" permission.

Hope this points you in the right direction.

like image 155
bonkydog Avatar answered Oct 14 '22 18:10

bonkydog