예제 #1
0
    def test_required_roles(self):
        """
        Validates whether the required_roles decorator works
        """
        from api.backend.decorators import required_roles

        @required_roles(['read', 'write', 'manage'])
        def the_function_rr(input_value, *args, **kwargs):
            """
            Decorated function
            """
            _ = args, kwargs
            output['value'] = input_value
            return HttpResponse(json.dumps(input_value))

        time.sleep(180)
        output = {'value': None}
        request = self.factory.get('/')
        with self.assertRaises(HttpUnauthorizedException) as context:
            the_function_rr(1, request)
        self.assertEqual(context.exception.status_code, 401)

        time.sleep(180)
        request.client = type('Client', (), {})
        request.user = type('User', (), {})
        request.user.username = '******'
        with self.assertRaises(HttpUnauthorizedException) as context:
            the_function_rr(2, request)
        self.assertEqual(context.exception.status_code, 401)

        time.sleep(180)
        user = UserList.get_user_by_username('user')
        access_token, _ = OAuth2Toolbox.generate_tokens(
            user.clients[0],
            generate_access=True,
            scopes=RoleList.get_roles_by_codes(['read']))
        access_token.expiration = int(time.time() + 86400)
        access_token.save()
        request.user.username = '******'
        request.token = access_token
        with self.assertRaises(HttpForbiddenException) as context:
            the_function_rr(3, request)
        self.assertEqual(context.exception.status_code, 403)
        self.assertEqual(context.exception.error, 'invalid_roles')
        self.assertEqual(context.exception.error_description,
                         'This call requires roles: read, write, manage')

        time.sleep(180)
        user = UserList.get_user_by_username('admin')
        access_token, _ = OAuth2Toolbox.generate_tokens(
            user.clients[0],
            generate_access=True,
            scopes=RoleList.get_roles_by_codes(['read', 'write', 'manage']))
        access_token.expiration = int(time.time() + 86400)
        access_token.save()
        request.username = '******'
        request.token = access_token
        response = the_function_rr(4, request)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, '4')
예제 #2
0
    def test_client_credentials(self):
        """
        Validates the Client Credentials
        """
        from api.oauth2.tokenview import OAuth2TokenView

        time.sleep(180)
        data = {'grant_type': 'client_credentials'}
        request = self.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.1')
        self._assert_failure(OAuth2TokenView.as_view(), request, 400, 'missing_header', HttpBadRequestException)

        time.sleep(180)
        header = 'Basic {0}'.format(base64.encodestring('{0}:{1}'.format('foo', 'bar')))
        request = self.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.2', HTTP_AUTHORIZATION=header)
        self._assert_failure(OAuth2TokenView.as_view(), request, 400, 'invalid_client', HttpBadRequestException)

        time.sleep(180)
        admin_na = UserList.get_user_by_username('admin_na')
        admin_na_client = Client()
        admin_na_client.ovs_type = 'USER'
        admin_na_client.grant_type = 'PASSWORD'
        admin_na_client.client_secret = OAuth2Toolbox.create_hash(64)
        admin_na_client.user = admin_na
        admin_na_client.save()
        header = 'Basic {0}'.format(base64.encodestring('{0}:{1}'.format(admin_na_client.guid, admin_na_client.client_secret)))
        request = self.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.3', HTTP_AUTHORIZATION=header)
        self._assert_failure(OAuth2TokenView.as_view(), request, 400, 'invalid_grant', HttpBadRequestException)

        time.sleep(180)
        admin_na_client.grant_type = 'CLIENT_CREDENTIALS'
        admin_na_client.save()
        request = self.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.4', HTTP_AUTHORIZATION=header)
        self._assert_failure(OAuth2TokenView.as_view(), request, 400, 'inactive_user', HttpBadRequestException)

        time.sleep(180)
        admin = UserList.get_user_by_username('admin')
        admin_client = Client()
        admin_client.ovs_type = 'USER'
        admin_client.grant_type = 'CLIENT_CREDENTIALS'
        admin_client.client_secret = OAuth2Toolbox.create_hash(64)
        admin_client.user = admin
        admin_client.save()
        header = 'Basic {0}'.format(base64.encodestring('{0}:foobar'.format(admin_client.guid)))
        request = self.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.5', HTTP_AUTHORIZATION=header)
        self._assert_failure(OAuth2TokenView.as_view(), request, 400, 'invalid_client', HttpBadRequestException)

        time.sleep(180)
        header = 'Basic {0}'.format(base64.encodestring('{0}:{1}'.format(admin_client.guid, admin_client.client_secret)))
        request = self.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.6', HTTP_AUTHORIZATION=header)
        response = OAuth2TokenView.as_view()(request)
        self.assertEqual(response.status_code, 200)
        response_content = json.loads(response.content)
        self.assertIn('access_token', response_content)
        result = {'access_token': response_content['access_token'],
                  'token_type': 'bearer',
                  'expires_in': 3600}
        self.assertDictEqual(response_content, result)
    def test_client_credentials(self):
        """
        Validates the Client Credentials
        """
        from oauth2.tokenview import OAuth2TokenView

        data = {'grant_type': 'client_credentials'}
        request = Authentication.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.1')
        response = OAuth2TokenView.as_view()(request)
        # Fails because the HTTP_AUTHORIZATION header is missing
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response.content, json.dumps({'error': 'missing_header'}))
        header = 'Basic {0}'.format(base64.encodestring('{0}:{1}'.format('foo', 'bar')))
        request = Authentication.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.1', HTTP_AUTHORIZATION=header)
        response = OAuth2TokenView.as_view()(request)
        # Fails because there is no such client
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response.content, json.dumps({'error': 'invalid_client'}))
        admin_na = UserList.get_user_by_username('admin_na')
        admin_na_client = Client()
        admin_na_client.ovs_type = 'USER'
        admin_na_client.grant_type = 'PASSWORD'
        admin_na_client.client_secret = OAuth2Toolbox.create_hash(64)
        admin_na_client.user = admin_na
        admin_na_client.save()
        header = 'Basic {0}'.format(base64.encodestring('{0}:{1}'.format(admin_na_client.guid, admin_na_client.client_secret)))
        request = Authentication.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.1', HTTP_AUTHORIZATION=header)
        response = OAuth2TokenView.as_view()(request)
        # Fails because the grant is of type Resource Owner Password Credentials
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response.content, json.dumps({'error': 'invalid_grant'}))
        admin_na_client.grant_type = 'CLIENT_CREDENTIALS'
        admin_na_client.save()
        request = Authentication.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.1', HTTP_AUTHORIZATION=header)
        response = OAuth2TokenView.as_view()(request)
        # Fails because the grant is of type Resource Owner Password Credentials
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response.content, json.dumps({'error': 'inactive_user'}))
        admin = UserList.get_user_by_username('admin')
        admin_client = Client()
        admin_client.ovs_type = 'USER'
        admin_client.grant_type = 'CLIENT_CREDENTIALS'
        admin_client.client_secret = OAuth2Toolbox.create_hash(64)
        admin_client.user = admin
        admin_client.save()
        header = 'Basic {0}'.format(base64.encodestring('{0}:{1}'.format(admin_client.guid, admin_client.client_secret)))
        request = Authentication.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.1', HTTP_AUTHORIZATION=header)
        response = OAuth2TokenView.as_view()(request)
        # Succeeds
        self.assertEqual(response.status_code, 200)
        response_content = json.loads(response.content)
        self.assertIn('access_token', response_content)
        result = {'access_token': response_content['access_token'],
                  'token_type': 'bearer',
                  'expires_in': 3600}
        self.assertDictEqual(response_content, result)
예제 #4
0
    def test_required_roles(self):
        """
        Validates whether the required_roles decorator works
        """
        from api.backend.decorators import required_roles

        @required_roles(['read', 'write', 'manage'])
        def the_function_rr(input_value, *args, **kwargs):
            """
            Decorated function
            """
            _ = args, kwargs
            output['value'] = input_value
            return HttpResponse(json.dumps(input_value))

        time.sleep(180)
        output = {'value': None}
        request = self.factory.get('/')
        with self.assertRaises(HttpUnauthorizedException) as context:
            the_function_rr(1, request)
        self.assertEqual(context.exception.status_code, 401)

        time.sleep(180)
        request.client = type('Client', (), {})
        request.user = type('User', (), {})
        request.user.username = '******'
        with self.assertRaises(HttpUnauthorizedException) as context:
            the_function_rr(2, request)
        self.assertEqual(context.exception.status_code, 401)

        time.sleep(180)
        user = UserList.get_user_by_username('user')
        access_token, _ = OAuth2Toolbox.generate_tokens(user.clients[0], generate_access=True, scopes=RoleList.get_roles_by_codes(['read']))
        access_token.expiration = int(time.time() + 86400)
        access_token.save()
        request.user.username = '******'
        request.token = access_token
        with self.assertRaises(HttpForbiddenException) as context:
            the_function_rr(3, request)
        self.assertEqual(context.exception.status_code, 403)
        self.assertEqual(context.exception.error, 'invalid_roles')
        self.assertEqual(context.exception.error_description, 'This call requires roles: read, write, manage')

        time.sleep(180)
        user = UserList.get_user_by_username('admin')
        access_token, _ = OAuth2Toolbox.generate_tokens(user.clients[0], generate_access=True, scopes=RoleList.get_roles_by_codes(['read', 'write', 'manage']))
        access_token.expiration = int(time.time() + 86400)
        access_token.save()
        request.username = '******'
        request.token = access_token
        response = the_function_rr(4, request)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, '4')
