def query(self, endpoint, headers=None, params=None):
        try:
            response = requests.get(
                f"{self.url.rstrip('/')}/{endpoint.lstrip('/')}",
                headers={**self.headers, **(headers or {})},
                params={**self.params, **(params or {})},
            )
        except SSLError as error:
            # Go through a few layers of wrapped exceptions.
            error = error.args[0].reason.args[0]
            # Assume that a certificate could not be verified.
            assert isinstance(error, SSLCertVerificationError)
            reason = (
                getattr(error, 'verify_message', error.args[0]).capitalize()
            )
            raise SSLCertificateVerificationFailedError(reason=reason)
        except (InvalidHeader, UnicodeEncodeError):
            raise AuthenticationRequiredError(reason=AUTHORIZATION_FAILED)

        if response.status_code == HTTPStatus.BAD_REQUEST:
            return None

        if response.status_code == HTTPStatus.FORBIDDEN:
            raise AuthenticationRequiredError(reason=AUTHORIZATION_FAILED)

        if response.status_code == HTTPStatus.NOT_FOUND:
            return None

        if response.status_code != HTTPStatus.OK:
            response_reason_phrase = HTTPStatus(response.status_code).phrase
            reason = f'Reason: {response.status_code} {response_reason_phrase}'
            raise RelayError(reason=reason)

        return response.json()
def get_key():
    """
    Get authorization token and validate its signature against the public key
    from /.well-known/jwks endpoint
    """
    expected_errors = {
        KeyError: WRONG_PAYLOAD_STRUCTURE,
        AssertionError: JWK_HOST_MISSING,
        InvalidSignatureError: WRONG_KEY,
        DecodeError: WRONG_JWT_STRUCTURE,
        InvalidAudienceError: WRONG_AUDIENCE,
        TypeError: KID_NOT_FOUND
    }

    token = get_auth_token()
    try:
        jwks_host = jwt.decode(token, options={
            'verify_signature': False
        }).get('jwks_host')
        assert jwks_host
        key = get_public_key(jwks_host, token)
        aud = request.url_root
        payload = jwt.decode(token,
                             key=key,
                             algorithms=['RS256'],
                             audience=[aud.rstrip('/')])

        set_ctr_entities_limit(payload)
        current_app.config['GTI_ALLOW_TEST_ACCOUNTS'] = \
            payload['GTI_ALLOW_TEST_ACCOUNTS']

        return payload['key']
    except tuple(expected_errors) as error:
        message = expected_errors[error.__class__]
        raise AuthenticationRequiredError(message)
def get_auth_token():
    expected_errors = {KeyError: NO_HEADER, AssertionError: WRONG_TYPE}

    try:
        scheme, token = request.headers['Authorization'].split()
        assert scheme.lower() == 'bearer'
        return token
    except tuple(expected_errors) as error:
        raise AuthenticationRequiredError(expected_errors[error.__class__])
def get_public_key(jwks_host, token):
    expected_errors = (ConnectionError, InvalidURL, JSONDecodeError, HTTPError)
    try:
        response = requests.get(f"https://{jwks_host}/.well-known/jwks")
        response.raise_for_status()
        jwks = response.json()

        public_keys = {}
        for jwk in jwks['keys']:
            kid = jwk['kid']
            public_keys[kid] = jwt.algorithms.RSAAlgorithm.from_jwk(
                json.dumps(jwk))
        kid = jwt.get_unverified_header(token)['kid']
        return public_keys.get(kid)

    except expected_errors:
        raise AuthenticationRequiredError(WRONG_JWKS_HOST)
def get_public_key(jwks_host, token):
    expected_errors = {
        ConnectionError: WRONG_JWKS_HOST,
        InvalidURL: WRONG_JWKS_HOST,
        JSONDecodeError: WRONG_JWKS_HOST,
    }
    try:
        response = requests.get(f"https://{jwks_host}/.well-known/jwks")
        jwks = response.json()

        public_keys = {}
        for jwk in jwks['keys']:
            kid = jwk['kid']
            public_keys[kid] = jwt.algorithms.RSAAlgorithm.from_jwk(
                json.dumps(jwk))
        kid = jwt.get_unverified_header(token)['kid']
        return public_keys.get(kid)

    except tuple(expected_errors) as error:
        message = expected_errors[error.__class__]
        raise AuthenticationRequiredError(message)