def test_create_fo_keys_bundle(): jb = JWKSBundle(ORGOP.iss, ORGOP.keyjar) jb[FOP.iss] = FOP.keyjar jb[FO1P.iss] = FO1P.keyjar sb = jb.create_signed_bundle() _jw = jws.factory(sb) assert _jw
def verify_self_signed_jwks(sjwt): """ Verify the signature of a signed JWT containing a JWKS. The JWT is signed by one of the keys in the JWKS. In the JWT the JWKS is stored using this format :: 'jwks': { 'keys': [ ] } :param sjwt: Signed Jason Web Token :return: Dictionary containing 'jwks' (the JWKS) and 'iss' (the issuer of the JWT) """ _jws = factory(sjwt) _json = _jws.jwt.part[1] _body = json.loads(as_unicode(_json)) iss = _body['iss'] _jwks = _body['jwks'] _kj = jwks_to_keyjar(_jwks, iss) try: _kid = _jws.jwt.headers['kid'] except KeyError: _keys = _kj.get_signing_key(owner=iss) else: _keys = _kj.get_signing_key(owner=iss, kid=_kid) _ver = _jws.verify_compact(sjwt, _keys) return {'jwks': _ver['jwks'], 'iss': iss}
def test_sign_encrypt_id_token(): client_info = RegistrationResponse(id_token_signed_response_alg='RS512', client_id='client_1') session_info = { 'authn_req': AREQN, 'sub': 'sub', 'authn_event': { "authn_info": 'loa2', "authn_time": time.time() } } ENDPOINT_CONTEXT.jwx_def["signing_alg"] = {'id_token': 'RS384'} ENDPOINT_CONTEXT.cdb['client_1'] = client_info.to_dict() _token = sign_encrypt_id_token(ENDPOINT_CONTEXT, session_info, 'client_1', sign=True) assert _token _jws = jws.factory(_token) assert _jws.jwt.headers['alg'] == 'RS512' client_keyjar = KeyJar() _jwks = KEYJAR.export_jwks() client_keyjar.import_jwks(_jwks, ENDPOINT_CONTEXT.issuer) _jwt = JWT(keyjar=client_keyjar, iss='client_1') res = _jwt.unpack(_token) assert isinstance(res, JsonWebToken) assert res['aud'] == ['client_1']
def _parse_remote_response(self, response): """ Parse simple JWKS or signed JWKS from the HTTP response. :param response: HTTP response from the 'jwks_uri' or 'signed_jwks_uri' endpoint :return: response parsed as JSON """ # Check if the content type is the right one. try: if response.headers["Content-Type"] == 'application/json': logger.debug( "Loaded JWKS: %s from %s" % (response.text, self.source)) try: return json.loads(response.text) except ValueError: return None elif response.headers["Content-Type"] == 'application/jose': logger.debug( "Signed JWKS: %s from %s" % (response.text, self.source)) _jws = factory(response.text) _resp = _jws.verify_compact( response.text, keys=self.verify_keys.get_signing_key()) return _resp else: logger.error('Wrong content type: {}'.format( response.headers['Content-Type'])) return None except KeyError: pass
def test_dj_usage(): pkey = import_private_rsa_key_from_file(full_path("./size2048.key")) payload = "Please take a moment to register today" keys = [RSAKey(key=pkey)] _jws = JWS(payload, alg='RS256') sjwt = _jws.sign_compact(keys) _jwt = factory(sjwt) assert _jwt.jwt.headers['alg'] == 'RS256'
def unfurl(jwt): """ Return the body of a signed JWT, without verifying the signature. :param jwt: A signed JWT :return: The body of the JWT as a 'UTF-8' string """ _rp_jwt = factory(jwt) return json.loads(_rp_jwt.jwt.part[1].decode('utf8'))
def test_internal_signing_service(): iss = InternalSigningService('https://swamid.sunet.se', KJ['https://swamid.sunet.se']) res = iss.sign( RegistrationRequest(redirect_uris=['https://example.com/rp/cb']), receiver='https://example.com/rp') _jws = factory(res) assert _jws.jwt.headers['alg'] == 'RS256' msg = _jws.jwt.payload() assert msg['iss'] == 'https://swamid.sunet.se' assert msg['aud'] == ['https://example.com/rp']
def test_signer_ps512(): payload = "Please take a moment to register today" # Key has to be big enough > 512+512+2 _pkey = import_private_rsa_key_from_file(full_path("./size2048.key")) keys = [RSAKey(key=_pkey)] # keys[0]._keytype = "private" _jws = JWS(payload, alg="PS512") _jwt = _jws.sign_compact(keys) vkeys = [RSAKey(key=_pkey.public_key())] _rj = factory(_jwt) info = _rj.verify_compact(_jwt, vkeys) assert info == payload
def test_pack_metadata_statement_other_alg(): _keyjar = build_keyjar(KEYDEFS)[1] op = Operator(keyjar=_keyjar, iss='https://example.com/') req = MetadataStatement(issuer='https://example.org/op') sms = op.pack_metadata_statement(req, alg='ES256') assert sms # Should be a signed JWT _jwt = factory(sms) _body = json.loads(as_unicode(_jwt.jwt.part[1])) assert _body['iss'] == 'https://example.com/' # verify signature _kj = public_keys_keyjar(_keyjar, '', None, op.iss) r = _jwt.verify_compact(sms, _kj.get_signing_key(owner=op.iss)) assert r
def parse_response(self, response): if 200 <= response.status_code < 300: _jw = factory(response.text) # First Just checking the issuer ID *not* verifying the Signature body = json.loads(as_unicode(_jw.jwt.part[1])) assert body['iss'] == self.iss # Now verifying the signature try: _jw.verify_compact(response.text, self.keyjar.get_verify_key(owner=self.iss)) except AssertionError: raise JWSException('JWS signature verification error') location = response.headers['Location'] return {'sms': response.text, 'loc': location} else: raise SigningServiceError("{}: {}".format(response.status_code, response.text))
def test_pack_metadata_statement(): jb = FSJWKSBundle('', None, 'fo_jwks', key_conv={'to': quote_plus, 'from': unquote_plus}) _keyjar = build_keyjar(KEYDEFS)[1] self_signer = InternalSigningService('https://example.com/op', keyjar=_keyjar) op = Operator(self_signer=self_signer, jwks_bundle=jb, iss='https://example.com/op') req = MetadataStatement(issuer='https://example.org/op') sms = op.pack_metadata_statement(req) assert sms # Should be a signed JWT _jwt = factory(sms) assert _jwt assert _jwt.jwt.headers['alg'] == 'RS256' _body = json.loads(as_unicode(_jwt.jwt.part[1])) assert _body['iss'] == op.iss assert _body['issuer'] == 'https://example.org/op' # verify signature _kj = public_keys_keyjar(_keyjar, '', None, op.iss) r = _jwt.verify_compact(sms, _kj.get_signing_key(owner=op.iss)) assert r
def verify_request_signed_by_signing_keys(smsreq): """ Verify that a JWT is signed with a key that is inside the JWT. :param smsreq: Signed Metadata Statement signing request :return: Dictionary containing 'ms' (the signed request) and 'iss' (the issuer of the JWT). """ _jws = factory(smsreq) _json = _jws.jwt.part[1] _body = json.loads(as_unicode(_json)) iss = _body['iss'] _jwks = _body['signing_keys'] _kj = jwks_to_keyjar(_jwks, iss) try: _kid = _jws.jwt.headers['kid'] except KeyError: _keys = _kj.get_signing_key(owner=iss) else: _keys = _kj.get_signing_key(owner=iss, kid=_kid) _ver = _jws.verify_compact(smsreq, _keys) # remove the JWT specific claims for k in JsonWebToken.c_param.keys(): try: del _ver[k] except KeyError: pass try: del _ver['kid'] except KeyError: pass return {'ms': MetadataStatement(**_ver), 'iss': iss}
def test_make_signed_metadata_statements(): mds = MetaDataStore('mds') mds.clear() liss = list(FO.values()) liss.extend(list(OA.values())) key_bundle = make_fs_jwks_bundle(TEST_ISS, liss, SIGN_KEYJAR, KEYDEFS, './') operator = {} for entity, _keyjar in key_bundle.items(): operator[entity] = Operator(iss=entity, keyjar=_keyjar) _spec = SMS_DEF[OA['sunet']]["discovery"][FO['swamid']] ms = make_signed_metadata_statement(_spec, operator, mds=mds, base_uri='https:/example.org/ms') assert ms _spec = SMS_DEF[OA['sunet']]["discovery"][FO['edugain']] res = make_signed_metadata_statement(_spec, operator, mds=mds, base_uri='https:/example.org/ms') assert list(res['ms_uri'].keys()) == [FO['edugain']] _spec = SMS_DEF[OA['sunet']]["discovery"][FO['example']] res = make_signed_metadata_statement(_spec, operator, mds=mds, base_uri='https:/example.org/ms') assert list(res['ms'].keys()) == [FO['example']] _jws = factory(res['ms'][FO['example']]) assert _jws
def unpack(self, token): """ Unpack a received signed or signed and encrypted Json Web Token :param token: The Json Web Token :return: If decryption and signature verification work the payload will be returned as a Message instance if possible. """ if not token: raise KeyError _content_type = 'jwt' _jwe_header = _jws_header = None # Check if it's an encrypted JWT _rj = jwe.factory(token) if _rj: # Yes, try to decode _info = self._decrypt(_rj, token) _jwe_header = _rj.jwt.headers # Try to find out if the information encrypted was a signed JWT try: _content_type = _rj.jwt.headers['cty'] except KeyError: pass else: _info = token # If I have reason to believe the information I have is a signed JWT if _content_type.lower() == 'jwt': # Check that is a signed JWT _rj = jws.factory(_info) if _rj: _info = self._verify(_rj, _info) else: raise Exception() _jws_header = _rj.jwt.headers else: # So, not a signed JWT try: # A JSON document ? _info = json.loads(_info) except JSONDecodeError: # Oh, no ! Not JSON return _info # If I know what message class the info should be mapped into if self.msg_cls: _msg_cls = self.msg_cls else: try: # try to find a issuer specific message class _msg_cls = self.iss2msg_cls[_info['iss']] except KeyError: _msg_cls = None if _msg_cls: vp_args = {'skew': self.skew} if self.iss: vp_args['aud'] = self.iss _info = self.verify_profile(_msg_cls, _info, **vp_args) _info.jwe_header = _jwe_header _info.jws_header = _jws_header return _info else: return _info