Example #1
0
    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
Example #2
0
    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