def getUser(self): """ Get the user from this request object @return: User object, or None @rtype: User or None """ # We only want to TRY to # authenticate them once, # so we use "False" if they've # already been attempted to be authed, # None if they haven't even been through # this yet if self._user == None: try: self._user = False # Basic Authentication auth_header = self.environ.get("HTTP_AUTHORIZATION") if auth_header: auth_type, encoded_info = auth_header.split(None, 1) if auth_type.lower() == "basic": unencoded_info = encoded_info.decode('base64') username, password = unencoded_info.split(':', 1) log.info("Looking up user: %s" % username) user = getCachedUser(username) if not user: try: user = botoweb.user.find(username=username, deleted=False).next() addCachedUser(user) except: user = None if user and user.password == password: self._user = user return self._user # ajax session authentication session_key = self.cookies.get("session") log.info(self.cookies) if session_key and botoweb.memc: import json user = None log.info("Starting ajax session auth") session = botoweb.memc.get(str(session_key)) if session: try: session = json.loads(session) addr = self.real_remote_addr if addr == session["last_ip"]: try: user = botoweb.user.get_by_id( session["user"]) addCachedUser(user) except: log.exception("User not available.") if user: self._user = user return self._user except: log.exception("Unavailable session: %s" % session_key) # Cookie based Authentication Token auth_token_header = self.cookies.get("BW_AUTH_TOKEN") if auth_token_header: unencoded_info = auth_token_header if ':' in unencoded_info: username, auth_token = unencoded_info.split(':', 1) if username and auth_token: user = getCachedUser(username) if not user or not user.auth_token == unencoded_info: try: user = botoweb.user.find( username=username, deleted=False).next() addCachedUser(user) except: user = None if user and user.auth_token == unencoded_info: self._user = user return self._user # google federated login openID = self.get("openid.op_endpoint") if openID: openParams = self.formDict() import urllib, urllib2, json, boto if 'openid.identity' in openParams and 'openid.ext1.value.email' in openParams: identifier = openParams['openid.identity'].split( '/id?id=')[1] email = openParams['openid.ext1.value.email'] user = None # Try to get a user by OpenID identifier if not user: try: user = botoweb.user.find(oid=identifier, deleted=False).next() except: user = None # If no OID match, try to match # via Email if not user and email: try: user = botoweb.user.find(email=email, deleted=False).next() except: user = None if user: boto.log.info("OID: %s as %s" % (identifier, user)) self._user = user # Re-use an old auth-token if it's available from datetime import datetime, timedelta now = datetime.utcnow() if user.auth_token and ( user.sys_modstamp - now ) <= timedelta( hours=6) and user.auth_token.startswith( user.username): bw_auth_token = user.auth_token else: # Set up an Auth Token bw_auth_token = "%s:%s" % (user.username, jr_auth_token) user.auth_token = bw_auth_token user.put() self.cookies['BW_AUTH_TOKEN'] = bw_auth_token addCachedUser(user) else: boto.log.warn("Invalid OpenID: %s" % identifier) botoweb.report("Invalid OpenID: %s" % identifier, status=401, req=self, name="LoginFailure", priority=3) else: boto.log.warn( "An error occured trying to authenticate the user: %s" % auth_info['err']['msg']) botoweb.report(auth_info['err']['msg'], status=500, req=self, name="LoginFailure", priority=1) # JanRain Authentication token jr_auth_token = self.POST.get("token") if jr_auth_token: import urllib, urllib2, json, boto api_params = { "token": jr_auth_token, "apiKey": boto.config.get("JanRain", "api_key"), "format": "json" } http_response = urllib2.urlopen( boto.config.get("JanRain", "url"), urllib.urlencode(api_params)) auth_info = json.loads(http_response.read()) if auth_info['stat'] == "ok": profile = auth_info['profile'] identifier = profile['identifier'] email = profile.get("verifiedEmail") user = None # First we see if they have a Primary Key, # if so we use that to get the user primary_key = profile.get("primaryKey") if primary_key: user = botoweb.user.get_by_id(primary_key) if user: boto.log.info( "User '%s' logged in using PrimaryKey: %s" % (user, primary_key)) # If that didn't work, check to see if they had an auth_token if not user: auth_token = self.GET.get("auth_token") if auth_token: try: user = botoweb.user.find( auth_token=auth_token, deleted=False).next() except: user = None if user: # If we matched a user, set the OpenID # for that user to our identifier user.oid = identifier # Try to get a user by OpenID identifier if not user: try: user = botoweb.user.find(oid=identifier, deleted=False).next() except: user = None # If no OID match, try to match # via Email if not user and email: try: user = botoweb.user.find(email=email, deleted=False).next() except: user = None if user: boto.log.info("Authenticated OID: %s as %s" % (identifier, user)) self._user = user # Re-use an old auth-token if it's available from datetime import datetime, timedelta now = datetime.utcnow() if user.auth_token and ( user.sys_modstamp - now ) <= timedelta( hours=6) and user.auth_token.startswith( user.username): bw_auth_token = user.auth_token else: # Set up an Auth Token bw_auth_token = "%s:%s" % (user.username, jr_auth_token) user.auth_token = bw_auth_token user.put() self.cookies['BW_AUTH_TOKEN'] = bw_auth_token addCachedUser(user) else: boto.log.warn("Invalid OpenID: %s" % identifier) botoweb.report("Invalid OpenID: %s" % identifier, status=401, req=self, name="LoginFailure", priority=3) else: boto.log.warn( "An error occured trying to authenticate the user: %s" % auth_info['err']['msg']) botoweb.report(auth_info['err']['msg'], status=500, req=self, name="LoginFailure", priority=1) except Exception: log.exception("Could not fetch user") # This False means we tried by there was no User # We always return None if there was no user # just for compatibility reasons if self._user == False: return None return self._user
def loginUsingGooglePlus(self): # Google+ login from httplib2 import Http from oauth2client.client import OAuth2WebServerFlow from apiclient.discovery import build if not (self.get('state') and self.get('state').startswith('googleplus')): return None flow = OAuth2WebServerFlow( client_id=boto.config.get('GooglePlus', 'client_id'), client_secret=boto.config.get('GooglePlus', 'client_secret'), scope='email', state='googleplus', redirect_uri='postmessage') flow.redirect_uri = 'postmessage' code = self.get('code') if not code: return None user = None try: credentials = flow.step2_exchange(code) http = credentials.authorize(Http()) service = build("plus", "v1", http=http) profile = service.people().get(userId='me').execute() log.info('Looking up user with profile %s', str(profile)) email = profile['emails'][0]['value'] if email: log.info('Looking up user email: "%s"' % email) try: user = botoweb.user.find(email=email, deleted=False).next() except StopIteration: log.warn("Unknown user using Google+ login: %s" % email) botoweb.report("Unknown user using Google+ login: %s" % email, status=401, req=self, name="LoginFailure", priority=3) user = None if user: log.info("Google+ login: %s as %s" % (email, user)) self._user = user # Re-use an old auth-token if it's available from datetime import datetime, timedelta now = datetime.utcnow() if user.auth_token and (user.sys_modstamp - now) <= timedelta( hours=6) and user.auth_token.startswith(user.username): bw_auth_token = user.auth_token else: # Set up an Auth Token bw_auth_token = "%s:%s" % (user.username, uuid.uuid4().hex) user.auth_token = bw_auth_token user.put() self.cookies['BW_AUTH_TOKEN'] = bw_auth_token addCachedUser(user) except: log.exception('Exception while trying Google+ login flow') return user