def test_jwt_wrong_key(self): new_keypair = service.create_secret_key() msg = 'bad jwt here❌' with self.assertRaises(exceptions.InvalidSignatureError): verify_jwt = jwts.make_jwt({"badmsg": msg}, self.keypair) jwts.verify_jwt(verify_jwt, new_keypair) with self.assertRaises(exceptions.InvalidSignatureError): verify_jwt = jwts.make_jwt({"badmsg": msg}, new_keypair) jwts.verify_jwt(verify_jwt, self.keypair)
def test_expired(self): now = int(time.time()) logger.debug('now=%s', now) exp = now - (jwts.TOKEN_EXPIRATION_LEEWAY_SEC + 1) jwt = jwts.make_jwt({'message': 'hi', 'exp': exp}, self.keypair) (jwts.verify_jwt.when.called_with(jwt, self.keypair) .should.throw(exceptions.InvalidClaimsError))
def test_jwt_invalid_base64(self): jwt = jwts.make_jwt({'message': 'hi'}, self.keypair) header = 'a' bad_jwt = '.'.join([header] + jwt.split('.')[:2]) with self.assertRaises(exceptions.InvalidFormatError): jwts.verify_jwt(bad_jwt, self.keypair)
def test_jwt_malformed_payload(self): jwt = jwts.make_jwt({'message': 'hi'}, self.keypair) header, payload, signature = jwt.split('.') payload = payload[:-8] bad_jwt = '.'.join([header, payload, signature]) with self.assertRaises(Exception): jwts.verify_jwt(bad_jwt, self.keypair)
def test_jwt_malformed_header(self): jwt = jwts.make_jwt({'message': 'hi'}, self.keypair) good_header = json.dumps(jwts.MINIMAL_JWT_HEADER) header = utils.base64url_encode(good_header).decode('utf-8')[:-4] bad_jwt = '.'.join([header] + jwt.split('.')[:2]) with self.assertRaises(exceptions.InvalidFormatError): jwts.verify_jwt(bad_jwt, self.keypair)
def test_extend_jws_signatures_from_jwt_single_key(self): jwt = jwts.make_jwt({'a': 1}, self.keypairs[0]) jws = jwts.extend_jws_signatures(jwt, self.keypairs[1], self.keypairs[1].identity) verified_msg = jwts.verify_jws(jws, self.keypairs[:2]) self.assertIsInstance(verified_msg, dict)
def test_jwt_bad_header_not_json(self): jwt = jwts.make_jwt({"message": "hi"}, self.keypair) plain_text = "woo-hoo! we just do what we want!!" bad_jwt = ".".join([utils.base64url_encode(plain_text).decode("utf-8")] + jwt.split(".")[1:]) with self.assertRaises(exceptions.InvalidFormatError): jwts.verify_jwt(bad_jwt, self.keypair)
def test_jwt_bad_header_invalid_alg(self): jwt = jwts.make_jwt({"message": "hi"}, self.keypair) header = json.dumps({"typ": "JWT", "alg": "NONE"}) header_str = utils.base64url_encode(header).decode("utf-8") bad_jwt = ".".join([header_str] + jwt.split(".")[1:]) with self.assertRaises(exceptions.InvalidFormatError): jwts.verify_jwt(bad_jwt, self.keypair)
def test_use_before_in_future(self): now = int(time.time()) logger.debug("now=%s", now) jwt = jwts.make_jwt({"message": "hi", "nbf": (now + (3 * 60))}, self.keypair) with self.assertRaises(exceptions.InvalidClaimsError): jwts.verify_jwt(jwt, self.keypair)
def test_jwt_malformed_payload(self): jwt = jwts.make_jwt({"message": "hi"}, self.keypair) header, payload, signature = jwt.split(".") payload = payload[:-8] bad_jwt = ".".join([header, payload, signature]) with self.assertRaises(Exception): jwts.verify_jwt(bad_jwt, self.keypair)
def test_non_standard_nonce(self): nonce = '0022020-02-31T02:28:42ZCdv3Yv' claims_in = {'jti': nonce} jwt = jwts.make_jwt(claims_in, self.keypair) self.assertTrue(jwt)
def test_invalid_nonce(self): nonce = "002" + time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) + "123456" logger.debug("nonce=%s", nonce) jwt = jwts.make_jwt({"message": "hi", "jti": nonce}, self.keypair) with self.assertRaises(exceptions.InvalidClaimsError): jwts.verify_jwt(jwt, self.keypair)
def test_valid_nonce(self): nonce = '001' + time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()) + '123456' logger.debug('nonce=%s', nonce) jwt = jwts.make_jwt({'message': 'hi', 'jti': nonce}, self.keypair) self.assertTrue(jwts.verify_jwt(jwt, self.keypair))
def test_jwt_invalid_base64(self): jwt = jwts.make_jwt({"message": "hi"}, self.keypair) header = "a" bad_jwt = ".".join([header] + jwt.split(".")[:2]) with self.assertRaises(exceptions.InvalidFormatError): jwts.verify_jwt(bad_jwt, self.keypair)
def test_extend_jws_signatures_from_jwt(self): jwt = jwts.make_jwt({"a": 1}, self.keypairs[0]) jws = jwts.extend_jws_signatures(jwt, self.keypairs[1:], self.keypairs[0].identity) verified_msg = jwts.verify_jws(jws, self.keypairs) self.assertIsInstance(verified_msg, dict)
def test_expired_nonce(self): then = datetime.utcnow().replace(tzinfo=tz.tzutc()) + timedelta(hours=-24) nonce = nonces.make_nonce(then) logger.debug('nonce=%s', nonce) jwt = jwts.make_jwt({'message': 'hi', 'jti': nonce}, self.keypair) with self.assertRaises(exceptions.InvalidClaimsError): jwts.verify_jwt(jwt, self.keypair)
def test_jwt_bad_header_not_json(self): jwt = jwts.make_jwt({'message': 'hi'}, self.keypair) bad_jwt = '.'.join( [utils.base64url_encode('woo-hoo! we just do what we want!!').decode('utf-8')] + jwt.split('.')[1:] ) (jwts.verify_jwt.when.called_with(bad_jwt, self.keypair) .should.throw(exceptions.InvalidFormatError))
def test_expired_nonce(self): now = int(time.time()) then = now-(1*24*60*60) nonce = '001' + time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(then)) + '123456' logger.debug('nonce=%s', nonce) jwt = jwts.make_jwt({'message': 'hi', 'jti': nonce}, self.keypair) (jwts.verify_jwt.when.called_with(jwt, self.keypair) .should.throw(exceptions.InvalidClaimsError))
def test_use_before_in_future(self): now = int(time.time()) logger.debug('now=%s', now) jwt = jwts.make_jwt({'message': 'hi', 'nbf': (now + (3 * 60))}, self.keypair) with self.assertRaises(exceptions.InvalidClaimsError): jwts.verify_jwt(jwt, self.keypair)
def test_invalid_nonce(self): nonce = '999' + time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()) + '123456' logger.debug('nonce=%s', nonce) jwt = jwts.make_jwt({'message': 'hi', 'jti': nonce}, self.keypair) with self.assertRaises(exceptions.InvalidClaimsError): jwts.verify_jwt(jwt, self.keypair)
def test_expired(self): now = int(time.time()) logger.debug('now=%s', now) exp = now - (jwts.TOKEN_EXPIRATION_LEEWAY_SEC + 1) jwt = jwts.make_jwt({'message': 'hi', 'exp': exp}, self.keypair) with self.assertRaises(exceptions.InvalidClaimsError): jwts.verify_jwt(jwt, self.keypair)
def test_invalid_nonce(self): nonce = '002' + time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()) + '123456' logger.debug('nonce=%s', nonce) jwt = jwts.make_jwt({'message': 'hi', 'jti': nonce}, self.keypair) with self.assertRaises(exceptions.InvalidClaimsError): jwts.verify_jwt(jwt, self.keypair)
def test_jwt_bad_header_not_json(self): jwt = jwts.make_jwt({'message': 'hi'}, self.keypair) plain_text = 'woo-hoo! we just do what we want!!' bad_jwt = '.'.join( [utils.base64url_encode(plain_text).decode('utf-8')] + jwt.split('.')[1:]) with self.assertRaises(exceptions.InvalidFormatError): jwts.verify_jwt(bad_jwt, self.keypair)
def test_jwt_bad_header_invalid_alg(self): jwt = jwts.make_jwt({'message': 'hi'}, self.keypair) header = json.dumps({ 'typ': 'JWT', 'alg': 'NONE', }) bad_jwt = '.'.join([utils.base64url_encode(header).decode('utf-8')] + jwt.split('.')[1:]) (jwts.verify_jwt.when.called_with(bad_jwt, self.keypair) .should.throw(exceptions.InvalidFormatError))
def test_jwt_wrong_key(self): new_keypair = service.create_secret_key() msg = 'bad jwt here❌' jwts.verify_jwt.when.called_with( jwts.make_jwt( {'badmsg': msg}, self.keypair ), new_keypair ).should.throw(exceptions.InvalidSignatureError) jwts.verify_jwt.when.called_with( jwts.make_jwt( {'badmsg': msg}, new_keypair ), self.keypair ).should.throw(exceptions.InvalidSignatureError)
def setUp(self): mock_keypair = keychain.Keypair.from_secret_pem(key_bytes=TestSession.id_key_bytes) mock_keypair.identity = 'server' self.server_credentials = keychain.Credentials(mock_keypair.identity, mock_keypair) mock_oneid_keypair = keychain.Keypair.from_secret_pem(key_bytes=TestSession.oneid_key_bytes) mock_oneid_keypair.identity = 'oneID' self.oneid_credentials = keychain.Credentials( mock_oneid_keypair.identity, mock_oneid_keypair ) mock_project_keypair = keychain.Keypair.from_secret_pem( key_bytes=TestSession.proj_key_bytes ) mock_project_keypair.identity = 'proj' self.project_credentials = keychain.Credentials( mock_project_keypair.identity, mock_project_keypair ) mock_resetA_keypair = keychain.Keypair.from_secret_pem( key_bytes=TestSession.reset_key_A_bytes ) mock_resetA_keypair.identity = 'resetA-id' self.resetA_credentials = keychain.Credentials( mock_resetA_keypair.identity, mock_resetA_keypair ) mock_resetB_keypair = keychain.Keypair.from_secret_pem( key_bytes=TestSession.reset_key_B_bytes ) mock_resetB_keypair.identity = 'resetB-id' self.resetB_credentials = keychain.Credentials( mock_resetB_keypair.identity, mock_resetB_keypair ) mock_resetC_keypair = keychain.Keypair.from_secret_pem( key_bytes=TestSession.reset_key_C_bytes ) mock_resetC_keypair.identity = 'resetC-id' self.resetC_credentials = keychain.Credentials( mock_resetC_keypair.identity, mock_resetC_keypair ) self.oneid_response = jwts.make_jwt({'a': 1}, mock_oneid_keypair) # TODO: JWS with both self.fake_config = { 'GLOBAL': { 'base_url': 'https://myservice', }, 'test_service': { 'test_method': { 'endpoint': '/my/endpoint', 'method': 'GET', 'arguments': {}, }, }, }
def test_expired_nonce(self): now = int(time.time()) then = now-(1*24*60*60) nonce = '001' + time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(then)) + '123456' logger.debug('nonce=%s', nonce) jwt = jwts.make_jwt({'message': 'hi', 'jti': nonce}, self.keypair) with self.assertRaises(exceptions.InvalidClaimsError): jwts.verify_jwt(jwt, self.keypair)
def test_jwt_bad_header_invalid_alg(self): jwt = jwts.make_jwt({'message': 'hi'}, self.keypair) header = json.dumps({ 'typ': 'JWT', 'alg': 'NONE', }) header_str = utils.base64url_encode(header).decode('utf-8') bad_jwt = '.'.join([header_str] + jwt.split('.')[1:]) with self.assertRaises(exceptions.InvalidFormatError): jwts.verify_jwt(bad_jwt, self.keypair)
def test_jwt_wrong_type(self): with self.assertRaises(Exception): jwts.make_jwt(123, self.keypair) with self.assertRaises(Exception): jwts.make_jwt(123.456, self.keypair) with self.assertRaises(Exception): jwts.make_jwt(['a', 'b'], self.keypair) with self.assertRaises(Exception): jwts.make_jwt(lambda a: a, self.keypair)
def test_verify_message_no_device_creds(self, mock_request): message = jwts.make_jwt({'c': 3}, self.id_credentials.keypair) sess = session.ServerSession( identity_credentials=self.alt_credentials, oneid_credentials=self.oneid_credentials, project_credentials=self.project_credentials, config=self.fake_config, ) with self.assertRaises(AttributeError): sess.verify_message(message, None)
def test_jwt_bad_header_not_json(self): jwt = jwts.make_jwt({'message': 'hi'}, self.keypair) plain_text = 'woo-hoo! we just do what we want!!' bad_jwt = '.'.join( [utils.base64url_encode(plain_text).decode('utf-8')] + jwt.split('.')[1:] ) with self.assertRaises(exceptions.InvalidFormatError): jwts.verify_jwt(bad_jwt, self.keypair)
def test_verify_message_failed_cosign(self, mock_request): message = jwts.make_jwt({'c': 3}, self.id_credentials.keypair) sess = session.ServerSession( identity_credentials=self.alt_credentials, oneid_credentials=self.oneid_credentials, project_credentials=self.project_credentials, config=self.fake_config, ) with self.assertRaises(exceptions.InvalidAuthentication): sess.verify_message(message, self.id_credentials)
def test_extend_jws_signatures_from_jwt_no_kid(self): keypair = service.create_secret_key() kid = str(uuid.uuid4()) jwt = jwts.make_jwt({'a': 1}, keypair) jws = jwts.extend_jws_signatures(jwt, self.keypairs, kid) keypair.identity = kid keypairs = self.keypairs + [keypair] jwts.verify_jws(jws, keypairs).should.be.a(dict)
def test_extend_jws_signatures_from_jwt_no_kid(self): keypair = service.create_secret_key() kid = str(uuid.uuid4()) jwt = jwts.make_jwt({'a': 1}, keypair) jws = jwts.extend_jws_signatures(jwt, self.keypairs, kid) keypair.identity = kid keypairs = self.keypairs + [keypair] verified_msg = jwts.verify_jws(jws, keypairs) self.assertIsInstance(verified_msg, dict)
def test_not_quite_expired_then_expired(self): now = int(time.time()) logger.debug('pre-sleep now=%s', now) exp = (now - jwts.TOKEN_EXPIRATION_LEEWAY_SEC) + 2 jwt = jwts.make_jwt({'message': 'hi', 'exp': exp}, self.keypair) jwts.verify_jwt(jwt, self.keypair).should.be.true time.sleep(jwts.TOKEN_EXPIRATION_LEEWAY_SEC + 4) logger.debug('post-sleep now=%s', int(time.time())) (jwts.verify_jwt.when.called_with(jwt, self.keypair) .should.throw(exceptions.InvalidClaimsError))
def test_verify_message_jwt(self, mock_request): message = jwts.make_jwt({'c': 3}, self.id_credentials.keypair) sess = session.ServerSession( identity_credentials=self.alt_credentials, oneid_credentials=self.oneid_credentials, project_credentials=self.project_credentials, config=self.fake_config, ) claims = sess.verify_message(message, self.id_credentials) self.assertIsInstance(claims, dict) self.assertIn("c", claims) self.assertEqual(claims.get("c"), 3)
def _create_and_verify_good_jwt(self, claims, keypair=None): keypair = keypair or self.keypair jwt = jwts.make_jwt(claims, keypair) claims1 = jwts.verify_jwt(jwt, keypair) claims2 = jwts.verify_jwt(jwt) claims1.should.be.truthy claims2.should.be.truthy for claim in claims: claims1.should.have.key(claim).equal_to(claims[claim]) claims2.should.have.key(claim).equal_to(claims[claim])
def test_not_quite_expired_then_expired(self): now = int(time.time()) logger.debug('pre-sleep now=%s', now) exp = now + 2 jwt = jwts.make_jwt({'message': 'hi', 'exp': exp}, self.keypair) self.assertTrue(jwts.verify_jwt(jwt, self.keypair)) time.sleep(jwts.TOKEN_EXPIRATION_LEEWAY_SEC + 4) logger.debug('post-sleep now=%s', int(time.time())) with self.assertRaises(exceptions.InvalidClaimsError): jwts.verify_jwt(jwt, self.keypair)
def setUp(self): # self.tmpdir = tempfile.mkdtemp() # os.environ['HOME'] = self.tmpdir # nonces.set_nonce_handlers(lambda _n: True, lambda _n: True) self.claim_keys = ['a', 'b', 'c', 'héllo!', '😬'] self.raw_claims = {k: 0 for k in self.claim_keys} self.keypair = service.create_secret_key() self.keypair.identity = str(uuid.uuid4()) self.jws = jwts.make_jws(self.raw_claims, self.keypair) self.jwt = jwts.make_jwt(self.raw_claims, self.keypair)
def test_not_quite_expired_then_expired(self): now = int(time.time()) logger.debug('pre-sleep now=%s', now) exp = (now - jwts.TOKEN_EXPIRATION_LEEWAY_SEC) + 2 jwt = jwts.make_jwt({'message': 'hi', 'exp': exp}, self.keypair) self.assertTrue(jwts.verify_jwt(jwt, self.keypair)) time.sleep(jwts.TOKEN_EXPIRATION_LEEWAY_SEC + 4) logger.debug('post-sleep now=%s', int(time.time())) with self.assertRaises(exceptions.InvalidClaimsError): jwts.verify_jwt(jwt, self.keypair)
def test_verify_message_failed_cosign(self, mock_request): message = jwts.make_jwt( {'c': 3}, self.id_credentials.keypair ) sess = session.ServerSession( identity_credentials=self.alt_credentials, oneid_credentials=self.oneid_credentials, project_credentials=self.project_credentials, config=self.fake_config, ) with self.assertRaises(exceptions.InvalidAuthentication): sess.verify_message(message, self.id_credentials)
def setUp(self): mock_keypair = keychain.Keypair.from_secret_pem( key_bytes=TestSession.id_key_bytes) mock_keypair.identity = 'server' self.server_credentials = keychain.Credentials(mock_keypair.identity, mock_keypair) mock_oneid_keypair = keychain.Keypair.from_secret_pem( key_bytes=TestSession.oneid_key_bytes) mock_oneid_keypair.identity = 'oneID' self.oneid_credentials = keychain.Credentials( mock_oneid_keypair.identity, mock_oneid_keypair) mock_project_keypair = keychain.Keypair.from_secret_pem( key_bytes=TestSession.proj_key_bytes) mock_project_keypair.identity = 'proj' self.project_credentials = keychain.Credentials( mock_project_keypair.identity, mock_project_keypair) mock_resetA_keypair = keychain.Keypair.from_secret_pem( key_bytes=TestSession.reset_key_A_bytes) mock_resetA_keypair.identity = 'resetA-id' self.resetA_credentials = keychain.Credentials( mock_resetA_keypair.identity, mock_resetA_keypair) mock_resetB_keypair = keychain.Keypair.from_secret_pem( key_bytes=TestSession.reset_key_B_bytes) mock_resetB_keypair.identity = 'resetB-id' self.resetB_credentials = keychain.Credentials( mock_resetB_keypair.identity, mock_resetB_keypair) mock_resetC_keypair = keychain.Keypair.from_secret_pem( key_bytes=TestSession.reset_key_C_bytes) mock_resetC_keypair.identity = 'resetC-id' self.resetC_credentials = keychain.Credentials( mock_resetC_keypair.identity, mock_resetC_keypair) self.oneid_response = jwts.make_jwt({'a': 1}, mock_oneid_keypair) # TODO: JWS with both self.fake_config = { 'GLOBAL': { 'base_url': 'https://myservice', }, 'test_service': { 'test_method': { 'endpoint': '/my/endpoint', 'method': 'GET', 'arguments': {}, }, }, }
def _create_and_verify_good_jwt(self, claims, keypair=None): keypair = keypair or self.keypair jwt = jwts.make_jwt(claims, keypair) claims1 = jwts.verify_jwt(jwt, keypair) claims2 = jwts.verify_jwt(jwt) self.assertTrue(claims1) self.assertEqual(claims1, claims2) for claim in claims: self.assertIn(claim, claims1) self.assertEqual(claims1.get(claim), claims[claim]) return claims1
def test_verify_message_from_device_key_only(self, mock_request): message = jwts.make_jwt({'c': 3}, self.id_credentials.keypair) sess = session.ServerSession( identity_credentials=self. alt_credentials, # id_cred needed for device/oneid oneid_credentials=self.oneid_credentials, project_credentials=self.project_credentials, config=self.fake_config, ) claims = sess.verify_message(message, self.id_credentials, get_oneid_cosignature=False) self.assertIsInstance(claims, dict) self.assertIn("c", claims) self.assertEqual(claims.get("c"), 3)
def test_add_signature_to_jwt(self): claims = { 'a': 1, } sess = session.DeviceSession(self.id_credentials) jwt = jwts.make_jwt(claims, self.alt_credentials.keypair) jws = sess.add_signature(jwt) claims = jwts.verify_jws( jws, [self.alt_credentials.keypair, self.id_credentials.keypair]) self.assertIsInstance(claims, dict) self.assertIn("a", claims) self.assertEqual(claims.get("a"), 1)
def test_jwt_verify_with_mult_sigs(self): jwt = jwts.make_jwt({'a': 1}, self.keypairs[0]) with self.assertRaises(Exception): jwts.verify_jws(jwt, self.keypairs[:2])
def test_get_jws_key_ids_from_jwt(self): jwt = jwts.make_jwt({'a': 1}, self.keypairs[0]) kids = [{'kid': self.keypairs[0].identity, 'kids': [], 'sidxs': []}] msg_ids = jwts.get_jws_key_ids(jwt) self.assertEqual(msg_ids, kids)
def test_verify_jws_from_jwt(self): jwt = jwts.make_jwt({'a': 1}, self.keypairs[0]) verified_msg = jwts.verify_jws(jwt, self.keypairs[0]) self.assertIsInstance(verified_msg, dict)
def test_valid_nonce(self): nonce = nonces.make_nonce() logger.debug('nonce=%s', nonce) jwt = jwts.make_jwt({'message': 'hi', 'jti': nonce}, self.keypair) self.assertTrue(jwts.verify_jwt(jwt, self.keypair))