예제 #5
0
    def test_required_roles(self):
        """
        Validates whether the required_roles decorator works
        """
        from backend.decorators import required_roles
        from rest_framework.exceptions import NotAuthenticated, PermissionDenied

        @required_roles(['read', 'write', 'manage'])
        def the_function(input_value, *args, **kwargs):
            """
            Decorated function
            """
            _ = args, kwargs
            output['value'] = input_value
            return HttpResponse(json.dumps(input_value))

        output = {'value': None}
        user = UserList.get_user_by_username('user')
        request = self.factory.get('/')
        with self.assertRaises(NotAuthenticated) as context:
            the_function(1, request)
        self.assertEqual(context.exception.status_code, 401)
        request.client = type('Client', (), {})
        request.user = type('User', (), {})
        request.user.username = '******'
        with self.assertRaises(NotAuthenticated) as context:
            the_function(2, request)
        self.assertEqual(context.exception.status_code, 401)
        access_token, _ = OAuth2Toolbox.generate_tokens(
            user.clients[0],
            generate_access=True,
            scopes=RoleList.get_roles_by_codes(['read']))
        access_token.expiration = int(time.time() + 86400)
        access_token.save()
        request.user.username = '******'
        request.token = access_token
        with self.assertRaises(PermissionDenied) as context:
            the_function(3, request)
        self.assertEqual(context.exception.status_code, 403)
        self.assertEqual(context.exception.detail,
                         'This call requires roles: read, write, manage')
        user = UserList.get_user_by_username('admin')
        access_token, _ = OAuth2Toolbox.generate_tokens(
            user.clients[0],
            generate_access=True,
            scopes=RoleList.get_roles_by_codes(['read', 'write', 'manage']))
        access_token.expiration = int(time.time() + 86400)
        access_token.save()
        request.username = '******'
        request.token = access_token
        response = the_function(4, request)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, '4')
예제 #6
0
    def test_required_roles(self):
        """
        Validates whether the required_roles decorator works
        """
        from backend.decorators import required_roles
        from rest_framework.exceptions import NotAuthenticated, PermissionDenied

        @required_roles(["read", "write", "manage"])
        def the_function(input_value, *args, **kwargs):
            """
            Decorated function
            """
            _ = args, kwargs
            output["value"] = input_value
            return HttpResponse(json.dumps(input_value))

        output = {"value": None}
        user = UserList.get_user_by_username("user")
        request = Decorators.factory.get("/")
        with self.assertRaises(NotAuthenticated) as context:
            the_function(1, request)
        self.assertEqual(context.exception.status_code, 401)
        request.client = type("Client", (), {})
        request.user = type("User", (), {})
        request.user.username = "******"
        with self.assertRaises(NotAuthenticated) as context:
            the_function(2, request)
        self.assertEqual(context.exception.status_code, 401)
        access_token, _ = OAuth2Toolbox.generate_tokens(
            user.clients[0], generate_access=True, scopes=RoleList.get_roles_by_codes(["read"])
        )
        access_token.expiration = int(time.time() + 86400)
        access_token.save()
        request.user.username = "******"
        request.token = access_token
        with self.assertRaises(PermissionDenied) as context:
            the_function(3, request)
        self.assertEqual(context.exception.status_code, 403)
        self.assertEqual(context.exception.detail, "This call requires roles: read, write, manage")
        user = UserList.get_user_by_username("admin")
        access_token, _ = OAuth2Toolbox.generate_tokens(
            user.clients[0], generate_access=True, scopes=RoleList.get_roles_by_codes(["read", "write", "manage"])
        )
        access_token.expiration = int(time.time() + 86400)
        access_token.save()
        request.username = "******"
        request.token = access_token
        response = the_function(4, request)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, "4")
예제 #7
0
 def create(self, request):
     """
     Creates a User
     """
     serializer = FullSerializer(User, instance=User(), data=request.DATA, allow_passwords=True)
     if serializer.is_valid():
         user = serializer.object
         if UserList.get_user_by_username(user.username) is not None:
             return Response('User already exists', status=status.HTTP_303_SEE_OTHER)
         user.save()
         pw_client = Client()
         pw_client.ovs_type = 'INTERNAL'
         pw_client.grant_type = 'PASSWORD'
         pw_client.user = user
         pw_client.save()
         cc_client = Client()
         cc_client.ovs_type = 'INTERNAL'
         cc_client.grant_type = 'CLIENT_CREDENTIALS'
         cc_client.client_secret = ''.join(random.choice(string.ascii_letters +
                                                         string.digits +
                                                         '|_=+*#@!/-[]{}<>.?,\'";:~')
                                           for _ in range(128))
         cc_client.user = user
         cc_client.save()
         for junction in user.group.roles:
             for client in [cc_client, pw_client]:
                 roleclient = RoleClient()
                 roleclient.client = client
                 roleclient.role = junction.role
                 roleclient.save()
         serializer = FullSerializer(User, instance=user)
         return Response(serializer.data, status=status.HTTP_201_CREATED)
     else:
         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
예제 #8
0
 def post(self, request, *args, **kwargs):
     """
     Handles token post
     """
     _ = args, kwargs
     if 'grant_type' not in request.POST:
         return HttpResponseBadRequest, {'error': 'invalid_request'}
     grant_type = request.POST['grant_type']
     scopes = None
     if 'scope' in request.POST:
         scopes = RoleList.get_roles_by_codes(request.POST['scope'].split(' '))
     if grant_type == 'password':
         # Resource Owner Password Credentials Grant
         if 'username' not in request.POST or 'password' not in request.POST:
             return HttpResponseBadRequest, {'error': 'invalid_request'}
         username = request.POST['username']
         password = request.POST['password']
         user = UserList.get_user_by_username(username)
         if user is None or user.password != hashlib.sha256(password).hexdigest():
             return HttpResponseBadRequest, {'error': 'invalid_client'}
         if user.is_active is False:
             return HttpResponseBadRequest, {'error': 'inactive_user'}
         clients = [client for client in user.clients if client.ovs_type == 'FRONTEND' and client.grant_type == 'PASSWORD']
         if len(clients) != 1:
             return HttpResponseBadRequest, {'error': 'unauthorized_client'}
         client = clients[0]
         try:
             access_token, _ = Toolbox.generate_tokens(client, generate_access=True, scopes=scopes)
             access_token.expiration = int(time.time() + 86400)
             access_token.save()
         except ValueError as error:
             return HttpResponseBadRequest, {'error': str(error)}
         Toolbox.clean_tokens(client)
         return HttpResponse, {'access_token': access_token.access_token,
                               'token_type': 'bearer',
                               'expires_in': 86400}
     elif grant_type == 'client_credentials':
         # Client Credentials
         if 'HTTP_AUTHORIZATION' not in request.META:
             return HttpResponseBadRequest, {'error': 'missing_header'}
         _, password_hash = request.META['HTTP_AUTHORIZATION'].split(' ')
         client_id, client_secret = base64.decodestring(password_hash).split(':', 1)
         try:
             client = Client(client_id)
             if client.grant_type != 'CLIENT_CREDENTIALS':
                 return HttpResponseBadRequest, {'error': 'invalid_grant'}
             if not client.user.is_active:
                 return HttpResponseBadRequest, {'error': 'inactive_user'}
             try:
                 access_token, _ = Toolbox.generate_tokens(client, generate_access=True, scopes=scopes)
             except ValueError as error:
                 return HttpResponseBadRequest, {'error': str(error)}
             Toolbox.clean_tokens(client)
             return HttpResponse, {'access_token': access_token.access_token,
                                   'token_type': 'bearer',
                                   'expires_in': 3600}
         except:
             return HttpResponseBadRequest, {'error': 'invalid_client'}
     else:
         return HttpResponseBadRequest, {'error': 'unsupported_grant_type'}
