コード例 #1
0
    def test_get_current_realm(self):
        request = RequestFactory().get('/')
        self.assertEqual(utils.get_current_realm(request),
                         settings.DEFAULT_REALM)

        meta_key = get_meta_http_name(settings.REALM_COOKIE)
        request.META[meta_key] = 'in-headers'
        self.assertEqual(utils.get_current_realm(request), 'in-headers')

        request.COOKIES[settings.REALM_COOKIE] = 'in-cookies'
        self.assertEqual(utils.get_current_realm(request), 'in-cookies')

        setattr(request, 'session', {})
        request.session[settings.REALM_COOKIE] = 'in-session'
        self.assertEqual(utils.get_current_realm(request), 'in-session')
コード例 #2
0
def post_authenticate(request):
    session_state = request.GET.get('session_state')
    code = request.GET.get('code')
    realm = get_current_realm(request, default_realm=None)

    if not session_state or not code or not realm:
        return

    redirect_uri = _get_login_url(request)
    token, userinfo = _authenticate(
        realm=realm,
        data={
            'grant_type': 'authorization_code',
            'client_id': settings.KEYCLOAK_CLIENT_ID,
            'client_session_state': session_state,
            'client_session_host': redirect_uri,
            'code': code,
            'redirect_uri': redirect_uri,
        })

    # save the user token in the session
    request.session[_KC_TOKEN_SESSION] = token
    request.session.modified = True

    return _get_or_create_user(request, userinfo)
コード例 #3
0
def unparse_username(request, username):
    # the internal username prepends the realm name
    realm = get_current_realm(request)

    if realm and username.startswith(f'{realm}__'):
        username = username[len(f'{realm}__'):]
    return username
コード例 #4
0
def parse_username(request, username):
    # the internal username prepends the realm name
    realm = get_current_realm(request)

    if realm and not username.startswith(f'{realm}__'):
        username = f'{realm}__{username}'
    return username
コード例 #5
0
def get_realm_auth_url(request):
    realm = get_current_realm(request, default_realm=None)
    redirect_uri = urllib.parse.quote(_get_login_url(request), safe='')

    return (
        f'{_KC_URL}/{realm}/{_KC_OID_URL}/auth?'
        f'&client_id={settings.KEYCLOAK_CLIENT_ID}'
        '&scope=openid'
        '&response_type=code'
        f'&redirect_uri={redirect_uri}'
    )
コード例 #6
0
    def add_to_realm(self, request):
        '''
        Adds the instance to the current realm.
        '''

        if not settings.MULTITENANCY:
            return

        # add instance to current realm
        realm = get_current_realm(request)
        try:
            self.mt.realm = realm
            self.mt.save()
        except ObjectDoesNotExist:
            MtInstance.objects.create(instance=self, realm=realm)
コード例 #7
0
def check_user_token(request):
    '''
    Checks if the user token is valid refreshing it in keycloak server.
    '''

    token = request.session.get(_KC_TOKEN_SESSION)
    realm = get_current_realm(request, default_realm=None)
    if token and realm:
        # refresh token
        response = refresh_kc_token(realm, token)
        try:
            response.raise_for_status()
            request.session[_KC_TOKEN_SESSION] = response.json()
            request.session.modified = True
        except Exception:
            logout(request)
コード例 #8
0
    def test_auth(self):
        realm_group = utils.get_auth_group(self.request)
        self.assertIsNotNone(realm_group)
        self.assertEqual(realm_group.name,
                         utils.get_current_realm(self.request))

        self.assertEqual(self.request.user.groups.count(), 0)
        # it does not complain if the user does not belong to the realm
        utils.remove_user_from_realm(self.request, self.request.user)

        utils.add_user_to_realm(self.request, self.request.user)
        self.assertEqual(self.request.user.groups.count(), 1)
        self.assertIn(realm_group, self.request.user.groups.all())
        utils.remove_user_from_realm(self.request, self.request.user)
        self.assertEqual(self.request.user.groups.count(), 0)
        self.assertNotIn(realm_group, self.request.user.groups.all())
コード例 #9
0
def get_or_create_user(request, username):
    # gets the existing user or creates a new one
    _username = parse_username(request, username)
    try:
        user = user_objects.get(username=_username)
    except UserModel.DoesNotExist:
        realm = get_current_realm(request)
        user = user_objects.create_user(
            username=_username,
            first_name=username,
            last_name=realm or '',
            password=user_objects.make_random_password(length=100),
        )
        # only add user if it doesn't exist.
        add_user_to_realm(request, user)

    return user
コード例 #10
0
def _user_logged_out(sender, user, request, **kwargs):
    '''
    Removes realm and token from session also logs out from keycloak server
    making the user token invalid.
    '''

    token = request.session.get(_KC_TOKEN_SESSION)
    realm = get_current_realm(request, default_realm=None)
    if token and realm:
        # logout
        exec_request(
            method='post',
            url=f'{_KC_URL}/{realm}/{_KC_OID_URL}/logout',
            data={
                'client_id': settings.KEYCLOAK_CLIENT_ID,
                'refresh_token': token['refresh_token'],
            },
        )
