Example #1
0
def get_credentials():
    expected_errors = {
        KeyError: WRONG_PAYLOAD_STRUCTURE,
        AssertionError: JWKS_HOST_MISSING,
        InvalidSignatureError: WRONG_KEY,
        DecodeError: WRONG_JWT_STRUCTURE,
        MissingRequiredClaimError: WRONG_PAYLOAD_STRUCTURE,
        InvalidAudienceError: WRONG_AUDIENCE,
        PyJWKClientError: KID_NOT_FOUND,
        URLError: WRONG_JWKS_HOST,
        HTTPError: WRONG_JWKS_HOST
    }

    try:
        token = get_auth_token()
        jwks_host = jwt.decode(token, options={
            'verify_signature': False
        }).get('jwks_host')
        assert jwks_host

        jwks_client = PyJWKClient(f'https://{jwks_host}/.well-known/jwks')
        signing_key = jwks_client.get_signing_key_from_jwt(token)

        aud = request.url_root
        payload = jwt.decode(token,
                             signing_key.key,
                             algorithms=['RS256'],
                             audience=[aud.rstrip('/')])
        current_app.config['SERVER_IP'] = payload['SERVER_IP']

        set_ctr_entities_limit(payload)
        return payload['user'], payload['pass']
    except tuple(expected_errors) as error:
        raise AuthorizationError(expected_errors[error.__class__])
Example #2
0
    def __init__(
        self,
        algorithm,
        signing_key=None,
        verifying_key="",
        audience=None,
        issuer=None,
        jwk_url: str = None,
        leeway: Union[float, int, timedelta] = None,
        json_encoder: Optional[Type[json.JSONEncoder]] = None,
    ):
        self._validate_algorithm(algorithm)

        self.algorithm = algorithm
        self.signing_key = signing_key
        self.verifying_key = verifying_key
        self.audience = audience
        self.issuer = issuer

        if JWK_CLIENT_AVAILABLE:
            self.jwks_client = PyJWKClient(jwk_url) if jwk_url else None
        else:
            self.jwks_client = None

        self.leeway = leeway
        self.json_encoder = json_encoder
def validated_token(token, verify=True):
    """Validate a token and return decoded token."""
    url = (
        requests.get(
            config.oauth.google_openid_config_uri(default=DEFAULT_GOOGLE_OPENID_CFG_URI)
        )
        .json()
        .get(
            config.oauth.google_openid_jkws_key(
                default=DEFAULT_GOOGLE_OPENID_CFG_JWKS_KEY
            )
        )
    )
    logger.info("JWK url is %s", url)
    jwks_client = PyJWKClient(url)
    signing_key = jwks_client.get_signing_key_from_jwt(token)

    data = jwt.decode(
        token,
        signing_key.key,
        algorithms=["RS256"],
        audience=config.oauth.audience(default=DEFAULT_AUDIENCE, cast=split_list),
        options={"verify_signature": verify},
    )

    return data
def verify_id_token(id_token: str, bundle_id=None) -> dict:

    if bundle_id is None:
        bundle_id = APPLE_SIGN_IN_AUD[0]
    if bundle_id not in APPLE_SIGN_IN_AUD:
        raise falcon.HTTPForbidden(description="Not allow bundle id.")

    jwt_header = jwt.get_unverified_header(id_token)

    # get kid to select public key
    kid = jwt_header.get("kid", None)
    if kid is None:
        raise falcon.HTTPUnauthorized(
            description=
            "Not found kid from your id_token, check your token is by apple sign in."
        )

    jwks_client = PyJWKClient(APPLE_AUTH_KEYS_URL)
    signing_key = jwks_client.get_signing_key_from_jwt(id_token)

    jwt_decode = jwt.decode(
        id_token,
        signing_key.key,
        algorithms=["RS256"],
        audience=bundle_id,
        options={"verify_exp": False},
    )
    return jwt_decode
Example #5
0
    def test_get_jwk_set(self, mocked_response):
        url = "https://dev-87evx9ru.auth0.com/.well-known/jwks.json"

        with requests_mock.mock() as m:
            m.get(url, json=mocked_response)
            jwks_client = PyJWKClient(url)
            jwk_set = jwks_client.get_jwk_set()

        assert len(jwk_set.keys) == 1
Example #6
0
    def test_get_signing_keys(self, mocked_response):
        url = "https://dev-87evx9ru.auth0.com/.well-known/jwks.json"

        with requests_mock.mock() as m:
            m.get(url, json=mocked_response)
            jwks_client = PyJWKClient(url)
            signing_keys = jwks_client.get_signing_keys()

        assert len(signing_keys) == 1
        assert isinstance(signing_keys[0], PyJWK)
