예제 #1
0
        def middleware(endpoint):

            logger.info('got new request to frontegg: method = %s, path = %s',
                        request.method, request.path)
            o = urlparse(request.base_url)
            response = self.proxy_request(request,
                                          method=request.method,
                                          path=request.path,
                                          host=o.hostname,
                                          params=request.args,
                                          body=request.data,
                                          cookies=request.cookies,
                                          headers=dict(request.headers))

            logger.info(
                'got response from frontegg: status_code = %s, path = %s, traceId = %s',
                response.status_code, request.path,
                response.headers.get('frontegg-trace-id'))

            flask_response = make_response(response.content,
                                           response.status_code,
                                           response.headers)

            for cookieKey in response.cookies.keys():
                flask_response.headers.add_header(
                    'set-cookie',
                    response.cookies.get(cookieKey).OutputString())

            return flask_response
예제 #2
0
def authentication_middleware(request: Request):
    try:
        __frontegg.frontegg.decode_jwt(request.headers.get('Authorization'))
        logger.info('JWT token verified')
        return None
    except Exception as e:
        logger.debug('could not verify JWT token, ' + str(e), )
    raise UnauthenticatedException()
예제 #3
0
def context_provider(request: Request):
    try:
        user = __frontegg.frontegg.decode_jwt(
            request.headers.get('Authorization'))
        logger.info('decoded entity')
        return FronteggContext(user.get('sub'), user.get('tenantId'))
    except:
        return FronteggContext('user-id', 'tenant-id')
예제 #4
0
def context_provider(request: Request):
    try:
        user = __frontegg.frontegg.decode_jwt(
            request.headers.get('Authorization'))
        logger.debug('get user from JWT' + str(user))
        return FronteggContext(user.get('sub'), user.get('tenantId'))
    except Exception as e:
        logger.debug('could not get user from JWT, ' + str(e))
        logger.info('will send default tenant-id and user-id')
        return FronteggContext('user-id', 'tenant-id')
예제 #5
0
 def decode_jwt(self, authorization_header, verify: typing.Optional[bool] = True):
     if not authorization_header:
         raise InvalidTokenError('Authorization headers is missing')
     logger.debug('found authorization header: ' +
                  str(authorization_header))
     jwt_token = authorization_header.replace('Bearer ', '')
     public_key = self.get_public_key()
     logger.debug('got public key' + str(public_key))
     decoded = self.__get_jwt_data(jwt_token, verify, public_key)
     logger.info('jwt was decoded successfully')
     logger.debug('JWT value - ' + str(decoded))
     return decoded
예제 #6
0
        def decorated_function(*args, **kwargs):
            # Initially
            valid_permissions = True
            valid_roles = True
            try:
                decoded = __frontegg.frontegg.decode_jwt(request.headers.get('Authorization'))
                g.user = decoded
                # Validate roles
                if role_keys is not None:
                    logger.info('will check if entity has one of required roles')
                    valid_roles = any(
                        role in decoded['roles'] for role in role_keys)

                if permission_keys is not None:
                    logger.info('will check if entity has one of required permissions')
                    valid_permissions = any(
                        permission in decoded['permissions'] for permission in permission_keys)

            except Exception as e:
                logger.debug('something went wrong while validating roles and permissions, ' + str(e))
                abort(401)

            if not valid_permissions or not valid_roles:
                logger.info('entity does not have required role and permissions')
                abort(403)
                return

            logger.info('entity passed authentication middleware')

            return f(*args, **kwargs)
예제 #7
0
    def get_public_key(self) -> str:
        if self.__publicKey:
            return self.__publicKey

        logger.info('could not find public key locally, will fetch public key')
        reties = 0
        while reties < 10:
            try:
                self.__publicKey = self.fetch_public_key()
                return self.__publicKey
            except Exception as e:
                reties = reties + 1
                logger.error(
                    'could not get public key from frontegg, retry number - ' + str(reties) + ', ' + str(e))

        logger.error('failed to get public key in all retries')
