Reputation: 1231
I'm trying to authorize my django application using oauth2 in order to interact with the google content for shopping API. However, I'm experiencing issues with oauth2 along the way.
I have oauth2client and google-api-python-client installed. My view is as follows:
CLIENT_SECRETS = os.path.join(os.path.dirname(__file__), 'client_secret.json')
FLOW = flow_from_clientsecrets(
CLIENT_SECRETS,
scope='https://www.googleapis.com/auth/content',
redirect_uri='https://127.0.0.1:8000/oauth2/oauth2callback')
def get_account_ids(service):
accounts = service.management().accounts().list().execute()
ids = []
if accounts.get('items'):
for account in accounts['items']:
ids.append(account['id'])
return ids
@login_required
def index(request):
user = request.user
storage = Storage(CredentialsModel, 'id', user, 'credential')
credential = storage.get()
if credential is None:
FLOW.params['state'] = xsrfutil.generate_token(
settings.SECRET_KEY, user)
authorize_url = FLOW.step1_get_authorize_url()
f = FlowModel(id=user, flow=FLOW)
f.save()
return HttpResponseRedirect(authorize_url)
else:
http = httplib2.Http()
http = credential.authorize(http)
service = build('content', 'v2', http=http)
ids = get_account_ids(service)
return render(
request, 'index.html', {'ids':ids})
@login_required
def auth_return(request):
user = request.user
if not xsrfutil.validate_token(settings.SECRET_KEY, bytes(request.GET['state'], 'utf-8'), user):
return HttpResponseBadRequest()
credential = FLOW.step2_exchange(request.GET, http=None)
storage = Storage(CredentialsModel, 'id', user, 'credential')
storage.put(credential)
return HttpResponseRedirect("/oauth2/")
At first, I was getting an error from the auth_return view that the string retuned by request.GET['state'] had no encoding, so I changed this:
if not xsrfutil.validate_token(settings.SECRET_KEY, request.GET['state'], user):
to this:
if not xsrfutil.validate_token(settings.SECRET_KEY, bytes(request.GET['state'], 'utf-8'), user):
return HttpResponseBadRequest()
and the error was gone. However, I'm now getting the error:
'bytes' object has no attribute 'authorize'
from the index view. The exact line causing the exception is:
http = credential.authorize(http)
It seems like this is being caused by the earlier change I made. I'm new to using oauth2 and I have spent a lot of hours already trying to debug. Can anyone please point me in the right direction?
Thank you in advance.
Upvotes: 1
Views: 224
Reputation: 1231
I finally found an answer.
It seems the django_orm module in oauth2client uses the 'to_python' function in the CredentialsField definition, which doesn't work and thus returns the Base64 data back.
TO solve this, you have to edit the oauth2client/django_orm source definition from:
class CredentialsField(models.Field):
to:
from django.utils.six import with_metaclass
class CredentialsField(with_metaclass(models.SubfieldBase, models.Field)):
This will allow it to return the Credentials object for both Python2 and Python3.
Make sure you delete the currently stored credentials object first since it is a string object and not a Credentials object.
Upvotes: 1