def verify_id_token(instance, check_hash=False, **kwargs): # Try to decode the JWT, checks the signature args = {} for arg in TOKEN_VERIFY_ARGS: try: args[arg] = kwargs[arg] except KeyError: pass _jws = str(instance["id_token"]) # It can be encrypted, so try to decrypt first _jwe = JWE_factory(_jws) if _jwe is not None: try: _jws = _jwe.decrypt(keys=kwargs["keyjar"].get_decrypt_key()) except JWEException as err: raise VerificationError("Could not decrypt id_token", err) _packer = JWT() _body = _packer.unpack(_jws).payload() if "keyjar" in kwargs: try: if _body["iss"] not in kwargs["keyjar"]: raise ValueError("Unknown issuer") except KeyError: raise MissingRequiredAttribute("iss") if _jwe is not None: # Use the original encrypted token to set correct headers idt = IdToken().from_jwt(str(instance["id_token"]), **args) else: idt = IdToken().from_jwt(_jws, **args) if not idt.verify(**kwargs): raise VerificationError("Could not verify id_token", idt) if check_hash: _alg = idt.jws_header["alg"] if _alg != "none": hfunc = "HS" + _alg[-3:] else: # This is allowed only for `code` and it needs to be checked by a Client hfunc = None if "access_token" in instance and hfunc is not None: if "at_hash" not in idt: raise MissingRequiredAttribute("Missing at_hash property", idt) if idt["at_hash"] != jws.left_hash(instance["access_token"], hfunc): raise AtHashError("Failed to verify access_token hash", idt) if "code" in instance and hfunc is not None: if "c_hash" not in idt: raise MissingRequiredAttribute("Missing c_hash property", idt) if idt["c_hash"] != jws.left_hash(instance["code"], hfunc): raise CHashError("Failed to verify code hash", idt) return idt
def verify_id_token(instance, check_hash=False, **kwargs): # Try to decode the JWT, checks the signature args = {} for arg in ["key", "keyjar", "algs", "sender"]: try: args[arg] = kwargs[arg] except KeyError: pass _jws = str(instance["id_token"]) # It can be encrypted, so try to decrypt first _jwe = JWE_factory(_jws) if _jwe is not None: try: _jws = _jwe.decrypt(keys=kwargs['keyjar'].get_decrypt_key()) except JWEException as err: raise VerificationError("Could not decrypt id_token", err) _packer = JWT() _body = _packer.unpack(_jws).payload() if 'keyjar' in kwargs: try: if _body['iss'] not in kwargs['keyjar']: raise ValueError('Unknown issuer') except KeyError: raise MissingRequiredAttribute('iss') if _jwe is not None: # Use the original encrypted token to set correct headers idt = IdToken().from_jwt(str(instance['id_token']), **args) else: idt = IdToken().from_jwt(_jws, **args) if not idt.verify(**kwargs): raise VerificationError("Could not verify id_token", idt) if check_hash: _alg = idt.jws_header["alg"] # What if _alg == 'none' hfunc = "HS" + _alg[-3:] if "access_token" in instance: if "at_hash" not in idt: raise MissingRequiredAttribute("Missing at_hash property", idt) if idt["at_hash"] != jws.left_hash(instance["access_token"], hfunc): raise AtHashError("Failed to verify access_token hash", idt) if "code" in instance: if "c_hash" not in idt: raise MissingRequiredAttribute("Missing c_hash property", idt) if idt["c_hash"] != jws.left_hash(instance["code"], hfunc): raise CHashError("Failed to verify code hash", idt) return idt
def verify_poet_via_url(my_jws): # load the Signed JWT (JWS) my_jws = my_jws.rstrip().lstrip() signed_token = JWS(my_jws) # create aplain old JWT so we can fish out the 'iss' t = JWT() unpacked = t.unpack(token=my_jws) payload = unpacked.payload() if "iss" not in payload: print("Missing 'iss' claim in the JWS payload.") exit(1) else: iss = payload['iss'] # Fetch the public key from iss url = "https://%s/.well-known/poet.jwk" % (iss) r = requests.get(url) if r.status_code != 200: print("The key could not be fetched.") exit(1) # load the JWK into an RSA Key structure rsak = RSAKey(**r.json()) try: vt = signed_token.verify_compact(signed_token.msg, keys=[rsak]) retval = vt except BadSignature: retval = {"error": "The signature did not match"} except NoSuitableSigningKeys: retval = {"error": str(sys.exc_info()[1])} except DeSerializationNotPossible: retval = {"error": str(sys.exc_info()[1])} except: retval = {"error": str(sys.exc_info())} return retval
# $ ssh-keygen -t rsa -b 4096 # and provide the foo filename with requested. # # Now a JWS can be created as follow: # - retrieve the rsa key (the example below will also print it in the JWK section) # - use the JWS object to create the token specifying the algorithm to be used for signing # - call the method sign_compact providing an array of keys (eventually containing 1 key only) to be used for signing # - the example belows shows the content of the JWT, by printing it # - the signature can be verified with the method verify_compact (of course providing the same keys used for signing) payload = {"iss": "jow", "exp": 1300819380, "http://example.com/is_root": True} keys = [RSAKey(key=import_rsa_key_from_file("foo"))] jws = JWS(payload, alg="RS512").sign_compact(keys) print "jwt signed:", jws print ######################################## jwt_received = JWT() jwt_received.unpack(jws) print "jwt headers:", jwt_received.headers print "jwt part 1:", jwt_received.part[1] print _rj = JWS() info = _rj.verify_compact(jws, keys) print "Verified info:", info
# The JWS class can not work directly with rsa keys. # In this case the rsa key is wrapped in a RSAKey keys = [RSAKey(key=import_rsa_key_from_file("foo"))] _jws = JWS(payload, alg="RS512") _jwt = _jws.sign_compact(keys) print("Signed jwt:", _jwt) print() # The JWT class can be used to peek into a JWT, whether is is signed or # encrypted. It will not do any verificiation or decryption just unpacking # the JWT. jwt = JWT() jwt.unpack(_jwt) print("jwt headers:", jwt.headers) # Part 0 is the headers # Part 1 is the payload message print("jwt part 1:", jwt.part[1]) print() # If you want to verify the signature you have to use the JWS class _rj = JWS() # If everything is OK the verify_compact method will return the payload message info = _rj.verify_compact(_jwt, keys) print("Verified info:", info)