예제 #9
0
 def create(self, request):
     """
     Creates a User
     :param request: The raw request
     :type request: Request
     """
     serializer = FullSerializer(User, instance=User(), data=request.DATA, allow_passwords=True)
     user = serializer.deserialize()
     if UserList.get_user_by_username(user.username) is not None:
         raise HttpNotAcceptableException(error_description='User with this username already exists',
                                          error='duplicate')
     user.save()
     pw_client = Client()
     pw_client.ovs_type = 'INTERNAL'
     pw_client.grant_type = 'PASSWORD'
     pw_client.user = user
     pw_client.save()
     cc_client = Client()
     cc_client.ovs_type = 'INTERNAL'
     cc_client.grant_type = 'CLIENT_CREDENTIALS'
     cc_client.client_secret = ''.join(random.choice(string.ascii_letters +
                                                     string.digits +
                                                     '|_=+*#@!/-[]{}<>.?,\'";:~')
                                       for _ in range(128))
     cc_client.user = user
     cc_client.save()
     for junction in user.group.roles:
         for client in [cc_client, pw_client]:
             roleclient = RoleClient()
             roleclient.client = client
             roleclient.role = junction.role
             roleclient.save()
     return user
예제 #10
0
 def create(self, request):
     """
     Creates a User
     :param request: The raw request
     :type request: Request
     """
     serializer = FullSerializer(User, instance=User(), data=request.DATA, allow_passwords=True)
     user = serializer.deserialize()
     if UserList.get_user_by_username(user.username) is not None:
         raise HttpNotAcceptableException(error='duplicate',
                                          error_description='User with this username already exists')
     user.save()
     pw_client = Client()
     pw_client.ovs_type = 'INTERNAL'
     pw_client.grant_type = 'PASSWORD'
     pw_client.user = user
     pw_client.save()
     cc_client = Client()
     cc_client.ovs_type = 'INTERNAL'
     cc_client.grant_type = 'CLIENT_CREDENTIALS'
     cc_client.client_secret = ''.join(random.choice(string.ascii_letters +
                                                     string.digits +
                                                     '|_=+*#@!/-[]{}<>.?,\'";:~')
                                       for _ in range(128))
     cc_client.user = user
     cc_client.save()
     for junction in user.group.roles:
         for client in [cc_client, pw_client]:
             roleclient = RoleClient()
             roleclient.client = client
             roleclient.role = junction.role
             roleclient.save()
     return user
예제 #11
0
 def new_function(*args, **kw):
     """
     Wrapped function
     """
     start = time.time()
     request = _find_request(args)
     if not hasattr(request, 'user') or not hasattr(request, 'client'):
         raise HttpUnauthorizedException(
             error_description='Not authenticated',
             error='not_authenticated')
     user = UserList.get_user_by_username(request.user.username)
     if user is None:
         raise HttpUnauthorizedException(
             error_description='Not authenticated',
             error='not_authenticated')
     if not ApiToolbox.is_token_in_roles(request.token, roles):
         raise HttpForbiddenException(
             error_description='This call requires roles: {0}'.format(
                 ', '.join(roles)),
             error='invalid_roles')
     duration = time.time() - start
     result = f(*args, **kw)
     if isinstance(result, OVSResponse):
         result.timings['security'] = [duration, 'Security']
     return result
예제 #12
0
    def test_required_roles(self):
        """
        Validates whether the required_roles decorator works
        """
        from backend.decorators import required_roles
        from rest_framework.exceptions import NotAuthenticated, PermissionDenied

        @required_roles(['read', 'write', 'manage'])
        def the_function(input_value, *args, **kwargs):
            """
            Decorated function
            """
            _ = args, kwargs
            output['value'] = input_value
            return HttpResponse(json.dumps(input_value))

        output = {'value': None}
        user = UserList.get_user_by_username('user')
        request = self.factory.get('/')
        with self.assertRaises(NotAuthenticated) as context:
            the_function(1, request)
        self.assertEqual(context.exception.status_code, 401)
        request.client = type('Client', (), {})
        request.user = type('User', (), {})
        request.user.username = '******'
        with self.assertRaises(NotAuthenticated) as context:
            the_function(2, request)
        self.assertEqual(context.exception.status_code, 401)
        access_token, _ = OAuth2Toolbox.generate_tokens(user.clients[0], generate_access=True, scopes=RoleList.get_roles_by_codes(['read']))
        access_token.expiration = int(time.time() + 86400)
        access_token.save()
        request.user.username = '******'
        request.token = access_token
        with self.assertRaises(PermissionDenied) as context:
            the_function(3, request)
        self.assertEqual(context.exception.status_code, 403)
        self.assertEqual(context.exception.detail, 'This call requires roles: read, write, manage')
        user = UserList.get_user_by_username('admin')
        access_token, _ = OAuth2Toolbox.generate_tokens(user.clients[0], generate_access=True, scopes=RoleList.get_roles_by_codes(['read', 'write', 'manage']))
        access_token.expiration = int(time.time() + 86400)
        access_token.save()
        request.username = '******'
        request.token = access_token
        response = the_function(4, request)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, '4')
예제 #13
0
 def list(self, request):
     """
     Lists all available Users where the logged in user has access to
     """
     if Toolbox.is_client_in_roles(request.client, ['manage']):
         return UserList.get_users()
     else:
         return [request.client.user]
예제 #14
0
 def list(self, request):
     """
     Lists all available Users where the logged in user has access to
     """
     if Toolbox.is_client_in_roles(request.client, ['manage']):
         return UserList.get_users()
     else:
         return [request.client.user]
예제 #15
0
    def test_authentication_backend(self):
        """
        Validates the Authentication backend
        """
        from django.contrib.auth.models import User as DUser
        from api.oauth2.tokenview import OAuth2TokenView
        from api.oauth2.backend import OAuth2Backend

        time.sleep(180)
        backend = OAuth2Backend()
        data = {
            'grant_type': 'password',
            'username': '******',
            'password': '******'
        }
        request = self.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.1')
        response = OAuth2TokenView.as_view()(request)
        response_content = json.loads(response.content)
        access_token = response_content['access_token']
        request = self.factory.get('/')
        response = backend.authenticate(request)
        self.assertIsNone(response)

        time.sleep(180)
        header = 'Bearer foobar'
        request = self.factory.get('/', HTTP_AUTHORIZATION=header)
        with self.assertRaises(HttpUnauthorizedException) as context:
            backend.authenticate(request)
        self.assertEqual(context.exception.status_code, 401)
        self.assertEqual(str(context.exception.error), 'invalid_token')

        time.sleep(180)
        header = 'Bearer {0}'.format(access_token)
        request = self.factory.get('/', HTTP_AUTHORIZATION=header)
        user, extra = backend.authenticate(request)
        self.assertIsInstance(user, DUser)
        self.assertIsNone(extra)
        self.assertEqual(request.token.access_token, access_token)
        self.assertEqual(request.client.user.username, 'admin')

        time.sleep(180)
        user = UserList.get_user_by_username('admin')
        user.is_active = False
        user.save()
        request = self.factory.get('/', HTTP_AUTHORIZATION=header)
        with self.assertRaises(HttpUnauthorizedException) as context:
            backend.authenticate(request)
        self.assertEqual(context.exception.status_code, 401)
        self.assertEqual(str(context.exception.error), 'inactive_user')
        user.is_active = True
        user.save()

        time.sleep(int(response_content['expires_in']))
        request = self.factory.get('/', HTTP_AUTHORIZATION=header)
        with self.assertRaises(HttpUnauthorizedException) as context:
            backend.authenticate(request)
        self.assertEqual(context.exception.status_code, 401)
        self.assertEqual(str(context.exception.error), 'token_expired')
예제 #16
0
    def test_authentication_backend(self):
        """
        Validates the Authentication backend
        """
        from django.contrib.auth.models import User as DUser
        from api.oauth2.tokenview import OAuth2TokenView
        from api.oauth2.backend import OAuth2Backend

        time.sleep(180)
        backend = OAuth2Backend()
        data = {'grant_type': 'password',
                'username': '******',
                'password': '******'}
        request = self.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.1')
        response = OAuth2TokenView.as_view()(request)
        response_content = json.loads(response.content)
        access_token = response_content['access_token']
        request = self.factory.get('/')
        response = backend.authenticate(request)
        self.assertIsNone(response)

        time.sleep(180)
        header = 'Bearer foobar'
        request = self.factory.get('/', HTTP_AUTHORIZATION=header)
        with self.assertRaises(HttpUnauthorizedException) as context:
            backend.authenticate(request)
        self.assertEqual(context.exception.status_code, 401)
        self.assertEqual(str(context.exception.error), 'invalid_token')

        time.sleep(180)
        header = 'Bearer {0}'.format(access_token)
        request = self.factory.get('/', HTTP_AUTHORIZATION=header)
        user, extra = backend.authenticate(request)
        self.assertIsInstance(user, DUser)
        self.assertIsNone(extra)
        self.assertEqual(request.token.access_token, access_token)
        self.assertEqual(request.client.user.username, 'admin')

        time.sleep(180)
        user = UserList.get_user_by_username('admin')
        user.is_active = False
        user.save()
        request = self.factory.get('/', HTTP_AUTHORIZATION=header)
        with self.assertRaises(HttpUnauthorizedException) as context:
            backend.authenticate(request)
        self.assertEqual(context.exception.status_code, 401)
        self.assertEqual(str(context.exception.error), 'inactive_user')
        user.is_active = True
        user.save()

        time.sleep(int(response_content['expires_in']))
        request = self.factory.get('/', HTTP_AUTHORIZATION=header)
        with self.assertRaises(HttpUnauthorizedException) as context:
            backend.authenticate(request)
        self.assertEqual(context.exception.status_code, 401)
        self.assertEqual(str(context.exception.error), 'token_expired')
