def verify(self, **kwargs): if "aud" in self: if "client_id" in kwargs: # check that it's for me if self["aud"] != kwargs["client_id"]: return False if "id_token" in self: # Try to decode the JWT, checks the signature idt = IdToken().from_jwt(str(self["id_token"]), kwargs["key"]) if not idt.verify(**kwargs): return False hfunc = "HS"+ jwt.unpack(self["id_token"])[0]["alg"][-3:] if "access_token" in self: try: assert "at_hash" in idt except AssertionError: raise Exception("Missing at_hash property") try: assert idt["at_hash"] == jwt.left_hash( self["access_token"], hfunc ) except AssertionError: raise Exception("Failed to verify access_token hash") if "code" in self: try: assert "c_hash" in idt except AssertionError: raise Exception("Missing c_hash property") try: assert idt["c_hash"] == jwt.left_hash(self["code"], hfunc) except AssertionError: raise Exception("Failed to verify code hash") self["id_token"] = idt return super(self.__class__, self).verify(**kwargs)
def test_make_id_token(): srv = Server(KEYS) session = {"user_id": "user0", "client_id": "http://oic.example/rp"} issuer = "http://oic.example/idp" code = "abcdefghijklmnop" idt_jwt = srv.make_id_token(session, loa="2", issuer=issuer, code=code, access_token="access_token") jwt_keys = srv.keystore.get_keys("ver", owner=None) idt = IdToken().from_jwt(idt_jwt, key=jwt_keys) print idt header = unpack(idt_jwt) lha = left_hash(code, func="HS" + header[0]["alg"][-3:]) assert lha == idt["c_hash"] atr = AccessTokenResponse(id_token=idt_jwt, access_token="access_token", token_type="Bearer") atr["code"] = code assert atr.verify(key=jwt_keys)
def test_left_hash_hs512(): hsh = jwt.left_hash("Please take a moment to register today", "HS512") assert hsh == "_h6feWLt8zbYcOFnaBmekTzMJYEHdVTaXlDgJSWsEeY"
def test_left_hash_hs256(): hsh = jwt.left_hash("Please take a moment to register today") assert hsh == "rCFHVJuxTqRxOsn2IUzgvA"
def make_id_token(self, session, loa="2", issuer="", keytype="rsa", code=None, access_token=None, user_info=None): #defaults inawhile = {"days": 1} # Handle the idtoken_claims extra = {} try: oidreq = OpenIDRequest().deserialize(session["oidreq"], "json") itc = oidreq["id_token"] logger.debug("ID Token claims: %s" % itc.to_dict()) try: inawhile = {"seconds": itc["max_age"]} except KeyError: inawhile = {} if "claims" in itc: for key, val in itc["claims"].items(): if key == "auth_time": extra["auth_time"] = time_util.utc_time_sans_frac() elif key == "acr": #["2","http://id.incommon.org/assurance/bronze"] extra["acr"] = verify_acr_level(val, loa) except KeyError: pass if user_info is None: _args = {} else: _args = user_info.to_dict() # Make sure that there are no name clashes for key in ["iss", "user_id", "aud", "exp", "acr", "nonce", "auth_time"]: try: del _args[key] except KeyError: pass if code: _args["c_hash"] = jwt.left_hash(code, "HS256") if access_token: _args["at_hash"] = jwt.left_hash(access_token, "HS256") idt = IdToken(iss=issuer, user_id=session["user_id"], aud = session["client_id"], exp = time_util.epoch_in_a_while(**inawhile), acr=loa, **_args) for key, val in extra.items(): idt[key] = val if "nonce" in session: idt.nonce = session["nonce"] # sign with clients secret key _keystore = self.keystore if keytype == "hmac": ckey = {"hmac": _keystore.get_sign_key("hmac", owner=session["client_id"])} algo = "HS256" elif keytype == "rsa": # own asymmetric key algo = "RS256" ckey = {"rsa": _keystore.get_sign_key("rsa")} else: algo = "ES256" ckey = {"ec":_keystore.get_sign_key("ec")} logger.debug("Sign idtoken with '%s'" % (ckey,)) return idt.to_jwt(key=ckey, algorithm=algo)