Django 1.7 google oauth2令牌验证失败

时间:2022-12-19 21:34:05

I'm trying to get through the process of authenticating a Google token for accessing a user's calendar within a Django application. Although I've followed several indications found on the web, I'm stuck with a 400 error code response to my callback function (Bad Request).

我正在尝试通过验证Google令牌来访问Django应用程序中的用户日历。虽然我已经在网上找到了几个指示,但我仍然遇到了对我的回调函数(错误请求)的400错误代码响应。

views.py

views.py

# -*- coding: utf-8 -*-
import os

import argparse
import httplib2
import logging

from apiclient.discovery import build
from oauth2client import tools
from oauth2client.django_orm import Storage
from oauth2client import xsrfutil
from oauth2client.client import flow_from_clientsecrets

from django.http import HttpResponse
from django.http import HttpResponseBadRequest
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.core.urlresolvers import reverse
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.conf import settings

from apps.tecnico.models import Credentials, Flow

CLIENT_SECRETS = os.path.join(
    os.path.dirname(__file__), '../../client_secrets.json')

@login_required
def index(request):
    storage = Storage(Credentials, 'id', request.user, 'credential')
    FLOW = flow_from_clientsecrets(
        CLIENT_SECRETS,
        scope='https://www.googleapis.com/auth/calendar.readonly',
        redirect_uri='http://MY_URL:8000/oauth2/oauth2callback'
    )
    credential = storage.get()
    if credential is None or credential.invalid is True:
        FLOW.params['state'] = xsrfutil.generate_token(
            settings.SECRET_KEY, request.user)
        authorize_url = FLOW.step1_get_authorize_url()
        f = Flow(id=request.user, flow=FLOW)
        f.save()
        return HttpResponseRedirect(authorize_url)
    else:
        http = httplib2.Http()
        http = credential.authorize(http)
        service = build(serviceName='calendar', version='v3', http=http,
                        developerKey='MY_DEV_KEY_FROM_GOOGLE_CONSOLE')

        events = service.events().list(calendarId='primary').execute()
        return render_to_response('calendario/welcome.html', {
            'events': events['items'],
        })


@login_required
def auth_return(request):
    if not xsrfutil.validate_token(
            settings.SECRET_KEY, request.REQUEST['state'], request.user):
        return HttpResponseBadRequest()

    storage = Storage(Credentials, 'id', request.user, 'credential')
    FLOW = Flow.objects.get(id=request.user).flow
    credential = FLOW.step2_exchange(request.REQUEST)
    storage.put(credential)
    return HttpResponseRedirect("http://MY_URL:8000/caly")

models.py

models.py

from oauth2client.django_orm import FlowField, CredentialsField

[...]

class Credentials(models.Model):
    id = models.ForeignKey(User, primary_key=True)
    credential = CredentialsField()


class Flow(models.Model):
    id = models.ForeignKey(User, primary_key=True)
    flow = FlowField()

I've downloaded the client_secrets.json file directly from the Google Dev Console. The specified Client ID type in the Dev Console is "web application", which I think is correct. What I've noticed is, if I remove the token validation code block:

我直接从Google Dev Console下载了client_secrets.json文件。开发者控制台中指定的客户端ID类型是“Web应用程序”,我认为这是正确的。我注意到的是,如果我删除令牌验证代码块:

if not xsrfutil.validate_token(
        settings.SECRET_KEY, request.REQUEST['state'], request.user):
    return HttpResponseBadRequest()

everything works correctly, flow and credentials get correctly stored in the database and I'm allowed to read the calendar. What can I possibly be wrong with?

一切正常,流和凭据得到正确存储在数据库中,我被允许阅读日历。我可能错在哪里?

EDIT: I've also checked outgoing (to Google) and incoming (to callback) data:

编辑:我还检查了传出(谷歌)和传入(回调)数据:

OUTGOING:

传出:

request.user:
admin
settings.SECRET_KEY:
I_AM_NOT_WRITING_IT_HERE
FLOW.params['state']:
SOME_OTHER_RANDOM_STUFF

INCOMING:

来电:

request.user:
admin
settings.SECRET_KEY:
I_AM_NOT_WRITING_IT_HERE
FLOW.params['state']:
SOME_OTHER_RANDOM_STUFF

Data is identical, at least to a print to console. Also, the generation/validation operations via console work correctly (xsrfutil.validate_token returns True, both with test and real data, including User model instances). I'm even more puzzled.

数据是相同的,至少是打印到控制台。此外,通过控制台生成/验证操作正常工作(xsrfutil.validate_token返回True,包括测试和实际数据,包括用户模型实例)。我更加困惑。

2 个解决方案

#1


14  

I have struggled exact the same issue for several hours, and I figured out the solution of which @Ryan Spaulding and @Hans Z answered. It works!

几个小时我一直在努力解决同样的问题,我想出了@Ryan Spaulding和@Hans Z回答的解决方案。有用!

This is due to the fact Django 1.7 returns a unicode object for the state variable above using request.REQUEST. I was previously using Django 1.6 which used to return a string.

这是因为Django 1.7使用request.REQUEST为上面的状态变量返回一个unicode对象。我之前使用的是用于返回字符串的Django 1.6。

One can find more detail here. https://github.com/google/google-api-python-client/issues/58 I wrote this post for future reference.

人们可以在这里找到更多细节。 https://github.com/google/google-api-python-client/issues/58我写了这篇文章以供将来参考。

if not xsrfutil.validate_token(
    settings.SECRET_KEY, 
    str(request.REQUEST['state']), 
    request.user):
return HttpResponseBadRequest()

#2


7  

It could be a unicode issue with request.REQUEST['state']. Try putting str() around it, i.e. str(request.REQUEST['state']).

它可能是request.REQUEST ['state']的unicode问题。尝试在它周围放置str(),即str(request.REQUEST ['state'])。

#1


14  

I have struggled exact the same issue for several hours, and I figured out the solution of which @Ryan Spaulding and @Hans Z answered. It works!

几个小时我一直在努力解决同样的问题,我想出了@Ryan Spaulding和@Hans Z回答的解决方案。有用!

This is due to the fact Django 1.7 returns a unicode object for the state variable above using request.REQUEST. I was previously using Django 1.6 which used to return a string.

这是因为Django 1.7使用request.REQUEST为上面的状态变量返回一个unicode对象。我之前使用的是用于返回字符串的Django 1.6。

One can find more detail here. https://github.com/google/google-api-python-client/issues/58 I wrote this post for future reference.

人们可以在这里找到更多细节。 https://github.com/google/google-api-python-client/issues/58我写了这篇文章以供将来参考。

if not xsrfutil.validate_token(
    settings.SECRET_KEY, 
    str(request.REQUEST['state']), 
    request.user):
return HttpResponseBadRequest()

#2


7  

It could be a unicode issue with request.REQUEST['state']. Try putting str() around it, i.e. str(request.REQUEST['state']).

它可能是request.REQUEST ['state']的unicode问题。尝试在它周围放置str(),即str(request.REQUEST ['state'])。