예제 #17
0
 def new_function(*args, **kw):
     """
     Wrapped function
     """
     request = _find_request(args)
     if not hasattr(request, 'user') or not hasattr(request, 'client'):
         raise NotAuthenticated()
     user = UserList.get_user_by_username(request.user.username)
     if user is None:
         raise NotAuthenticated()
     if not Toolbox.is_token_in_roles(request.token, roles):
         raise PermissionDenied('This call requires roles: %s' % (', '.join(roles)))
     return f(*args, **kw)
예제 #18
0
 def new_function(*args, **kw):
     """
     Wrapped function
     """
     request = args[1]
     if not hasattr(request, 'user') or not hasattr(request, 'client'):
         raise NotAuthenticated()
     user = UserList.get_user_by_username(request.user.username)
     if user is None:
         raise NotAuthenticated()
     if not Toolbox.is_token_in_roles(request.token, roles):
         raise PermissionDenied('This call requires roles: %s' %
                                (', '.join(roles)))
     return f(*args, **kw)
예제 #19
0
 def new_function(*args, **kw):
     """
     Wrapped function
     """
     request = _find_request(args)
     if not hasattr(request, 'user') or not hasattr(request, 'client'):
         raise HttpUnauthorizedException(error_description='Not authenticated',
                                         error='not_authenticated')
     user = UserList.get_user_by_username(request.user.username)
     if user is None:
         raise HttpUnauthorizedException(error_description='Not authenticated',
                                         error='not_authenticated')
     if not Toolbox.is_token_in_roles(request.token, roles):
         raise HttpForbiddenException(error_description='This call requires roles: {0}'.format(', '.join(roles)),
                                      error='invalid_roles')
     return f(*args, **kw)
예제 #20
0
def user():
    admin = UserList.get_user_by_username('admin')

    alba_client = None
    alba_secret = None

    clients = admin.clients

    for client in clients:
        if client.name == 'alba':
            alba_client = client.client_id
            alba_secret = client.client_secret

    if alba_client is None:
        return {'error': 'user not found'}

    return {'client': alba_client, 'secret': alba_secret}
예제 #21
0
def user():
    admin = UserList.get_user_by_username("admin")

    alba_client = None
    alba_secret = None

    clients = admin.clients

    for client in clients:
        if client.name == "alba":
            alba_client = client.client_id
            alba_secret = client.client_secret

    if alba_client is None:
        return {"error": "user not found"}

    return {"client": alba_client, "secret": alba_secret}
예제 #22
0
 def new_function(*args, **kw):
     """
     Wrapped function
     """
     request = _find_request(args)
     if not hasattr(request, 'user') or not hasattr(request, 'client'):
         raise HttpUnauthorizedException(
             error_description='Not authenticated',
             error='not_authenticated')
     user = UserList.get_user_by_username(request.user.username)
     if user is None:
         raise HttpUnauthorizedException(
             error_description='Not authenticated',
             error='not_authenticated')
     if not Toolbox.is_token_in_roles(request.token, roles):
         raise HttpForbiddenException(
             error_description='This call requires roles: {0}'.format(
                 ', '.join(roles)),
             error='invalid_roles')
     return f(*args, **kw)
예제 #23
0
def user():
    admin = UserList.get_user_by_username("admin")
    print "[+] admin guid: %s" % admin.guid

    alba_client = None
    alba_secret = None

    clients = admin.clients

    for client in clients:
        if client.name == "alba":
            alba_client = client.client_id
            alba_secret = client.client_secret
            print "[+] alba client already set"

    if alba_client is None:
        print '[+] adding "alba" oauth2 client'
        choice = string.ascii_letters + string.digits

        # Creating user
        alclient = Client()
        alclient.ovs_type = "USER"
        alclient.name = "alba"
        alclient.grant_type = "CLIENT_CREDENTIALS"
        alclient.client_secret = "".join(
            random.choice(choice) for _ in range(64))
        alclient.user = admin
        alclient.save()

        # Adding roles
        for junction in admin.group.roles:
            roleclient = RoleClient()
            roleclient.client = alclient
            roleclient.role = junction.role
            roleclient.save()

        alba_client = alclient.client_id
        alba_secret = alclient.client_secret

    return {"client_id": alba_client, "client_secret": alba_secret}
예제 #24
0
 def create(self, request):
     """
     Creates a User
     """
     serializer = FullSerializer(User,
                                 instance=User(),
                                 data=request.DATA,
                                 allow_passwords=True)
     if serializer.is_valid():
         user = serializer.object
         if UserList.get_user_by_username(user.username) is not None:
             return Response('User already exists',
                             status=status.HTTP_303_SEE_OTHER)
         user.save()
         pw_client = Client()
         pw_client.ovs_type = 'INTERNAL'
         pw_client.grant_type = 'PASSWORD'
         pw_client.user = user
         pw_client.save()
         cc_client = Client()
         cc_client.ovs_type = 'INTERNAL'
         cc_client.grant_type = 'CLIENT_CREDENTIALS'
         cc_client.client_secret = ''.join(
             random.choice(string.ascii_letters + string.digits +
                           '|_=+*#@!/-[]{}<>.?,\'";:~') for _ in range(128))
         cc_client.user = user
         cc_client.save()
         for junction in user.group.roles:
             for client in [cc_client, pw_client]:
                 roleclient = RoleClient()
                 roleclient.client = client
                 roleclient.role = junction.role
                 roleclient.save()
         serializer = FullSerializer(User, instance=user)
         return Response(serializer.data, status=status.HTTP_201_CREATED)
     else:
         return Response(serializer.errors,
                         status=status.HTTP_400_BAD_REQUEST)
예제 #25
0
 def create(self, request):
     """
     Creates a User
     """
     serializer = FullSerializer(User, instance=User(), data=request.DATA, allow_passwords=True)
     if serializer.is_valid():
         user = serializer.object
         if UserList.get_user_by_username(user.username) is not None:
             return Response('User already exists', status=status.HTTP_303_SEE_OTHER)
         user.save()
         client = Client()
         client.ovs_type = 'FRONTEND'
         client.grant_type = 'PASSWORD'
         client.user = user
         client.save()
         for junction in user.group.roles:
             roleclient = RoleClient()
             roleclient.client = client
             roleclient.role = junction.role
             roleclient.save()
         serializer = FullSerializer(User, instance=user)
         return Response(serializer.data, status=status.HTTP_201_CREATED)
     else:
         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
