Example #1
0
    def __init__(self, config_json: Dict[str, Any]) -> None:
        self.config_json = config_json

        # Algorithms to use when encoding / decoding JWTs
        self.algorithms: List[str] = self.config_json["algorithms"]

        # The "aud" (audience) claim identifies the recipients that the JWT is intended for.
        # If presented with a token that does not match this audience, we will raise an `AuthorizationError` exception
        self.audience: str = self.config_json["audience"]

        # The public identifier of the Application we are authenticating with.
        # This is used by the front-end for authenticating with the correct Auth0 application
        self.client_id: str = self.config_json["clientId"]

        # The domain of our Auth0 tenant
        # This is used by the front-end when redirecting to the hosted Auth0 authentication flow
        self.domain: str = self.config_json["domain"]

        # The "iss" (issuer) claim identifies the application that issued the token
        # If presented with a token that was not issued by this value, we will raise an `AuthorizationError` exception
        self.issuer: str = f"https://{self.domain}/"

        jwks = PyJWKSet.from_json(
            urlopen(f"https://{self.domain}/.well-known/jwks.json").read())

        self.jwks: Dict[str, RSAPublicKey] = {
            jwk.key_id: jwk.key
            for jwk in jwks.keys
        }

        # Validate `algorithms` input value
        if "RS256" not in self.algorithms or len(self.algorithms) > 1:
            raise ValueError(
                "Our Auth0 integration currently only supports the RS256 algorithm"
            )
Example #2
0
    def test_should_load_keys_from_jwk_data_json_string(self):
        algo = RSAAlgorithm(RSAAlgorithm.SHA256)

        with open(key_path("jwk_rsa_pub.json"), "r") as keyfile:
            pub_key = algo.from_jwk(keyfile.read())

        key_data_str = algo.to_jwk(pub_key)
        key_data = json.loads(key_data_str)

        # TODO Should `to_jwk` set these?
        key_data["alg"] = "RS256"
        key_data["use"] = "sig"
        key_data["kid"] = "keyid-abc123"

        jwk_set = PyJWKSet.from_json(json.dumps({"keys": [key_data]}))
        jwk = jwk_set.keys[0]

        assert jwk.key_type == "RSA"
        assert jwk.key_id == "keyid-abc123"
        assert jwk.public_key_use == "sig"
Example #3
0
    def parse(cls, trust_domain: TrustDomain,
              bundle_bytes: bytes) -> 'JwtBundle':
        """Parses a bundle from bytes. The data must be a standard RFC 7517 JWKS document.

        Args:
            trust_domain: A TrustDomain to associate to the bundle.
            bundle_bytes: An array of bytes that represents a set of JWKs.

        Returns:
            An instance of 'JWTBundle' with the JWT authorities associated to the given trust domain.

        Raises:
            ArgumentError: In case the trust_domain is empty or bundle_bytes is empty.
            ParseJWTBundleError: In case the set of jwt_authorities cannot be parsed from the bundle_bytes.
        """

        if not trust_domain:
            raise ArgumentError(MISSING_TRUST_DOMAIN)

        if not bundle_bytes:
            raise ArgumentError('Bundle bytes cannot be empty')

        try:
            jwks = PyJWKSet.from_json(bundle_bytes)
        except InvalidKeyError as ike:
            raise ParseJWTBundleError('Cannot parse jwks from bundle_bytes: ' +
                                      str(ike))
        except (JSONDecodeError, AttributeError):
            raise ParseJWTBundleError(
                'Cannot parse jwks. bundle_bytes does not represent a valid jwks'
            )

        jwt_authorities = {}
        for jwk in jwks.keys:
            if not jwk.key_id:
                raise ParseJWTBundleError(
                    'Error adding authority from JWKS: keyID cannot be empty')

            jwt_authorities[jwk.key_id] = jwk.key

        return JwtBundle(trust_domain, jwt_authorities)