예제 #1
0
 def test_extract_username(self):
     self.assertEquals(extract_username('username'), 'username')
     self.assertEquals(extract_username('*****@*****.**'),
                       'u2wqblarhim5su7pxemcbwdyryrghmuk')
     # test unicode/punycode (straight UTF8 and urlencoded)
     self.assertEquals(extract_username('*****@*****.**'),
                       'ym3nccfhvptfrhn7nkhhyvzgf2yl7r5y')  # proper char
     self.assertRaises(UnicodeError, extract_username,
                       '*****@*****.**')  # bad utf-8 char
     self.assertRaises(UnicodeError, extract_username,
                       '*****@*****.**')  # invalid BIDI
예제 #2
0
 def test_extract_username(self):
     self.assertEquals(extract_username('username'), 'username')
     self.assertEquals(extract_username('*****@*****.**'),
                       'u2wqblarhim5su7pxemcbwdyryrghmuk')
     # test unicode/punycode (straight UTF8 and urlencoded)
     self.assertEquals(extract_username('*****@*****.**'),
                       'ym3nccfhvptfrhn7nkhhyvzgf2yl7r5y')  # proper char
     self.assertRaises(UnicodeError, extract_username,
                       '*****@*****.**')        # bad utf-8 char
     self.assertRaises(UnicodeError, extract_username,
                       '*****@*****.**')      # invalid BIDI
예제 #3
0
    def get_user_info(self, request, **params):
        """ Display the appropriate user page or discovery page """
        user_info = {}
        user = str(request.sync_info['user'])
        params = {'user': user,
                  'host': self.app.config['oid.host'],
                  'config': self.app.config,
                  'request': request }

        uid = self.get_session_uid(request)
        if uid is not None:
            # Convert the user name to a standardized token
            user_name = extract_username(user)
            user_id = self.app.auth.backend.get_user_id(user_name)
            if user_id == uid:
                # hey that's me !
                user_info = self.app.storage.get_user_info(user_id) or {}
                params['user_info'] = user_info
                params['sig'] = self.gen_signature(uid, request)
        # Use the older style of discovery (with link refs)
        template = get_template('user')
        ct = 'text/html'
        res = template.render(**params)
        response = Response(str(res), content_type=ct)
        if not user_info:
            response.delete_cookie('beaker.session.id')
        return response
    def do_delete_account(self, request):
        """Do the delete."""
        user_name = request.POST.get('username')
        password = request.POST.get('password')
        if user_name is None or password is None:
            return text_response('Missing data')

        user_name = extract_username(user_name)
        user_id = self.auth.authenticate_user(user_name, password)
        if user_id is None:
            return text_response('Bad credentials')

        # data deletion
        self.app.get_storage(request).delete_user(user_id)

        # user deletion (ldap etc.)
        user_id = self.auth.get_user_id(user_name)
        if user_id is not None:
            res = self.auth.delete_user(user_id, password)
        else:
            res = True

        if res:
            return text_response('Account removed.')
        else:
            return text_response('Deletion failed.')
예제 #5
0
    def do_delete_account(self, request):
        """Do the delete."""
        user_name = request.POST.get("username")
        password = request.POST.get("password")
        if user_name is None or password is None:
            return text_response("Missing data")

        user_name = extract_username(user_name)
        user_id = self.auth.authenticate_user(user_name, password)
        if user_id is None:
            return text_response("Bad credentials")

        # data deletion
        self.app.get_storage(request).delete_user(user_id)

        # user deletion (ldap etc.)
        user_id = self.auth.get_user_id(user_name)
        if user_id is not None:
            res = self.auth.delete_user(user_id, password)
        else:
            res = True

        if res:
            return text_response("Account removed.")
        else:
            return text_response("Deletion failed.")
    def do_delete_account(self, request):
        """Do the delete."""
        user_name = request.POST.get('username')
        password = request.POST.get('password')
        if user_name is None or password is None:
            return text_response('Missing data')

        user_name = extract_username(user_name)
        user = User(user_name)
        user_id = self.auth.authenticate_user(user, password)
        if user_id is None:
            return text_response('Bad credentials')

        # data deletion
        self.app.get_storage(request).delete_user(user_id)

        # user deletion (ldap etc.)
        res = self.auth.delete_user(user, password)

        if res:
            return text_response('Account removed.')
        else:
            return text_response('Deletion failed.')
예제 #7
0
    def authenticate_user(self, request, config, username=None):
        """Authenticates a user and returns his id.

        "request" is the request received.
        The function makes sure that the user name found in the headers
        is compatible with the username if provided.

        It returns the user id from the database, if the password is the right
        one.
        """
        environ = request.environ

        if 'REMOTE_USER' in environ:
            # already authenticated
            return environ['REMOTE_USER']

        auth = environ.get('HTTP_AUTHORIZATION')
        if auth is not None:
            # for now, only supporting basic authentication
            # let's decipher the base64 encoded value
            if not auth.startswith('Basic '):
                raise HTTPUnauthorized('Invalid token')

            auth = auth[len('Basic '):].strip()
            try:
                user_name, password = base64.decodestring(auth).split(':')
            except (binascii.Error, ValueError):
                raise HTTPUnauthorized('Invalid token')

            # let's reject the call if the url is not owned by the user
            if (username is not None and user_name != username):
                log_cef('Username Does Not Match URL', 7, environ, config)
                raise HTTPUnauthorized()

            # if this is an email, hash it. Save the original for logging and
            #  debugging.
            remote_user_original = user_name
            try:
                user_name = extract_username(user_name)
            except UnicodeError:
                log_cef('Invalid characters specified in username ', 5,
                        environ, config)
                raise HTTPBadRequest(
                    'Invalid characters specified in ' + 'username', {},
                    'Username must be BIDI ' + 'compliant UTF-8')

            # let's try an authentication
            user_id = self.backend.authenticate_user(user_name, password)
            if user_id is None:
                err = 'Authentication Failed for Backend service ' + user_name
                if remote_user_original is not None and \
                    user_name != remote_user_original:
                    err += ' (%s)' % (remote_user_original)
                log_cef(err, 5, environ, config)
                raise HTTPUnauthorized()

            # we're all clear ! setting up REMOTE_USER
            request.remote_user = environ['REMOTE_USER'] = user_name

            # we also want to keep the password in clear text to reuse it
            # and remove it from the environ
            request.user_password = password
            request._authorization = environ['HTTP_AUTHORIZATION']
            del environ['HTTP_AUTHORIZATION']
            return user_id