Example #7
0
    async def test_full_flow(self) -> None:
        key = await random_key()
        uuid_identifier = uuid4()

        # Register a new key
        # This is done using direct json since KeyRequest.dump doesn't dump key (on purpose)
        request = RegisterKeyRequest(key, uuid4())
        response = await self.client.post(
            "/register_key",
            json=self.register_key_request_schema.dump(request))
        assert response.status == HTTPStatus.CREATED

        # Check that the key was registered
        request2 = KeyRequest(key)
        response = await self.client.post(
            "/is_key_registered", json=self.key_request_schema.dump(request2))
        assert response.status == HTTPStatus.OK

        # Authenticate and get access + refres tokens
        request = self.auth_request_schema.dump(
            AuthRequest(key=key, identifier=uuid_identifier))
        response = await self.client.post("/authenticate", json=request)
        assert response.status == HTTPStatus.OK
        response_json = await response.json()

        # Check access token is valid
        request = self.jwt_validate_request_schema.dump(
            JWTValidateRequest(jwt=response_json["jwt"]))
        response = await self.client.post("/validate", json=request)
        assert response.status == HTTPStatus.OK

        # Use refresh token to create a new access token
        request = self.refresh_request_schema.dump(
            RefreshRequest(refresh_token=response_json["refresh_token"],
                           identifier=uuid_identifier))
        response = await self.client.post("/refresh", json=request)
        assert response.status == HTTPStatus.OK
        response_json = await response.json()

        # Check that new access token is also valid
        token = response_json["jwt"]
        request = self.jwt_validate_request_schema.dump(
            JWTValidateRequest(jwt=token))
        response = await self.client.post("/validate", json=request)
        assert response.status == HTTPStatus.OK

        # Test JWKS
        response = await self.client.get("/jwks")
        assert response.status == HTTPStatus.OK
        response_json = await response.json()
        jwks_client = PyJWKClient("")
        jwks_client.fetch_data = MagicMock(
            return_value=response_json)  # type: ignore
        assert jwks_client.get_signing_key_from_jwt(token)
Example #8
0
 def _get_public_key(self):
     if self.header["alg"][:2] == "RS":
         try:
             wk_res = requests.get(self.payload["iss"] +
                                   "/.well-known/openid-configuration",
                                   verify=False)
             jwks_uri = wk_res.json()["jwks_uri"]
             jwks_client = PyJWKClient(jwks_uri)
             return jwks_client.get_signing_key_from_jwt(
                 self.encoded).key.public_bytes(
                     encoding=serialization.Encoding.PEM,
                     format=serialization.PublicFormat.SubjectPublicKeyInfo)
         except Exception as ex:
             self.errors.append("Error getting public Key: {0}".format(
                 str(ex)))
     return None
Example #9
0
                        async def query_jwks():
                            #dump('NO CACHE, TRY CONSUMER: ' + consumer_name)

                            # Get default or overridden jwks_url
                            jwks_url = consumer.jwks_url or default_jwks_url
                            self.log.debug(
                                'Verifying JWT via JWKS URL {}'.format(
                                    jwks_url))

                            # Get signing_key from jwks
                            jwks_client = PyJWKClient(jwks_url)
                            signing_key = jwks_client.get_signing_key_from_jwt(
                                token)
                            return Dict(
                                decode(jwt=token,
                                       key=signing_key.key,
                                       audience=consumer.aud,
                                       algorithms=consumer.algorithms))
Example #10
0
def validate_id_token(identity_token):
    identity_token = base64.b64decode(identity_token)
    jwk_client = PyJWKClient('https://appleid.apple.com/auth/keys')
    signing_key = jwk_client.get_signing_key_from_jwt(identity_token)

    try:
        data = jwt.decode(identity_token,
                          signing_key.key,
                          algorithms=['RS256'],
                          audience=os.environ['BUNDLE_ID'],
                          issuer='https://appleid.apple.com',
                          options={
                              'verify_aud': True,
                              'verify_exp': True,
                              'verify_iss': True
                          })
    except exceptions.InvalidTokenError as error:
        return False

    return True
    def __init__(
        self,
        algorithm,
        signing_key=None,
        verifying_key="",
        audience=None,
        issuer=None,
        jwk_url: str = None,
        leeway=0,
    ):
        self._validate_algorithm(algorithm)

        self.algorithm = algorithm
        self.signing_key = signing_key
        self.verifying_key = verifying_key
        self.audience = audience
        self.issuer = issuer

        if JWK_CLIENT_AVAILABLE:
            self.jwks_client = PyJWKClient(jwk_url) if jwk_url else None
        else:
            self.jwks_client = None
        self.leeway = leeway
