async def test_force_fetch_jwks_uri(): secret_keys = read_file_path('jwks_private.json') token = get_bearer_token() id_token = generate_id_token( token, {'sub': '123'}, secret_keys, alg='RS256', iss='https://i.b', aud='dev', exp=3600, nonce='n', ) app = AsyncPathMapDispatch({ '/jwks': {'body': read_file_path('jwks_public.json')} }) oauth = OAuth() client = oauth.register( 'dev', client_id='dev', client_secret='dev', fetch_token=get_bearer_token, jwks_uri='https://i.b/jwks', issuer='https://i.b', client_kwargs={ 'app': app, } ) req_scope = {'type': 'http', 'session': {'_dev_authlib_nonce_': 'n'}} req = Request(req_scope) token['id_token'] = id_token user = await client.parse_id_token(req, token) assert user.sub == '123'
def test_rsa_encode_decode(self): jws = JWS(algorithms=JWS_ALGORITHMS) s = jws.encode({'alg': 'RS256'}, 'hello', read_file_path('rsa_private.pem')) header, payload = jws.decode(s, read_file_path('rsa_public.pem')) self.assertEqual(payload, b'hello') self.assertEqual(header['alg'], 'RS256')
def test_compact_rsa(self): jws = JWS(algorithms=JWS_ALGORITHMS) s = jws.serialize({'alg': 'RS256'}, 'hello', read_file_path('rsa_private.pem')) data = jws.deserialize(s, read_file_path('rsa_public.pem')) header, payload = data['header'], data['payload'] self.assertEqual(payload, b'hello') self.assertEqual(header['alg'], 'RS256')
def test_EdDSA_alg(self): jws = JsonWebSignature(algorithms=RFC8037_ALGORITHMS) private_key = read_file_path('ed25519-pkcs8.pem') public_key = read_file_path('ed25519-pub.pem') s = jws.serialize({'alg': 'EdDSA'}, 'hello', private_key) data = jws.deserialize(s, public_key) header, payload = data['header'], data['payload'] self.assertEqual(payload, b'hello') self.assertEqual(header['alg'], 'EdDSA')
def test_ES256K_alg(self): jws = JsonWebSignature(algorithms=['ES256K']) private_key = read_file_path('secp256k1-private.pem') public_key = read_file_path('secp256k1-pub.pem') s = jws.serialize({'alg': 'ES256K'}, 'hello', private_key) data = jws.deserialize(s, public_key) header, payload = data['header'], data['payload'] self.assertEqual(payload, b'hello') self.assertEqual(header['alg'], 'ES256K')
def test_use_jwks(self): header = {'alg': 'RS256', 'kid': 'abc'} payload = {'name': 'hi'} private_key = read_file_path('jwks_private.json') pub_key = read_file_path('jwks_public.json') data = jwt.encode(header, payload, private_key) self.assertEqual(data.count(b'.'), 2) claims = jwt.decode(data, pub_key) self.assertEqual(claims['name'], 'hi')
def test_use_jws(self): payload = {'name': 'hi'} private_key = read_file_path('rsa_private.pem') pub_key = read_file_path('rsa_public.pem') data = jwt.encode({'alg': 'RS256'}, payload, private_key) self.assertEqual(data.count(b'.'), 2) claims = jwt.decode(data, pub_key) self.assertEqual(claims['name'], 'hi')
def test_with_ec(self): payload = {'name': 'hi'} private_key = read_file_path('ec_private.json') pub_key = read_file_path('ec_public.json') data = jwt.encode({'alg': 'ES256'}, payload, private_key) self.assertEqual(data.count(b'.'), 2) claims = jwt.decode(data, pub_key) self.assertEqual(claims['name'], 'hi')
def test_ES512_alg(self): jws = JsonWebSignature() private_key = read_file_path('secp521r1-private.json') public_key = read_file_path('secp521r1-public.json') self.assertRaises(ValueError, jws.serialize, {'alg': 'ES256'}, 'hello', private_key) s = jws.serialize({'alg': 'ES512'}, 'hello', private_key) data = jws.deserialize(s, public_key) header, payload = data['header'], data['payload'] self.assertEqual(payload, b'hello') self.assertEqual(header['alg'], 'ES512')
def test_compact_rsa(self): jwe = JsonWebEncryption(algorithms=JWE_ALGORITHMS) s = jwe.serialize_compact({ 'alg': 'RSA-OAEP', 'enc': 'A256GCM' }, 'hello', read_file_path('rsa_public.pem')) data = jwe.deserialize_compact(s, read_file_path('rsa_private.pem')) header, payload = data['header'], data['payload'] self.assertEqual(payload, b'hello') self.assertEqual(header['alg'], 'RSA-OAEP')
def test_compact_rsa_pss(self): jws = JsonWebSignature(algorithms=JWS_ALGORITHMS) private_key = read_file_path('rsa_private.pem') public_key = read_file_path('rsa_public.pem') s = jws.serialize({'alg': 'PS256'}, 'hello', private_key) data = jws.deserialize(s, public_key) header, payload = data['header'], data['payload'] self.assertEqual(payload, b'hello') self.assertEqual(header['alg'], 'PS256') ssh_pub_key = read_file_path('ssh_public.pem') self.assertRaises(errors.BadSignatureError, jws.deserialize, s, ssh_pub_key)
def test_rsa_alg(self): alg = JsonWebEncryption.JWE_AVAILABLE_ALGORITHMS['RSA-OAEP'] pub_key = alg.prepare_key(read_file_path('rsa_public.pem')) private_key = alg.prepare_key(read_file_path('rsa_private.pem')) cek = (b'\xb1\xa1\xf4\x80T\x8f\xe1s?\xb4\x03\xffk\x9a\xd4\xf6\x8a\x07' b'n[p."i/\x82\xcb.z\xea@\xfc') ek = alg.wrap(cek, {}, pub_key) self.assertEqual(alg.unwrap(ek, {}, private_key), cek) invalid_ek = b'a' + ek[1:] self.assertRaises(ValueError, alg.unwrap, invalid_ek, {}, private_key)
def test_with_zip_header(self): jwe = JWE(algorithms=JWE_ALGORITHMS) s = jwe.serialize_compact( {'alg': 'RSA-OAEP', 'enc': 'A128CBC-HS256', 'zip': 'DEF'}, 'hello', read_file_path('rsa_public.pem') ) data = jwe.deserialize_compact(s, read_file_path('rsa_private.pem')) header, payload = data['header'], data['payload'] self.assertEqual(payload, b'hello') self.assertEqual(header['alg'], 'RSA-OAEP')
def test_dumps_okp_public_key(self): key = read_file_path('ed25519-ssh.pub') self.assertRaises(ValueError, jwk.dumps, key) obj = jwk.dumps(key, 'OKP') self.assertEqual(obj['kty'], 'OKP') self.assertEqual(obj['crv'], 'Ed25519') key = read_file_path('ed25519-pub.pem') obj = jwk.dumps(key, 'OKP') self.assertEqual(obj['kty'], 'OKP') self.assertEqual(obj['crv'], 'Ed25519')
def test_import_okp_private_pem(self): raw = read_file_path('ed25519-pkcs8.pem') key = OKPKey.import_key(raw) obj = key.as_dict(is_private=True) self.assertEqual(obj['kty'], 'OKP') self.assertEqual(obj['crv'], 'Ed25519') self.assertIn('d', obj)
def test_signature_methods(self, generate_nonce, generate_timestamp): generate_nonce.return_value = 'abc' generate_timestamp.return_value = '123' signature = ', '.join([ 'OAuth oauth_nonce="abc"', 'oauth_timestamp="123"', 'oauth_version="1.0"', 'oauth_signature_method="HMAC-SHA1"', 'oauth_consumer_key="foo"', 'oauth_signature="h2sRqLArjhlc5p3FTkuNogVHlKE%3D"' ]) auth = OAuth1Session('foo') auth.send = self.verify_signature(signature) auth.post('https://i.b') signature = ( 'OAuth ' 'oauth_nonce="abc", oauth_timestamp="123", oauth_version="1.0", ' 'oauth_signature_method="PLAINTEXT", oauth_consumer_key="foo", ' 'oauth_signature="%26"') auth = OAuth1Session('foo', signature_method=SIGNATURE_PLAINTEXT) auth.send = self.verify_signature(signature) auth.post('https://i.b') signature = ( 'OAuth ' 'oauth_nonce="abc", oauth_timestamp="123", oauth_version="1.0", ' 'oauth_signature_method="RSA-SHA1", oauth_consumer_key="foo", ' 'oauth_signature="{sig}"').format(sig=TEST_RSA_OAUTH_SIGNATURE) rsa_key = read_file_path('rsa_private.pem') auth = OAuth1Session('foo', signature_method=SIGNATURE_RSA_SHA1, rsa_key=rsa_key) auth.send = self.verify_signature(signature) auth.post('https://i.b')
def test_rsa_public_key(self): # https://tools.ietf.org/html/rfc7520#section-3.3 obj = read_file_path('jwk_public.json') key = RSAKey.import_key(obj) new_obj = key.as_dict() self.assertBase64IntEqual(new_obj['n'], obj['n']) self.assertBase64IntEqual(new_obj['e'], obj['e'])
def test_compact_rsa(self): jws = JsonWebSignature() private_key = read_file_path('rsa_private.pem') public_key = read_file_path('rsa_public.pem') s = jws.serialize({'alg': 'RS256'}, 'hello', private_key) data = jws.deserialize(s, public_key) header, payload = data['header'], data['payload'] self.assertEqual(payload, b'hello') self.assertEqual(header['alg'], 'RS256') # can deserialize with private key data2 = jws.deserialize(s, private_key) self.assertEqual(data, data2) ssh_pub_key = read_file_path('ssh_public.pem') self.assertRaises(errors.BadSignatureError, jws.deserialize, s, ssh_pub_key)
def test_rsa_sha1_signature(self): self.prepare_data() url = '/user' params = [ ('oauth_consumer_key', 'client'), ('oauth_token', 'valid-token'), ('oauth_signature_method', 'RSA-SHA1'), ('oauth_timestamp', str(int(time.time()))), ('oauth_nonce', 'rsa-sha1-nonce'), ] base_string = signature.construct_base_string( 'GET', 'http://localhost/user', params ) sig = signature.rsa_sha1_signature( base_string, read_file_path('rsa_private.pem')) params.append(('oauth_signature', sig)) auth_param = ','.join(['{}="{}"'.format(k, v) for k, v in params]) auth_header = 'OAuth ' + auth_param headers = {'Authorization': auth_header} rv = self.client.get(url, headers=headers) data = json.loads(rv.data) self.assertIn('username', data) # case: invalid signature auth_param = auth_param.replace('rsa-sha1-nonce', 'alt-sha1-nonce') auth_header = 'OAuth ' + auth_param headers = {'Authorization': auth_header} rv = self.client.get(url, headers=headers) data = json.loads(rv.data) self.assertEqual(data['error'], 'invalid_signature')
def test_rsa_sha1_signature(self): self.prepare_data() url = '/oauth/token' self.prepare_temporary_credential() params = [ ('oauth_consumer_key', 'client'), ('oauth_token', 'abc'), ('oauth_verifier', 'abc-verifier'), ('oauth_signature_method', 'RSA-SHA1'), ('oauth_timestamp', str(int(time.time()))), ('oauth_nonce', 'rsa-sha1-nonce'), ] base_string = signature.construct_base_string( 'POST', 'http://localhost/oauth/token', params) sig = signature.rsa_sha1_signature(base_string, read_file_path('rsa_private.pem')) params.append(('oauth_signature', sig)) auth_param = ','.join(['{}="{}"'.format(k, v) for k, v in params]) auth_header = 'OAuth ' + auth_param headers = {'Authorization': auth_header} rv = self.client.post(url, headers=headers) data = decode_response(rv.data) self.assertIn('oauth_token', data) # case: invalid signature self.prepare_temporary_credential() auth_param = auth_param.replace('rsa-sha1-nonce', 'alt-sha1-nonce') auth_header = 'OAuth ' + auth_param headers = {'Authorization': auth_header} rv = self.client.post(url, headers=headers) data = decode_response(rv.data) self.assertEqual(data['error'], 'invalid_signature')
def test_rsa_public_key(self): # https://tools.ietf.org/html/rfc7520#section-3.3 obj = read_file_path('jwk_public.json') key = jwk.loads(obj) new_obj = jwk.dumps(key) self.assertBase64IntEqual(new_obj['n'], obj['n']) self.assertBase64IntEqual(new_obj['e'], obj['e'])
def test_rsa_sha1_signature(self): self.prepare_data() server = self.create_server() url = '/oauth/token' self.prepare_temporary_credential(server) params = [ ('oauth_consumer_key', 'client'), ('oauth_token', 'abc'), ('oauth_verifier', 'abc-verifier'), ('oauth_signature_method', 'RSA-SHA1'), ('oauth_timestamp', str(int(time.time()))), ('oauth_nonce', 'rsa-sha1-nonce'), ] base_string = signature.construct_base_string( 'POST', 'http://testserver/oauth/token', params) sig = signature.rsa_sha1_signature(base_string, read_file_path('rsa_private.pem')) params.append(('oauth_signature', sig)) auth_param = ','.join(['{}="{}"'.format(k, v) for k, v in params]) auth_header = 'OAuth ' + auth_param request = self.factory.post(url, HTTP_AUTHORIZATION=auth_header) resp = server.create_token_response(request) data = decode_response(resp.content) self.assertIn('oauth_token', data) # case: invalid signature self.prepare_temporary_credential(server) auth_param = auth_param.replace('rsa-sha1-nonce', 'alt-sha1-nonce') auth_header = 'OAuth ' + auth_param request = self.factory.post(url, HTTP_AUTHORIZATION=auth_header) resp = server.create_token_response(request) data = decode_response(resp.content) self.assertEqual(data['error'], 'invalid_signature')
def test_rsa_sha1_signature(self): self.prepare_data() handle = self.create_route() url = '/user' params = [ ('oauth_consumer_key', 'client'), ('oauth_token', 'valid-token'), ('oauth_signature_method', 'RSA-SHA1'), ('oauth_timestamp', str(int(time.time()))), ('oauth_nonce', 'rsa-sha1-nonce'), ] base_string = signature.construct_base_string( 'GET', 'http://testserver/user', params ) sig = signature.rsa_sha1_signature( base_string, read_file_path('rsa_private.pem')) params.append(('oauth_signature', sig)) auth_param = ','.join(['{}="{}"'.format(k, v) for k, v in params]) auth_header = 'OAuth ' + auth_param request = self.factory.get(url, HTTP_AUTHORIZATION=auth_header) resp = handle(request) data = json.loads(to_unicode(resp.content)) self.assertIn('username', data) # case: invalid signature auth_param = auth_param.replace('rsa-sha1-nonce', 'alt-sha1-nonce') auth_header = 'OAuth ' + auth_param request = self.factory.get(url, HTTP_AUTHORIZATION=auth_header) resp = handle(request) data = json.loads(to_unicode(resp.content)) self.assertEqual(data['error'], 'invalid_signature')
def test_not_supported_alg(self): public_key = read_file_path('rsa_public.pem') private_key = read_file_path('rsa_private.pem') jwe = JsonWebEncryption(algorithms=JWE_ALGORITHMS) s = jwe.serialize_compact({ 'alg': 'RSA-OAEP', 'enc': 'A256GCM' }, 'hello', public_key) jwe = JsonWebEncryption(algorithms=['RSA1_5', 'A256GCM']) self.assertRaises(errors.UnsupportedAlgorithmError, jwe.serialize_compact, { 'alg': 'RSA-OAEP', 'enc': 'A256GCM' }, 'hello', public_key) self.assertRaises(errors.UnsupportedCompressionAlgorithmError, jwe.serialize_compact, { 'alg': 'RSA1_5', 'enc': 'A256GCM', 'zip': 'DEF' }, 'hello', public_key) self.assertRaises( errors.UnsupportedAlgorithmError, jwe.deserialize_compact, s, private_key, ) jwe = JsonWebEncryption(algorithms=['RSA-OAEP', 'A192GCM']) self.assertRaises(errors.UnsupportedEncryptionAlgorithmError, jwe.serialize_compact, { 'alg': 'RSA-OAEP', 'enc': 'A256GCM' }, 'hello', public_key) self.assertRaises(errors.UnsupportedCompressionAlgorithmError, jwe.serialize_compact, { 'alg': 'RSA-OAEP', 'enc': 'A192GCM', 'zip': 'DEF' }, 'hello', public_key) self.assertRaises( errors.UnsupportedEncryptionAlgorithmError, jwe.deserialize_compact, s, private_key, )
def test_dumps_okp_private_key(self): key = read_file_path('ed25519-pkcs8.pem') jwk = JsonWebKey(RFC8037_ALGORITHMS) self.assertRaises(ValueError, jwk.dumps, key) obj = jwk.dumps(key, 'OKP') self.assertEqual(obj['kty'], 'OKP') self.assertEqual(obj['crv'], 'Ed25519') self.assertIn('d', obj)
def test_ec_private_key(self): # https://tools.ietf.org/html/rfc7520#section-3.2 obj = read_file_path('secp521r1-private.json') key = ECKey.import_key(obj) new_obj = key.as_dict(is_private=True) self.assertEqual(new_obj['crv'], obj['crv']) self.assertBase64IntEqual(new_obj['x'], obj['x']) self.assertBase64IntEqual(new_obj['y'], obj['y']) self.assertBase64IntEqual(new_obj['d'], obj['d'])
def test_ec_private_key(self): # https://tools.ietf.org/html/rfc7520#section-3.2 obj = read_file_path('ec_private.json') key = jwk.loads(obj) new_obj = jwk.dumps(key, 'EC') self.assertEqual(new_obj['crv'], obj['crv']) self.assertBase64IntEqual(new_obj['x'], obj['x']) self.assertBase64IntEqual(new_obj['y'], obj['y']) self.assertBase64IntEqual(new_obj['d'], obj['d'])
def test_ec_public_key(self): # https://tools.ietf.org/html/rfc7520#section-3.1 obj = read_file_path('secp521r1-public.json') key = ECKey.import_key(obj) new_obj = key.as_dict() self.assertEqual(new_obj['crv'], obj['crv']) self.assertBase64IntEqual(new_obj['x'], obj['x']) self.assertBase64IntEqual(new_obj['y'], obj['y']) self.assertEqual(key.as_json()[0], '{')
def test_ec_public_key(self): # https://tools.ietf.org/html/rfc7520#section-3.1 obj = read_file_path('ec_public.json') key = jwk.loads(obj) new_obj = jwk.dumps(key) self.assertEqual(new_obj['crv'], obj['crv']) self.assertBase64IntEqual(new_obj['x'], obj['x']) self.assertBase64IntEqual(new_obj['y'], obj['y']) self.assertEqual(key.as_json()[0], '{')
def test_import_keys(self): rsa_pub_pem = read_file_path('rsa_public.pem') self.assertRaises(ValueError, JsonWebKey.import_key, rsa_pub_pem, {'kty': 'EC'}) key = JsonWebKey.import_key(raw=rsa_pub_pem, options={'kty': 'RSA'}) self.assertIn('e', dict(key)) self.assertIn('n', dict(key)) key = JsonWebKey.import_key(raw=rsa_pub_pem) self.assertIn('e', dict(key)) self.assertIn('n', dict(key))