/* * Copyright 2015, Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.google.auth.oauth2; import static org.junit.Assert.*; import com.google.api.client.json.GenericJson; import com.google.api.client.util.Clock; import com.google.auth.Credentials; import com.google.auth.TestUtils; import com.google.auth.http.HttpTransportFactory; import com.google.auth.oauth2.ExternalAccountAuthorizedUserCredentialsTest.MockExternalAccountAuthorizedUserCredentialsTransportFactory; import com.google.auth.oauth2.IdentityPoolCredentialsTest.MockExternalAccountCredentialsTransportFactory; import com.google.auth.oauth2.ImpersonatedCredentialsTest.MockIAMCredentialsServiceTransportFactory; import com.google.common.collect.ImmutableList; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** Test case for {@link GoogleCredentials}. */ @RunWith(JUnit4.class) public class GoogleCredentialsTest extends BaseSerializationTest { private static final String SA_CLIENT_EMAIL = "36680232662-vrd7ji19qe3nelgchd0ah2csanun6bnr@developer.gserviceaccount.com"; private static final String SA_CLIENT_ID = "36680232662-vrd7ji19qe3nelgchd0ah2csanun6bnr.apps.googleusercontent.com"; private static final String SA_PRIVATE_KEY_ID = "d84a4fefcf50791d4a90f2d7af17469d6282df9d"; private static final String SA_PRIVATE_KEY_PKCS8 = ServiceAccountCredentialsTest.PRIVATE_KEY_PKCS8; private static final String GDCH_SA_FORMAT_VERSION = GdchCredentials.SUPPORTED_FORMAT_VERSION; private static final String GDCH_SA_PROJECT_ID = "gdch-service-account-project-id"; private static final String GDCH_SA_PRIVATE_KEY_ID = "d84a4fefcf50791d4a90f2d7af17469d6282df9d"; private static final String GDCH_SA_PRIVATE_KEY_PKC8 = GdchCredentialsTest.PRIVATE_KEY_PKCS8; private static final String GDCH_SA_SERVICE_IDENTITY_NAME = "gdch-service-account-service-identity-name"; private static final URI GDCH_SA_TOKEN_SERVER_URI = URI.create("https://service-identity.domain/authenticate"); private static final String GDCH_SA_CA_CERT_FILE_NAME = "cert.pem"; private static final String GDCH_SA_CA_CERT_PATH = GdchCredentialsTest.class.getClassLoader().getResource(GDCH_SA_CA_CERT_FILE_NAME).getPath(); private static final URI GDCH_API_AUDIENCE = URI.create("https://gdch-api-audience"); private static final String USER_CLIENT_SECRET = "jakuaL9YyieakhECKL2SwZcu"; private static final String USER_CLIENT_ID = "ya29.1.AADtN_UtlxN3PuGAxrN2XQnZTVRvDyVWnYq4I6dws"; private static final String REFRESH_TOKEN = "1/Tl6awhpFjkMkSJoj1xsli0H2eL5YsMgU_NKPY2TyGWY"; private static final String ACCESS_TOKEN = "1/MkSJoj1xsli0AccessToken_NKPY2"; private static final HttpTransportFactory DUMMY_TRANSPORT_FACTORY = new MockTokenServerTransportFactory(); private static final URI CALL_URI = URI.create("http://googleapis.com/testapi/v1/foo"); private static final String QUOTA_PROJECT = "sample-quota-project-id"; private static final Collection SCOPES = Collections.unmodifiableCollection(Arrays.asList("scope1", "scope2")); private static final Collection DEFAULT_SCOPES = Collections.unmodifiableCollection(Arrays.asList("scope3")); private static final String GOOGLE_DEFAULT_UNIVERSE = "googleapis.com"; private static final String TPC_UNIVERSE = "foo.bar"; @Test public void getApplicationDefault_nullTransport_throws() throws IOException { try { GoogleCredentials.getApplicationDefault(null); fail(); } catch (NullPointerException expected) { // Expected } } @Test public void fromStream_unknownType_throws() throws IOException { MockHttpTransportFactory transportFactory = new MockHttpTransportFactory(); GenericJson json = new GenericJson(); json.put("type", "unsupported_credential"); InputStream stream = TestUtils.jsonToInputStream(json); try { GoogleCredentials.fromStream(stream, transportFactory); fail("Should throw if type is unknown."); } catch (IOException expected) { String expectedError = "Error reading credentials from stream, 'type' value " + "'unsupported_credential' not recognized. Valid values are 'authorized_user', " + "'service_account', 'gdch_service_account', 'external_account', " + "'external_account_authorized_user', 'impersonated_service_account'."; assertTrue(expected.getMessage().contains(expectedError)); } } @Test public void fromStream_nullTransport_throws() throws IOException { InputStream stream = new ByteArrayInputStream("foo".getBytes()); try { GoogleCredentials.fromStream(stream, null); fail("Should throw if HttpTransportFactory is null"); } catch (NullPointerException expected) { // Expected } } @Test public void fromStream_noType_throws() throws IOException { MockHttpTransportFactory transportFactory = new MockHttpTransportFactory(); GenericJson json = ServiceAccountCredentialsTest.writeServiceAccountJson( "project_id", QUOTA_PROJECT, "universe"); json.remove("type"); InputStream stream = TestUtils.jsonToInputStream(json); try { GoogleCredentials.fromStream(stream, transportFactory); fail("Should throw if type is unknown."); } catch (IOException expected) { String expectedError = "Error reading credentials from stream, 'type' field not specified."; assertEquals(expectedError, expected.getMessage()); } } @Test public void fromStream_nullStream_throws() throws IOException { MockHttpTransportFactory transportFactory = new MockHttpTransportFactory(); try { GoogleCredentials.fromStream(null, transportFactory); fail("Should throw if InputStream is null"); } catch (NullPointerException expected) { // Expected } } @Test public void fromStream_serviceAccount_noUniverse_providesToken() throws IOException { MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory(); transportFactory.transport.addServiceAccount(SA_CLIENT_EMAIL, ACCESS_TOKEN); InputStream serviceAccountStream = ServiceAccountCredentialsTest.writeServiceAccountStream( SA_CLIENT_ID, SA_CLIENT_EMAIL, SA_PRIVATE_KEY_PKCS8, SA_PRIVATE_KEY_ID); GoogleCredentials credentials = GoogleCredentials.fromStream(serviceAccountStream, transportFactory); assertNotNull(credentials); assertEquals(GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); assertEquals(false, credentials.isExplicitUniverseDomain()); credentials = credentials.createScoped(SCOPES); Map> metadata = credentials.getRequestMetadata(CALL_URI); TestUtils.assertContainsBearerToken(metadata, ACCESS_TOKEN); credentials = credentials.createScoped(SCOPES, DEFAULT_SCOPES); metadata = credentials.getRequestMetadata(CALL_URI); TestUtils.assertContainsBearerToken(metadata, ACCESS_TOKEN); } @Test public void fromStream_serviceAccount_Universe_noToken() throws IOException { MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory(); transportFactory.transport.addServiceAccount(SA_CLIENT_EMAIL, ACCESS_TOKEN); InputStream serviceAccountStream = ServiceAccountCredentialsTest.writeServiceAccountStream( SA_CLIENT_ID, SA_CLIENT_EMAIL, SA_PRIVATE_KEY_PKCS8, SA_PRIVATE_KEY_ID, TPC_UNIVERSE); GoogleCredentials credentials = GoogleCredentials.fromStream(serviceAccountStream, transportFactory); assertNotNull(credentials); assertEquals(TPC_UNIVERSE, credentials.getUniverseDomain()); assertEquals(true, credentials.isExplicitUniverseDomain()); credentials = credentials.createScoped(SCOPES); Map> metadata = credentials.getRequestMetadata(CALL_URI); assertNotNull(((ServiceAccountCredentials) credentials).getSelfSignedJwtCredentialsWithScope()); } @Test public void fromStream_serviceAccountNoClientId_throws() throws IOException { InputStream serviceAccountStream = ServiceAccountCredentialsTest.writeServiceAccountStream( null, SA_CLIENT_EMAIL, SA_PRIVATE_KEY_PKCS8, SA_PRIVATE_KEY_ID); testFromStreamException(serviceAccountStream, "client_id"); } @Test public void fromStream_serviceAccountNoClientEmail_throws() throws IOException { InputStream serviceAccountStream = ServiceAccountCredentialsTest.writeServiceAccountStream( SA_CLIENT_ID, null, SA_PRIVATE_KEY_PKCS8, SA_PRIVATE_KEY_ID); testFromStreamException(serviceAccountStream, "client_email"); } @Test public void fromStream_serviceAccountNoPrivateKey_throws() throws IOException { InputStream serviceAccountStream = ServiceAccountCredentialsTest.writeServiceAccountStream( SA_CLIENT_ID, SA_CLIENT_EMAIL, null, SA_PRIVATE_KEY_ID); testFromStreamException(serviceAccountStream, "private_key"); } @Test public void fromStream_serviceAccountNoPrivateKeyId_throws() throws IOException { InputStream serviceAccountStream = ServiceAccountCredentialsTest.writeServiceAccountStream( SA_CLIENT_ID, SA_CLIENT_EMAIL, SA_PRIVATE_KEY_PKCS8, null); testFromStreamException(serviceAccountStream, "private_key_id"); } @Test public void fromStream_gdchServiceAccount_correct() throws IOException { MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory(); InputStream gdchServiceAccountStream = GdchCredentialsTest.writeGdchServiceAccountStream( GDCH_SA_FORMAT_VERSION, GDCH_SA_PROJECT_ID, GDCH_SA_PRIVATE_KEY_ID, GDCH_SA_PRIVATE_KEY_PKC8, GDCH_SA_SERVICE_IDENTITY_NAME, GDCH_SA_CA_CERT_PATH, GDCH_SA_TOKEN_SERVER_URI); GoogleCredentials credentials = GoogleCredentials.fromStream(gdchServiceAccountStream, transportFactory); assertNotNull(credentials); assertTrue(credentials instanceof GdchCredentials); assertEquals(GDCH_SA_PROJECT_ID, ((GdchCredentials) credentials).getProjectId()); assertEquals( GDCH_SA_SERVICE_IDENTITY_NAME, ((GdchCredentials) credentials).getServiceIdentityName()); assertEquals(GDCH_SA_TOKEN_SERVER_URI, ((GdchCredentials) credentials).getTokenServerUri()); assertEquals(GDCH_SA_CA_CERT_PATH, ((GdchCredentials) credentials).getCaCertPath()); assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); assertNull(((GdchCredentials) credentials).getApiAudience()); credentials = ((GdchCredentials) credentials).createWithGdchAudience(GDCH_API_AUDIENCE); assertNotNull(credentials); assertTrue(credentials instanceof GdchCredentials); assertEquals(GDCH_SA_PROJECT_ID, ((GdchCredentials) credentials).getProjectId()); assertEquals( GDCH_SA_SERVICE_IDENTITY_NAME, ((GdchCredentials) credentials).getServiceIdentityName()); assertEquals(GDCH_SA_TOKEN_SERVER_URI, ((GdchCredentials) credentials).getTokenServerUri()); assertEquals(GDCH_SA_CA_CERT_PATH, ((GdchCredentials) credentials).getCaCertPath()); assertNotNull(((GdchCredentials) credentials).getApiAudience()); } @Test public void fromStream_gdchServiceAccountNoFormatVersion_throws() throws IOException { InputStream gdchServiceAccountStream = GdchCredentialsTest.writeGdchServiceAccountStream( null, GDCH_SA_PROJECT_ID, GDCH_SA_PRIVATE_KEY_ID, GDCH_SA_PRIVATE_KEY_PKC8, GDCH_SA_SERVICE_IDENTITY_NAME, GDCH_SA_CA_CERT_PATH, GDCH_SA_TOKEN_SERVER_URI); testFromStreamException(gdchServiceAccountStream, "format_version"); } @Test public void fromStream_gdchServiceAccountNoProjectId_throws() throws IOException { InputStream gdchServiceAccountStream = GdchCredentialsTest.writeGdchServiceAccountStream( GDCH_SA_FORMAT_VERSION, null, GDCH_SA_PRIVATE_KEY_ID, GDCH_SA_PRIVATE_KEY_PKC8, GDCH_SA_SERVICE_IDENTITY_NAME, GDCH_SA_CA_CERT_PATH, GDCH_SA_TOKEN_SERVER_URI); testFromStreamException(gdchServiceAccountStream, "project"); } @Test public void fromStream_gdchServiceAccountNoPrivateKeyId_throws() throws IOException { InputStream gdchServiceAccountStream = GdchCredentialsTest.writeGdchServiceAccountStream( GDCH_SA_FORMAT_VERSION, GDCH_SA_PROJECT_ID, null, GDCH_SA_PRIVATE_KEY_PKC8, GDCH_SA_SERVICE_IDENTITY_NAME, GDCH_SA_CA_CERT_PATH, GDCH_SA_TOKEN_SERVER_URI); testFromStreamException(gdchServiceAccountStream, "private_key_id"); } @Test public void fromStream_gdchServiceAccountNoPrivateKey_throws() throws IOException { InputStream gdchServiceAccountStream = GdchCredentialsTest.writeGdchServiceAccountStream( GDCH_SA_FORMAT_VERSION, GDCH_SA_PROJECT_ID, GDCH_SA_PRIVATE_KEY_ID, null, GDCH_SA_SERVICE_IDENTITY_NAME, GDCH_SA_CA_CERT_PATH, GDCH_SA_TOKEN_SERVER_URI); testFromStreamException(gdchServiceAccountStream, "private_key"); } @Test public void fromStream_gdchServiceAccountNoServiceIdentityName_throws() throws IOException { InputStream gdchServiceAccountStream = GdchCredentialsTest.writeGdchServiceAccountStream( GDCH_SA_FORMAT_VERSION, GDCH_SA_PROJECT_ID, GDCH_SA_PRIVATE_KEY_ID, GDCH_SA_PRIVATE_KEY_PKC8, null, GDCH_SA_CA_CERT_PATH, GDCH_SA_TOKEN_SERVER_URI); testFromStreamException(gdchServiceAccountStream, "name"); } @Test public void fromStream_gdchServiceAccountNoTokenServerUri_throws() throws IOException { InputStream gdchServiceAccountStream = GdchCredentialsTest.writeGdchServiceAccountStream( GDCH_SA_FORMAT_VERSION, GDCH_SA_PROJECT_ID, GDCH_SA_PRIVATE_KEY_ID, GDCH_SA_PRIVATE_KEY_PKC8, GDCH_SA_SERVICE_IDENTITY_NAME, GDCH_SA_CA_CERT_PATH, null); testFromStreamException(gdchServiceAccountStream, "token_uri"); } @Test public void fromStream_gdchServiceAccountInvalidFormatVersion_throws() throws IOException { InputStream gdchServiceAccountStream = GdchCredentialsTest.writeGdchServiceAccountStream( "100", GDCH_SA_PROJECT_ID, GDCH_SA_PRIVATE_KEY_ID, GDCH_SA_PRIVATE_KEY_PKC8, GDCH_SA_SERVICE_IDENTITY_NAME, GDCH_SA_CA_CERT_PATH, GDCH_SA_TOKEN_SERVER_URI); testFromStreamException( gdchServiceAccountStream, String.format("Only format version %s is supported", GDCH_SA_FORMAT_VERSION)); } @Test public void fromStream_gdchServiceAccountInvalidCaCertPath_throws() throws IOException { InputStream gdchServiceAccountStream = GdchCredentialsTest.writeGdchServiceAccountStream( GDCH_SA_FORMAT_VERSION, GDCH_SA_PROJECT_ID, GDCH_SA_PRIVATE_KEY_ID, GDCH_SA_PRIVATE_KEY_PKC8, GDCH_SA_SERVICE_IDENTITY_NAME, "/path/to/missing/file", GDCH_SA_TOKEN_SERVER_URI); testFromStreamException( gdchServiceAccountStream, String.format("Error reading certificate file from CA cert path")); } @Test public void fromStream_userCredentials_providesToken() throws IOException { MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory(); transportFactory.transport.addClient(USER_CLIENT_ID, USER_CLIENT_SECRET); transportFactory.transport.addRefreshToken(REFRESH_TOKEN, ACCESS_TOKEN); InputStream userStream = UserCredentialsTest.writeUserStream( USER_CLIENT_ID, USER_CLIENT_SECRET, REFRESH_TOKEN, null); GoogleCredentials credentials = GoogleCredentials.fromStream(userStream, transportFactory); assertNotNull(credentials); Map> metadata = credentials.getRequestMetadata(CALL_URI); TestUtils.assertContainsBearerToken(metadata, ACCESS_TOKEN); } @Test public void fromStream_userCredentials_defaultUniverse() throws IOException { MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory(); InputStream userStream = UserCredentialsTest.writeUserStream( USER_CLIENT_ID, USER_CLIENT_SECRET, REFRESH_TOKEN, null); GoogleCredentials credentials = GoogleCredentials.fromStream(userStream, transportFactory); assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); } @Test public void fromStream_userCredentials_NoClientId_throws() throws IOException { InputStream userStream = UserCredentialsTest.writeUserStream(null, USER_CLIENT_SECRET, REFRESH_TOKEN, QUOTA_PROJECT); testFromStreamException(userStream, "client_id"); } @Test public void fromStream_userCredentials_NoClientSecret_throws() throws IOException { InputStream userStream = UserCredentialsTest.writeUserStream(USER_CLIENT_ID, null, REFRESH_TOKEN, QUOTA_PROJECT); testFromStreamException(userStream, "client_secret"); } @Test public void fromStream_userCredentials_NoRefreshToken_throws() throws IOException { InputStream userStream = UserCredentialsTest.writeUserStream( USER_CLIENT_ID, USER_CLIENT_SECRET, null, QUOTA_PROJECT); testFromStreamException(userStream, "refresh_token"); } @Test public void fromStream_identityPoolCredentials_providesToken() throws IOException { MockExternalAccountCredentialsTransportFactory transportFactory = new MockExternalAccountCredentialsTransportFactory(); InputStream identityPoolCredentialStream = IdentityPoolCredentialsTest.writeIdentityPoolCredentialsStream( transportFactory.transport.getStsUrl(), transportFactory.transport.getMetadataUrl(), /* serviceAccountImpersonationUrl= */ null, /* serviceAccountImpersonationOptionsMap= */ null); GoogleCredentials credentials = GoogleCredentials.fromStream(identityPoolCredentialStream, transportFactory); assertNotNull(credentials); credentials = credentials.createScoped(SCOPES); Map> metadata = credentials.getRequestMetadata(CALL_URI); TestUtils.assertContainsBearerToken(metadata, transportFactory.transport.getAccessToken()); } @Test public void fromStream_identityPoolCredentials_defaultUniverse() throws IOException { MockExternalAccountCredentialsTransportFactory transportFactory = new MockExternalAccountCredentialsTransportFactory(); InputStream identityPoolCredentialStream = IdentityPoolCredentialsTest.writeIdentityPoolCredentialsStream( transportFactory.transport.getStsUrl(), transportFactory.transport.getMetadataUrl(), /* serviceAccountImpersonationUrl= */ null, /* serviceAccountImpersonationOptionsMap= */ null); GoogleCredentials credentials = GoogleCredentials.fromStream(identityPoolCredentialStream, transportFactory); assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); } @Test public void fromStream_awsCredentials_providesToken() throws IOException { MockExternalAccountCredentialsTransportFactory transportFactory = new MockExternalAccountCredentialsTransportFactory(); InputStream awsCredentialStream = AwsCredentialsTest.writeAwsCredentialsStream( transportFactory.transport.getStsUrl(), transportFactory.transport.getAwsRegionUrl(), transportFactory.transport.getAwsCredentialsUrl()); GoogleCredentials credentials = GoogleCredentials.fromStream(awsCredentialStream, transportFactory); assertNotNull(credentials); credentials = credentials.createScoped(SCOPES); Map> metadata = credentials.getRequestMetadata(CALL_URI); TestUtils.assertContainsBearerToken(metadata, transportFactory.transport.getAccessToken()); } @Test public void fromStream_awsCredentials_defaultUniverse() throws IOException { MockExternalAccountCredentialsTransportFactory transportFactory = new MockExternalAccountCredentialsTransportFactory(); InputStream awsCredentialStream = AwsCredentialsTest.writeAwsCredentialsStream( transportFactory.transport.getStsUrl(), transportFactory.transport.getAwsRegionUrl(), transportFactory.transport.getAwsCredentialsUrl()); GoogleCredentials credentials = GoogleCredentials.fromStream(awsCredentialStream, transportFactory); assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); } @Test public void fromStream_pluggableAuthCredentials_providesToken() throws IOException { MockExternalAccountCredentialsTransportFactory transportFactory = new MockExternalAccountCredentialsTransportFactory(); InputStream stream = PluggableAuthCredentialsTest.writeCredentialsStream(transportFactory.transport.getStsUrl()); GoogleCredentials credentials = GoogleCredentials.fromStream(stream, transportFactory); assertNotNull(credentials); // Create copy with mock executable handler. PluggableAuthCredentials copy = PluggableAuthCredentials.newBuilder((PluggableAuthCredentials) credentials) .setExecutableHandler(options -> "pluggableAuthToken") .build(); copy = copy.createScoped(SCOPES); Map> metadata = copy.getRequestMetadata(CALL_URI); TestUtils.assertContainsBearerToken(metadata, transportFactory.transport.getAccessToken()); } @Test public void fromStream_pluggableAuthCredentials_defaultUniverse() throws IOException { MockExternalAccountCredentialsTransportFactory transportFactory = new MockExternalAccountCredentialsTransportFactory(); InputStream stream = PluggableAuthCredentialsTest.writeCredentialsStream(transportFactory.transport.getStsUrl()); GoogleCredentials credentials = GoogleCredentials.fromStream(stream, transportFactory); assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); } @Test public void fromStream_externalAccountAuthorizedUserCredentials_providesToken() throws IOException { MockExternalAccountAuthorizedUserCredentialsTransportFactory transportFactory = new MockExternalAccountAuthorizedUserCredentialsTransportFactory(); InputStream stream = TestUtils.jsonToInputStream( ExternalAccountAuthorizedUserCredentialsTest.buildJsonCredentials()); GoogleCredentials credentials = GoogleCredentials.fromStream(stream, transportFactory); Map> metadata = credentials.getRequestMetadata(CALL_URI); TestUtils.assertContainsBearerToken(metadata, transportFactory.transport.getAccessToken()); } @Test public void fromStream_externalAccountAuthorizedUserCredentials_defaultUniverse() throws IOException { MockExternalAccountAuthorizedUserCredentialsTransportFactory transportFactory = new MockExternalAccountAuthorizedUserCredentialsTransportFactory(); GenericJson json = ExternalAccountAuthorizedUserCredentialsTest.buildJsonCredentials(); json.remove("universe_domain"); InputStream stream = TestUtils.jsonToInputStream(json); GoogleCredentials credentials = GoogleCredentials.fromStream(stream, transportFactory); assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); } @Test public void fromStream_Impersonation_providesToken_WithQuotaProject() throws IOException { MockTokenServerTransportFactory transportFactoryForSource = new MockTokenServerTransportFactory(); transportFactoryForSource.transport.addServiceAccount( ImpersonatedCredentialsTest.SA_CLIENT_EMAIL, ImpersonatedCredentialsTest.ACCESS_TOKEN); MockIAMCredentialsServiceTransportFactory transportFactory = new MockIAMCredentialsServiceTransportFactory(); transportFactory.transport.setTargetPrincipal( ImpersonatedCredentialsTest.IMPERSONATED_CLIENT_EMAIL); transportFactory.transport.setAccessToken(ImpersonatedCredentialsTest.ACCESS_TOKEN); transportFactory.transport.setExpireTime(ImpersonatedCredentialsTest.getDefaultExpireTime()); transportFactory.transport.setAccessTokenEndpoint( ImpersonatedCredentialsTest.IMPERSONATION_URL); InputStream impersonationCredentialsStream = ImpersonatedCredentialsTest.writeImpersonationCredentialsStream( ImpersonatedCredentialsTest.IMPERSONATION_URL, ImpersonatedCredentialsTest.DELEGATES, ImpersonatedCredentialsTest.QUOTA_PROJECT_ID); ImpersonatedCredentials credentials = (ImpersonatedCredentials) GoogleCredentials.fromStream(impersonationCredentialsStream, transportFactoryForSource); credentials.setTransportFactory(transportFactory); Map> metadata = credentials.getRequestMetadata(CALL_URI); TestUtils.assertContainsBearerToken(metadata, ImpersonatedCredentialsTest.ACCESS_TOKEN); assertTrue(metadata.containsKey("x-goog-user-project")); List headerValues = metadata.get("x-goog-user-project"); assertEquals(1, headerValues.size()); assertEquals(ImpersonatedCredentialsTest.QUOTA_PROJECT_ID, headerValues.get(0)); } @Test public void fromStream_Impersonation_defaultUniverse() throws IOException { MockTokenServerTransportFactory transportFactoryForSource = new MockTokenServerTransportFactory(); transportFactoryForSource.transport.addServiceAccount( ImpersonatedCredentialsTest.SA_CLIENT_EMAIL, ImpersonatedCredentialsTest.ACCESS_TOKEN); MockIAMCredentialsServiceTransportFactory transportFactory = new MockIAMCredentialsServiceTransportFactory(); InputStream impersonationCredentialsStream = ImpersonatedCredentialsTest.writeImpersonationCredentialsStream( ImpersonatedCredentialsTest.IMPERSONATION_URL, ImpersonatedCredentialsTest.DELEGATES, ImpersonatedCredentialsTest.QUOTA_PROJECT_ID); ImpersonatedCredentials credentials = (ImpersonatedCredentials) GoogleCredentials.fromStream(impersonationCredentialsStream, transportFactoryForSource); credentials.setTransportFactory(transportFactory); assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); } @Test public void fromStream_Impersonation_providesToken_WithoutQuotaProject() throws IOException { MockTokenServerTransportFactory transportFactoryForSource = new MockTokenServerTransportFactory(); transportFactoryForSource.transport.addServiceAccount( ImpersonatedCredentialsTest.SA_CLIENT_EMAIL, ImpersonatedCredentialsTest.ACCESS_TOKEN); MockIAMCredentialsServiceTransportFactory transportFactory = new MockIAMCredentialsServiceTransportFactory(); transportFactory.transport.setTargetPrincipal( ImpersonatedCredentialsTest.IMPERSONATED_CLIENT_EMAIL); transportFactory.transport.setAccessToken(ImpersonatedCredentialsTest.ACCESS_TOKEN); transportFactory.transport.setExpireTime(ImpersonatedCredentialsTest.getDefaultExpireTime()); transportFactory.transport.setAccessTokenEndpoint( ImpersonatedCredentialsTest.IMPERSONATION_URL); InputStream impersonationCredentialsStream = ImpersonatedCredentialsTest.writeImpersonationCredentialsStream( ImpersonatedCredentialsTest.IMPERSONATION_URL, ImpersonatedCredentialsTest.DELEGATES, null); ImpersonatedCredentials credentials = (ImpersonatedCredentials) GoogleCredentials.fromStream(impersonationCredentialsStream, transportFactoryForSource); credentials.setTransportFactory(transportFactory); Map> metadata = credentials.getRequestMetadata(CALL_URI); TestUtils.assertContainsBearerToken(metadata, ImpersonatedCredentialsTest.ACCESS_TOKEN); assertFalse(metadata.containsKey("x-goog-user-project")); } @Test public void createScoped_overloadCallsImplementation() { final AtomicReference> called = new AtomicReference<>(); final GoogleCredentials expectedScopedCredentials = new GoogleCredentials(); GoogleCredentials credentials = new GoogleCredentials() { @Override public GoogleCredentials createScoped(Collection scopes) { called.set(scopes); return expectedScopedCredentials; } }; GoogleCredentials scopedCredentials = credentials.createScoped("foo", "bar"); assertEquals(expectedScopedCredentials, scopedCredentials); assertEquals(ImmutableList.of("foo", "bar"), called.get()); } @Test public void create_withoutUniverse() throws IOException { AccessToken token = AccessToken.newBuilder().setTokenValue(ACCESS_TOKEN).build(); GoogleCredentials credentials = GoogleCredentials.create(token); assertEquals(GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); assertEquals(false, credentials.isExplicitUniverseDomain()); } @Test public void create_withUniverse() throws IOException { AccessToken token = AccessToken.newBuilder().setTokenValue(ACCESS_TOKEN).build(); GoogleCredentials credentials = GoogleCredentials.create("some-universe", token); assertEquals("some-universe", credentials.getUniverseDomain()); assertEquals(true, credentials.isExplicitUniverseDomain()); } @Test public void buildWithQuotaProject() { final GoogleCredentials googleCredentials = new GoogleCredentials.Builder().setQuotaProjectId("old_quota").build(); GoogleCredentials withUpdatedQuota = googleCredentials.createWithQuotaProject("new_quota"); assertEquals("old_quota", googleCredentials.getQuotaProjectId()); assertEquals("new_quota", withUpdatedQuota.getQuotaProjectId()); GoogleCredentials withEmptyQuota = googleCredentials.createWithQuotaProject(""); assertEquals("", withEmptyQuota.getQuotaProjectId()); GoogleCredentials sameCredentials = googleCredentials.createWithQuotaProject(null); assertEquals(null, sameCredentials.getQuotaProjectId()); } @Test public void buildWithUniverseDomain() throws IOException { final GoogleCredentials original = new GoogleCredentials.Builder().setUniverseDomain("universe1").build(); GoogleCredentials updated = original.toBuilder().setUniverseDomain("universe2").build(); assertEquals("universe1", original.getUniverseDomain()); assertEquals(true, original.isExplicitUniverseDomain()); assertEquals("universe2", updated.getUniverseDomain()); assertEquals(true, updated.isExplicitUniverseDomain()); GoogleCredentials withEmpty = original.toBuilder().setUniverseDomain("").build(); assertEquals(GOOGLE_DEFAULT_UNIVERSE, withEmpty.getUniverseDomain()); assertEquals(false, withEmpty.isExplicitUniverseDomain()); GoogleCredentials withNull = original.toBuilder().setUniverseDomain(null).build(); assertEquals(GOOGLE_DEFAULT_UNIVERSE, withNull.getUniverseDomain()); assertEquals(false, withNull.isExplicitUniverseDomain()); } @Test public void serialize() throws IOException, ClassNotFoundException { final GoogleCredentials testCredentials = new GoogleCredentials.Builder().build(); GoogleCredentials deserializedCredentials = serializeAndDeserialize(testCredentials); assertEquals(testCredentials, deserializedCredentials); assertEquals(testCredentials.hashCode(), deserializedCredentials.hashCode()); assertEquals(testCredentials.toString(), deserializedCredentials.toString()); assertSame(deserializedCredentials.clock, Clock.SYSTEM); } @Test public void toString_containsFields() throws IOException { String expectedToString = String.format( "GoogleCredentials{quotaProjectId=%s, universeDomain=%s, isExplicitUniverseDomain=%s}", "some-project", "googleapis.com", false, "[some scope]"); GoogleCredentials credentials = GoogleCredentials.newBuilder().setQuotaProjectId("some-project").build(); assertEquals(expectedToString, credentials.toString()); } @Test public void hashCode_equals() throws IOException { GoogleCredentials credentials = GoogleCredentials.newBuilder().setUniverseDomain("some-domain").build(); GoogleCredentials otherCredentials = GoogleCredentials.newBuilder().setUniverseDomain("some-domain").build(); assertEquals(credentials.hashCode(), otherCredentials.hashCode()); } @Test public void equals_true() throws IOException { GoogleCredentials credentials = GoogleCredentials.newBuilder().setUniverseDomain("some-domain").build(); GoogleCredentials otherCredentials = GoogleCredentials.newBuilder().setUniverseDomain("some-domain").build(); assertTrue(credentials.equals(otherCredentials)); assertTrue(otherCredentials.equals(credentials)); } private static void testFromStreamException(InputStream stream, String expectedMessageContent) { try { GoogleCredentials.fromStream(stream, DUMMY_TRANSPORT_FACTORY); fail( String.format( "Should throw exception with message containing '%s'", expectedMessageContent)); } catch (IOException expected) { assertTrue(expected.getMessage().contains(expectedMessageContent)); } } }