Example #12
0
    def __init__(
        self,
        algorithm,
        signing_key=None,
        verifying_key=None,
        audience=None,
        issuer=None,
        jwk_url: str = None,
        leeway=0,
    ):
        self._validate_algorithm(algorithm)

        self.algorithm = algorithm
        self.signing_key = signing_key
        self.audience = audience
        self.issuer = issuer

        self.jwks_client = PyJWKClient(jwk_url) if jwk_url else None
        self.leeway = leeway

        if algorithm.startswith("HS"):
            self.verifying_key = signing_key
        else:
            self.verifying_key = verifying_key
Example #13
0
    def test_get_signing_key_caches_result(self):
        url = "https://dev-87evx9ru.auth0.com/.well-known/jwks.json"
        kid = "NEE1QURBOTM4MzI5RkFDNTYxOTU1MDg2ODgwQ0UzMTk1QjYyRkRFQw"

        jwks_client = PyJWKClient(url)

        with mocked_response(RESPONSE_DATA):
            jwks_client.get_signing_key(kid)

        # mocked_response does not allow urllib.request.urlopen to be called twice
        # so a second mock is needed
        with mocked_response(RESPONSE_DATA) as repeated_call:
            jwks_client.get_signing_key(kid)

        assert repeated_call.call_count == 0
class TokenBackend:
    def __init__(
        self,
        algorithm,
        signing_key=None,
        verifying_key="",
        audience=None,
        issuer=None,
        jwk_url: str = None,
        leeway: Union[float, int, timedelta] = None,
    ):
        self._validate_algorithm(algorithm)

        self.algorithm = algorithm
        self.signing_key = signing_key
        self.verifying_key = verifying_key
        self.audience = audience
        self.issuer = issuer

        if JWK_CLIENT_AVAILABLE:
            self.jwks_client = PyJWKClient(jwk_url) if jwk_url else None
        else:
            self.jwks_client = None

        self.leeway = leeway

    def _validate_algorithm(self, algorithm):
        """
        Ensure that the nominated algorithm is recognized, and that cryptography is installed for those
        algorithms that require it
        """
        if algorithm not in ALLOWED_ALGORITHMS:
            raise TokenBackendError(
                format_lazy(_("Unrecognized algorithm type '{}'"), algorithm))

        if algorithm in algorithms.requires_cryptography and not algorithms.has_crypto:
            raise TokenBackendError(
                format_lazy(
                    _("You must have cryptography installed to use {}."),
                    algorithm))

    def get_leeway(self) -> timedelta:
        if self.leeway is None:
            return timedelta(seconds=0)
        elif isinstance(self.leeway, (int, float)):
            return timedelta(seconds=self.leeway)
        elif isinstance(self.leeway, timedelta):
            return self.leeway
        else:
            raise TokenBackendError(
                format_lazy(
                    _("Unrecognized type '{}', 'leeway' must be of type int, float or timedelta."
                      ),
                    type(self.leeway),
                ))

    def get_verifying_key(self, token):
        if self.algorithm.startswith("HS"):
            return self.signing_key

        if self.jwks_client:
            return self.jwks_client.get_signing_key_from_jwt(token).key

        return self.verifying_key

    def encode(self, payload):
        """
        Returns an encoded token for the given payload dictionary.
        """
        jwt_payload = payload.copy()
        if self.audience is not None:
            jwt_payload["aud"] = self.audience
        if self.issuer is not None:
            jwt_payload["iss"] = self.issuer

        token = jwt.encode(jwt_payload,
                           self.signing_key,
                           algorithm=self.algorithm)
        if isinstance(token, bytes):
            # For PyJWT <= 1.7.1
            return token.decode("utf-8")
        # For PyJWT >= 2.0.0a1
        return token

    def decode(self, token, verify=True):
        """
        Performs a validation of the given token and returns its payload
        dictionary.

        Raises a `TokenBackendError` if the token is malformed, if its
        signature check fails, or if its 'exp' claim indicates it has expired.
        """
        try:
            return jwt.decode(
                token,
                self.get_verifying_key(token),
                algorithms=[self.algorithm],
                audience=self.audience,
                issuer=self.issuer,
                leeway=self.get_leeway(),
                options={
                    "verify_aud": self.audience is not None,
                    "verify_signature": verify,
                },
            )
        except InvalidAlgorithmError as ex:
            raise TokenBackendError(_("Invalid algorithm specified")) from ex
        except InvalidTokenError:
            raise TokenBackendError(_("Token is invalid or expired"))
Example #15
0
import os
import logging
import jwt
from jwt import PyJWKClient

try:
    region = os.environ["AWS_REGION"]
    userPoolId = os.environ["USER_POOL_ID"]
    url = (
        f"https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json"
    )
    app_client = os.environ["APP_CLIENT_ID"]

    # fetching jwks
    jwks_client = PyJWKClient(url)
except Exception as e:
    logging.error(e)
    raise ("Unable to download JWKS")


def return_response(isAuthorized, other_params={}):
    return {"isAuthorized": isAuthorized, "context": other_params}