예제 #8
0
    def login(self, request, extra = {}, **kw):
        """ Log a user into the ID server
        """
        response = {}
        error = {}
        uid = None
        email = None
        storage = self.app.storage

        if not self.is_internal(request):
            raise HTTPForbidden()
        (content_type, template) = self.get_template_from_request(request,
                                                    html_template = 'login')
        # User is not logged in or the association is not present.
        if (len(request.POST.get('id', '')) and
            len(request.POST.get('password', ''))):
            email = request.POST['id']
            password = request.POST['password']
            try:
                username = extract_username(email)
            except UnicodeError:
                # Log the invalid username for diagnostics ()
                logger.warn('Invalid username specified: %s (%s) '
                            % (email, username))
                raise HTTPBadRequest()
            # user normalization complete, check to see if we know this
            # person
            uid = self.app.auth.backend.authenticate_user(username,
                                                          password)
            if uid is None:
                error = self.error_codes.get('LOGIN_ERROR')
                logger.debug('Login failed for %s ' % email)
                body = template.render(error = error,
                                       response = response,
                                       extra = extra,
                                       request = request,
                                       config = self.app.config)
                response = Response(str(body), content_type = content_type)
                logger.debug('Nuking session cookie')
                response.delete_cookie('beaker.session.uid')
                try:
                    del request.environ['beaker.session']['uid']
                except KeyError:
                    pass
                return response
            logger.debug('setting uid to %s' % uid)
            request.environ['beaker.session']['uid'] = uid

            # if this is an email validation, skip to that.
            if 'validate' in request.params:
                return self.validate(request)
        # Attempt to get the uid.
        if not email:
            email = request.params.get('id', None)
        if uid is None:
            logger.debug('attempting to get uid')
            uid = self.get_uid(request, strict = False)
            if uid is None:
                logger.debug('no uid present')
                # Presume that this is the first time in.
                # Display the login page for HTML only
                body = template.render(error = error,
                                        response = response,
                                        config = self.app.config,
                                        extra = extra,
                                        request = request)
                response = Response(str(body), content_type = content_type)
                response.delete_cookie('beaker.session.uid')
                return response
        # Ok, got a UID, so let's get the user info
        user = storage.get_user_info(uid)
        if user is None:
            user = storage.create_user(uid, email)
        if email:
            if email not in user.get('emails', []):
                self.send_validate_email(uid, email)
            if (len(request.params.get('audience', ''))):
                return self.registered_emails(request)
            location = "%s/%s" % (self.app.config.get('oid.login_host',
                                                          'localhost'),
                 quote(email))
        else:
            del (request.environ['beaker.session']['uid'])
            location = "%s/%s/login" % (self.app.config.get('oid.login_host',
                                                            'localhost'),
                                        VERSION)
        logger.debug('Sending user to admin page %s' % location)
        raise HTTPFound(location = location)
예제 #9
0
    def authenticate_user(self, request, config, username=None):
        """Authenticates a user and returns his id.

        "request" is the request received.
        The function makes sure that the user name found in the headers
        is compatible with the username if provided.

        It returns the user id from the database, if the password is the right
        one.
        """
        environ = request.environ

        if 'REMOTE_USER' in environ:
            # already authenticated
            return environ['REMOTE_USER']

        auth = environ.get('HTTP_AUTHORIZATION')
        if auth is not None:
            # for now, only supporting basic authentication
            # let's decipher the base64 encoded value
            if not auth.startswith('Basic '):
                raise HTTPUnauthorized('Invalid token')

            auth = auth[len('Basic '):].strip()
            try:
                user_name, password = base64.decodestring(auth).split(':')
            except (binascii.Error, ValueError):
                raise HTTPUnauthorized('Invalid token')

            # let's reject the call if the url is not owned by the user
            if (username is not None and user_name != username):
                log_cef('Username Does Not Match URL', 7, environ, config)
                raise HTTPUnauthorized()

            # if this is an email, hash it. Save the original for logging and
            #  debugging.
            remote_user_original = user_name
            try:
                user_name = extract_username(user_name)
            except UnicodeError:
                log_cef('Invalid characters specified in username ', 5,
                            environ, config)
                raise HTTPBadRequest('Invalid characters specified in ' +
                                     'username', {}, 'Username must be BIDI ' +
                                     'compliant UTF-8')

            # let's try an authentication
            user_id = self.backend.authenticate_user(user_name, password)
            if user_id is None:
                err = 'Authentication Failed for Backend service ' + user_name
                if remote_user_original is not None and \
                    user_name != remote_user_original:
                        err += ' (%s)' % (remote_user_original)
                log_cef(err, 5, environ, config)
                raise HTTPUnauthorized()

            # we're all clear ! setting up REMOTE_USER
            request.remote_user = environ['REMOTE_USER'] = user_name

            # we also want to keep the password in clear text to reuse it
            # and remove it from the environ
            request.user_password = password
            request._authorization = environ['HTTP_AUTHORIZATION']
            del environ['HTTP_AUTHORIZATION']
            return user_id