コード例 #11
0
def check_gateway_token(request):
    '''
    Checks if the gateway token is valid fetching the user info from keycloak server.
    '''

    token = find_in_request_headers(request, settings.GATEWAY_HEADER_TOKEN)
    realm = get_current_realm(request, default_realm=None)
    if token and realm:
        try:
            userinfo = _get_user_info(realm, token)

            # flags that we are using the gateway to authenticate
            request.session[settings.GATEWAY_HEADER_TOKEN] = True
            request.session[settings.REALM_COOKIE] = realm
            request.session.modified = True

            user = _get_or_create_user(request, userinfo)
            # only login if the user changed otherwise it will refresh the Csrf
            # token and make the AJAX calls fail.
            if not hasattr(request, 'user') or request.user.pk != user.pk:
                login(request, user)

                # WORKAROUND!!!
                # Using curl behind the gateway always returns CSRF errors due
                # to the missing CSRF Token in the request headers.
                # We are adding it manually to skip this issue but
                # only if it needs to login
                csrfCookie = request.META.get('CSRF_COOKIE')
                if not request.META.get(settings.CSRF_HEADER_NAME):
                    request.META[settings.CSRF_HEADER_NAME] = csrfCookie
                if not request.session.get(CSRF_SESSION_KEY):
                    request.session[CSRF_SESSION_KEY] = csrfCookie
            request.user = user

        except Exception:
            # something went wrong
            logout(request)

    elif request.session.get(settings.GATEWAY_HEADER_TOKEN):
        # this session was using the gateway to authenticate before
        logout(request)
コード例 #12
0
    def test_no_multitenancy(self, *args):
        self.assertIsNone(utils.get_multitenancy_model())
        self.assertIsNone(utils.get_current_realm(None))

        obj1 = TestModel.objects.create(name='two')
        self.assertFalse(obj1.is_accessible(TEST_REALM))
        self.assertFalse(obj1.is_accessible(settings.DEFAULT_REALM))
        self.assertIsNone(obj1.get_realm())
        self.assertTrue(MtInstance.objects.count() == 0)

        self.assertTrue(utils.is_accessible_by_realm(self.request, obj1))
        self.assertEqual(utils.add_instance_realm_in_headers(obj1, {}), {})
        self.assertEqual(utils.add_current_realm_in_headers(self.request, {}),
                         {})

        initial_data = TestModel.objects.all()
        self.assertEqual(utils.filter_by_realm(self.request, initial_data),
                         initial_data)

        initial_users = get_user_model().objects.all()
        self.assertEqual(
            utils.filter_users_by_realm(self.request, initial_users),
            initial_users)

        obj1.add_to_realm(self.request)
        self.assertTrue(MtInstance.objects.count() == 0)

        self.assertIsNone(utils.get_auth_group(self.request))
        self.assertEqual(self.request.user.groups.count(), 0)
        self.assertTrue(
            utils.check_user_in_realm(self.request, self.request.user))

        utils.add_user_to_realm(self.request, self.request.user)
        self.assertEqual(self.request.user.groups.count(), 0)
        self.assertTrue(
            utils.check_user_in_realm(self.request, self.request.user))

        utils.remove_user_from_realm(self.request, self.request.user)
        self.assertEqual(self.request.user.groups.count(), 0)
        self.assertTrue(
            utils.check_user_in_realm(self.request, self.request.user))

        self.client.logout()

        username = '******'
        email = '*****@*****.**'
        password = '******'
        user = get_user_model().objects.create_user(
            f'{TEST_REALM}__{username}', email, password)

        token_key = 'token-123456'
        Token.objects.create(user=user, key=token_key)

        token_headers = {'HTTP_AUTHORIZATION': f'Token {token_key}'}

        auth_str = f'{username}:{password}'
        basic = base64.b64encode(bytearray(auth_str, 'utf-8')).decode('ascii')
        basic_headers = {'HTTP_AUTHORIZATION': f'Basic {basic}'}

        auth_str = f'{TEST_REALM}__{username}:{password}'
        basic = base64.b64encode(bytearray(auth_str, 'utf-8')).decode('ascii')
        basic_realm_headers = {'HTTP_AUTHORIZATION': f'Basic {basic}'}

        url = reverse('http-200')
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
        self.assertEqual(
            response.json(),
            {'detail': 'Authentication credentials were not provided.'})

        response = self.client.get(url, **basic_headers)
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
        self.assertEqual(response.json(),
                         {'detail': 'Invalid username/password.'})

        response = self.client.get(url, **basic_realm_headers)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        response = self.client.get(url, **token_headers)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        username = '******'
        email = '*****@*****.**'
        password = '******'
        get_user_model().objects.create_superuser(username, email, password)
        self.assertTrue(self.client.login(username=username,
                                          password=password))

        response = self.client.get(reverse('get-realms'))
        self.assertEqual(response.json(),
                         {'realms': [settings.NO_MULTITENANCY_REALM]})
コード例 #13
0
 def authenticate_header(self, request):
     realm = get_current_realm(request) or self.www_authenticate_realm
     return f'Basic realm="{realm}"'