예제 #1
0
    def create_refresh_response_dic(self):
        # See https://tools.ietf.org/html/rfc6749#section-6

        scope_param = self.params['scope']
        scope = (scope_param.split(' ')
                 if scope_param else self.refresh_token.scope)
        unauthorized_scopes = set(scope) - set(self.refresh_token.scope)
        if unauthorized_scopes:
            raise TokenError('invalid_scope')

        # update refresh token scope
        self.refresh_token.scope = scope
        self.refresh_token.save()

        token = create_token_with_refresh_token(
            refresh_token=self.refresh_token, )

        # All refresh token grants are authentication flows.
        id_token_dic = create_id_token(
            user=self.refresh_token.user,
            aud=self.client.client_id,
            token=token,
            nonce=None,
            at_hash=token.at_hash,
            request=self.request,
            scope=token.scope,
        )
        token.id_token = id_token_dic

        # Store the token.
        token.save()

        dic = {
            'access_token': token.access_token,
            'refresh_token': token.refresh_token.refresh_token,
            'token_type': 'bearer',
            'expires_in': settings.get('OIDC_TOKEN_EXPIRE'),
            'id_token': encode_id_token(id_token_dic, token.client),
        }

        return dic
예제 #2
0
    def create_code_response_dic(self):
        # See https://tools.ietf.org/html/rfc6749#section-4.1

        refresh_token = create_refresh_token(
            user=self.code.user,
            client=self.code.client,
            scope=self.code.scope,
        )
        refresh_token.save()

        token = create_token_with_refresh_token(refresh_token=refresh_token, )

        if self.code.is_authentication:
            id_token_dic = create_id_token(
                user=self.code.user,
                aud=self.client.client_id,
                token=token,
                nonce=self.code.nonce,
                at_hash=token.at_hash,
                request=self.request,
                scope=token.scope,
            )
        else:
            id_token_dic = {}
        token.id_token = id_token_dic

        # Store the token.
        token.save()

        # We don't need to store the code anymore.
        self.code.delete()

        dic = {
            'access_token': token.access_token,
            'refresh_token': token.refresh_token.refresh_token,
            'token_type': 'bearer',
            'expires_in': settings.get('OIDC_TOKEN_EXPIRE'),
            'id_token': encode_id_token(id_token_dic, token.client),
        }

        return dic
예제 #3
0
    def test_redirects_when_aud_is_str(self):
        query_params = {
            'post_logout_redirect_uri': self.LOGOUT_URL,
        }
        response = self.client.get(self.url, query_params)
        # With no id_token the OP MUST NOT redirect to the requested
        # redirect_uri.
        self.assertRedirects(
            response, settings.get('OIDC_LOGIN_URL'),
            fetch_redirect_response=False)

        token = create_token(self.user, self.oidc_client, [])
        id_token_dic = create_id_token(
            token=token, user=self.user, aud=self.oidc_client.client_id)
        id_token = encode_id_token(id_token_dic, self.oidc_client)

        query_params['id_token_hint'] = id_token

        response = self.client.get(self.url, query_params)
        self.assertRedirects(
            response, self.LOGOUT_URL, fetch_redirect_response=False)
    def _create_token(self, extra_scope=[]):
        """
        Generate a valid token.
        """
        scope = ['openid', 'email'] + extra_scope

        id_token_dic = create_id_token(
            user=self.user,
            aud=self.client.client_id,
            nonce=FAKE_NONCE,
            scope=scope,
        )

        token = create_token(
            user=self.user,
            client=self.client,
            id_token_dic=id_token_dic,
            scope=scope)
        token.save()

        return token
    def _create_token(self, extra_scope=None):
        """
        Generate a valid token.
        """
        if extra_scope is None:
            extra_scope = []
        scope = ['openid', 'email'] + extra_scope

        token = create_token(user=self.user, client=self.client, scope=scope)

        id_token_dic = create_id_token(
            token=token,
            user=self.user,
            aud=self.client.client_id,
            nonce=FAKE_NONCE,
            scope=scope,
        )

        token.id_token = id_token_dic
        token.save()

        return token
