使用访问令牌时出现 Gmail API 禁止错误

0 投票
1 回答
605 浏览
提问于 2025-04-18 14:49

我正在尝试使用 Gmail 的 API 来获取一些数据。下面是程序的工作流程。首先,我向谷歌服务器提交请求,这样用户就可以给我的应用程序指定权限:

def oauth_connect(request):
    if request.method == 'GET' and request.user.is_authenticated():
        auth_uri = 'https://accounts.google.com/o/oauth2/auth?response_type=code&scope=https://www.googleapis.com/auth/gmail.compose&client_id={0}&redirect_uri={1}&approval_prompt=force'.format(GOOGLE_CLIENT_ID, HOSTNAME_URI + 'oauth2callback')
        return HttpResponseRedirect(auth_uri)

在回调中,我保存了谷歌发送的访问令牌。我本来还期待在响应中看到刷新令牌,但显然没有。

def google_oauth_return(request):
    if request.method == 'GET' and request.user.is_authenticated():
        # Get the auth code from the GET request
        code = request.GET['code']
        agent = Agent.objects.get(user=request.user)

        # Create a list of 2-tuples for the parameters to send in the POST request back to eventbrite to get the auth token
        post_data = [('code', code), ('client_secret', GOOGLE_CLIENT_SECRET), ('client_id', GOOGLE_CLIENT_ID), 
            ('redirect_uri', HOSTNAME_URI + 'oauth2callback'), ('grant_type', 'authorization_code'),
        ]

        # Send POST request and get json sent back
        result = urllib2.urlopen('https://accounts.google.com/o/oauth2/token', urllib.urlencode(post_data))
        pprint.pprint(result)
        # Load the json into a python dict
        data = json.load(result)
        pprint.pprint(data)
        # Get the access token
        access_token = data['access_token']
        expiration_time = data['expires_in']
        if 'refresh_token' in data:
            refresh_token = data['refresh_token']
        else:
            refresh_token = ''
        agent.google_access_token = access_token
        agent.google_access_token_expiration_time = datetime.utcnow().replace(tzinfo=tz.tzutc()) + timedelta(seconds=int(expiration_time))
        agent.google_refresh_token = refresh_token
        agent.save()

        return HttpResponseRedirect('/profile')

但是,当我使用访问令牌来获取数据时,我遇到了 HTTP 403 禁止访问的错误。

def get_gmail_data(request):
    if request.method == 'GET':
        agent = Agent.objects.get(user=request.user)
        access_token = agent.google_access_token
        pprint.pprint(access_token)
        expiration_time = agent.google_access_token_expiration_time
        # TODO Check if access token expired. tzinfo=tz.utc is used because utcnow returns a offset-naive datetime
        # Set up HTTPS request and add access token as a header
        get_mail = urllib2.Request('https://www.googleapis.com/gmail/v1/users/me/messages')
        get_mail.add_header('Authorization', 'Bearer ' + access_token)
        # Open the connection and get the json, turn it into a python dict
        gmail_data = urllib2.urlopen(get_mail)
        gmail = json.load(gmail_data)

        pprint.pprint(gmail)

我对 OAuth 还不太熟悉,如果有人能指出问题所在,那就太好了。

1 个回答

1

根据Google APIs Explorer的信息,你现在使用的OAuth 2.0权限范围是:

https://www.googleapis.com/auth/gmail.compose

… 这个权限范围只允许:

管理草稿和发送邮件

但是你想要做的是:

https://www.googleapis.com/gmail/v1/users/me/messages

也就是说,你想查看邮件。你需要一个合适的权限范围:

https://mail.google.com/

… 这个权限范围允许:

查看和管理你的邮件

所以这个错误信息是完全合理的。你请求并获得了做一件事情的权限,但尝试去做了另一件事情,因此出现了权限错误。

撰写回答