[Answered ]-How do I get credentials of python-social-auth for google drive sdk?

1๐Ÿ‘

Iโ€™ve run into the same case, and Iโ€™ve been seeing how oauth2client works, so Iโ€™ve generated the credential from the data obtained by the authentication with python-social-auth, I put this logic inside a pipeline when a user logged in the website for the first time. As follows:

import datetime
from django.conf import settings
from oauth2client import GOOGLE_REVOKE_URI, GOOGLE_TOKEN_URI
from oauth2client.client import OAuth2Credentials, _extract_id_token
from oauth2client.django_orm import Storage
from website.models import CredentialsModel


def set_google_credentials(strategy, details, response, user=None, *args, **kwargs):
    if user and kwargs.get('is_new'):
        token_expiry = datetime.datetime.utcnow() + datetime.timedelta(seconds=int(response.get('expires_in')))
        id_token = _extract_id_token(response.get('id_token'))
        credential = OAuth2Credentials(
            access_token=response.get('access_token'),
            client_id=settings.SOCIAL_AUTH_GOOGLE_PLUS_KEY,
            client_secret=settings.SOCIAL_AUTH_GOOGLE_PLUS_SECRET,
            refresh_token=response.get('refresh_token'),
            token_expiry=token_expiry,
            token_uri=GOOGLE_TOKEN_URI,
            user_agent=None,
            revoke_uri=GOOGLE_REVOKE_URI,
            id_token=id_token,
            token_response=response)
        storage = Storage(CredentialsModel, 'id', user, 'credential')
        storage.put(credential)

then in my settings:

SOCIAL_AUTH_PIPELINE = (
    'social.pipeline.social_auth.social_details',
    'social.pipeline.social_auth.social_uid',
    'social.pipeline.social_auth.social_user',
    'social.pipeline.user.get_username',
    'social.pipeline.user.create_user',
    'myapp.pipeline.set_google_credentials'    
    # more pipelines
)

then when I need credentials for a user:

UPDATE: As @bcoover noted the results got from Storage needed to be decoded and depickled.

user = # get a user instance, from the request for example
storage = Storage(CredentialsModel, 'id', user, 'credential')
import pickle, base64
credentials = (pickle.loads(base64.b64decode(storage.get())))
# do what ever you want with the credentials

this approach works for me at the moment, but if someone has a better way to do, Iโ€™ll be grateful. The Storage and CredentialsModel are from https://developers.google.com/api-client-library/python/guide/django

๐Ÿ‘คeyscode

1๐Ÿ‘

This was immensely helpful, thanks @eyscode!
I had the same problem as @areyoueye, and it turns out after looking at the Google code, the results needed to be decoded and depickled, and then it works great!
Here is the modified code:

import pickle
...
storage = Storage(GoogleCredential, 'id', user, 'credential')
credentials = (pickle.loads(base64.b64decode(storage.get())))
...

Then doing the print(), you should get an object as output like this:

...
print(credentials)
<oauth2client.client.OAuth2Credentials object at 0x7fa2837af630>
๐Ÿ‘คbcoover

0๐Ÿ‘

There seems to be a better solution from this Gist here: https://github.com/python-social-auth/social-core/issues/125#issuecomment-389070863

It seems better in the sense that it uses the python social auth mechanisms for refreshing the token in case the Google API requests it. This means that the refreshed token goes to the DB.

๐Ÿ‘คRaffi

Leave a comment