예제 #26
0
    def test_metadata(self):
        """
        Validates the authentication related information at the API root's metadata.
        - The 'roles' key is already checked in the Scope-related tests
        """
        from ovs.dal.lists.bearertokenlist import BearerTokenList
        from api.oauth2.tokenview import OAuth2TokenView
        from api.view import MetadataView

        def _raise_exception(argument):
            _ = argument
            raise RuntimeError('foobar')

        result_data = {
            'authenticated': False,
            'authentication_state': None,
            'username': None,
            'userguid': None
        }

        time.sleep(180)
        data = {
            'grant_type': 'password',
            'username': '******',
            'password': '******'
        }
        request = self.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.1')
        response = OAuth2TokenView.as_view()(request)
        response_content = json.loads(response.content)
        self.assertIn('expires_in', response_content)
        self.assertIn('access_token', response_content)

        time.sleep(180)
        expiry = int(response_content['expires_in'])
        access_token = response_content['access_token']
        request = self.factory.get('/', HTTP_X_REAL_IP='127.0.0.1')
        response = MetadataView.as_view()(request)
        response_content = json.loads(response.content)
        self.assertDictContainsSubset(
            dict(result_data.items() +
                 {'authentication_state': 'unauthenticated'}.items()),
            response_content)

        time.sleep(180)
        header = 'Basic foobar'
        request = self.factory.get('/',
                                   HTTP_X_REAL_IP='127.0.0.1',
                                   HTTP_AUTHORIZATION=header)
        response = MetadataView.as_view()(request)
        response_content = json.loads(response.content)
        self.assertDictContainsSubset(
            dict(result_data.items() +
                 {'authentication_state': 'invalid_authorization_type'
                  }.items()), response_content)

        time.sleep(180)
        header = 'Bearer foobar'
        request = self.factory.get('/',
                                   HTTP_X_REAL_IP='127.0.0.1',
                                   HTTP_AUTHORIZATION=header)
        response = MetadataView.as_view()(request)
        response_content = json.loads(response.content)
        self.assertDictContainsSubset(
            dict(result_data.items() +
                 {'authentication_state': 'invalid_token'}.items()),
            response_content)

        time.sleep(180)
        user = UserList.get_user_by_username('admin')
        header = 'Bearer {0}'.format(access_token)
        request = self.factory.get('/',
                                   HTTP_X_REAL_IP='127.0.0.1',
                                   HTTP_AUTHORIZATION=header)
        response = MetadataView.as_view()(request)
        response_content = json.loads(response.content)
        self.assertDictContainsSubset(
            dict(
                result_data.items() + {
                    'authenticated': True,
                    'authentication_state': 'authenticated',
                    'username': user.username,
                    'userguid': user.guid
                }.items()), response_content)

        time.sleep(180)
        user.is_active = False
        user.save()
        request = self.factory.get('/',
                                   HTTP_X_REAL_IP='127.0.0.1',
                                   HTTP_AUTHORIZATION=header)
        response = MetadataView.as_view()(request)
        response_content = json.loads(response.content)
        self.assertDictContainsSubset(
            dict(result_data.items() +
                 {'authentication_state': 'inactive_user'}.items()),
            response_content)
        user.is_active = True
        user.save()

        time.sleep(180)
        original_method = BearerTokenList.get_by_access_token
        BearerTokenList.get_by_access_token = staticmethod(_raise_exception)
        request = self.factory.get('/',
                                   HTTP_X_REAL_IP='127.0.0.1',
                                   HTTP_AUTHORIZATION=header)
        response = MetadataView.as_view()(request)
        response_content = json.loads(response.content)
        self.assertDictContainsSubset(
            dict(result_data.items() +
                 {'authentication_state': 'unexpected_exception'}.items()),
            response_content)

        time.sleep(180)
        BearerTokenList.get_by_access_token = staticmethod(original_method)
        time.sleep(expiry)
        request = self.factory.get('/',
                                   HTTP_X_REAL_IP='127.0.0.1',
                                   HTTP_AUTHORIZATION=header)
        response = MetadataView.as_view()(request)
        response_content = json.loads(response.content)
        self.assertDictContainsSubset(
            dict(result_data.items() +
                 {'authentication_state': 'token_expired'}.items()),
            response_content)
예제 #27
0
    def test_client_credentials(self):
        """
        Validates the Client Credentials
        """
        from api.oauth2.tokenview import OAuth2TokenView

        time.sleep(180)
        data = {'grant_type': 'client_credentials'}
        request = self.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.1')
        self._assert_failure(OAuth2TokenView.as_view(), request, 400,
                             'missing_header', HttpBadRequestException)

        time.sleep(180)
        header = 'Basic {0}'.format(
            base64.encodestring('{0}:{1}'.format('foo', 'bar')))
        request = self.factory.post('/',
                                    data=data,
                                    HTTP_X_REAL_IP='127.0.0.2',
                                    HTTP_AUTHORIZATION=header)
        self._assert_failure(OAuth2TokenView.as_view(), request, 400,
                             'invalid_client', HttpBadRequestException)

        time.sleep(180)
        admin_na = UserList.get_user_by_username('admin_na')
        admin_na_client = Client()
        admin_na_client.ovs_type = 'USER'
        admin_na_client.grant_type = 'PASSWORD'
        admin_na_client.client_secret = OAuth2Toolbox.create_hash(64)
        admin_na_client.user = admin_na
        admin_na_client.save()
        header = 'Basic {0}'.format(
            base64.encodestring('{0}:{1}'.format(
                admin_na_client.guid, admin_na_client.client_secret)))
        request = self.factory.post('/',
                                    data=data,
                                    HTTP_X_REAL_IP='127.0.0.3',
                                    HTTP_AUTHORIZATION=header)
        self._assert_failure(OAuth2TokenView.as_view(), request, 400,
                             'invalid_grant', HttpBadRequestException)

        time.sleep(180)
        admin_na_client.grant_type = 'CLIENT_CREDENTIALS'
        admin_na_client.save()
        request = self.factory.post('/',
                                    data=data,
                                    HTTP_X_REAL_IP='127.0.0.4',
                                    HTTP_AUTHORIZATION=header)
        self._assert_failure(OAuth2TokenView.as_view(), request, 400,
                             'inactive_user', HttpBadRequestException)

        time.sleep(180)
        admin = UserList.get_user_by_username('admin')
        admin_client = Client()
        admin_client.ovs_type = 'USER'
        admin_client.grant_type = 'CLIENT_CREDENTIALS'
        admin_client.client_secret = OAuth2Toolbox.create_hash(64)
        admin_client.user = admin
        admin_client.save()
        header = 'Basic {0}'.format(
            base64.encodestring('{0}:foobar'.format(admin_client.guid)))
        request = self.factory.post('/',
                                    data=data,
                                    HTTP_X_REAL_IP='127.0.0.5',
                                    HTTP_AUTHORIZATION=header)
        self._assert_failure(OAuth2TokenView.as_view(), request, 400,
                             'invalid_client', HttpBadRequestException)

        time.sleep(180)
        header = 'Basic {0}'.format(
            base64.encodestring('{0}:{1}'.format(admin_client.guid,
                                                 admin_client.client_secret)))
        request = self.factory.post('/',
                                    data=data,
                                    HTTP_X_REAL_IP='127.0.0.6',
                                    HTTP_AUTHORIZATION=header)
        response = OAuth2TokenView.as_view()(request)
        self.assertEqual(response.status_code, 200)
        response_content = json.loads(response.content)
        self.assertIn('access_token', response_content)
        result = {
            'access_token': response_content['access_token'],
            'token_type': 'bearer',
            'expires_in': 3600
        }
        self.assertDictEqual(response_content, result)
예제 #28
0
 def post(self, request, *args, **kwargs):
     """
     Handles token post
     """
     logger = LogHandler.get('api', 'oauth2')
     _ = args, kwargs
     if 'grant_type' not in request.POST:
         raise HttpBadRequestException(error='invalid_request',
                                       error_description='No grant type specified')
     grant_type = request.POST['grant_type']
     scopes = None
     if 'scope' in request.POST:
         scopes = RoleList.get_roles_by_codes(request.POST['scope'].split(' '))
     if grant_type == 'password':
         # Resource Owner Password Credentials Grant
         if 'username' not in request.POST or 'password' not in request.POST:
             raise HttpBadRequestException(error='invalid_request',
                                           error_description='Invalid request')
         username = request.POST['username']
         password = request.POST['password']
         user = UserList.get_user_by_username(username)
         if user is None or user.password != hashlib.sha256(password).hexdigest():
             raise HttpBadRequestException(error='invalid_client',
                                           error_description='Invalid client')
         if user.is_active is False:
             raise HttpBadRequestException(error='inactive_user',
                                           error_description='User is inactive')
         clients = [client for client in user.clients if client.ovs_type == 'INTERNAL' and client.grant_type == 'PASSWORD']
         if len(clients) != 1:
             raise HttpBadRequestException(error='unauthorized_client',
                                           error_description='Client is unautorized')
         client = clients[0]
         try:
             access_token, _ = Toolbox.generate_tokens(client, generate_access=True, scopes=scopes)
             access_token.expiration = int(time.time() + 86400)
             access_token.save()
         except ValueError as error:
             if error.message == 'invalid_scope':
                 raise HttpBadRequestException(error='invalid_scope',
                                               error_description='Invalid scope requested')
             raise
         Toolbox.clean_tokens(client)
         return HttpResponse(json.dumps({'access_token': access_token.access_token,
                                         'token_type': 'bearer',
                                         'expires_in': 86400}),
                             content_type='application/json')
     elif grant_type == 'client_credentials':
         # Client Credentials
         if 'HTTP_AUTHORIZATION' not in request.META:
             raise HttpBadRequestException(error='missing_header',
                                           error_description='Authorization header missing')
         _, password_hash = request.META['HTTP_AUTHORIZATION'].split(' ')
         client_id, client_secret = base64.b64decode(password_hash).split(':', 1)
         try:
             client = Client(client_id)
             if client.grant_type != 'CLIENT_CREDENTIALS':
                 raise HttpBadRequestException(error='invalid_grant',
                                               error_description='The given grant type is not supported')
             if client.client_secret != client_secret:
                 raise HttpBadRequestException(error='invalid_client',
                                               error_description='Invalid client')
             if not client.user.is_active:
                 raise HttpBadRequestException(error='inactive_user',
                                               error_description='User is inactive')
             try:
                 access_token, _ = Toolbox.generate_tokens(client, generate_access=True, scopes=scopes)
             except ValueError as error:
                 if error.message == 'invalid_scope':
                     raise HttpBadRequestException(error='invalid_scope',
                                                   error_description='Invalid scope requested')
                 raise
             try:
                 Toolbox.clean_tokens(client)
             except Exception as error:
                 logger.error('Error during session cleanup: {0}'.format(error))
             return HttpResponse(json.dumps({'access_token': access_token.access_token,
                                             'token_type': 'bearer',
                                             'expires_in': 3600}),
                                 content_type='application/json')
         except HttpBadRequestException:
             raise
         except ObjectNotFoundException as ex:
             logger.warning('Error matching client: {0}'.format(ex))
             raise HttpBadRequestException(error='invalid_client',
                                           error_description='Client could not be found')
         except Exception as ex:
             logger.exception('Error matching client: {0}'.format(ex))
             raise HttpBadRequestException(error='invalid_client',
                                           error_description='Error loading client')
     else:
         raise HttpBadRequestException(error='unsupported_grant_type',
                                       error_description='Unsupported grant type')
