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" )
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"
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)