diff --git a/VERSION b/VERSION index 3b53d293..a1ea15e3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 1.99.7 (2012-03-09 01:59:43) dev +Version 1.99.7 (2012-03-09 13:49:42) dev diff --git a/gluon/contrib/login_methods/oauth20_account.py b/gluon/contrib/login_methods/oauth20_account.py index 6b46bb39..bb8bda66 100644 --- a/gluon/contrib/login_methods/oauth20_account.py +++ b/gluon/contrib/login_methods/oauth20_account.py @@ -12,10 +12,10 @@ OAuth 2.0 Draft: http://tools.ietf.org/html/draft-ietf-oauth-v2-10 import time import cgi - -from urllib2 import urlopen import urllib2 + from urllib import urlencode +from gluon import current, redirect, HTTP class OAuthAccount(object): """ @@ -35,30 +35,27 @@ class OAuthAccount(object): writable=False, readable=False)) auth_table.username.requires = IS_NOT_IN_DB(db, auth_table.username) - . - . - . auth.define_tables() - . - . - . CLIENT_ID=\"\" CLIENT_SECRET=\"\" AUTH_URL="http://..." TOKEN_URL="http://..." from gluon.contrib.login_methods.oauth20_account import OAuthAccount - auth.settings.login_form=OAuthAccount(globals(),CLIENT_ID,CLIENT_SECRET,AUTH_URL, TOKEN_URL, **args ) + auth.settings.login_form=OAuthAccount( + None,CLIENT_ID,CLIENT_SECRET,AUTH_URL, TOKEN_URL, **args) + Any optional arg will be passed as is to remote server for requests. It can be used for the optional "scope" parameters for Facebook. """ def __redirect_uri(self, next=None): - """Build the uri used by the authenticating server to redirect + """ + Build the uri used by the authenticating server to redirect the client back to the page originating the auth request. Appends the _next action to the generated url so the flows continues. """ - r = self.request + r = current.request http_host=r.env.http_x_forwarded_for if not http_host: http_host=r.env.http_host @@ -74,8 +71,12 @@ class OAuthAccount(object): def __build_url_opener(self, uri): - """Build the url opener for managing HTTP Basic Athentication""" - # Create an OpenerDirector with support for Basic HTTP Authentication... + """ + Build the url opener for managing HTTP Basic Athentication + """ + # Create an OpenerDirector with support + # for Basic HTTP Authentication... + auth_handler = urllib2.HTTPBasicAuthHandler() auth_handler.add_password(None, uri, @@ -86,22 +87,23 @@ class OAuthAccount(object): def accessToken(self): - """Return the access token generated by the authenticating server. + """ + Return the access token generated by the authenticating server. If token is already in the session that one will be used. Otherwise the token is fetched from the auth server. """ - if self.session.token and self.session.token.has_key('expires'): - expires = self.session.token['expires'] + if current.session.token and current.session.token.has_key('expires'): + expires = current.session.token['expires'] # reuse token until expiration if expires == 0 or expires > time.time(): - return self.session.token['access_token'] - if self.session.code: + return current.session.token['access_token'] + if current.session.code: data = dict(client_id=self.client_id, client_secret=self.client_secret, - redirect_uri=self.session.redirect_uri, - response_type='token', code=self.session.code) + redirect_uri=current.session.redirect_uri, + response_type='token', code=current.session.code) if self.args: @@ -113,33 +115,36 @@ class OAuthAccount(object): except urllib2.HTTPError, e: raise Exception(e.read()) finally: - del self.session.code # throw it away + del current.session.code # throw it away if open_url: try: tokendata = cgi.parse_qs(open_url.read()) - self.session.token = dict([(k,v[-1]) for k,v in tokendata.items()]) + current.session.token = \ + dict([(k,v[-1]) for k,v in tokendata.items()]) # set expiration absolute time try to avoid broken # implementations where "expires_in" becomes "expires" - if self.session.token.has_key('expires_in'): + if current.session.token.has_key('expires_in'): exps = 'expires_in' else: - exps = 'expires' - self.session.token['expires'] = int(self.session.token[exps]) + \ + exps = 'expires' + current.session.token['expires'] = \ + int(current.session.token[exps]) + \ time.time() finally: opener.close() - return self.session.token['access_token'] + return current.session.token['access_token'] - self.session.token = None + current.session.token = None return None - def __init__(self, g, client_id, client_secret, auth_url, token_url, **args): - self.globals = g + def __init__(self, g, + client_id, client_secret, auth_url, token_url, **args): + """ + first argument is unused. Here only for legacy reasons. + """ self.client_id = client_id self.client_secret = client_secret - self.request = g['request'] - self.session = g['session'] self.auth_url = auth_url self.token_url = token_url self.args = args @@ -149,12 +154,13 @@ class OAuthAccount(object): return next def logout_url(self, next="/"): - del self.session.token + del current.session.token return next def get_user(self): - '''Returns the user using the Graph API. - ''' + """ + Returns the user using the Graph API. + """ raise NotImplementedError, "Must override get_user()" if not self.accessToken(): return None @@ -166,7 +172,7 @@ class OAuthAccount(object): try: user = self.graph.get_object("me") except GraphAPIError: - self.session.token = None + current.session.token = None self.graph = None if user: @@ -175,9 +181,9 @@ class OAuthAccount(object): username = user['id']) - def __oauth_login(self, next): - '''This method redirects the user to the authenticating form + """ + This method redirects the user to the authenticating form on authentication server if the authentication code and the authentication token are not available to the application yet. @@ -185,23 +191,23 @@ class OAuthAccount(object): Once the authentication code has been received this method is called to set the access token into the session by calling accessToken() - ''' + """ + if not self.accessToken(): - if not self.request.vars.code: - self.session.redirect_uri=self.__redirect_uri(next) - data = dict(redirect_uri=self.session.redirect_uri, + if not current.request.vars.code: + current.session.redirect_uri=self.__redirect_uri(next) + data = dict(redirect_uri=current.session.redirect_uri, response_type='code', client_id=self.client_id) if self.args: data.update(self.args) auth_request_url = self.auth_url + "?" +urlencode(data) - HTTP = self.globals['HTTP'] raise HTTP(307, "You are not authenticated: you are being redirected to the authentication server", Location=auth_request_url) else: - self.session.code = self.request.vars.code + current.session.code = current.request.vars.code self.accessToken() - return self.session.code + return current.session.code return None