如何在创建会话时检测过期的访问令牌?

时间:2013-04-20 10:27:05

标签: python oauth rauth

我有以下测试程序:

from   rauth.service import OAuth1Service, OAuth2Service

SUPPORTED_SERVICES = {
    'twitter'  : ( 'OAuth1', 'twitter',  'https://api.twitter.com/oauth',        'request_token', 'access_token', 'authorize', 'https://api.twitter.com/1/',  None),
    'facebook' : ( 'OAuth2', 'facebook', 'https://graph.facebook.com/oauth',     None,            'access_token', 'authorize', 'https://graph.facebook.com/', 'https://www.facebook.com/connect/login_success.html'),
    'google'   : ( 'OAuth2', 'google',   'https://accounts.google.com/o/oauth2', None,            'token',        'auth',      None,                          'http://localhost'),
}

CLIENT_DATA = {
    'twitter'  : ('dummy_client_id', 'dummy_client_secret'),
    'facebook' : ('dummy_client_id', 'dummy_client_secret'),
    'google'   : ('dummy_client_id', 'dummy_client_secret'),
}

USER_TOKENS = {
    'user1' : {
        'twitter'  : ('dummy_access_token', 'dummy_access_token_secret'),
        'facebook' : ('dummy_access_token', None),
        'google'   : ('dummy_access_token', None),
    }
}

def test_google(user_id):
    service_id = 'google'
    oauthver, name, oauth_base_url, request_token_url, access_token_url, authorize_url, base_url, redirect_uri = SUPPORTED_SERVICES[service_id]
    request_token_url = oauth_base_url + '/' + (request_token_url or '')
    access_token_url  = oauth_base_url + '/' + access_token_url
    authorize_url     = oauth_base_url + '/' + authorize_url
    client_id, client_secret = CLIENT_DATA[service_id]
    google = OAuth2Service(
        client_id=client_id,
        client_secret=client_secret,
        name=name,
        authorize_url=authorize_url,
        access_token_url=access_token_url,
        base_url=base_url)
    access_token, access_token_secret = USER_TOKENS[user_id][service_id] # access_token_secret only needed for twitter (OAuth1)
    session = google.get_session(access_token)
    user = session.get('https://www.googleapis.com/oauth2/v1/userinfo').json()
    print user

test_google('user1')

我已授权我的应用访问user1的Google帐户,并获得了access_token。该访问令牌已经过期,我的程序输出为:

{u'error': {u'code': 401, u'message': u'Invalid Credentials', u'errors': [{u'locationType': u'header', u'domain': u'global', u'message': u'Invalid Credentials', u'reason': u'authError', u'location': u'Authorization'}]}}

我想在创建会话时检查访问令牌是否已过期,不是在请求数据时。这可能吗? 如何验证会话对象是否真正获得授权?

为了澄清,我要做的是以下内容:

  1. 首先,让用户授权我的应用程序
  2. 保存访问令牌以供将来使用(在数据库中,但在测试代码中,这是在脚本中硬编码的)
  3. 每当后来的访问检测到令牌已过期时,请返回步骤1
  4. 我目前在第3步遇到问题。我当然可以在json回复我的GET中检测到401,但是被迫验证所有GET访问看起来相当麻烦。我要做的是在创建会话时验证会话是否真正处于活动状态,然后在会话对象的整个持续时间内假设它将保持活动状态。通常这只是几毫秒,而我的webapp正在处理请求并使用OAuth会话对象访问google API。

1 个答案:

答案 0 :(得分:4)

您必须先调用get_authorization_url,哪个用户必须打开并授予您访问其帐户的权限,作为回报,您将获得redirect_uri回调查询参数的代码,您可以将其换成{ {1}}:

access_token

根据documentation,此代码应该有效:

params = {
    'scope': 'email',
    'response_type': 'code',
    'redirect_uri': redirect_uri,
    'access_type': 'offline', # to get refresh_token
}

print google.get_authorize_url(**params)

作为回应,您将获得如下的JSON数据:

data = {
    'code': 'code you got from callback',
    'grant_type': 'authorization_code',
    'redirect_uri': 'http://localhost/oauth2',
}

response = google.get_raw_access_token(data=data)

正如您所看到的那样{ "access_token" : "ya29.AHE<....>n3w", "token_type" : "Bearer", "expires_in" : 3600, "id_token" : "eyJh<...>QwNRzc", "refresh_token" : "1/X86S<...>Vg4" } (秒),您必须存储获得令牌的时间,并在稍后与当前时间+ expires_in进行比较。

如果令牌已过期,您可以稍后使用expires_in刷新它,而无需再次要求用户确认:

refresh_token

请注意,response = google.get_raw_access_token(data={ 'refresh_token': refresh_token, 'grant_type': 'refresh_token', }) print response.content 仅在用户首次授权应用时返回。 有关详细信息,请参阅this question

唉,似乎你不能使用refresh_token,因为在内部它只提取get_auth_session而其他一切都被丢弃了。

如果您在未获得身份验证access_token的情况下立即获得access_token,则仍会在回调中获得code。来自docs

  

https://oauth2-login-demo.appspot.com/oauthcallback#access_token=1/fFBGRNJru1FQd44AzqT3Zg&token_type=Bearer&expires_in=3600