예제 #29
0
 def post(self, request, *args, **kwargs):
     """
     Handles token post
     """
     logger = LogHandler.get('api', 'oauth2')
     _ = args, kwargs
     if 'grant_type' not in request.POST:
         return HttpResponseBadRequest, {'error': 'invalid_request'}
     grant_type = request.POST['grant_type']
     scopes = None
     if 'scope' in request.POST:
         scopes = RoleList.get_roles_by_codes(request.POST['scope'].split(' '))
     if grant_type == 'password':
         # Resource Owner Password Credentials Grant
         if 'username' not in request.POST or 'password' not in request.POST:
             return HttpResponseBadRequest, {'error': 'invalid_request'}
         username = request.POST['username']
         password = request.POST['password']
         user = UserList.get_user_by_username(username)
         if user is None or user.password != hashlib.sha256(password).hexdigest():
             return HttpResponseBadRequest, {'error': 'invalid_client'}
         if user.is_active is False:
             return HttpResponseBadRequest, {'error': 'inactive_user'}
         clients = [client for client in user.clients if client.ovs_type == 'INTERNAL' and client.grant_type == 'PASSWORD']
         if len(clients) != 1:
             return HttpResponseBadRequest, {'error': 'unauthorized_client'}
         client = clients[0]
         try:
             access_token, _ = Toolbox.generate_tokens(client, generate_access=True, scopes=scopes)
             access_token.expiration = int(time.time() + 86400)
             access_token.save()
         except ValueError as error:
             return HttpResponseBadRequest, {'error': str(error)}
         Toolbox.clean_tokens(client)
         return HttpResponse, {'access_token': access_token.access_token,
                               'token_type': 'bearer',
                               'expires_in': 86400}
     elif grant_type == 'client_credentials':
         # Client Credentials
         if 'HTTP_AUTHORIZATION' not in request.META:
             return HttpResponseBadRequest, {'error': 'missing_header'}
         _, password_hash = request.META['HTTP_AUTHORIZATION'].split(' ')
         client_id, client_secret = base64.b64decode(password_hash).split(':', 1)
         try:
             client = Client(client_id)
             if client.grant_type != 'CLIENT_CREDENTIALS':
                 return HttpResponseBadRequest, {'error': 'invalid_grant'}
             if client.client_secret != client_secret:
                 return HttpResponseBadRequest, {'error': 'invalid_client'}
             if not client.user.is_active:
                 return HttpResponseBadRequest, {'error': 'inactive_user'}
             try:
                 access_token, _ = Toolbox.generate_tokens(client, generate_access=True, scopes=scopes)
             except ValueError as error:
                 return HttpResponseBadRequest, {'error': str(error)}
             try:
                 Toolbox.clean_tokens(client)
             except Exception as error:
                 logger.error('Error during session cleanup: {0}'.format(error))
             return HttpResponse, {'access_token': access_token.access_token,
                                   'token_type': 'bearer',
                                   'expires_in': 3600}
         except Exception as ex:
             logger.exception('Error matching client: {0}'.format(ex))
             return HttpResponseBadRequest, {'error': 'invalid_client'}
     else:
         return HttpResponseBadRequest, {'error': 'unsupported_grant_type'}
예제 #30
0
    def test_load(self):
        """
        Validates whether the load decorator works
        """
        from backend.decorators import load
        from rest_framework.exceptions import NotAcceptable
        from django.http import Http404

        @load(User, min_version=2, max_version=2)
        def the_function_1(input_value, request, user, version, mandatory, optional="default"):
            """
            Decorated function
            """
            output["value"] = {
                "request": request,
                "mandatory": mandatory,
                "optional": optional,
                "version": version,
                "user": user,
            }
            return HttpResponse(json.dumps(input_value))

        @load(User)
        def the_function_2(input_value, request, user, pk, version):
            """
            Decorated function
            """
            output["value"] = {"request": request, "user": user, "pk": pk, "version": version}
            return HttpResponse(json.dumps(input_value))

        output = {"value": None}
        user = UserList.get_user_by_username("user")
        request = Decorators.factory.get("/", HTTP_ACCEPT="application/json; version=1")
        with self.assertRaises(NotAcceptable) as context:
            the_function_1(1, request)
        self.assertEqual(context.exception.status_code, 406)
        self.assertEqual(
            context.exception.detail, "API version requirements: {0} <= <version> <= {1}. Got {2}".format(2, 2, 1)
        )
        request = Decorators.factory.get("/", HTTP_ACCEPT="application/json; version=*")
        with self.assertRaises(Http404):
            the_function_1(2, request, pk=str(uuid.uuid4()))
        request = Decorators.factory.get("/", HTTP_ACCEPT="application/json; version=*")
        request.DATA = {}
        request.QUERY_PARAMS = {}
        with self.assertRaises(NotAcceptable) as context:
            the_function_1(3, request, pk=user.guid)
        self.assertEqual(context.exception.status_code, 406)
        self.assertEqual(context.exception.detail, "Invalid data passed: mandatory is missing")
        request = Decorators.factory.get("/", HTTP_ACCEPT="application/json; version=*")
        request.DATA = {"mandatory": "mandatory"}
        request.QUERY_PARAMS = {}
        response = the_function_1(4, request, pk=user.guid)
        self.assertEqual(response.status_code, 200)
        self.assertDictContainsSubset({"mandatory": "mandatory", "optional": "default", "user": user}, output["value"])
        self.assertIn("request", output["value"].keys())
        self.assertEqual(json.loads(response.content), 4)
        request = Decorators.factory.get("/", HTTP_ACCEPT="application/json; version=*")
        request.DATA = {}
        request.QUERY_PARAMS = {"mandatory": "mandatory", "optional": "optional"}
        response = the_function_1(5, request, pk=user.guid)
        self.assertEqual(response.status_code, 200)
        self.assertDictContainsSubset(
            {"mandatory": "mandatory", "optional": "optional", "version": 2, "user": user}, output["value"]
        )
        self.assertIn("request", output["value"].keys())
        self.assertEqual(json.loads(response.content), 5)
        request = Decorators.factory.get("/", HTTP_ACCEPT="application/json; version=*")
        request.DATA = {}
        request.QUERY_PARAMS = {"mandatory": "mandatory", "optional": "optional"}
        response = the_function_2(6, request, pk=user.guid)
        self.assertEqual(response.status_code, 200)
        self.assertDictContainsSubset({"pk": user.guid, "version": 3, "user": user}, output["value"])
        self.assertIn("request", output["value"].keys())
        self.assertEqual(json.loads(response.content), 6)