예제 #6
0
 def test_create_id_token(self):
     start_time = int(time.time())
     login_timestamp = start_time - 1234
     self.user.last_login = timestamp_to_datetime(login_timestamp)
     client = create_fake_client("code")
     token = create_token(self.user, client, [])
     id_token_data = create_id_token(token=token,
                                     user=self.user,
                                     aud='test-aud')
     iat = id_token_data['iat']
     self.assertEqual(type(iat), int)
     self.assertGreaterEqual(iat, start_time)
     self.assertLessEqual(iat - start_time, 5)  # Can't take more than 5 s
     self.assertEqual(
         id_token_data, {
             'aud': 'test-aud',
             'auth_time': login_timestamp,
             'exp': iat + 600,
             'iat': iat,
             'iss': 'http://localhost:8000/openid',
             'sub': str(self.user.id),
         })
    def create_response_uri(self):
        uri = urlsplit(self.params['redirect_uri'])
        query_params = parse_qs(uri.query)
        query_fragment = {}

        try:
            if self.grant_type in ['authorization_code', 'hybrid']:
                code = create_code(
                    user=self.request.user,
                    client=self.client,
                    scope=self.params['scope'],
                    nonce=self.params['nonce'],
                    is_authentication=self.is_authentication,
                    code_challenge=self.params['code_challenge'],
                    code_challenge_method=self.params['code_challenge_method'])
                code.save()

            if self.grant_type == 'authorization_code':
                query_params['code'] = code.code
                query_params['state'] = self.params['state'] if self.params[
                    'state'] else ''
            elif self.grant_type in ['implicit', 'hybrid']:
                token = create_token(user=self.request.user,
                                     client=self.client,
                                     scope=self.params['scope'])

                # Check if response_type must include access_token in the response.
                if (self.params['response_type'] in [
                        'id_token token', 'token', 'code token',
                        'code id_token token'
                ]):
                    query_fragment['access_token'] = token.access_token

                # We don't need id_token if it's an OAuth2 request.
                if self.is_authentication:
                    kwargs = {
                        'token': token,
                        'user': self.request.user,
                        'aud': self.client.client_id,
                        'nonce': self.params['nonce'],
                        'request': self.request,
                        'scope': self.params['scope'],
                    }
                    # Include at_hash when access_token is being returned.
                    if 'access_token' in query_fragment:
                        kwargs['at_hash'] = token.at_hash
                    id_token_dic = create_id_token(**kwargs)

                    # Check if response_type must include id_token in the response.
                    if self.params['response_type'] in [
                            'id_token', 'id_token token', 'code id_token',
                            'code id_token token'
                    ]:
                        query_fragment['id_token'] = encode_id_token(
                            id_token_dic, self.client)
                else:
                    id_token_dic = {}

                # Store the token.
                token.id_token = id_token_dic
                token.save()

                # Code parameter must be present if it's Hybrid Flow.
                if self.grant_type == 'hybrid':
                    query_fragment['code'] = code.code

                query_fragment['token_type'] = 'bearer'

                query_fragment['expires_in'] = settings.get(
                    'OIDC_TOKEN_EXPIRE')

                query_fragment['state'] = self.params['state'] if self.params[
                    'state'] else ''

            if settings.get('OIDC_SESSION_MANAGEMENT_ENABLE'):
                # Generate client origin URI from the redirect_uri param.
                redirect_uri_parsed = urlsplit(self.params['redirect_uri'])
                client_origin = '{0}://{1}'.format(redirect_uri_parsed.scheme,
                                                   redirect_uri_parsed.netloc)

                # Create random salt.
                salt = md5(uuid4().hex.encode()).hexdigest()

                # The generation of suitable Session State values is based
                # on a salted cryptographic hash of Client ID, origin URL,
                # and OP browser state.
                session_state = '{client_id} {origin} {browser_state} {salt}'.format(
                    client_id=self.client.client_id,
                    origin=client_origin,
                    browser_state=get_browser_state_or_default(self.request),
                    salt=salt)
                session_state = sha256(
                    session_state.encode('utf-8')).hexdigest()
                session_state += '.' + salt
                if self.grant_type == 'authorization_code':
                    query_params['session_state'] = session_state
                elif self.grant_type in ['implicit', 'hybrid']:
                    query_fragment['session_state'] = session_state

        except Exception as error:
            logger.exception(
                '[Authorize] Error when trying to create response uri: %s',
                error)
            raise AuthorizeError(self.params['redirect_uri'], 'server_error',
                                 self.grant_type)

        uri = uri._replace(query=urlencode(query_params, doseq=True),
                           fragment=uri.fragment +
                           urlencode(query_fragment, doseq=True))

        return urlunsplit(uri)
