diff --git a/oauth2_http/java/com/google/auth/oauth2/GoogleCredentials.java b/oauth2_http/java/com/google/auth/oauth2/GoogleCredentials.java index 94fa4a879..7d91a33ac 100644 --- a/oauth2_http/java/com/google/auth/oauth2/GoogleCredentials.java +++ b/oauth2_http/java/com/google/auth/oauth2/GoogleCredentials.java @@ -38,6 +38,8 @@ import com.google.auth.Credentials; import com.google.auth.http.HttpTransportFactory; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.MoreObjects; +import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.collect.ImmutableList; import java.io.IOException; import java.io.InputStream; @@ -48,6 +50,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import javax.annotation.Nullable; /** Base type for credentials for authorizing calls to Google APIs using OAuth2. */ @@ -227,17 +230,6 @@ static GoogleCredentials fromJson(Map json) throws IOException { return credentialsBuilder.build(); } - /** - * Creates a credential with the provided universe domain. - * - * @param universeDomain the universe domain to set on the credential. Empty or null value will - * result in the default universe domain 'googleapis.com' - * @return credential with the provided universe domain - */ - public GoogleCredentials createWithUniverseDomain(String universeDomain) { - return this.toBuilder().setUniverseDomain(universeDomain).build(); - } - /** * Creates a credential with the provided quota project. * @@ -354,6 +346,38 @@ protected GoogleCredentials( this.universeDomain = null; } + /** + * A helper for overriding toString that allows inheritance of super class fields + * Extending classes can override this implementation and call super implementation and then + * add more fields. Same cannot be done with ToString() directly. + * @return an instance of the ToStringHelper that has all the relevant fields added + */ + protected ToStringHelper toStringHelper() { + return MoreObjects.toStringHelper(this).omitNullValues() + .add("quotaProjectId", quotaProjectId) + .add("universeDomain", getUniverseDomain()); + } + + @Override + public String toString() { + return toStringHelper().toString(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof GoogleCredentials)) { + return false; + } + GoogleCredentials other = (GoogleCredentials) obj; + return Objects.equals(this.getQuotaProjectId(), other.getQuotaProjectId()) + && Objects.equals(this.getUniverseDomain(), other.getUniverseDomain()); + } + + @Override + public int hashCode() { + return Objects.hash(getQuotaProjectId(), getUniverseDomain()); + } + public static Builder newBuilder() { return new Builder(); } diff --git a/oauth2_http/java/com/google/auth/oauth2/ServiceAccountCredentials.java b/oauth2_http/java/com/google/auth/oauth2/ServiceAccountCredentials.java index 0b2866fd8..907511d1c 100644 --- a/oauth2_http/java/com/google/auth/oauth2/ServiceAccountCredentials.java +++ b/oauth2_http/java/com/google/auth/oauth2/ServiceAccountCredentials.java @@ -55,6 +55,7 @@ import com.google.auth.http.HttpTransportFactory; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; +import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.collect.ImmutableSet; import java.io.IOException; import java.io.InputStream; @@ -754,28 +755,26 @@ public int hashCode() { tokenServerUri, scopes, defaultScopes, - quotaProjectId, lifetime, useJwtAccessWithScope, - defaultRetriesEnabled); + defaultRetriesEnabled, + super.hashCode()); } @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("clientId", clientId) - .add("clientEmail", clientEmail) - .add("privateKeyId", privateKeyId) - .add("transportFactoryClassName", transportFactoryClassName) - .add("tokenServerUri", tokenServerUri) - .add("scopes", scopes) - .add("defaultScopes", defaultScopes) - .add("serviceAccountUser", serviceAccountUser) - .add("quotaProjectId", quotaProjectId) - .add("lifetime", lifetime) - .add("useJwtAccessWithScope", useJwtAccessWithScope) - .add("defaultRetriesEnabled", defaultRetriesEnabled) - .toString(); + protected ToStringHelper toStringHelper() { + return super.toStringHelper() + .add("clientId", clientId) + .add("clientEmail", clientEmail) + .add("privateKeyId", privateKeyId) + .add("transportFactoryClassName", transportFactoryClassName) + .add("tokenServerUri", tokenServerUri) + .add("scopes", scopes) + .add("defaultScopes", defaultScopes) + .add("serviceAccountUser", serviceAccountUser) + .add("lifetime", lifetime) + .add("useJwtAccessWithScope", useJwtAccessWithScope) + .add("defaultRetriesEnabled", defaultRetriesEnabled); } @Override @@ -783,6 +782,10 @@ public boolean equals(Object obj) { if (!(obj instanceof ServiceAccountCredentials)) { return false; } + if (!super.equals(obj)) { + return false; + } + ServiceAccountCredentials other = (ServiceAccountCredentials) obj; return Objects.equals(this.clientId, other.clientId) && Objects.equals(this.clientEmail, other.clientEmail) @@ -792,7 +795,6 @@ public boolean equals(Object obj) { && Objects.equals(this.tokenServerUri, other.tokenServerUri) && Objects.equals(this.scopes, other.scopes) && Objects.equals(this.defaultScopes, other.defaultScopes) - && Objects.equals(this.quotaProjectId, other.quotaProjectId) && Objects.equals(this.lifetime, other.lifetime) && Objects.equals(this.useJwtAccessWithScope, other.useJwtAccessWithScope) && Objects.equals(this.defaultRetriesEnabled, other.defaultRetriesEnabled); diff --git a/oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountCredentialsTest.java b/oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountCredentialsTest.java index 5760714fa..2681df42e 100644 --- a/oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountCredentialsTest.java +++ b/oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountCredentialsTest.java @@ -51,6 +51,7 @@ import com.google.api.client.testing.http.MockLowLevelHttpResponse; import com.google.api.client.util.Clock; import com.google.api.client.util.Joiner; +import com.google.auth.Credentials; import com.google.auth.RequestMetadataCallback; import com.google.auth.TestUtils; import com.google.auth.http.AuthHttpConstants; @@ -414,8 +415,7 @@ public void createdScoped_withAud_noUniverse_jwtWithScopesDisabled_accessToken() @Test public void createdScoped_withUniverse_selfSignedJwt() throws IOException { - GoogleCredentials credentials = createDefaultBuilder().build(); - credentials = credentials.createWithUniverseDomain("foo.bar"); + GoogleCredentials credentials = createDefaultBuilder().setUniverseDomain("foo.bar").build(); try { credentials.getRequestMetadata(null); @@ -452,8 +452,7 @@ public void createdScoped_withUniverse_selfSignedJwt() throws IOException { @Test public void noScopes_withUniverse_selfSignedJwt() throws IOException { - GoogleCredentials credentials = createDefaultBuilder().build(); - credentials = credentials.createWithUniverseDomain("foo.bar"); + GoogleCredentials credentials = createDefaultBuilder().setUniverseDomain("foo.bar").build(); try { credentials.getRequestMetadata(null); @@ -1027,6 +1026,35 @@ public void equals_false_email() throws IOException { assertFalse(otherCredentials.equals(credentials)); } + @Test + public void equals_false_super() throws IOException { + final URI tokenServer1 = URI.create("https://foo1.com/bar"); + MockTokenServerTransportFactory serverTransportFactory = new MockTokenServerTransportFactory(); + OAuth2Credentials credentials = + ServiceAccountCredentials.fromPkcs8( + CLIENT_ID, + CLIENT_EMAIL, + PRIVATE_KEY_PKCS8, + PRIVATE_KEY_ID, + SCOPES, + serverTransportFactory, + tokenServer1); + OAuth2Credentials otherCredentials = + ServiceAccountCredentials.fromPkcs8( + CLIENT_ID, + CLIENT_EMAIL, + PRIVATE_KEY_PKCS8, + PRIVATE_KEY_ID, + SCOPES, + serverTransportFactory, + tokenServer1) + .toBuilder() + .setUniverseDomain("universe.com") + .build(); + assertFalse(credentials.equals(otherCredentials)); + assertFalse(otherCredentials.equals(credentials)); + } + @Test public void equals_false_keyId() throws IOException { final URI tokenServer1 = URI.create("https://foo1.com/bar"); @@ -1152,9 +1180,11 @@ public void toString_containsFields() throws IOException { OAuth2Credentials credentials = ServiceAccountCredentials.fromPkcs8(PRIVATE_KEY_PKCS8, builder); String expectedToString = String.format( - "ServiceAccountCredentials{clientId=%s, clientEmail=%s, privateKeyId=%s, " - + "transportFactoryClassName=%s, tokenServerUri=%s, scopes=%s, defaultScopes=%s, serviceAccountUser=%s, " - + "quotaProjectId=%s, lifetime=3600, useJwtAccessWithScope=false, defaultRetriesEnabled=true}", + "ServiceAccountCredentials{quotaProjectId=%s, universeDomain=%s, clientId=%s, clientEmail=%s, " + + "privateKeyId=%s, transportFactoryClassName=%s, tokenServerUri=%s, scopes=%s, defaultScopes=%s, " + + "serviceAccountUser=%s, lifetime=3600, useJwtAccessWithScope=false, defaultRetriesEnabled=true}", + QUOTA_PROJECT, + Credentials.GOOGLE_DEFAULT_UNIVERSE, CLIENT_ID, CLIENT_EMAIL, PRIVATE_KEY_ID, @@ -1162,8 +1192,7 @@ public void toString_containsFields() throws IOException { tokenServer, SCOPES, DEFAULT_SCOPES, - USER, - QUOTA_PROJECT); + USER); assertEquals(expectedToString, credentials.toString()); } @@ -1179,7 +1208,11 @@ public void hashCode_equals() throws IOException { PRIVATE_KEY_ID, SCOPES, transportFactory, - tokenServer); + tokenServer) + .createWithQuotaProject(QUOTA_PROJECT) + .toBuilder() + .setUniverseDomain("universe.com") + .build(); OAuth2Credentials otherCredentials = ServiceAccountCredentials.fromPkcs8( CLIENT_ID, @@ -1188,10 +1221,40 @@ public void hashCode_equals() throws IOException { PRIVATE_KEY_ID, SCOPES, transportFactory, - tokenServer); + tokenServer) + .createWithQuotaProject(QUOTA_PROJECT) + .toBuilder() + .setUniverseDomain("universe.com") + .build(); assertEquals(credentials.hashCode(), otherCredentials.hashCode()); } + @Test + public void hashCode_not_equals_quota() throws IOException { + final URI tokenServer = URI.create("https://foo.com/bar"); + MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory(); + OAuth2Credentials credentials = + ServiceAccountCredentials.fromPkcs8( + CLIENT_ID, + CLIENT_EMAIL, + PRIVATE_KEY_PKCS8, + PRIVATE_KEY_ID, + SCOPES, + transportFactory, + tokenServer); + OAuth2Credentials otherCredentials = + ServiceAccountCredentials.fromPkcs8( + CLIENT_ID, + CLIENT_EMAIL, + PRIVATE_KEY_PKCS8, + PRIVATE_KEY_ID, + SCOPES, + transportFactory, + tokenServer) + .createWithQuotaProject("some_quota"); + assertNotEquals(credentials.hashCode(), otherCredentials.hashCode()); + } + @Test public void serialize() throws IOException, ClassNotFoundException { final URI tokenServer = URI.create("https://foo.com/bar");