예제 #8
0
 def func_with_retries(*args, **kwargs):
     _tries = 0
     while _tries < total_tries:
         try:
             return f(*args, **kwargs)
         except Exception as e:
             if _tries == 0:
                 logger.info((action or f'function "{f.__name__}"') +
                             f' failed on first try, {e}')
             if +_tries >= total_tries - 1:
                 logger.info(
                     (action or f'function "{f.__name__}"') +
                     f' failed on the last retry attempt ({total_tries}), {e}'
                 )
                 raise e
             _tries += 1
             if retry_delay > 0:
                 sleep(retry_delay)
예제 #9
0
        def middleware(endpoint):

            logger.info('got new request to frontegg: method = %s, path = %s',
                        request.method, request.path)
            o = urlparse(request.base_url)
            response = self.proxy_request(request,
                                          method=request.method,
                                          path=request.path,
                                          host=o.hostname,
                                          params=request.args,
                                          body=request.data,
                                          cookies=request.cookies,
                                          headers=dict(request.headers))

            logger.info(
                'got response from frontegg: status_code = %s, path = %s',
                response.status_code, request.path)

            return make_response(response.content, response.status_code,
                                 response.headers)
    def refresh_vendor_token(self) -> None:
        body = {'clientId': self.client_id, 'secret': self.api_key}
        logger.info('will refresh vendor token')
        auth_url = frontegg_urls.authentication_service['authenticate_vendor']

        auth_response = self.vendor_session_request.post(auth_url, json=body)
        auth_response.raise_for_status()
        logger.info('got new vendor token from frontegg')
        response_body = auth_response.json()
        self.__access_token = response_body['token']
        self.__access_token_expiration = arrow.utcnow().shift(
            seconds=response_body['expiresIn'] * 0.8)

        self.vendor_session_request.headers.update(
            {'x-access-token': self.__access_token})

        logger.info('new vendor token was set successfully')
예제 #11
0
    def proxy_request(self, request, method: str, path: str, host: str, params: dict,
                      body: typing.Optional[any], cookies: typing.Optional[dict] = None,
                      headers: typing.Optional[dict] = {}):
        if not request:
            raise Exception('request is required')

        if not method:
            raise Exception('method is required')

        if not path:
            raise Exception('path is required')

        path_without_frontegg = path.replace(
            '/' + self.middleware_prefix, '', 1).replace(self.middleware_prefix, '', 1)

        logger.info('removed path prefix before sending to frontegg, new path - %s', path_without_frontegg)

        public_route = self.is_public_route(
            path_without_frontegg, params, method)

        logger.info('route is %s public route', '' if public_route else 'not')

        if self.authentication_middleware is not None and not public_route:
            try:
                logger.info('will validate user authentication')
                self.authentication_middleware(request)
            except HttpException as response:
                logger.info('failed to authorize entity')
                return response
            except Exception as e:
                logger.info('something went wrong, could not run authentication middleware')
                logger.debug('auth middleware error - %s', str(e))
                return HttpException('Something went wrong', 500)

        url = urljoin(frontegg_urls.base_url, path_without_frontegg)
        headers = self.clean_request_headers(headers, host)
        headers = self.set_context(headers, request)
        logger.info('adjusted headers before proxying request to frontegg')
        logger.debug('new headers - %s', str(headers))

        if self.should_refresh_vendor_token:
            logger.info('refresh vendor token is required, will refresh token')
            self.refresh_vendor_token()

        logger.info('will proxy request to frontegg')
        logger.debug('request data: method=%s, url=%s,cookies=%s, body=%s, params=%s, headers=%s', method, url,
                     str(cookies), str(body), str(params), str(headers))
        response = self.vendor_session_request.request(
            method,
            url,
            headers=headers,
            cookies=cookies,
            data=body,
            params=params
        )

        logger.info('got response from frontegg')

        response.headers = self.clean_response_headers(response.headers)
        response.cookies = self.get_cookies(response.headers)
        return response