예제 #31
0
    def test_client_credentials(self):
        """
        Validates the Client Credentials
        """
        from oauth2.tokenview import OAuth2TokenView

        data = {'grant_type': 'client_credentials'}
        request = self.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.1')
        response = OAuth2TokenView.as_view()(request)
        # Fails because the HTTP_AUTHORIZATION header is missing
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response.content,
                         json.dumps({'error': 'missing_header'}))
        header = 'Basic {0}'.format(
            base64.encodestring('{0}:{1}'.format('foo', 'bar')))
        request = self.factory.post('/',
                                    data=data,
                                    HTTP_X_REAL_IP='127.0.0.2',
                                    HTTP_AUTHORIZATION=header)
        response = OAuth2TokenView.as_view()(request)
        # Fails because there is no such client
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response.content,
                         json.dumps({'error': 'invalid_client'}))
        admin_na = UserList.get_user_by_username('admin_na')
        admin_na_client = Client()
        admin_na_client.ovs_type = 'USER'
        admin_na_client.grant_type = 'PASSWORD'
        admin_na_client.client_secret = OAuth2Toolbox.create_hash(64)
        admin_na_client.user = admin_na
        admin_na_client.save()
        header = 'Basic {0}'.format(
            base64.encodestring('{0}:{1}'.format(
                admin_na_client.guid, admin_na_client.client_secret)))
        request = self.factory.post('/',
                                    data=data,
                                    HTTP_X_REAL_IP='127.0.0.3',
                                    HTTP_AUTHORIZATION=header)
        response = OAuth2TokenView.as_view()(request)
        # Fails because the grant is of type Resource Owner Password Credentials
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response.content,
                         json.dumps({'error': 'invalid_grant'}))
        admin_na_client.grant_type = 'CLIENT_CREDENTIALS'
        admin_na_client.save()
        request = self.factory.post('/',
                                    data=data,
                                    HTTP_X_REAL_IP='127.0.0.4',
                                    HTTP_AUTHORIZATION=header)
        response = OAuth2TokenView.as_view()(request)
        # Fails because the grant is of type Resource Owner Password Credentials
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response.content,
                         json.dumps({'error': 'inactive_user'}))
        admin = UserList.get_user_by_username('admin')
        admin_client = Client()
        admin_client.ovs_type = 'USER'
        admin_client.grant_type = 'CLIENT_CREDENTIALS'
        admin_client.client_secret = OAuth2Toolbox.create_hash(64)
        admin_client.user = admin
        admin_client.save()
        header = 'Basic {0}'.format(
            base64.encodestring('{0}:foobar'.format(admin_client.guid)))
        request = self.factory.post('/',
                                    data=data,
                                    HTTP_X_REAL_IP='127.0.0.5',
                                    HTTP_AUTHORIZATION=header)
        response = OAuth2TokenView.as_view()(request)
        # Fails because it's an invalid secret
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response.content,
                         json.dumps({'error': 'invalid_client'}))
        header = 'Basic {0}'.format(
            base64.encodestring('{0}:{1}'.format(admin_client.guid,
                                                 admin_client.client_secret)))
        request = self.factory.post('/',
                                    data=data,
                                    HTTP_X_REAL_IP='127.0.0.6',
                                    HTTP_AUTHORIZATION=header)
        response = OAuth2TokenView.as_view()(request)
        # Succeeds
        self.assertEqual(response.status_code, 200)
        response_content = json.loads(response.content)
        self.assertIn('access_token', response_content)
        result = {
            'access_token': response_content['access_token'],
            'token_type': 'bearer',
            'expires_in': 3600
        }
        self.assertDictEqual(response_content, result)
예제 #32
0
    def test_load(self):
        """
        Validates whether the load decorator works
        """
        from backend.decorators import load
        from rest_framework.exceptions import NotAcceptable
        from django.http import Http404

        @load(User, min_version=2, max_version=2)
        def the_function_1(input_value,
                           request,
                           user,
                           version,
                           mandatory,
                           optional='default'):
            """
            Decorated function
            """
            output['value'] = {
                'request': request,
                'mandatory': mandatory,
                'optional': optional,
                'version': version,
                'user': user
            }
            return HttpResponse(json.dumps(input_value))

        @load(User)
        def the_function_2(input_value, request, user, pk, version):
            """
            Decorated function
            """
            output['value'] = {
                'request': request,
                'user': user,
                'pk': pk,
                'version': version
            }
            return HttpResponse(json.dumps(input_value))

        output = {'value': None}
        user = UserList.get_user_by_username('user')
        request = self.factory.get('/',
                                   HTTP_ACCEPT='application/json; version=1')
        with self.assertRaises(NotAcceptable) as context:
            the_function_1(1, request)
        self.assertEqual(context.exception.status_code, 406)
        self.assertEqual(
            context.exception.detail,
            'API version requirements: {0} <= <version> <= {1}. Got {2}'.
            format(2, 2, 1))
        request = self.factory.get('/',
                                   HTTP_ACCEPT='application/json; version=*')
        with self.assertRaises(Http404):
            the_function_1(2, request, pk=str(uuid.uuid4()))
        request = self.factory.get('/',
                                   HTTP_ACCEPT='application/json; version=*')
        request.DATA = {}
        request.QUERY_PARAMS = {}
        with self.assertRaises(NotAcceptable) as context:
            the_function_1(3, request, pk=user.guid)
        self.assertEqual(context.exception.status_code, 406)
        self.assertEqual(context.exception.detail,
                         'Invalid data passed: mandatory is missing')
        request = self.factory.get('/',
                                   HTTP_ACCEPT='application/json; version=*')
        request.DATA = {'mandatory': 'mandatory'}
        request.QUERY_PARAMS = {}
        response = the_function_1(4, request, pk=user.guid)
        self.assertEqual(response.status_code, 200)
        self.assertDictContainsSubset(
            {
                'mandatory': 'mandatory',
                'optional': 'default',
                'user': user
            }, output['value'])
        self.assertIn('request', output['value'].keys())
        self.assertEqual(json.loads(response.content), 4)
        request = self.factory.get('/',
                                   HTTP_ACCEPT='application/json; version=*')
        request.DATA = {}
        request.QUERY_PARAMS = {
            'mandatory': 'mandatory',
            'optional': 'optional'
        }
        response = the_function_1(5, request, pk=user.guid)
        self.assertEqual(response.status_code, 200)
        self.assertDictContainsSubset(
            {
                'mandatory': 'mandatory',
                'optional': 'optional',
                'version': 2,
                'user': user
            }, output['value'])
        self.assertIn('request', output['value'].keys())
        self.assertEqual(json.loads(response.content), 5)
        request = self.factory.get('/',
                                   HTTP_ACCEPT='application/json; version=*')
        request.DATA = {}
        request.QUERY_PARAMS = {
            'mandatory': 'mandatory',
            'optional': 'optional'
        }
        response = the_function_2(6, request, pk=user.guid)
        self.assertEqual(response.status_code, 200)
        self.assertDictContainsSubset(
            {
                'pk': user.guid,
                'version': 3,
                'user': user
            }, output['value'])
        self.assertIn('request', output['value'].keys())
        self.assertEqual(json.loads(response.content), 6)