예제 #8
0
    def create_response_uri(self):
        uri = urlsplit(self.params.redirect_uri)
        query_params = parse_qs(uri.query)
        query_fragment = parse_qs(uri.fragment)

        try:
            if self.grant_type == 'authorization_code':
                code = create_code(
                    user=self.request.user,
                    client=self.client,
                    scope=self.params.scope,
                    nonce=self.params.nonce,
                    is_authentication=self.is_authentication,
                    code_challenge=self.params.code_challenge,
                    code_challenge_method=self.params.code_challenge_method)

                code.save()

                query_params['code'] = code.code
                query_params['state'] = self.params.state if self.params.state else ''

            elif self.grant_type == 'implicit':
                token = create_token(
                    user=self.request.user,
                    client=self.client,
                    scope=self.params.scope)

                # Check if response_type is an OpenID request with value 'id_token token'
                # or it's an OAuth2 Implicit Flow request.
                if self.params.response_type in ['id_token token', 'token']:
                    query_fragment['access_token'] = token.access_token

                # We don't need id_token if it's an OAuth2 request.
                if self.is_authentication:
                    kwargs = {
                        "user": self.request.user,
                        "aud": self.client.client_id,
                        "nonce": self.params.nonce,
                        "request": self.request
                    }
                    # Include at_hash when access_token is being returned.
                    if 'access_token' in query_fragment:
                        kwargs['at_hash'] = token.at_hash
                    id_token_dic = create_id_token(**kwargs)
                    query_fragment['id_token'] = encode_id_token(id_token_dic, self.client)
                    token.id_token = id_token_dic
                else:
                    id_token_dic = {}

                # Store the token.
                token.id_token = id_token_dic
                token.save()

                query_fragment['token_type'] = 'bearer'
                # TODO: Create setting 'OIDC_TOKEN_EXPIRE'.
                query_fragment['expires_in'] = 60 * 10

                query_fragment['state'] = self.params.state if self.params.state else ''

        except Exception as error:
            logger.debug('[Authorize] Error when trying to create response uri: %s', error)
            raise AuthorizeError(
                self.params.redirect_uri,
                'server_error',
                self.grant_type)

        uri = uri._replace(query=urlencode(query_params, doseq=True))
        uri = uri._replace(fragment=urlencode(query_fragment, doseq=True))

        return urlunsplit(uri)
예제 #9
0
    def create_response_uri(self):
        uri = urlsplit(self.params['redirect_uri'])
        query_params = parse_qs(uri.query)
        query_fragment = parse_qs(uri.fragment)

        try:
            if self.grant_type in ['authorization_code', 'hybrid']:
                code = create_code(
                    user=self.request.user,
                    client=self.client,
                    scope=self.params['scope'],
                    nonce=self.params['nonce'],
                    is_authentication=self.is_authentication,
                    code_challenge=self.params['code_challenge'],
                    code_challenge_method=self.params['code_challenge_method'])
                code.save()

            if self.grant_type == 'authorization_code':
                query_params['code'] = code.code
                query_params['state'] = self.params['state'] if self.params['state'] else ''
            elif self.grant_type in ['implicit', 'hybrid']:
                token = create_token(
                    user=self.request.user,
                    client=self.client,
                    scope=self.params['scope'])

                # Check if response_type must include access_token in the response.
                if self.params['response_type'] in ['id_token token', 'token', 'code token', 'code id_token token']:
                    query_fragment['access_token'] = token.access_token

                # We don't need id_token if it's an OAuth2 request.
                if self.is_authentication:
                    kwargs = {
                        'user': self.request.user,
                        'aud': self.client.client_id,
                        'nonce': self.params['nonce'],
                        'request': self.request,
                        'scope': self.params['scope'],
                    }
                    # Include at_hash when access_token is being returned.
                    if 'access_token' in query_fragment:
                        kwargs['at_hash'] = token.at_hash
                    id_token_dic = create_id_token(**kwargs)

                    # Check if response_type must include id_token in the response.
                    if self.params['response_type'] in ['id_token', 'id_token token', 'code id_token', 'code id_token token']:
                        query_fragment['id_token'] = encode_id_token(id_token_dic, self.client)
                else:
                    id_token_dic = {}

                # Store the token.
                token.id_token = id_token_dic
                token.save()

                # Code parameter must be present if it's Hybrid Flow.
                if self.grant_type == 'hybrid':
                    query_fragment['code'] = code.code

                query_fragment['token_type'] = 'bearer'

                query_fragment['expires_in'] = settings.get('OIDC_TOKEN_EXPIRE')

                query_fragment['state'] = self.params['state'] if self.params['state'] else ''

        except Exception as error:
            logger.debug('[Authorize] Error when trying to create response uri: %s', error)
            raise AuthorizeError(self.params['redirect_uri'], 'server_error', self.grant_type)

        uri = uri._replace(query=urlencode(query_params, doseq=True))
        uri = uri._replace(fragment=urlencode(query_fragment, doseq=True))

        return urlunsplit(uri)