def test_authenticate_with_expired_auth_token(self): url = get_url(IntegrationTest._JWKS_PATH) self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig(False, url) IntegrationTest._mock_timer.return_value = 0 # Create an auth token that expires in 10 seconds. jwt_claims = copy.deepcopy(IntegrationTest._JWT_CLAIMS) jwt_claims["exp"] = time.time() + 10 auth_token = token_utils.generate_auth_token(jwt_claims, IntegrationTest._jwks._keys, alg="RS256", kid=IntegrationTest._rsa_key.kid) # Verify that the auth token can be authenticated successfully. self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN, self._auth_info, IntegrationTest._SERVICE_NAME) # Advance the timer by 20 seconds and make sure the token is expired. IntegrationTest._mock_timer.return_value += 20 message = "The auth token has already expired" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(auth_token, self._auth_info, IntegrationTest._SERVICE_NAME)
def test_authenticate_with_expired_auth_token(self): url = get_url(IntegrationTest._JWKS_PATH) self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig( False, url) IntegrationTest._mock_timer.return_value = 0 # Create an auth token that expires in 10 seconds. jwt_claims = copy.deepcopy(IntegrationTest._JWT_CLAIMS) jwt_claims[u"exp"] = time.time() + 10 auth_token = token_utils.generate_auth_token( jwt_claims, IntegrationTest._jwks._keys, alg=u"RS256", kid=IntegrationTest._rsa_key.kid) # Verify that the auth token can be authenticated successfully. self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN, self._auth_info, IntegrationTest._SERVICE_NAME) # Advance the timer by 20 seconds and make sure the token is expired. IntegrationTest._mock_timer.return_value += 20 message = u"The auth token has already expired" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(auth_token, self._auth_info, IntegrationTest._SERVICE_NAME)
def assert_missing_claim_raise_exception(claim_name): jwt_claims = copy.deepcopy(self._jwt_claims) del jwt_claims[claim_name] auth_token = token_utils.generate_auth_token(jwt_claims, self._jwks._keys, kid=self._ec_kid) with self.assertRaisesRegexp(suppliers.UnauthenticatedException, 'Missing "%s" claim' % claim_name): self._authenticator.get_jwt_claims(auth_token)
def test_authenticate_with_nbf_claim(self): # Set the "nbf" claim to some time in the future. self._jwt_claims["nbf"] = long(time.time() + 5) auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys) message = 'Current time is less than the "nbf" time' with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(auth_token, self._method_info, "service.name")
def assert_missing_claim_raise_exception(claim_name): jwt_claims = copy.deepcopy(self._jwt_claims) del jwt_claims[claim_name] auth_token = token_utils.generate_auth_token(jwt_claims, self._jwks._keys, kid=self._ec_kid) with self.assertRaisesRegexp(suppliers.UnauthenticatedException, u'Missing "%s" claim' % claim_name): self._authenticator.get_jwt_claims(auth_token)
def assert_malformed_time_claim_raises_exception(claim_name, expiration): jwt_claims = copy.deepcopy(self._jwt_claims) jwt_claims[claim_name] = expiration auth_token = token_utils.generate_auth_token(jwt_claims, self._jwks._keys) message = u'Malformed claim: "%s" must be an integer' % claim_name with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(auth_token, self._method_info, u"service.name")
def assert_malformed_time_claim_raises_exception(claim_name, expiration): jwt_claims = copy.deepcopy(self._jwt_claims) jwt_claims[claim_name] = expiration auth_token = token_utils.generate_auth_token(jwt_claims, self._jwks._keys) message = 'Malformed claim: "%s" must be an integer' % claim_name with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(auth_token, self._method_info, "service.name")
def test_authenticate_with_nbf_claim(self): # Set the "nbf" claim to some time in the future. self._jwt_claims[u"nbf"] = long(time.time() + 5) auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys) message = u'Current time is less than the "nbf" time' with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(auth_token, self._method_info, u"service.name")
def test_authenticate_with_expired_auth_token(self): self._jwt_claims["exp"] = long(time.time() - 10) auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys) message = "The auth token has already expired" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(auth_token, self._method_info, "service.name")
def test_authenticate_with_expired_auth_token(self): self._jwt_claims[u"exp"] = long(time.time() - 10) auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys) message = u"The auth token has already expired" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(auth_token, self._method_info, u"service.name")
def test_authenticate_with_disallowed_audiences(self): auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys, kid=self._ec_kid) self._method_info.get_allowed_audiences.return_value = [] self._issuers_to_provider_ids[self._jwt_claims["iss"]] = "project-id" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, "Audiences not allowed"): self._authenticator.authenticate(auth_token, self._method_info, self._service_name)
def test_authenticate_with_disallowed_audiences(self): auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys, kid=self._ec_kid) self._method_info.get_allowed_audiences.return_value = [] self._issuers_to_provider_ids[self._jwt_claims[u"iss"]] = u"project-id" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, u"Audiences not allowed"): self._authenticator.authenticate(auth_token, self._method_info, self._service_name)
def test_authenticate_with_single_audience(self): aud = "first.aud.com" self._jwt_claims["aud"] = aud auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys, kid=self._ec_kid) self._issuers_to_provider_ids[self._jwt_claims["iss"]] = "provider-id" actual_user_info = self._authenticator.authenticate(auth_token, self._method_info, aud) self.assertEqual([aud], actual_user_info.audiences)
def test_authenticate_with_single_audience(self): aud = u"first.aud.com" self._jwt_claims[u"aud"] = aud auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys, kid=self._ec_kid) self._issuers_to_provider_ids[self._jwt_claims[u"iss"]] = u"provider-id" actual_user_info = self._authenticator.authenticate(auth_token, self._method_info, aud) self.assertEqual([aud], actual_user_info.audiences)
def test_authenticate_with_disallowed_provider_id(self): auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys, kid=self._ec_kid) self._method_info.is_provider_allowed.return_value = False self._issuers_to_provider_ids[self._jwt_claims["iss"]] = "id" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, "The requested method does not allow provider " "id: id"): self._authenticator.authenticate(auth_token, self._method_info, self._service_name)
def test_authenticate_with_disallowed_provider_id(self): auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys, kid=self._ec_kid) self._method_info.is_provider_allowed.return_value = False self._issuers_to_provider_ids[self._jwt_claims[u"iss"]] = u"id" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, u"The requested method does not allow provider " u"id: id"): self._authenticator.authenticate(auth_token, self._method_info, self._service_name)
def test_authenticate_successfully(self): auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys, kid=self._ec_kid) self._method_info.get_allowed_audiences.return_value = ["first.com"] self._issuers_to_provider_ids[self._jwt_claims["iss"]] = "provider-id" actual_user_info = self._authenticator.authenticate( auth_token, self._method_info, "service.name.com") self.assert_user_info(actual_user_info, self._jwt_claims["aud"], self._jwt_claims["email"], self._jwt_claims["sub"], self._jwt_claims["iss"])
def test_authenticate_with_service_name_as_audience(self): self._jwt_claims["aud"].append(self._service_name) self._issuers_to_provider_ids[self._jwt_claims["iss"]] = "provider-id" self._method_info.get_allowed_audiences.return_value = [] auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys, kid=self._ec_kid) actual_user_info = self._authenticator.authenticate( auth_token, self._method_info, self._service_name) self.assert_user_info(actual_user_info, self._jwt_claims["aud"], self._jwt_claims["email"], self._jwt_claims["sub"], self._jwt_claims["iss"])
def test_authenticate_successfully(self): auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys, kid=self._ec_kid) self._method_info.get_allowed_audiences.return_value = ["first.com"] self._issuers_to_provider_ids[self._jwt_claims["iss"]] = "provider-id" actual_user_info = self._authenticator.authenticate(auth_token, self._method_info, "service.name.com") self.assert_user_info(actual_user_info, self._jwt_claims["aud"], self._jwt_claims["email"], self._jwt_claims["sub"], self._jwt_claims["iss"])
def test_auth_token_cache_capacity(self): authenticator = tokens.Authenticator({}, self._jwks_supplier, cache_capacity=2) self._jwt_claims[u"email"] = u"*****@*****.**" auth_token1 = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys) self._jwt_claims[u"email"] = u"*****@*****.**" auth_token2 = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys) # Populate the decoded result into cache. authenticator.get_jwt_claims(auth_token1) authenticator.get_jwt_claims(auth_token2) # Reset the returned JWKS so the signature verification will fail next # time. new_ec_jwk = jwk.ECKey(use=u"sig").load_key(ecc.P256) new_ec_jwk.kid = self._ec_kid new_jwks = jwk.KEYS() new_jwks._keys.append(new_ec_jwk) self._jwks_supplier.supply.return_value = new_jwks # Verify the following calls still succeed since the auth tokens are # cached. authenticator.get_jwt_claims(auth_token1) authenticator.get_jwt_claims(auth_token2) # Populate a third auth token into the cache. self._jwt_claims[u"email"] = u"*****@*****.**" auth_token3 = token_utils.generate_auth_token(self._jwt_claims, new_jwks._keys) authenticator.get_jwt_claims(auth_token3) # Make sure the first auth token is evicted from the cache since the cache # is full. with self.assertRaises(suppliers.UnauthenticatedException): authenticator.get_jwt_claims(auth_token1)
def test_authenticate_with_service_name_as_audience(self): self._jwt_claims["aud"].append(self._service_name) self._issuers_to_provider_ids[self._jwt_claims["iss"]] = "provider-id" self._method_info.get_allowed_audiences.return_value = [] auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys, kid=self._ec_kid) actual_user_info = self._authenticator.authenticate(auth_token, self._method_info, self._service_name) self.assert_user_info(actual_user_info, self._jwt_claims["aud"], self._jwt_claims["email"], self._jwt_claims["sub"], self._jwt_claims["iss"])
def test_verify_fails(self): auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys, kid=self._ec_kid) # Let the _jwks_supplier return a different key than the one we use to sign # the JWT. new_jwk = jwk.ECKey(use=u"sig").load_key(ecc.P256) new_jwks = jwk.KEYS() new_jwks._keys.append(new_jwk) self._jwks_supplier.supply.return_value = new_jwks with self.assertRaises(suppliers.UnauthenticatedException): self._authenticator.get_jwt_claims(auth_token)
def test_verify_fails(self): auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys, kid=self._ec_kid) # Let the _jwks_supplier return a different key than the one we use to sign # the JWT. new_jwk = jwk.ECKey(use="sig").load_key(ecc.P256) new_jwks = jwk.KEYS() new_jwks._keys.append(new_jwk) self._jwks_supplier.supply.return_value = new_jwks with self.assertRaises(suppliers.UnauthenticatedException): self._authenticator.get_jwt_claims(auth_token)
def test_auth_token_cache_capacity(self): authenticator = tokens.Authenticator({}, self._jwks_supplier, cache_capacity=2) self._jwt_claims["email"] = "*****@*****.**" auth_token1 = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys) self._jwt_claims["email"] = "*****@*****.**" auth_token2 = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys) # Populate the decoded result into cache. authenticator.get_jwt_claims(auth_token1) authenticator.get_jwt_claims(auth_token2) # Reset the returned JWKS so the signature verification will fail next # time. new_ec_jwk = jwk.ECKey(use="sig").load_key(ecc.P256) new_ec_jwk.kid = self._ec_kid new_jwks = jwk.KEYS() new_jwks._keys.append(new_ec_jwk) self._jwks_supplier.supply.return_value = new_jwks # Verify the following calls still succeed since the auth tokens are # cached. authenticator.get_jwt_claims(auth_token1) authenticator.get_jwt_claims(auth_token2) # Populate a third auth token into the cache. self._jwt_claims["email"] = "*****@*****.**" auth_token3 = token_utils.generate_auth_token(self._jwt_claims, new_jwks._keys) authenticator.get_jwt_claims(auth_token3) # Make sure the first auth token is evicted from the cache since the cache # is full. with self.assertRaises(suppliers.UnauthenticatedException): authenticator.get_jwt_claims(auth_token1)
def test_invalid_openid_discovery_url(self): issuer = "https://invalid.issuer" self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[issuer] = suppliers.IssuerUriConfig(True, None) jwt_claims = copy.deepcopy(IntegrationTest._JWT_CLAIMS) jwt_claims["iss"] = issuer auth_token = token_utils.generate_auth_token(jwt_claims, IntegrationTest._jwks._keys, alg="RS256", kid=IntegrationTest._rsa_key.kid) message = "Cannot discover the jwks uri" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(auth_token, self._auth_info, IntegrationTest._SERVICE_NAME)
def test_authenticate_auth_token_with_bad_signature(self): new_rsa_key = jwk.RSAKey(use="sig").load_key(PublicKey.RSA.generate(2048)) kid = IntegrationTest._rsa_key.kid new_rsa_key.kid = kid new_jwks = jwk.KEYS() new_jwks._keys.append(new_rsa_key) auth_token = token_utils.generate_auth_token(IntegrationTest._JWT_CLAIMS, new_jwks._keys, alg="RS256", kid=kid) url = get_url(IntegrationTest._JWKS_PATH) self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig(False, url) message = "Signature verification failed" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(auth_token, self._auth_info, IntegrationTest._SERVICE_NAME)
def test_invalid_openid_discovery_url(self): issuer = u"https://invalid.issuer" self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[issuer] = suppliers.IssuerUriConfig(True, None) jwt_claims = copy.deepcopy(IntegrationTest._JWT_CLAIMS) jwt_claims[u"iss"] = issuer auth_token = token_utils.generate_auth_token( jwt_claims, IntegrationTest._jwks._keys, alg=u"RS256", kid=IntegrationTest._rsa_key.kid) message = u"Cannot discover the jwks uri" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(auth_token, self._auth_info, IntegrationTest._SERVICE_NAME)
def test_authenticate_auth_token_with_bad_signature(self): new_rsa_key = jwk.RSAKey(use=u"sig").load_key( PublicKey.RSA.generate(2048)) kid = IntegrationTest._rsa_key.kid new_rsa_key.kid = kid new_jwks = jwk.KEYS() new_jwks._keys.append(new_rsa_key) auth_token = token_utils.generate_auth_token( IntegrationTest._JWT_CLAIMS, new_jwks._keys, alg=u"RS256", kid=kid) url = get_url(IntegrationTest._JWKS_PATH) self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig( False, url) message = u"Signature verification failed" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(auth_token, self._auth_info, IntegrationTest._SERVICE_NAME)
def test_get_jwt_claims_via_caching(self): AuthenticatorTest._mock_timer.return_value = 10 auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys) # Populate the decoded result into cache. self._authenticator.get_jwt_claims(auth_token) # Reset the returned JWKS so the signature verification will fail next # time. self._jwks_supplier.supply.return_value = jwk.KEYS() # Forword time by 10 seconds. AuthenticatorTest._mock_timer.return_value += 10 # This call should succeed since the auth_token is cached. self._authenticator.get_jwt_claims(auth_token) # Forword time by 5 minutes. AuthenticatorTest._mock_timer.return_value += 5 * 60 # This call should fail since the cache expires and it needs to re-decode # the auth token with a different key set. with self.assertRaises(suppliers.UnauthenticatedException): self._authenticator.get_jwt_claims(auth_token)
class IntegrationTest(unittest.TestCase): _CURRENT_TIME = int(time.time()) _PORT = 8080 _ISSUER = u"https://*****:*****@name.com" _X509_PATH = u"x509" _JWT_CLAIMS = { u"aud": [u"https://aud1.local.host", u"https://aud2.local.host"], u"exp": _CURRENT_TIME + 60, u"email": u"*****@*****.**", u"iss": _ISSUER, u"sub": u"subject-id" } _ec_jwk = jwk.ECKey(use=u"sig").load_key(ecc.P256) _rsa_key = jwk.RSAKey(use=u"sig").load_key(PublicKey.RSA.generate(1024)) _ec_jwk.kid = u"ec-key-id" _rsa_key.kid = u"rsa-key-id" _mock_timer = mock.MagicMock() _jwks = jwk.KEYS() _jwks._keys.append(_ec_jwk) _jwks._keys.append(_rsa_key) _AUTH_TOKEN = token_utils.generate_auth_token(_JWT_CLAIMS, _jwks._keys, alg=u"RS256", kid=_rsa_key.kid) @classmethod def setUpClass(cls): dirname = os.path.dirname(os.path.realpath(__file__)) cls._cert_file = os.path.join(dirname, u"ssl.cert") cls._key_file = os.path.join(dirname, u"ssl.key") os.environ[u"REQUESTS_CA_BUNDLE"] = cls._cert_file rest_server = cls._RestServer() rest_server.start() def setUp(self): self._provider_ids = {} self._configs = {} self._authenticator = auth.create_authenticator( self._provider_ids, self._configs) self._auth_info = mock.MagicMock() self._auth_info.is_provider_allowed.return_value = True self._auth_info.get_allowed_audiences.return_value = [ u"https://aud1.local.host" ] def test_verify_auth_token_with_jwks(self): url = get_url(IntegrationTest._JWKS_PATH) self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig( False, url) user_info = self._authenticator.authenticate( IntegrationTest._AUTH_TOKEN, self._auth_info, IntegrationTest._SERVICE_NAME) self._assert_user_info_equals( tokens.UserInfo(IntegrationTest._JWT_CLAIMS), user_info) def test_authenticate_auth_token_with_bad_signature(self): new_rsa_key = jwk.RSAKey(use=u"sig").load_key( PublicKey.RSA.generate(2048)) kid = IntegrationTest._rsa_key.kid new_rsa_key.kid = kid new_jwks = jwk.KEYS() new_jwks._keys.append(new_rsa_key) auth_token = token_utils.generate_auth_token( IntegrationTest._JWT_CLAIMS, new_jwks._keys, alg=u"RS256", kid=kid) url = get_url(IntegrationTest._JWKS_PATH) self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig( False, url) message = u"Signature verification failed" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(auth_token, self._auth_info, IntegrationTest._SERVICE_NAME) def test_verify_auth_token_with_x509(self): url = get_url(IntegrationTest._X509_PATH) self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig( False, url) user_info = self._authenticator.authenticate( IntegrationTest._AUTH_TOKEN, self._auth_info, IntegrationTest._SERVICE_NAME) self._assert_user_info_equals( tokens.UserInfo(IntegrationTest._JWT_CLAIMS), user_info) def test_verify_auth_token_with_invalid_x509(self): url = get_url(IntegrationTest._INVALID_X509_PATH) self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig( False, url) message = u"Cannot load X.509 certificate" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN, self._auth_info, IntegrationTest._SERVICE_NAME) def test_openid_discovery(self): self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig( True, None) user_info = self._authenticator.authenticate( IntegrationTest._AUTH_TOKEN, self._auth_info, IntegrationTest._SERVICE_NAME) self._assert_user_info_equals( tokens.UserInfo(IntegrationTest._JWT_CLAIMS), user_info) def test_openid_discovery_failed(self): self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig( False, None) message = (u"Cannot find the `jwks_uri` for issuer %s" % IntegrationTest._ISSUER) with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN, self._auth_info, IntegrationTest._SERVICE_NAME) def test_authenticate_with_malformed_auth_code(self): with self.assertRaisesRegexp(suppliers.UnauthenticatedException, u"Cannot decode the auth token"): self._authenticator.authenticate(u"invalid-auth-code", self._auth_info, IntegrationTest._SERVICE_NAME) def test_authenticate_with_disallowed_issuer(self): url = get_url(IntegrationTest._JWKS_PATH) self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig( False, url) message = u"Unknown issuer: " + self._ISSUER with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN, self._auth_info, IntegrationTest._SERVICE_NAME) def test_authenticate_with_unknown_issuer(self): message = (u"Cannot find the `jwks_uri` for issuer %s: " u"either the issuer is unknown") % IntegrationTest._ISSUER with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN, self._auth_info, IntegrationTest._SERVICE_NAME) def test_authenticate_with_invalid_audience(self): url = get_url(IntegrationTest._JWKS_PATH) self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig( False, url) self._auth_info.get_allowed_audiences.return_value = [] with self.assertRaisesRegexp(suppliers.UnauthenticatedException, u"Audiences not allowed"): self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN, self._auth_info, IntegrationTest._SERVICE_NAME) @mock.patch(u"time.time", _mock_timer) def test_authenticate_with_expired_auth_token(self): url = get_url(IntegrationTest._JWKS_PATH) self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig( False, url) IntegrationTest._mock_timer.return_value = 0 # Create an auth token that expires in 10 seconds. jwt_claims = copy.deepcopy(IntegrationTest._JWT_CLAIMS) jwt_claims[u"exp"] = time.time() + 10 auth_token = token_utils.generate_auth_token( jwt_claims, IntegrationTest._jwks._keys, alg=u"RS256", kid=IntegrationTest._rsa_key.kid) # Verify that the auth token can be authenticated successfully. self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN, self._auth_info, IntegrationTest._SERVICE_NAME) # Advance the timer by 20 seconds and make sure the token is expired. IntegrationTest._mock_timer.return_value += 20 message = u"The auth token has already expired" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(auth_token, self._auth_info, IntegrationTest._SERVICE_NAME) def test_invalid_openid_discovery_url(self): issuer = u"https://invalid.issuer" self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[issuer] = suppliers.IssuerUriConfig(True, None) jwt_claims = copy.deepcopy(IntegrationTest._JWT_CLAIMS) jwt_claims[u"iss"] = issuer auth_token = token_utils.generate_auth_token( jwt_claims, IntegrationTest._jwks._keys, alg=u"RS256", kid=IntegrationTest._rsa_key.kid) message = u"Cannot discover the jwks uri" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(auth_token, self._auth_info, IntegrationTest._SERVICE_NAME) def test_invalid_jwks_uri(self): url = u"https://invalid.jwks.uri" self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig( False, url) message = u"Cannot retrieve valid verification keys from the `jwks_uri`" with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN, self._auth_info, IntegrationTest._SERVICE_NAME) def _assert_user_info_equals(self, expected, actual): self.assertEqual(expected.audiences, actual.audiences) self.assertEqual(expected.email, actual.email) self.assertEqual(expected.subject_id, actual.subject_id) self.assertEqual(expected.issuer, actual.issuer) class _RestServer(object): def __init__(self): app = flask.Flask(u"integration-test-server") @app.route(u"/" + IntegrationTest._JWKS_PATH) def get_json_web_key_set(): # pylint: disable=unused-variable return IntegrationTest._jwks.dump_jwks() @app.route(u"/" + IntegrationTest._X509_PATH) def get_x509_certificates(): # pylint: disable=unused-variable cert = IntegrationTest._rsa_key.key.publickey().exportKey( u"PEM") return flask.jsonify( {IntegrationTest._rsa_key.kid: cert.decode('ascii')}) @app.route(u"/" + IntegrationTest._INVALID_X509_PATH) def get_invalid_x509_certificates(): # pylint: disable=unused-variable return flask.jsonify( {IntegrationTest._rsa_key.kid: u"invalid cert"}) @app.route(u"/.well-known/openid-configuration") def get_openid_configuration(): # pylint: disable=unused-variable return flask.jsonify( {u"jwks_uri": get_url(IntegrationTest._JWKS_PATH)}) self._application = app def start(self): def run_app(): ssl_context = (IntegrationTest._cert_file, IntegrationTest._key_file) self._application.run(port=IntegrationTest._PORT, ssl_context=ssl_context) thread = threading.Thread(target=run_app, args=()) thread.daemon = True thread.start()
def test_get_jwt_claims_without_kid(self): auth_token = token_utils.generate_auth_token(self._jwt_claims, self._jwks._keys) actual_jwt_claims = self._authenticator.get_jwt_claims(auth_token) self.assertEqual(self._jwt_claims, actual_jwt_claims)