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 _create_authenticator(a_service): """Create an instance of :class:`google.auth.tokens.Authenticator`. Args: a_service (:class:`google.api.gen.servicecontrol_v1_messages.Service`): a service instance """ if not isinstance(a_service, messages.Service): raise ValueError("service is None or not an instance of Service") authentication = a_service.authentication if not authentication: logger.info("authentication is not configured in service, " "authentication checks will be disabled") return issuers_to_provider_ids = {} issuer_uri_configs = {} for provider in authentication.providers: issuer = provider.issuer jwks_uri = provider.jwksUri # Enable openID discovery if jwks_uri is unset open_id = jwks_uri is None issuer_uri_configs[issuer] = suppliers.IssuerUriConfig( open_id, jwks_uri) issuers_to_provider_ids[issuer] = provider.id key_uri_supplier = suppliers.KeyUriSupplier(issuer_uri_configs) jwks_supplier = suppliers.JwksSupplier(key_uri_supplier) authenticator = tokens.Authenticator(issuers_to_provider_ids, jwks_supplier) return authenticator
def test_supply_issuer(self): issuer = "https://issuer.com" jwks_uri = "https://issuer.com/jwks/uri" configs = {issuer: suppliers.IssuerUriConfig(False, jwks_uri)} supplier = suppliers.KeyUriSupplier(configs) self.assertEquals(jwks_uri, supplier.supply(issuer)) self.assertIsNone(supplier.supply("random-issuer"))
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_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_with_disallowed_issuer(self): url = get_url(IntegrationTest._JWKS_PATH) self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig( False, url) message = "Unknown issuer: " + self._ISSUER with self.assertRaisesRegexp(suppliers.UnauthenticatedException, message): self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN, self._auth_info, IntegrationTest._SERVICE_NAME)
def test_openid_discovery_with_bad_json(self): @httmock.urlmatch(scheme="https", netloc="issuer.com") def _mock_response_with_bad_json(url, request): # pylint: disable=unused-argument return "bad-json" issuer = "https://issuer.com" configs = {issuer: suppliers.IssuerUriConfig(True, None)} supplier = suppliers.KeyUriSupplier(configs) with httmock.HTTMock(_mock_response_with_bad_json): with self.assertRaises(suppliers.UnauthenticatedException): supplier.supply(issuer)
def test_invalid_jwks_uri(self): url = "https://invalid.jwks.uri" self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig( False, url) message = "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 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, "Audiences not allowed"): self._authenticator.authenticate(IntegrationTest._AUTH_TOKEN, self._auth_info, IntegrationTest._SERVICE_NAME)
def test_openid_discovery_failed(self): self._provider_ids[self._ISSUER] = self._PROVIDER_ID self._configs[IntegrationTest._ISSUER] = suppliers.IssuerUriConfig( False, None) message = ("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_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 = "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): jwks_uri = "https://issuer.com/jwks/uri" @httmock.urlmatch(scheme="https", netloc="issuer.com", path="/" + suppliers._OPEN_ID_CONFIG_PATH) def _mock_response(url, request): # pylint: disable=unused-argument response = {"jwks_uri": jwks_uri} return json.dumps(response) issuer = "https://issuer.com" configs = {issuer: suppliers.IssuerUriConfig(True, None)} supplier = suppliers.KeyUriSupplier(configs) with httmock.HTTMock(_mock_response): self.assertEquals(jwks_uri, supplier.supply(issuer))
def test_issuer_without_protocol(self): jwks_uri = "https://issuer.com/jwks/uri" @httmock.urlmatch(scheme="https", netloc="issuer.com", path="/" + suppliers._OPEN_ID_CONFIG_PATH) def _mock_response(url, request): # pylint: disable=unused-argument response = {"jwks_uri": jwks_uri} return json.dumps(response) # Specify an issuer without protocol to make sure the "https://" prefix is # added automatically. issuer = "issuer.com" configs = {issuer: suppliers.IssuerUriConfig(True, None)} supplier = suppliers.KeyUriSupplier(configs) with httmock.HTTMock(_mock_response): self.assertEquals(jwks_uri, supplier.supply(issuer))
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)