예제 #33
0
    def test_load(self):
        """
        Validates whether the load decorator works
        """
        from backend.decorators import load
        from rest_framework.exceptions import NotAcceptable
        from django.http import Http404

        @load(User, min_version=2, max_version=2)
        def the_function_1(input_value, request, user, version, mandatory, optional='default'):
            """
            Decorated function
            """
            output['value'] = {'request': request,
                               'mandatory': mandatory,
                               'optional': optional,
                               'version': version,
                               'user': user}
            return HttpResponse(json.dumps(input_value))

        @load(User)
        def the_function_2(input_value, request, user, pk, version):
            """
            Decorated function
            """
            output['value'] = {'request': request,
                               'user': user,
                               'pk': pk,
                               'version': version}
            return HttpResponse(json.dumps(input_value))

        output = {'value': None}
        user = UserList.get_user_by_username('user')
        request = self.factory.get('/', HTTP_ACCEPT='application/json; version=1')
        with self.assertRaises(NotAcceptable) as context:
            the_function_1(1, request)
        self.assertEqual(context.exception.status_code, 406)
        self.assertEqual(context.exception.detail, 'API version requirements: {0} <= <version> <= {1}. Got {2}'.format(2, 2, 1))
        request = self.factory.get('/', HTTP_ACCEPT='application/json; version=*')
        with self.assertRaises(Http404):
            the_function_1(2, request, pk=str(uuid.uuid4()))
        request = self.factory.get('/', HTTP_ACCEPT='application/json; version=*')
        request.DATA = {}
        request.QUERY_PARAMS = {}
        with self.assertRaises(NotAcceptable) as context:
            the_function_1(3, request, pk=user.guid)
        self.assertEqual(context.exception.status_code, 406)
        self.assertEqual(context.exception.detail, 'Invalid data passed: mandatory is missing')
        request = self.factory.get('/', HTTP_ACCEPT='application/json; version=*')
        request.DATA = {'mandatory': 'mandatory'}
        request.QUERY_PARAMS = {}
        response = the_function_1(4, request, pk=user.guid)
        self.assertEqual(response.status_code, 200)
        self.assertDictContainsSubset({'mandatory': 'mandatory',
                                       'optional': 'default',
                                       'user': user}, output['value'])
        self.assertIn('request', output['value'].keys())
        self.assertEqual(json.loads(response.content), 4)
        request = self.factory.get('/', HTTP_ACCEPT='application/json; version=*')
        request.DATA = {}
        request.QUERY_PARAMS = {'mandatory': 'mandatory',
                                'optional': 'optional'}
        response = the_function_1(5, request, pk=user.guid)
        self.assertEqual(response.status_code, 200)
        self.assertDictContainsSubset({'mandatory': 'mandatory',
                                       'optional': 'optional',
                                       'version': 2,
                                       'user': user}, output['value'])
        self.assertIn('request', output['value'].keys())
        self.assertEqual(json.loads(response.content), 5)
        request = self.factory.get('/', HTTP_ACCEPT='application/json; version=*')
        request.DATA = {}
        request.QUERY_PARAMS = {'mandatory': 'mandatory',
                                'optional': 'optional'}
        response = the_function_2(6, request, pk=user.guid)
        self.assertEqual(response.status_code, 200)
        self.assertDictContainsSubset({'pk': user.guid,
                                       'version': 3,
                                       'user': user}, output['value'])
        self.assertIn('request', output['value'].keys())
        self.assertEqual(json.loads(response.content), 6)
    def test_metadata(self):
        """
        Validates the authentication related information at the API root's metadata.
        - The 'roles' key is already checked in the Scope-related tests
        """
        from ovs.dal.lists.bearertokenlist import BearerTokenList
        from oauth2.tokenview import OAuth2TokenView
        from view import MetadataView

        def raise_exception(argument):
            _ = argument
            raise RuntimeError('foobar')

        result_data = {'authenticated': False,
                       'authentication_state': None,
                       'username': None,
                       'userguid': None}
        data = {'grant_type': 'password',
                'username': '******',
                'password': '******'}
        request = Authentication.factory.post('/', data=data, HTTP_X_REAL_IP='127.0.0.1')
        response = OAuth2TokenView.as_view()(request)
        response_content = json.loads(response.content)
        expiry = int(response_content['expires_in'])
        access_token = response_content['access_token']
        request = Authentication.factory.get('/', HTTP_X_REAL_IP='127.0.0.1')
        response = MetadataView.as_view()(request)
        response_content = json.loads(response.content)
        self.assertDictContainsSubset(dict(result_data.items() + {'authentication_state': 'unauthenticated'}.items()), response_content)
        header = 'Basic foobar'
        request = Authentication.factory.get('/', HTTP_X_REAL_IP='127.0.0.1', HTTP_AUTHORIZATION=header)
        response = MetadataView.as_view()(request)
        response_content = json.loads(response.content)
        self.assertDictContainsSubset(dict(result_data.items() + {'authentication_state': 'invalid_authorization_type'}.items()), response_content)
        header = 'Bearer foobar'
        request = Authentication.factory.get('/', HTTP_X_REAL_IP='127.0.0.1', HTTP_AUTHORIZATION=header)
        response = MetadataView.as_view()(request)
        response_content = json.loads(response.content)
        self.assertDictContainsSubset(dict(result_data.items() + {'authentication_state': 'invalid_token'}.items()), response_content)
        user = UserList.get_user_by_username('admin')
        header = 'Bearer {0}'.format(access_token)
        request = Authentication.factory.get('/', HTTP_X_REAL_IP='127.0.0.1', HTTP_AUTHORIZATION=header)
        response = MetadataView.as_view()(request)
        response_content = json.loads(response.content)
        self.assertDictContainsSubset(dict(result_data.items() + {'authenticated': True,
                                                                  'username': user.username,
                                                                  'userguid': user.guid}.items()), response_content)
        time.sleep(180)  # Make sure to not hit the rate limit
        user.is_active = False
        user.save()
        request = Authentication.factory.get('/', HTTP_X_REAL_IP='127.0.0.1', HTTP_AUTHORIZATION=header)
        response = MetadataView.as_view()(request)
        response_content = json.loads(response.content)
        self.assertDictContainsSubset(dict(result_data.items() + {'authentication_state': 'inactive_user'}.items()), response_content)
        original_method = BearerTokenList.get_by_access_token
        BearerTokenList.get_by_access_token = staticmethod(raise_exception)
        request = Authentication.factory.get('/', HTTP_X_REAL_IP='127.0.0.1', HTTP_AUTHORIZATION=header)
        response = MetadataView.as_view()(request)
        response_content = json.loads(response.content)
        self.assertDictContainsSubset(dict(result_data.items() + {'authentication_state': 'unexpected_exception'}.items()), response_content)
        BearerTokenList.get_by_access_token = staticmethod(original_method)
        time.sleep(expiry)
        request = Authentication.factory.get('/', HTTP_X_REAL_IP='127.0.0.1', HTTP_AUTHORIZATION=header)
        response = MetadataView.as_view()(request)
        response_content = json.loads(response.content)
        self.assertDictContainsSubset(dict(result_data.items() + {'authentication_state': 'token_expired'}.items()), response_content)
예제 #35
0
 def post(self, request, *args, **kwargs):
     """
     Handles token post
     """
     logger = LogHandler.get('api', 'oauth2')
     _ = args, kwargs
     if 'grant_type' not in request.POST:
         raise HttpBadRequestException(error='invalid_request',
                                       error_description='No grant type specified')
     grant_type = request.POST['grant_type']
     scopes = None
     if 'scope' in request.POST:
         scopes = RoleList.get_roles_by_codes(request.POST['scope'].split(' '))
     if grant_type == 'password':
         # Resource Owner Password Credentials Grant
         if 'username' not in request.POST or 'password' not in request.POST:
             raise HttpBadRequestException(error='invalid_request',
                                           error_description='Invalid request')
         username = request.POST['username']
         password = request.POST['password']
         user = UserList.get_user_by_username(username)
         if user is None or user.password != hashlib.sha256(password).hexdigest():
             raise HttpBadRequestException(error='invalid_client',
                                           error_description='Invalid client')
         if user.is_active is False:
             raise HttpBadRequestException(error='inactive_user',
                                           error_description='User is inactive')
         clients = [client for client in user.clients if client.ovs_type == 'INTERNAL' and client.grant_type == 'PASSWORD']
         if len(clients) != 1:
             raise HttpBadRequestException(error='unauthorized_client',
                                           error_description='Client is unauthorized')
         client = clients[0]
         try:
             access_token, _ = OAuth2Toolbox.generate_tokens(client, generate_access=True, scopes=scopes)
             access_token.expiration = int(time.time() + 86400)
             access_token.save()
         except ValueError as error:
             if error.message == 'invalid_scope':
                 raise HttpBadRequestException(error='invalid_scope',
                                               error_description='Invalid scope requested')
             raise
         OAuth2Toolbox.clean_tokens(client)
         return HttpResponse(json.dumps({'access_token': access_token.access_token,
                                         'token_type': 'bearer',
                                         'expires_in': 86400}),
                             content_type='application/json')
     elif grant_type == 'client_credentials':
         # Client Credentials
         if 'HTTP_AUTHORIZATION' not in request.META:
             raise HttpBadRequestException(error='missing_header',
                                           error_description='Authorization header missing')
         _, password_hash = request.META['HTTP_AUTHORIZATION'].split(' ')
         client_id, client_secret = base64.b64decode(password_hash).split(':', 1)
         try:
             client = Client(client_id)
             if client.grant_type != 'CLIENT_CREDENTIALS':
                 raise HttpBadRequestException(error='invalid_grant',
                                               error_description='The given grant type is not supported')
             if client.client_secret != client_secret:
                 raise HttpBadRequestException(error='invalid_client',
                                               error_description='Invalid client')
             if not client.user.is_active:
                 raise HttpBadRequestException(error='inactive_user',
                                               error_description='User is inactive')
             try:
                 access_token, _ = OAuth2Toolbox.generate_tokens(client, generate_access=True, scopes=scopes)
             except ValueError as error:
                 if error.message == 'invalid_scope':
                     raise HttpBadRequestException(error='invalid_scope',
                                                   error_description='Invalid scope requested')
                 raise
             try:
                 OAuth2Toolbox.clean_tokens(client)
             except Exception as error:
                 logger.error('Error during session cleanup: {0}'.format(error))
             return HttpResponse(json.dumps({'access_token': access_token.access_token,
                                             'token_type': 'bearer',
                                             'expires_in': 3600}),
                                 content_type='application/json')
         except HttpBadRequestException:
             raise
         except ObjectNotFoundException as ex:
             logger.warning('Error matching client: {0}'.format(ex))
             raise HttpBadRequestException(error='invalid_client',
                                           error_description='Client could not be found')
         except Exception as ex:
             logger.exception('Error matching client: {0}'.format(ex))
             raise HttpBadRequestException(error='invalid_client',
                                           error_description='Error loading client')
     else:
         raise HttpBadRequestException(error='unsupported_grant_type',
                                       error_description='Unsupported grant type')