def lambda_handler(event, context):

    try:
        # fetching access token from event
        token = event["headers"]["authorization"]
    def verify_jwt_using_jwks(self, token, jwks_url, audience):
        jwks_client = PyJWKClient(jwks_url)
        signing_key = jwks_client.get_signing_key_from_jwt(token)
        secret = signing_key.key

        return self.verify_jwt_using_secret(token, secret, audience)
Example #17
0
import os
import json
import time
import jwt
from jwt import PyJWKClient
from jwt.exceptions import DecodeError, ExpiredSignatureError, InvalidTokenError

region = os.environ['AWS_REGION']
user_pool_id = os.environ['USER_POOL_ID']
app_client_id = os.environ['APP_CLIENT_ID']

cognito_keys_url = "https://cognito-idp.{}.amazonaws.com/{}/.well-known/jwks.json".format(
    region, user_pool_id)

jwks_client = PyJWKClient(cognito_keys_url)


# Expected incoming payload:
# {
#     "authorizationToken": "ExampleAUTHtoken123123123",
#     "requestContext": {
#         "apiId": "aaaaaa123123123example123",
#         "accountId": "111122223333",
#         "requestId": "f4081827-1111-4444-5555-5cf4695f339f",
#         "queryString": "mutation CreateEvent {...}\n\nquery MyQuery {...}\n",
#         "operationName": "MyQuery",
#         "variables": {}
#     }
# }
#
# Response payload:
Example #18
0
class TokenBackend:
    def __init__(
        self,
        algorithm,
        signing_key=None,
        verifying_key=None,
        audience=None,
        issuer=None,
        jwk_url: str = None,
        leeway=0,
    ):
        self._validate_algorithm(algorithm)

        self.algorithm = algorithm
        self.signing_key = signing_key
        self.audience = audience
        self.issuer = issuer

        self.jwks_client = PyJWKClient(jwk_url) if jwk_url else None
        self.leeway = leeway

        if algorithm.startswith("HS"):
            self.verifying_key = signing_key
        else:
            self.verifying_key = verifying_key

    def _validate_algorithm(self, algorithm):
        """
        Ensure that the nominated algorithm is recognized, and that cryptography is installed for those
        algorithms that require it
        """
        if algorithm not in ALLOWED_ALGORITHMS:
            raise TokenBackendError(
                format_lazy(_("Unrecognized algorithm type '{}'"), algorithm))

        if algorithm in algorithms.requires_cryptography and not algorithms.has_crypto:
            raise TokenBackendError(
                format_lazy(
                    _("You must have cryptography installed to use {}."),
                    algorithm))

    def get_verifying_key(self, token):
        if self.algorithm.startswith("HS"):
            return self.signing_key

        if self.jwks_client:
            return self.jwks_client.get_signing_key_from_jwt(token).key

        return self.verifying_key

    def encode(self, payload):
        """
        Returns an encoded token for the given payload dictionary.
        """
        jwt_payload = payload.copy()
        if self.audience is not None:
            jwt_payload['aud'] = self.audience
        if self.issuer is not None:
            jwt_payload['iss'] = self.issuer

        token = jwt.encode(jwt_payload,
                           self.signing_key,
                           algorithm=self.algorithm)
        if isinstance(token, bytes):
            # For PyJWT <= 1.7.1
            return token.decode('utf-8')
        # For PyJWT >= 2.0.0a1
        return token

    def decode(self, token, verify=True):
        """
        Performs a validation of the given token and returns its payload
        dictionary.

        Raises a `TokenBackendError` if the token is malformed, if its
        signature check fails, or if its 'exp' claim indicates it has expired.
        """
        try:
            return jwt.decode(
                token,
                self.get_verifying_key(token),
                algorithms=[self.algorithm],
                audience=self.audience,
                issuer=self.issuer,
                leeway=self.leeway,
                options={
                    'verify_aud': self.audience is not None,
                    'verify_signature': verify,
                },
            )
        except InvalidAlgorithmError as ex:
            raise TokenBackendError(_('Invalid algorithm specified')) from ex
        except InvalidTokenError:
            raise TokenBackendError(_('Token is invalid or expired'))
Example #19
0
    def _get_key(self, kid):
        if not PyJWKClient:
            raise NotImplementedError("PyJWK isn't supported")

        jwks_client = PyJWKClient(self.public_key_jwk_uri, cache_keys=False)
        return jwks_client.get_signing_key(kid).key
Example #20
0
 def _get_key(self, kid):
     jwks_client = PyJWKClient(self.public_key_jwk_uri, cache_keys=False)
     return jwks_client.get_signing_key(kid).key
Example #21
0
def get_jwks_client():
    well_known_metadata = get_well_known_metadata()
    jwks_client = PyJWKClient(well_known_metadata["jwks_uri"])
    return jwks_client