diff --git a/google-auth-library-java/appengine/javatests/com/google/auth/appengine/AppEngineCredentialsTest.java b/google-auth-library-java/appengine/javatests/com/google/auth/appengine/AppEngineCredentialsTest.java
index 05f81d57825f..3830d62dda20 100644
--- a/google-auth-library-java/appengine/javatests/com/google/auth/appengine/AppEngineCredentialsTest.java
+++ b/google-auth-library-java/appengine/javatests/com/google/auth/appengine/AppEngineCredentialsTest.java
@@ -36,8 +36,8 @@
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import com.google.auth.Credentials;
import com.google.auth.oauth2.AccessToken;
@@ -135,11 +135,7 @@ void createScoped_clonesWithScopes() throws IOException {
.setAppIdentityService(appIdentity)
.build();
assertTrue(credentials.createScopedRequired());
- try {
- credentials.getRequestMetadata(CALL_URI);
- fail("Should not be able to use credential without scopes.");
- } catch (Exception expected) {
- }
+ assertThrows(IOException.class, () -> credentials.getRequestMetadata(CALL_URI));
assertEquals(0, appIdentity.getGetAccessTokenCallCount());
GoogleCredentials scopedCredentials = credentials.createScoped(SCOPES);
diff --git a/google-auth-library-java/oauth2_http/java/com/google/auth/mtls/MtlsUtils.java b/google-auth-library-java/oauth2_http/java/com/google/auth/mtls/MtlsUtils.java
new file mode 100644
index 000000000000..0d34cf271986
--- /dev/null
+++ b/google-auth-library-java/oauth2_http/java/com/google/auth/mtls/MtlsUtils.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * 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 LLC 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.mtls;
+
+import com.google.api.core.InternalApi;
+import com.google.auth.oauth2.EnvironmentProvider;
+import com.google.auth.oauth2.PropertyProvider;
+import com.google.common.base.Strings;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Locale;
+
+/**
+ * Utility class for mTLS related operations.
+ *
+ *
For internal use only.
+ */
+@InternalApi
+public class MtlsUtils {
+ static final String CERTIFICATE_CONFIGURATION_ENV_VARIABLE = "GOOGLE_API_CERTIFICATE_CONFIG";
+ static final String WELL_KNOWN_CERTIFICATE_CONFIG_FILE = "certificate_config.json";
+ static final String CLOUDSDK_CONFIG_DIRECTORY = "gcloud";
+
+ private MtlsUtils() {
+ // Prevent instantiation for Utility class
+ }
+
+ /**
+ * Returns the path to the client certificate file specified by the loaded workload certificate
+ * configuration.
+ *
+ * @return The path to the certificate file.
+ * @throws IOException if the certificate configuration cannot be found or loaded.
+ */
+ public static String getCertificatePath(
+ EnvironmentProvider envProvider, PropertyProvider propProvider, String certConfigPathOverride)
+ throws IOException {
+ String certPath =
+ getWorkloadCertificateConfiguration(envProvider, propProvider, certConfigPathOverride)
+ .getCertPath();
+ if (Strings.isNullOrEmpty(certPath)) {
+ throw new CertificateSourceUnavailableException(
+ "Certificate configuration loaded successfully, but does not contain a 'certificate_file' path.");
+ }
+ return certPath;
+ }
+
+ /**
+ * Resolves and loads the workload certificate configuration.
+ *
+ *
The configuration file is resolved in the following order of precedence: 1. The provided
+ * certConfigPathOverride (if not null). 2. The path specified by the
+ * GOOGLE_API_CERTIFICATE_CONFIG environment variable. 3. The well-known certificate configuration
+ * file in the gcloud config directory.
+ *
+ * @param envProvider the environment provider to use for resolving environment variables
+ * @param propProvider the property provider to use for resolving system properties
+ * @param certConfigPathOverride optional override path for the configuration file
+ * @return the loaded WorkloadCertificateConfiguration
+ * @throws IOException if the configuration file cannot be found, read, or parsed
+ */
+ static WorkloadCertificateConfiguration getWorkloadCertificateConfiguration(
+ EnvironmentProvider envProvider, PropertyProvider propProvider, String certConfigPathOverride)
+ throws IOException {
+ File certConfig;
+ if (certConfigPathOverride != null) {
+ certConfig = new File(certConfigPathOverride);
+ } else {
+ String envCredentialsPath = envProvider.getEnv(CERTIFICATE_CONFIGURATION_ENV_VARIABLE);
+ if (!Strings.isNullOrEmpty(envCredentialsPath)) {
+ certConfig = new File(envCredentialsPath);
+ } else {
+ certConfig = getWellKnownCertificateConfigFile(envProvider, propProvider);
+ }
+ }
+
+ if (!certConfig.isFile()) {
+ throw new CertificateSourceUnavailableException(
+ "Certificate configuration file does not exist or is not a file: "
+ + certConfig.getAbsolutePath());
+ }
+ try (InputStream certConfigStream = new FileInputStream(certConfig)) {
+ return WorkloadCertificateConfiguration.fromCertificateConfigurationStream(certConfigStream);
+ }
+ }
+
+ private static File getWellKnownCertificateConfigFile(
+ EnvironmentProvider envProvider, PropertyProvider propProvider) throws IOException {
+ File cloudConfigPath;
+ String envPath = envProvider.getEnv("CLOUDSDK_CONFIG");
+ if (envPath != null) {
+ cloudConfigPath = new File(envPath);
+ } else {
+ String osName = propProvider.getProperty("os.name", "").toLowerCase(Locale.US);
+ if (osName.indexOf("windows") >= 0) {
+ String appData = envProvider.getEnv("APPDATA");
+ if (Strings.isNullOrEmpty(appData)) {
+ throw new CertificateSourceUnavailableException(
+ "APPDATA environment variable is not set on Windows.");
+ }
+ File appDataPath = new File(appData);
+ cloudConfigPath = new File(appDataPath, CLOUDSDK_CONFIG_DIRECTORY);
+ } else {
+ File configPath = new File(propProvider.getProperty("user.home", ""), ".config");
+ cloudConfigPath = new File(configPath, CLOUDSDK_CONFIG_DIRECTORY);
+ }
+ }
+ return new File(cloudConfigPath, WELL_KNOWN_CERTIFICATE_CONFIG_FILE);
+ }
+}
diff --git a/google-auth-library-java/oauth2_http/java/com/google/auth/mtls/X509Provider.java b/google-auth-library-java/oauth2_http/java/com/google/auth/mtls/X509Provider.java
index 7ff490f0f147..4127b1492460 100644
--- a/google-auth-library-java/oauth2_http/java/com/google/auth/mtls/X509Provider.java
+++ b/google-auth-library-java/oauth2_http/java/com/google/auth/mtls/X509Provider.java
@@ -31,15 +31,17 @@
package com.google.auth.mtls;
import com.google.api.client.util.SecurityUtils;
-import com.google.common.base.Strings;
+import com.google.api.core.InternalApi;
+import com.google.auth.oauth2.EnvironmentProvider;
+import com.google.auth.oauth2.PropertyProvider;
+import com.google.auth.oauth2.SystemEnvironmentProvider;
+import com.google.auth.oauth2.SystemPropertyProvider;
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.security.KeyStore;
-import java.util.Locale;
/**
* This class implements {@link MtlsProvider} for the Google Auth library transport layer via {@link
@@ -47,11 +49,10 @@
* libraries, and the public facing methods may be changed without notice, and have no guarantee of
* backwards compatibility.
*/
+@InternalApi
public class X509Provider implements MtlsProvider {
- static final String CERTIFICATE_CONFIGURATION_ENV_VARIABLE = "GOOGLE_API_CERTIFICATE_CONFIG";
- static final String WELL_KNOWN_CERTIFICATE_CONFIG_FILE = "certificate_config.json";
- static final String CLOUDSDK_CONFIG_DIRECTORY = "gcloud";
-
+ private final EnvironmentProvider envProvider;
+ private final PropertyProvider propProvider;
private final String certConfigPathOverride;
/**
@@ -59,12 +60,32 @@ public class X509Provider implements MtlsProvider {
* normal checks for the well known certificate configuration file path and environment variable.
* This is meant for internal Google Cloud usage and behavior may be changed without warning.
*
+ * @param envProvider environment provider used for environment variables
+ * @param propProvider property provider used for system properties
* @param certConfigPathOverride the path to read the certificate configuration from.
*/
- public X509Provider(String certConfigPathOverride) {
+ @InternalApi
+ public X509Provider(
+ EnvironmentProvider envProvider,
+ PropertyProvider propProvider,
+ String certConfigPathOverride) {
+ this.envProvider = envProvider;
+ this.propProvider = propProvider;
this.certConfigPathOverride = certConfigPathOverride;
}
+ /**
+ * Creates an X509 provider with an override path for the certificate configuration.
+ *
+ * @param certConfigPathOverride the path to read the certificate configuration from.
+ */
+ public X509Provider(String certConfigPathOverride) {
+ this(
+ SystemEnvironmentProvider.getInstance(),
+ SystemPropertyProvider.getInstance(),
+ certConfigPathOverride);
+ }
+
/**
* Creates a new X.509 provider that will check the environment variable path and the well known
* Gcloud certificate configuration location. This is meant for internal Google Cloud usage and
@@ -74,29 +95,6 @@ public X509Provider() {
this(null);
}
- /**
- * Returns the path to the client certificate file specified by the loaded workload certificate
- * configuration.
- *
- *
If the configuration has not been loaded yet (e.g., if {@link #getKeyStore()} has not been
- * called), this method will attempt to load it first by searching the override path, environment
- * variable, and well-known locations.
- *
- * @return The path to the certificate file.
- * @throws IOException if the certificate configuration cannot be found or loaded, or if the
- * configuration file does not specify a certificate path.
- * @throws CertificateSourceUnavailableException if the configuration file is not found.
- */
- public String getCertificatePath() throws IOException {
- String certPath = getWorkloadCertificateConfiguration().getCertPath();
- if (Strings.isNullOrEmpty(certPath)) {
- // Ensure the loaded configuration actually contains the required path.
- throw new CertificateSourceUnavailableException(
- "Certificate configuration loaded successfully, but does not contain a 'certificate_file' path.");
- }
- return certPath;
- }
-
/**
* Finds the certificate configuration file, then builds a Keystore using the X.509 certificate
* and private key pointed to by the configuration. This will check the following locations in
@@ -115,12 +113,14 @@ public String getCertificatePath() throws IOException {
*/
@Override
public KeyStore getKeyStore() throws CertificateSourceUnavailableException, IOException {
- WorkloadCertificateConfiguration workloadCertConfig = getWorkloadCertificateConfiguration();
+ WorkloadCertificateConfiguration workloadCertConfig =
+ MtlsUtils.getWorkloadCertificateConfiguration(
+ envProvider, propProvider, certConfigPathOverride);
// Read the certificate and private key file paths into streams.
- try (InputStream certStream = createInputStream(new File(workloadCertConfig.getCertPath()));
+ try (InputStream certStream = new FileInputStream(new File(workloadCertConfig.getCertPath()));
InputStream privateKeyStream =
- createInputStream(new File(workloadCertConfig.getPrivateKeyPath()));
+ new FileInputStream(new File(workloadCertConfig.getPrivateKeyPath()));
SequenceInputStream certAndPrivateKeyStream =
new SequenceInputStream(certStream, privateKeyStream)) {
@@ -149,74 +149,4 @@ public boolean isAvailable() throws IOException {
}
return true;
}
-
- private WorkloadCertificateConfiguration getWorkloadCertificateConfiguration()
- throws IOException {
- File certConfig;
- if (this.certConfigPathOverride != null) {
- certConfig = new File(certConfigPathOverride);
- } else {
- String envCredentialsPath = getEnv(CERTIFICATE_CONFIGURATION_ENV_VARIABLE);
- if (!Strings.isNullOrEmpty(envCredentialsPath)) {
- certConfig = new File(envCredentialsPath);
- } else {
- certConfig = getWellKnownCertificateConfigFile();
- }
- }
- InputStream certConfigStream = null;
- try {
- if (!isFile(certConfig)) {
- // Path will be put in the message from the catch block below
- throw new CertificateSourceUnavailableException("File does not exist.");
- }
- certConfigStream = createInputStream(certConfig);
- return WorkloadCertificateConfiguration.fromCertificateConfigurationStream(certConfigStream);
- } finally {
- if (certConfigStream != null) {
- certConfigStream.close();
- }
- }
- }
-
- /*
- * Start of methods to allow overriding in the test code to isolate from the environment.
- */
- boolean isFile(File file) {
- return file.isFile();
- }
-
- InputStream createInputStream(File file) throws FileNotFoundException {
- return new FileInputStream(file);
- }
-
- String getEnv(String name) {
- return System.getenv(name);
- }
-
- String getOsName() {
- return getProperty("os.name", "").toLowerCase(Locale.US);
- }
-
- String getProperty(String property, String def) {
- return System.getProperty(property, def);
- }
-
- /*
- * End of methods to allow overriding in the test code to isolate from the environment.
- */
-
- private File getWellKnownCertificateConfigFile() {
- File cloudConfigPath;
- String envPath = getEnv("CLOUDSDK_CONFIG");
- if (envPath != null) {
- cloudConfigPath = new File(envPath);
- } else if (getOsName().indexOf("windows") >= 0) {
- File appDataPath = new File(getEnv("APPDATA"));
- cloudConfigPath = new File(appDataPath, CLOUDSDK_CONFIG_DIRECTORY);
- } else {
- File configPath = new File(getProperty("user.home", ""), ".config");
- cloudConfigPath = new File(configPath, CLOUDSDK_CONFIG_DIRECTORY);
- }
- return new File(cloudConfigPath, WELL_KNOWN_CERTIFICATE_CONFIG_FILE);
- }
}
diff --git a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/AwsCredentials.java b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/AwsCredentials.java
index 3085765317b7..bb943fcdf3b2 100644
--- a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/AwsCredentials.java
+++ b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/AwsCredentials.java
@@ -196,11 +196,6 @@ String getRegionalCredentialVerificationUrl() {
return this.regionalCredentialVerificationUrl;
}
- @VisibleForTesting
- String getEnv(String name) {
- return System.getenv(name);
- }
-
@VisibleForTesting
AwsSecurityCredentialsSupplier getAwsSecurityCredentialsSupplier() {
return this.awsSecurityCredentialsSupplier;
diff --git a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/EnvironmentProvider.java b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/EnvironmentProvider.java
index 5c77ecc65764..26373f4cd729 100644
--- a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/EnvironmentProvider.java
+++ b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/EnvironmentProvider.java
@@ -1,6 +1,43 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * 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 LLC 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;
-/** Interface for an environment provider. */
-interface EnvironmentProvider {
+import com.google.api.core.InternalApi;
+
+/**
+ * Interface for an environment provider.
+ *
+ *
For internal use only.
+ */
+@InternalApi
+public interface EnvironmentProvider {
String getEnv(String name);
}
diff --git a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/ExternalAccountCredentials.java b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/ExternalAccountCredentials.java
index 7f9f0c20774b..e92c64bed90e 100644
--- a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/ExternalAccountCredentials.java
+++ b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/ExternalAccountCredentials.java
@@ -97,6 +97,7 @@ public abstract class ExternalAccountCredentials extends GoogleCredentials {
@Nullable protected ImpersonatedCredentials impersonatedCredentials;
private EnvironmentProvider environmentProvider;
+ private PropertyProvider propertyProvider;
private int connectTimeout;
private int readTimeout;
@@ -205,6 +206,7 @@ protected ExternalAccountCredentials(
: scopes;
this.environmentProvider =
environmentProvider == null ? SystemEnvironmentProvider.getInstance() : environmentProvider;
+ this.propertyProvider = SystemPropertyProvider.getInstance();
this.workforcePoolUserProject = null;
this.serviceAccountImpersonationOptions =
new ServiceAccountImpersonationOptions(new HashMap());
@@ -253,6 +255,10 @@ protected ExternalAccountCredentials(ExternalAccountCredentials.Builder builder)
builder.environmentProvider == null
? SystemEnvironmentProvider.getInstance()
: builder.environmentProvider;
+ this.propertyProvider =
+ builder.propertyProvider == null
+ ? SystemPropertyProvider.getInstance()
+ : builder.propertyProvider;
this.serviceAccountImpersonationOptions =
builder.serviceAccountImpersonationOptions == null
? new ServiceAccountImpersonationOptions(new HashMap())
@@ -657,6 +663,10 @@ EnvironmentProvider getEnvironmentProvider() {
return environmentProvider;
}
+ PropertyProvider getPropertyProvider() {
+ return propertyProvider;
+ }
+
/**
* @return whether the current configuration is for Workforce Pools (which enable 3p user
* identities, rather than workloads)
@@ -772,6 +782,7 @@ public abstract static class Builder extends GoogleCredentials.Builder {
protected String tokenInfoUrl;
protected CredentialSource credentialSource;
protected EnvironmentProvider environmentProvider;
+ protected PropertyProvider propertyProvider;
protected HttpTransportFactory transportFactory;
@Nullable protected String serviceAccountImpersonationUrl;
@@ -806,6 +817,7 @@ protected Builder(ExternalAccountCredentials credentials) {
this.clientSecret = credentials.clientSecret;
this.scopes = credentials.scopes;
this.environmentProvider = credentials.environmentProvider;
+ this.propertyProvider = credentials.propertyProvider;
this.workforcePoolUserProject = credentials.workforcePoolUserProject;
this.serviceAccountImpersonationOptions = credentials.serviceAccountImpersonationOptions;
this.metricsHandler = credentials.metricsHandler;
@@ -1029,6 +1041,18 @@ Builder setEnvironmentProvider(EnvironmentProvider environmentProvider) {
return this;
}
+ /**
+ * Sets the optional Property Provider.
+ *
+ * @param propertyProvider the {@code PropertyProvider} to set
+ * @return this {@code Builder} object
+ */
+ @CanIgnoreReturnValue
+ Builder setPropertyProvider(PropertyProvider propertyProvider) {
+ this.propertyProvider = propertyProvider;
+ return this;
+ }
+
@Override
public abstract ExternalAccountCredentials build();
}
diff --git a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/GdchCredentials.java b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/GdchCredentials.java
index a71a8c39029e..e8b81c71c35d 100644
--- a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/GdchCredentials.java
+++ b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/GdchCredentials.java
@@ -37,18 +37,25 @@
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.HttpResponseException;
import com.google.api.client.http.HttpTransport;
-import com.google.api.client.http.UrlEncodedContent;
import com.google.api.client.http.javanet.NetHttpTransport;
+import com.google.api.client.http.json.JsonHttpContent;
import com.google.api.client.json.GenericJson;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.JsonObjectParser;
+import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.json.webtoken.JsonWebSignature;
import com.google.api.client.json.webtoken.JsonWebToken;
+import com.google.api.client.util.Clock;
import com.google.api.client.util.GenericData;
+import com.google.api.client.util.PemReader;
+import com.google.api.client.util.SecurityUtils;
+import com.google.api.client.util.StringUtils;
+import com.google.api.core.ObsoleteApi;
import com.google.auth.http.HttpTransportFactory;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.File;
import java.io.FileInputStream;
@@ -56,10 +63,19 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
+import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
import java.security.PrivateKey;
+import java.security.spec.ECGenParameterSpec;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPrivateKeySpec;
+import java.util.Base64;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
@@ -67,8 +83,23 @@
public class GdchCredentials extends GoogleCredentials {
private static final LoggerProvider LOGGER_PROVIDER =
LoggerProvider.forClazz(GdchCredentials.class);
- static final String SUPPORTED_FORMAT_VERSION = "1";
private static final String PARSE_ERROR_PREFIX = "Error parsing token refresh response. ";
+
+ /**
+ * The expected format version for GDCH credential profiles. Version "1" indicates the initial and
+ * currently supported JSON format for these credentials. See go/gdch-python-auth-lib for more
+ * info.
+ */
+ @VisibleForTesting static final String SUPPORTED_JSON_FORMAT_VERSION = "1";
+
+ // Custom URN used by GDCH to identify service account tokens in token exchange requests.
+ // See go/gdch-python-auth-lib for more information.
+ private static final String SERVICE_ACCOUNT_TOKEN_TYPE =
+ "urn:k8s:params:oauth:token-type:serviceaccount";
+
+ private static final String PRIVATE_KEY_PEM_TITLE = "PRIVATE KEY";
+ private static final String EC_PRIVATE_KEY_PEM_TITLE = "EC PRIVATE KEY";
+
private static final int DEFAULT_LIFETIME_IN_SECONDS = 3600;
private final PrivateKey privateKey;
@@ -76,7 +107,7 @@ public class GdchCredentials extends GoogleCredentials {
private final String projectId;
private final String serviceIdentityName;
private final URI tokenServerUri;
- private final URI apiAudience;
+ private final String apiAudience;
private final int lifetime;
private final String transportFactoryClassName;
private final String caCertPath;
@@ -181,15 +212,15 @@ static GdchCredentials fromJson(Map json, HttpTransportFactory t
String formatVersion = validateField((String) json.get("format_version"), "format_version");
String projectId = validateField((String) json.get("project"), "project");
String privateKeyId = validateField((String) json.get("private_key_id"), "private_key_id");
- String privateKeyPkcs8 = validateField((String) json.get("private_key"), "private_key");
+ String privateKeyPem = validateField((String) json.get("private_key"), "private_key");
String serviceIdentityName = validateField((String) json.get("name"), "name");
String tokenServerUriStringFromCreds =
validateField((String) json.get("token_uri"), "token_uri");
String caCertPath = (String) json.get("ca_cert_path");
- if (!SUPPORTED_FORMAT_VERSION.equals(formatVersion)) {
+ if (!SUPPORTED_JSON_FORMAT_VERSION.equals(formatVersion)) {
throw new IOException(
- String.format("Only format version %s is supported.", SUPPORTED_FORMAT_VERSION));
+ String.format("Only format version %s is supported.", SUPPORTED_JSON_FORMAT_VERSION));
}
URI tokenServerUriFromCreds = null;
@@ -208,32 +239,71 @@ static GdchCredentials fromJson(Map json, HttpTransportFactory t
.setCaCertPath(caCertPath)
.setHttpTransportFactory(transportFactory);
- return fromPkcs8(privateKeyPkcs8, builder);
+ return fromPem(privateKeyPem, builder);
}
/**
- * Internal constructor.
+ * Reads a private key from a PEM encoded string, supporting both PKCS#8 and SEC1 formats.
*
- * @param privateKeyPkcs8 RSA private key object for the service account in PKCS#8 format.
+ * If the key is labeled with "PRIVATE KEY", it is parsed as PKCS#8 as per RFC 7468 Section 10.
+ * If it is labeled with "EC PRIVATE KEY", it is parsed as SEC1 as per RFC 5915 Section 3.
+ *
+ * @see RFC 7468 Section 10
+ * @see RFC 5915 Section 3
+ * @param privateKeyPem EC private key object for the service account in PEM format (PKCS#8 or
+ * SEC1).
* @param builder A builder for GdchCredentials.
* @return an instance of GdchCredentials.
*/
- static GdchCredentials fromPkcs8(String privateKeyPkcs8, GdchCredentials.Builder builder)
+ static GdchCredentials fromPem(String privateKeyPem, GdchCredentials.Builder builder)
throws IOException {
- PrivateKey privateKey = OAuth2Utils.privateKeyFromPkcs8(privateKeyPkcs8);
+ Reader reader = new StringReader(privateKeyPem);
+ // Read the first section regardless of title
+ PemReader.Section section = PemReader.readFirstSectionAndClose(reader);
+
+ if (section == null) {
+ throw new GoogleAuthException(false, 0, "Invalid key data: no PEM section found.", null);
+ }
+
+ String title = section.getTitle();
+ PrivateKey privateKey;
+
+ if (PRIVATE_KEY_PEM_TITLE.equals(title)) {
+ privateKey = OAuth2Utils.privateKeyFromPkcs8(privateKeyPem, OAuth2Utils.Pkcs8Algorithm.EC);
+ } else if (EC_PRIVATE_KEY_PEM_TITLE.equals(title)) {
+ privateKey = privateKeyFromSec1(section.getBase64DecodedBytes());
+ } else {
+ throw new GoogleAuthException(false, 0, "Unsupported key type: " + title, null);
+ }
+
builder.setPrivateKey(privateKey);
return new GdchCredentials(builder);
}
/**
- * Create a copy of GDCH credentials with the specified audience.
+ * This method is obsolete. Please use {@link #createWithGdchAudience(String)}} instead. Create a
+ * copy of GDCH credentials with the specified audience.
*
* @param apiAudience The intended audience for GDCH credentials.
*/
- public GdchCredentials createWithGdchAudience(URI apiAudience) throws IOException {
+ @ObsoleteApi("Use createWithGdchAudience(String) instead.")
+ public GdchCredentials createWithGdchAudience(URI apiAudience) {
Preconditions.checkNotNull(
apiAudience, "Audience are not configured for GDCH service account credentials.");
+ return this.toBuilder().setGdchAudience(apiAudience.toString()).build();
+ }
+
+ /**
+ * Create a copy of GDCH credentials with the specified audience.
+ *
+ * @param apiAudience The intended audience for GDCH credentials.
+ */
+ public GdchCredentials createWithGdchAudience(String apiAudience) {
+ if (Strings.isNullOrEmpty(apiAudience)) {
+ throw new IllegalArgumentException(
+ "Audience cannot be null or empty for GDCH service account credentials.");
+ }
return this.toBuilder().setGdchAudience(apiAudience).build();
}
@@ -248,17 +318,22 @@ public GdchCredentials createWithGdchAudience(URI apiAudience) throws IOExceptio
public AccessToken refreshAccessToken() throws IOException {
Preconditions.checkNotNull(
this.apiAudience,
- "Audience are not configured for GDCH service account. Specify the "
- + "audience by calling createWithGDCHAudience.");
+ "Audience cannot be null or empty for GDCH service account credentials. "
+ + "Specify the audience by calling createWithGdchAudience.");
- JsonFactory jsonFactory = OAuth2Utils.JSON_FACTORY;
- long currentTime = clock.currentTimeMillis();
- String assertion = createAssertion(jsonFactory, currentTime, getApiAudience());
+ JsonFactory jsonFactory = GsonFactory.getDefaultInstance();
+
+ long currentTime = Clock.SYSTEM.currentTimeMillis();
+ String assertion = createAssertion(jsonFactory, currentTime);
GenericData tokenRequest = new GenericData();
+ tokenRequest.set("audience", apiAudience);
tokenRequest.set("grant_type", OAuth2Utils.TOKEN_TYPE_TOKEN_EXCHANGE);
- tokenRequest.set("assertion", assertion);
- UrlEncodedContent content = new UrlEncodedContent(tokenRequest);
+ tokenRequest.set("requested_token_type", OAuth2Utils.TOKEN_TYPE_ACCESS_TOKEN);
+ tokenRequest.set("subject_token", assertion);
+ tokenRequest.set("subject_token_type", SERVICE_ACCOUNT_TOKEN_TYPE);
+
+ JsonHttpContent content = new JsonHttpContent(jsonFactory, tokenRequest);
HttpRequestFactory requestFactory = transportFactory.create().createRequestFactory();
HttpRequest request = requestFactory.buildPostRequest(new GenericUrl(tokenServerUri), content);
@@ -280,8 +355,8 @@ public AccessToken refreshAccessToken() throws IOException {
String message = String.format(errorTemplate, re.getMessage(), getServiceIdentityName());
throw GoogleAuthException.createWithTokenEndpointResponseException(re, message);
} catch (IOException e) {
- throw GoogleAuthException.createWithTokenEndpointIOException(
- e, String.format(errorTemplate, e.getMessage(), getServiceIdentityName()));
+ String message = String.format(errorTemplate, e.getMessage(), getServiceIdentityName());
+ throw GoogleAuthException.createWithTokenEndpointIOException(e, message);
}
GenericData responseData = response.parseAs(GenericData.class);
@@ -302,10 +377,9 @@ public AccessToken refreshAccessToken() throws IOException {
* (tokenServerUri), not for API call. It uses the serviceIdentityName as the `iss` and `sub`
* claim, and the tokenServerUri as the `aud` claim. The JWT is signed with the privateKey.
*/
- String createAssertion(JsonFactory jsonFactory, long currentTime, URI apiAudience)
- throws IOException {
+ String createAssertion(JsonFactory jsonFactory, long currentTime) throws IOException {
JsonWebSignature.Header header = new JsonWebSignature.Header();
- header.setAlgorithm("RS256");
+ header.setAlgorithm("ES256");
header.setType("JWT");
header.setKeyId(privateKeyId);
@@ -314,15 +388,14 @@ String createAssertion(JsonFactory jsonFactory, long currentTime, URI apiAudienc
payload.setSubject(getIssuerSubjectValue(projectId, serviceIdentityName));
payload.setIssuedAtTimeSeconds(currentTime / 1000);
payload.setExpirationTimeSeconds(currentTime / 1000 + this.lifetime);
- payload.setAudience(getTokenServerUri().toString());
+ payload.setAudience(tokenServerUri.toString());
String assertion;
try {
- payload.set("api_audience", apiAudience.toString());
- assertion = JsonWebSignature.signUsingRsaSha256(privateKey, jsonFactory, header, payload);
+ assertion = signUsingEsSha256(privateKey, jsonFactory, header, payload);
} catch (GeneralSecurityException e) {
- throw new IOException(
- "Error signing service account access token request with private key.", e);
+ throw new GoogleAuthException(
+ false, 0, "Error signing service account access token request with private key.", e);
}
return assertion;
@@ -363,10 +436,35 @@ public final URI getTokenServerUri() {
return tokenServerUri;
}
- public final URI getApiAudience() {
+ /**
+ * Returns the underlying audience string set for this credentials object.
+ *
+ * @return the audience string, or null if no audience has been set.
+ */
+ public final String getGdchAudience() {
return apiAudience;
}
+ /**
+ * NOTE: This method is obsolete, please use {@link #getGdchAudience()} instead. Returns a URI
+ * representation of the underlying audience string set for this credentials object. This method
+ * may fail if the underlying audience string does not conform to a URI format.
+ *
+ * @return a URI object representing the audience of the credentials, or null if no audience has
+ * been set or if the audience string is not a valid URI.
+ */
+ @ObsoleteApi("Use getGdchAudience() instead.")
+ public final URI getApiAudience() {
+ if (Strings.isNullOrEmpty(apiAudience)) {
+ return null;
+ }
+ try {
+ return new URI(apiAudience);
+ } catch (URISyntaxException e) {
+ return null;
+ }
+ }
+
public final HttpTransportFactory getTransportFactory() {
return transportFactory;
}
@@ -446,7 +544,7 @@ public static class Builder extends GoogleCredentials.Builder {
private PrivateKey privateKey;
private String serviceIdentityName;
private URI tokenServerUri;
- private URI apiAudience;
+ private String apiAudience;
private HttpTransportFactory transportFactory;
private String caCertPath;
private int lifetime = DEFAULT_LIFETIME_IN_SECONDS;
@@ -506,8 +604,19 @@ public Builder setCaCertPath(String caCertPath) {
return this;
}
+ /**
+ * Sets the intended audience for GDCH credentials.
+ *
+ * @param apiAudience The audience string. Cannot be null or empty.
+ * @return this builder.
+ * @throws IllegalArgumentException if the audience is null or empty.
+ */
@CanIgnoreReturnValue
- public Builder setGdchAudience(URI apiAudience) {
+ public Builder setGdchAudience(String apiAudience) {
+ if (Strings.isNullOrEmpty(apiAudience)) {
+ throw new IllegalArgumentException(
+ "Audience cannot be null or empty for GDCH service account credentials.");
+ }
this.apiAudience = apiAudience;
return this;
}
@@ -563,13 +672,16 @@ private static String validateField(String field, String fieldName) throws IOExc
/*
* Internal HttpTransportFactory for GDCH credentials.
*
- *
GDCH authentication server could use a self-signed certificate, thus the client could
+ *
GDCH authentication server could use a self-signed certificate, thus the
+ * client could
* provide the CA certificate path through the `ca_cert_path` in GDCH JSON file.
*
- *
The TransportFactoryForGdch subclass would read the certificate and create a trust store,
+ *
The TransportFactoryForGdch subclass would read the certificate and
+ * create a trust store,
* then use the trust store to create a transport.
*
- *
If the GDCH authentication server uses well known CA certificate, then a regular transport
+ *
If the GDCH authentication server uses well known CA certificate, then a
+ * regular transport
* would be set.
*/
static class TransportFactoryForGdch implements HttpTransportFactory {
@@ -604,4 +716,231 @@ private void setTransport(String caCertPath) throws IOException {
}
}
}
+
+ /**
+ * Signs the JWS header and payload using the ES256 algorithm (ECDSA with SHA-256).
+ *
+ *
The ES256 algorithm is defined in RFC 7518 Section 3.4. This method
+ * follows the JWS Compact Serialization format described in RFC 7515 Section 3.1.
+ *
+ *
Unlike RSA signatures, ECDSA signatures produced by the Java Cryptography Architecture (JCA)
+ * are DER-encoded. This method transcodes the DER-encoded signature into the concatenated R|S
+ * format required by the JWS standard, as specified in RFC 7515 Appendix A.3.
+ *
+ * @param privateKey The Elliptic Curve private key used for signing.
+ * @param jsonFactory The JSON factory to serialize header and payload.
+ * @param header The JWS header (e.g., containing "alg": "ES256").
+ * @param payload The JWS payload containing claims like "iss", "sub", and "aud".
+ * @return A complete, signed JWS string in the format {@code [header].[payload].[signature]}.
+ * @throws GeneralSecurityException If signing fails due to cryptographic errors.
+ * @throws IOException If serialization or transcoding fails.
+ */
+ @VisibleForTesting
+ static String signUsingEsSha256(
+ PrivateKey privateKey,
+ JsonFactory jsonFactory,
+ JsonWebSignature.Header header,
+ JsonWebToken.Payload payload)
+ throws GeneralSecurityException, GoogleAuthException {
+
+ try {
+ // 1. Construct the JWS Signing Input: Base64URL(UTF8(Header)) + '.' +
+ // Base64URL(UTF8(Payload))
+ String content =
+ Base64.getUrlEncoder().withoutPadding().encodeToString(jsonFactory.toByteArray(header))
+ + "."
+ + Base64.getUrlEncoder()
+ .withoutPadding()
+ .encodeToString(jsonFactory.toByteArray(payload));
+ byte[] contentBytes = StringUtils.getBytesUtf8(content);
+
+ // 2. Create the digital signature using SHA256withECDSA.
+ byte[] signature =
+ SecurityUtils.sign(SecurityUtils.getEs256SignatureAlgorithm(), privateKey, contentBytes);
+
+ // 3. Transcode the signature from DER to Concatenated R|S.
+ byte[] jwsSignature = transcodeDerToConcat(signature, 64);
+
+ // 4. Return final JWS: [Signing Input] + '.' + Base64URL(Signature)
+ return content + "." + Base64.getUrlEncoder().withoutPadding().encodeToString(jwsSignature);
+ } catch (IOException e) {
+ throw new GoogleAuthException(false, 0, "Error serializing or transcoding JWT.", e);
+ }
+ }
+
+ /**
+ * Transcodes a DER-encoded ECDSA signature into the concatenated R|S format.
+ *
+ *
DER format (ASN.1): {@code SEQUENCE { r INTEGER, s INTEGER }}
+ *
+ *
Concatenated format: {@code r | s} (where {@code |} is concatenation).
+ *
+ * @param derSignature The raw bytes of the DER-encoded signature.
+ * @param outputLength The total expected length of the concatenated signature (64 bytes for
+ * ES256).
+ * @return The signature in concatenated R|S format.
+ * @throws IOException If the DER format is invalid.
+ */
+ @VisibleForTesting
+ static byte[] transcodeDerToConcat(byte[] derSignature, int outputLength)
+ throws GoogleAuthException {
+ // Validate basic ASN.1 DER structure (0x30 = SEQUENCE)
+ if (derSignature.length < 8 || derSignature[0] != 0x30) {
+ throw new GoogleAuthException(false, 0, "Invalid DER signature format.", null);
+ }
+
+ int offset = 2;
+ int seqLength = derSignature[1] & 0xFF;
+ // Handle long-form length encoding for the sequence
+ if (seqLength == 0x81) {
+ offset = 3;
+ seqLength = derSignature[2] & 0xFF;
+ }
+
+ if (derSignature.length - offset != seqLength) {
+ throw new GoogleAuthException(false, 0, "Invalid DER signature length.", null);
+ }
+
+ // Parse Integer R (0x02 = INTEGER)
+ if (derSignature[offset++] != 0x02) {
+ throw new GoogleAuthException(false, 0, "Expected INTEGER for R.", null);
+ }
+ int rLength = derSignature[offset++];
+ // Skip leading zero byte if it exists (DER integers are signed; zero is added to stay positive)
+ if (derSignature[offset] == 0x00 && rLength > 1 && (derSignature[offset + 1] & 0x80) != 0) {
+ offset++;
+ rLength--;
+ }
+ byte[] r = new byte[rLength];
+ System.arraycopy(derSignature, offset, r, 0, rLength);
+ offset += rLength;
+
+ // Parse Integer S
+ if (derSignature[offset++] != 0x02) {
+ throw new GoogleAuthException(false, 0, "Expected INTEGER for S.", null);
+ }
+ int sLength = derSignature[offset++];
+ if (derSignature[offset] == 0x00 && sLength > 1 && (derSignature[offset + 1] & 0x80) != 0) {
+ offset++;
+ sLength--;
+ }
+ byte[] s = new byte[sLength];
+ System.arraycopy(derSignature, offset, s, 0, sLength);
+
+ // Concatenate r and s into fixed-length segments (32 bytes each for ES256)
+ int keySizeBytes = outputLength / 2;
+ if (r.length > keySizeBytes || s.length > keySizeBytes) {
+ throw new GoogleAuthException(
+ false,
+ 0,
+ String.format(
+ "Invalid R or S length. R: %d, S: %d, Expected: %d",
+ r.length, s.length, keySizeBytes),
+ null);
+ }
+
+ byte[] result = new byte[outputLength];
+ System.arraycopy(r, 0, result, keySizeBytes - r.length, r.length);
+ System.arraycopy(s, 0, result, outputLength - s.length, s.length);
+
+ return result;
+ }
+
+ /**
+ * Parses an EC private key in SEC1 format using fixed prefix verification.
+ *
+ *
This function assumes that standard SEC1 keys for P-256 generated by OpenSSL have a known,
+ * stable structure of bytes at the beginning. This "fingerprint" allows us to verify the format
+ * without complete ASN.1 parsing. If the fingerprint matches, we can safely extract the private
+ * key value using fixed offsets.
+ *
+ * @param bytes The raw bytes of the SEC1 key.
+ * @return The PrivateKey object.
+ * @throws GoogleAuthException If parsing fails or the key format is unsupported.
+ */
+ private static PrivateKey privateKeyFromSec1(byte[] bytes) throws IOException {
+ if (!hasStandardSec1P256Prefix(bytes)) {
+ throw new GoogleAuthException(
+ false, 0, "Unsupported SEC1 key format: standard prefix not found.", null);
+ }
+ BigInteger s = extractPrivateKeyValue(bytes);
+ return createEcPrivateKey(s);
+ }
+
+ /**
+ * Verifies if the bytes start with the standard SEC1 P-256 prefix.
+ *
+ *
The prefix is derived from the standard DER encoding of the ECPrivateKey structure defined
+ * in RFC 5915 Section 3. For P-256 with named curve parameters and public key included, the
+ * prefix is stable: [0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20]
+ *
+ * @see RFC 5915 Section 3
+ * @param bytes The raw bytes of the key.
+ * @return true if the prefix matches.
+ */
+ private static boolean hasStandardSec1P256Prefix(byte[] bytes) {
+ if (bytes.length < 7) return false;
+ return bytes[0] == 0x30 // Sequence
+ && bytes[1] == 0x77 // Length
+ && bytes[2] == 0x02 // Integer
+ && bytes[3] == 0x01 // Length
+ && bytes[4] == 0x01 // Version
+ && bytes[5] == 0x04 // Octet String
+ && bytes[6] == 0x20; // Length 32
+ }
+
+ /**
+ * Extracts the private key value 's' from the SEC1 bytes using fixed offset.
+ *
+ *
Assumes the prefix has already been verified by {@link #hasStandardSec1P256Prefix(byte[])}.
+ *
+ * @param bytes The raw bytes of the key.
+ * @return The BigInteger value of 's'.
+ */
+ private static BigInteger extractPrivateKeyValue(byte[] bytes) {
+ // P-256 private key size is 32 bytes as per RFC 5915 Section 3.
+ byte[] sBytes = new byte[32];
+ // Copy 32 bytes starting at offset 7 (after the 7-byte metadata prefix verified by
+ // hasStandardSec1P256Prefix).
+ System.arraycopy(bytes, 7, sBytes, 0, 32);
+ // Use signum 1 to ensure the byte array is interpreted as a positive integer.
+ return new BigInteger(1, sBytes);
+ }
+
+ /**
+ * Creates an EC PrivateKey from the private key value 's' using P-256 parameters.
+ *
+ *
Algorithm steps: 1. Get an instance of AlgorithmParameters for "EC". 2. Initialize it with
+ * secp256r1 curve spec (requirement as per GDCH supported curve). 3. Extract ECParameterSpec from
+ * parameters. 4. Create ECPrivateKeySpec with the extracted private key value and parameters. 5.
+ * Generate PrivateKey using KeyFactory.
+ *
+ * @param s The private key value.
+ * @return The PrivateKey object.
+ * @throws GoogleAuthException If key creation fails.
+ */
+ private static PrivateKey createEcPrivateKey(BigInteger s) throws IOException {
+ try {
+ AlgorithmParameters params = AlgorithmParameters.getInstance("EC");
+
+ params.init(new ECGenParameterSpec("secp256r1"));
+
+ ECParameterSpec ecParams = params.getParameterSpec(ECParameterSpec.class);
+
+ ECPrivateKeySpec keySpec = new ECPrivateKeySpec(s, ecParams);
+
+ KeyFactory keyFactory = KeyFactory.getInstance("EC");
+
+ return keyFactory.generatePrivate(keySpec);
+ } catch (GeneralSecurityException e) {
+ throw new GoogleAuthException(
+ false,
+ 0,
+ "Failed to create EC Private Key for GDCH. Please ensure the private key data is valid and represents a P-256 private key.",
+ e);
+ }
+ }
}
diff --git a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/IdentityPoolCredentials.java b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/IdentityPoolCredentials.java
index ee5df1466c36..0ff9da853e2d 100644
--- a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/IdentityPoolCredentials.java
+++ b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/IdentityPoolCredentials.java
@@ -33,6 +33,7 @@
import com.google.auth.http.HttpTransportFactory;
import com.google.auth.mtls.MtlsHttpTransportFactory;
+import com.google.auth.mtls.MtlsUtils;
import com.google.auth.mtls.X509Provider;
import com.google.auth.oauth2.IdentityPoolCredentialSource.IdentityPoolCredentialSourceType;
import com.google.common.annotations.VisibleForTesting;
@@ -166,28 +167,37 @@ private IdentityPoolSubjectTokenSupplier createCertificateSubjectTokenSupplier(
this.transportFactory = new MtlsHttpTransportFactory(mtlsKeyStore);
// Initialize the subject token supplier with the certificate path.
- credentialSource.setCredentialLocation(x509Provider.getCertificatePath());
+ String explicitCertConfigPath = getExplicitCertConfigPath(credentialSource);
+ credentialSource.setCredentialLocation(
+ MtlsUtils.getCertificatePath(
+ getEnvironmentProvider(), getPropertyProvider(), explicitCertConfigPath));
return new CertificateIdentityPoolSubjectTokenSupplier(credentialSource);
}
private X509Provider getX509Provider(
Builder builder, IdentityPoolCredentialSource credentialSource) {
- final IdentityPoolCredentialSource.CertificateConfig certConfig =
- credentialSource.getCertificateConfig();
-
// Use the provided X509Provider if available, otherwise initialize a default one.
X509Provider x509Provider = builder.x509Provider;
if (x509Provider == null) {
// Determine the certificate path based on the configuration.
- String explicitCertConfigPath =
- certConfig.useDefaultCertificateConfig()
- ? null
- : certConfig.getCertificateConfigLocation();
- x509Provider = new X509Provider(explicitCertConfigPath);
+ String explicitCertConfigPath = getExplicitCertConfigPath(credentialSource);
+ x509Provider =
+ new X509Provider(getEnvironmentProvider(), getPropertyProvider(), explicitCertConfigPath);
}
return x509Provider;
}
+ private static String getExplicitCertConfigPath(IdentityPoolCredentialSource credentialSource) {
+ IdentityPoolCredentialSource.CertificateConfig certConfig =
+ credentialSource.getCertificateConfig();
+ if (certConfig == null) {
+ return null;
+ }
+ return certConfig.useDefaultCertificateConfig()
+ ? null
+ : certConfig.getCertificateConfigLocation();
+ }
+
public static class Builder extends ExternalAccountCredentials.Builder {
private IdentityPoolSubjectTokenSupplier subjectTokenSupplier;
@@ -212,6 +222,7 @@ public static class Builder extends ExternalAccountCredentials.Builder {
* @return this {@code Builder} object
*/
@CanIgnoreReturnValue
+ @VisibleForTesting
Builder setX509Provider(X509Provider x509Provider) {
this.x509Provider = x509Provider;
return this;
diff --git a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/OAuth2Credentials.java b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/OAuth2Credentials.java
index b4a933963fe8..e17714c3eee8 100644
--- a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/OAuth2Credentials.java
+++ b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/OAuth2Credentials.java
@@ -86,7 +86,7 @@ public class OAuth2Credentials extends Credentials {
// Change listeners are not serialized
private transient List changeListeners;
// Until we expose this to the users it can remain transient and non-serializable
- @VisibleForTesting transient Clock clock = Clock.SYSTEM;
+ transient Clock clock = Clock.SYSTEM;
/**
* Returns the credentials instance from the given access token.
diff --git a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/OAuth2Utils.java b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/OAuth2Utils.java
index 7efec082fe16..643c3dc7dc65 100644
--- a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/OAuth2Utils.java
+++ b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/OAuth2Utils.java
@@ -40,7 +40,6 @@
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.util.PemReader;
import com.google.api.client.util.PemReader.Section;
-import com.google.api.client.util.SecurityUtils;
import com.google.api.core.InternalApi;
import com.google.auth.http.AuthHttpConstants;
import com.google.auth.http.HttpTransportFactory;
@@ -82,6 +81,11 @@
@InternalApi
public class OAuth2Utils {
+ enum Pkcs8Algorithm {
+ RSA,
+ EC
+ }
+
static final String SIGNATURE_ALGORITHM = "SHA256withRSA";
public static final String TOKEN_TYPE_ACCESS_TOKEN =
@@ -269,6 +273,24 @@ static Map validateMap(Map map, String key, Stri
* key creation.
*/
public static PrivateKey privateKeyFromPkcs8(String privateKeyPkcs8) throws IOException {
+ return privateKeyFromPkcs8(privateKeyPkcs8, Pkcs8Algorithm.RSA);
+ }
+
+ /**
+ * Reads a private key from a PKCS#8 encoded string.
+ *
+ * If the key is labeled with "-----BEGIN PRIVATE KEY-----", it is parsed as PKCS#8 as per RFC
+ * 7468 Section 10.
+ *
+ * @see RFC 7468 Section 10
+ * @param privateKeyPkcs8 base64 encoded private key string
+ * @param algorithm expected algorithm of the private key
+ * @return the private key.
+ * @throws IOException if the private key data is invalid or if an unexpected exception occurs
+ * during key creation.
+ */
+ public static PrivateKey privateKeyFromPkcs8(String privateKeyPkcs8, Pkcs8Algorithm algorithm)
+ throws IOException {
Reader reader = new StringReader(privateKeyPkcs8);
Section section = PemReader.readFirstSectionAndClose(reader, "PRIVATE KEY");
if (section == null) {
@@ -278,7 +300,7 @@ public static PrivateKey privateKeyFromPkcs8(String privateKeyPkcs8) throws IOEx
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
Exception unexpectedException;
try {
- KeyFactory keyFactory = SecurityUtils.getRsaKeyFactory();
+ KeyFactory keyFactory = KeyFactory.getInstance(algorithm.toString());
return keyFactory.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException | InvalidKeySpecException exception) {
unexpectedException = exception;
diff --git a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/PropertyProvider.java b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/PropertyProvider.java
new file mode 100644
index 000000000000..93343c84ebab
--- /dev/null
+++ b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/PropertyProvider.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * 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 LLC 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 com.google.api.core.InternalApi;
+
+/**
+ * Interface for a system property provider.
+ *
+ *
For internal use only.
+ */
+@InternalApi
+public interface PropertyProvider {
+ String getProperty(String property, String def);
+}
diff --git a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/SystemEnvironmentProvider.java b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/SystemEnvironmentProvider.java
index a2970772135a..a58285831598 100644
--- a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/SystemEnvironmentProvider.java
+++ b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/SystemEnvironmentProvider.java
@@ -1,9 +1,45 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * 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 LLC 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 com.google.api.core.InternalApi;
import java.io.Serializable;
-/** Represents the default system environment provider. */
-class SystemEnvironmentProvider implements EnvironmentProvider, Serializable {
+/**
+ * Represents the default system environment provider.
+ *
+ *
For internal use only.
+ */
+@InternalApi
+public class SystemEnvironmentProvider implements EnvironmentProvider, Serializable {
static final SystemEnvironmentProvider INSTANCE = new SystemEnvironmentProvider();
private static final long serialVersionUID = -4698164985883575244L;
diff --git a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/SystemPropertyProvider.java b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/SystemPropertyProvider.java
new file mode 100644
index 000000000000..6c2042329be8
--- /dev/null
+++ b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/SystemPropertyProvider.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * 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 LLC 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 com.google.api.core.InternalApi;
+import java.io.Serializable;
+
+/**
+ * Represents the default system property provider.
+ *
+ *
For internal use only.
+ */
+@InternalApi
+public class SystemPropertyProvider implements PropertyProvider, Serializable {
+ public static final SystemPropertyProvider INSTANCE = new SystemPropertyProvider();
+ private static final long serialVersionUID = 1L;
+
+ private SystemPropertyProvider() {}
+
+ @Override
+ public String getProperty(String property, String def) {
+ return System.getProperty(property, def);
+ }
+
+ public static SystemPropertyProvider getInstance() {
+ return INSTANCE;
+ }
+}
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/TestUtils.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/TestUtils.java
index d794ba18486d..91b648992848 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/TestUtils.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/TestUtils.java
@@ -46,9 +46,9 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
@@ -90,17 +90,20 @@ private static boolean hasBearerToken(Map> metadata, String
public static InputStream jsonToInputStream(GenericJson json) throws IOException {
json.setFactory(JSON_FACTORY);
String text = json.toPrettyString();
- return new ByteArrayInputStream(text.getBytes("UTF-8"));
+ return new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
}
public static InputStream stringToInputStream(String text) {
- try {
- return new ByteArrayInputStream(text.getBytes("UTF-8"));
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException("Unexpected encoding exception", e);
- }
+ return new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
}
+ /**
+ * Parses a URI query string into a map of key-value pairs.
+ *
+ * @param query The URI query string (e.g., "key1=val1&key2=val2").
+ * @return A map of decoded keys to decoded values.
+ * @throws IOException If the query string is malformed.
+ */
public static Map parseQuery(String query) throws IOException {
Map map = new HashMap<>();
Iterable entries = Splitter.on('&').split(query);
@@ -116,6 +119,23 @@ public static Map parseQuery(String query) throws IOException {
return map;
}
+ /**
+ * Parses a JSON string into a map of key-value pairs.
+ *
+ * @param content The JSON string representation of a flat object.
+ * @return A map of keys to string representations of their values.
+ * @throws IOException If the JSON is malformed.
+ */
+ public static Map parseJson(String content) throws IOException {
+ GenericJson json = JSON_FACTORY.fromString(content, GenericJson.class);
+ Map map = new HashMap<>();
+ for (Map.Entry entry : json.entrySet()) {
+ Object value = entry.getValue();
+ map.put(entry.getKey(), value == null ? null : value.toString());
+ }
+ return map;
+ }
+
public static String errorJson(String message) throws IOException {
GenericJson errorResponse = new GenericJson();
errorResponse.setFactory(JSON_FACTORY);
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/http/HttpCredentialsAdapterTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/http/HttpCredentialsAdapterTest.java
index 10d2141fd7b3..666be521e9ed 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/http/HttpCredentialsAdapterTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/http/HttpCredentialsAdapterTest.java
@@ -79,7 +79,7 @@ void initialize_populatesOAuth2Credentials() throws IOException {
HttpHeaders requestHeaders = request.getHeaders();
String authorizationHeader = requestHeaders.getAuthorization();
- assertEquals(authorizationHeader, expectedAuthorization);
+ assertEquals(expectedAuthorization, authorizationHeader);
}
@Test
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/mtls/MtlsUtilsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/mtls/MtlsUtilsTest.java
new file mode 100644
index 000000000000..f3fdf05a4c32
--- /dev/null
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/mtls/MtlsUtilsTest.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2026, 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.mtls;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import com.google.auth.oauth2.EnvironmentProvider;
+import com.google.auth.oauth2.PropertyProvider;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+class MtlsUtilsTest {
+
+ @TempDir Path tempDir;
+
+ @Test
+ void getCertificatePath_succeeds() throws IOException {
+ Path configFile = tempDir.resolve("config.json");
+ Files.write(
+ configFile,
+ "{\"cert_configs\":{\"workload\":{\"cert_path\":\"cert.pem\",\"key_path\":\"key.pem\"}}}"
+ .getBytes());
+
+ EnvironmentProvider envProvider =
+ new EnvironmentProvider() {
+ @Override
+ public String getEnv(String name) {
+ return null;
+ }
+ };
+ PropertyProvider propProvider =
+ new PropertyProvider() {
+ @Override
+ public String getProperty(String name, String def) {
+ return def;
+ }
+ };
+
+ String certPath =
+ MtlsUtils.getCertificatePath(envProvider, propProvider, configFile.toString());
+
+ assertEquals("cert.pem", certPath);
+ }
+
+ @Test
+ void getCertificatePath_missingCertPath_throws() throws IOException {
+ Path configFile = tempDir.resolve("config.json");
+ Files.write(
+ configFile, "{\"cert_configs\":{\"workload\":{\"key_path\":\"key.pem\"}}}".getBytes());
+
+ EnvironmentProvider envProvider =
+ new EnvironmentProvider() {
+ @Override
+ public String getEnv(String name) {
+ return null;
+ }
+ };
+ PropertyProvider propProvider =
+ new PropertyProvider() {
+ @Override
+ public String getProperty(String name, String def) {
+ return def;
+ }
+ };
+
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> MtlsUtils.getCertificatePath(envProvider, propProvider, configFile.toString()));
+ }
+
+ @Test
+ void getWorkloadCertificateConfiguration_overridePath() throws IOException {
+ Path configFile = tempDir.resolve("custom_config.json");
+ Files.write(
+ configFile,
+ "{\"cert_configs\":{\"workload\":{\"cert_path\":\"cert.pem\",\"key_path\":\"key.pem\"}}}"
+ .getBytes());
+
+ EnvironmentProvider envProvider =
+ new EnvironmentProvider() {
+ @Override
+ public String getEnv(String name) {
+ return null;
+ }
+ };
+ PropertyProvider propProvider =
+ new PropertyProvider() {
+ @Override
+ public String getProperty(String name, String def) {
+ return def;
+ }
+ };
+
+ WorkloadCertificateConfiguration config =
+ MtlsUtils.getWorkloadCertificateConfiguration(
+ envProvider, propProvider, configFile.toString());
+
+ assertNotNull(config);
+ assertEquals("cert.pem", config.getCertPath());
+ assertEquals("key.pem", config.getPrivateKeyPath());
+ }
+
+ @Test
+ void getWorkloadCertificateConfiguration_envVar() throws IOException {
+ Path configFile = tempDir.resolve("env_config.json");
+ Files.write(
+ configFile,
+ "{\"cert_configs\":{\"workload\":{\"cert_path\":\"cert.pem\",\"key_path\":\"key.pem\"}}}"
+ .getBytes());
+
+ EnvironmentProvider envProvider =
+ new EnvironmentProvider() {
+ @Override
+ public String getEnv(String name) {
+ return "GOOGLE_API_CERTIFICATE_CONFIG".equals(name) ? configFile.toString() : null;
+ }
+ };
+ PropertyProvider propProvider =
+ new PropertyProvider() {
+ @Override
+ public String getProperty(String name, String def) {
+ return def;
+ }
+ };
+
+ WorkloadCertificateConfiguration config =
+ MtlsUtils.getWorkloadCertificateConfiguration(envProvider, propProvider, null);
+
+ assertNotNull(config);
+ assertEquals("cert.pem", config.getCertPath());
+ }
+
+ @Test
+ void getWellKnownCertificateConfigFile_windows() throws IOException {
+ EnvironmentProvider envProvider =
+ new EnvironmentProvider() {
+ @Override
+ public String getEnv(String name) {
+ return "APPDATA".equals(name) ? tempDir.toString() : null;
+ }
+ };
+ PropertyProvider propProvider =
+ new PropertyProvider() {
+ @Override
+ public String getProperty(String name, String def) {
+ return "os.name".equals(name) ? "Windows 10" : def;
+ }
+ };
+
+ CertificateSourceUnavailableException exception =
+ assertThrows(
+ CertificateSourceUnavailableException.class,
+ () -> MtlsUtils.getWorkloadCertificateConfiguration(envProvider, propProvider, null));
+
+ String expectedPath =
+ new File(tempDir.toFile(), "gcloud/certificate_config.json").getAbsolutePath();
+ assertTrue(exception.getMessage().contains(expectedPath));
+ }
+
+ @Test
+ void getWellKnownCertificateConfigFile_linux() throws IOException {
+ EnvironmentProvider envProvider =
+ new EnvironmentProvider() {
+ @Override
+ public String getEnv(String name) {
+ return null;
+ }
+ };
+ PropertyProvider propProvider =
+ new PropertyProvider() {
+ @Override
+ public String getProperty(String name, String def) {
+ if ("os.name".equals(name)) return "Linux";
+ if ("user.home".equals(name)) return tempDir.toString();
+ return def;
+ }
+ };
+
+ CertificateSourceUnavailableException exception =
+ assertThrows(
+ CertificateSourceUnavailableException.class,
+ () -> MtlsUtils.getWorkloadCertificateConfiguration(envProvider, propProvider, null));
+
+ String expectedPath =
+ new File(tempDir.toFile(), ".config/gcloud/certificate_config.json").getAbsolutePath();
+ assertTrue(exception.getMessage().contains(expectedPath));
+ }
+
+ @Test
+ void getWellKnownCertificateConfigFile_windows_missingAppData_throws() {
+ EnvironmentProvider envProvider =
+ new EnvironmentProvider() {
+ @Override
+ public String getEnv(String name) {
+ return null;
+ }
+ };
+ PropertyProvider propProvider =
+ new PropertyProvider() {
+ @Override
+ public String getProperty(String name, String def) {
+ return "os.name".equals(name) ? "Windows 10" : def;
+ }
+ };
+
+ CertificateSourceUnavailableException exception =
+ assertThrows(
+ CertificateSourceUnavailableException.class,
+ () -> MtlsUtils.getWorkloadCertificateConfiguration(envProvider, propProvider, null));
+
+ assertEquals("APPDATA environment variable is not set on Windows.", exception.getMessage());
+ }
+}
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/mtls/SecureConnectProviderTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/mtls/SecureConnectProviderTest.java
index 7e962014ae25..fab805fa9520 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/mtls/SecureConnectProviderTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/mtls/SecureConnectProviderTest.java
@@ -38,7 +38,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.security.GeneralSecurityException;
import java.util.List;
import org.junit.jupiter.api.Test;
@@ -70,7 +69,7 @@ public InputStream getErrorStream() {
}
@Override
- public int waitFor() throws InterruptedException {
+ public int waitFor() {
return 0;
}
@@ -83,7 +82,9 @@ public int exitValue() {
}
@Override
- public void destroy() {}
+ public void destroy() {
+ // Nothing was initialized and nothing needs to be destroyed
+ }
}
static class TestProcessProvider implements SecureConnectProvider.ProcessProvider {
@@ -102,19 +103,22 @@ public Process createProcess(InputStream metadata) throws IOException {
@Test
void testGetKeyStoreNonZeroExitCode() {
- InputStream metadata =
+ try (InputStream metadata =
this.getClass()
.getClassLoader()
- .getResourceAsStream("com/google/api/gax/rpc/mtls/mtlsCertAndKey.pem");
- IOException actual =
- assertThrows(
- IOException.class,
- () -> SecureConnectProvider.getKeyStore(metadata, new TestProcessProvider(1)));
- assertTrue(
- actual
- .getMessage()
- .contains("SecureConnect: Cert provider command failed with exit code: 1"),
- "expected to fail with nonzero exit code");
+ .getResourceAsStream("com/google/api/gax/rpc/mtls/mtlsCertAndKey.pem")) {
+ IOException actual =
+ assertThrows(
+ IOException.class,
+ () -> SecureConnectProvider.getKeyStore(metadata, new TestProcessProvider(1)));
+ assertTrue(
+ actual
+ .getMessage()
+ .contains("SecureConnect: Cert provider command failed with exit code: 1"),
+ "expected to fail with nonzero exit code");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
@Test
@@ -147,8 +151,7 @@ void testRunCertificateProviderCommandTimeout() {
}
@Test
- void testGetKeyStore_FileNotFoundException()
- throws IOException, GeneralSecurityException, InterruptedException {
+ void testGetKeyStore_FileNotFoundException() {
SecureConnectProvider provider =
new SecureConnectProvider(new TestProcessProvider(0), "/invalid/metadata/path.json");
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/mtls/WorkloadCertificateConfigurationTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/mtls/WorkloadCertificateConfigurationTest.java
index bd17436c16ee..8d74f7978ce9 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/mtls/WorkloadCertificateConfigurationTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/mtls/WorkloadCertificateConfigurationTest.java
@@ -58,71 +58,77 @@ void workloadCertificateConfig_fromStream_Succeeds() throws IOException {
void workloadCertificateConfig_fromStreamMissingCertPath_Fails() throws IOException {
String certPath = "";
String privateKeyPath = "key.crt";
- InputStream configStream = writeWorkloadCertificateConfigStream(certPath, privateKeyPath);
-
- IllegalArgumentException exception =
- assertThrows(
- IllegalArgumentException.class,
- () ->
- WorkloadCertificateConfiguration.fromCertificateConfigurationStream(configStream));
- assertTrue(
- exception
- .getMessage()
- .contains(
- "The cert_path field must be provided in the workload certificate configuration."));
+ try (InputStream configStream =
+ writeWorkloadCertificateConfigStream(certPath, privateKeyPath)) {
+ IllegalArgumentException exception =
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ WorkloadCertificateConfiguration.fromCertificateConfigurationStream(
+ configStream));
+ assertTrue(
+ exception
+ .getMessage()
+ .contains(
+ "The cert_path field must be provided in the workload certificate configuration."));
+ }
}
@Test
void workloadCertificateConfig_fromStreamMissingPrivateKeyPath_Fails() throws IOException {
String certPath = "cert.crt";
String privateKeyPath = "";
- InputStream configStream = writeWorkloadCertificateConfigStream(certPath, privateKeyPath);
-
- IllegalArgumentException exception =
- assertThrows(
- IllegalArgumentException.class,
- () ->
- WorkloadCertificateConfiguration.fromCertificateConfigurationStream(configStream));
- assertTrue(
- exception
- .getMessage()
- .contains(
- "The key_path field must be provided in the workload certificate configuration."));
+ try (InputStream configStream =
+ writeWorkloadCertificateConfigStream(certPath, privateKeyPath)) {
+ IllegalArgumentException exception =
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ WorkloadCertificateConfiguration.fromCertificateConfigurationStream(
+ configStream));
+ assertTrue(
+ exception
+ .getMessage()
+ .contains(
+ "The key_path field must be provided in the workload certificate configuration."));
+ }
}
@Test
void workloadCertificateConfig_fromStreamMissingWorkload_Fails() throws IOException {
GenericJson json = new GenericJson();
json.put("cert_configs", new GenericJson());
- InputStream configStream = TestUtils.jsonToInputStream(json);
-
- CertificateSourceUnavailableException exception =
- assertThrows(
- CertificateSourceUnavailableException.class,
- () ->
- WorkloadCertificateConfiguration.fromCertificateConfigurationStream(configStream));
- assertTrue(
- exception
- .getMessage()
- .contains(
- "A workload certificate configuration must be provided in the cert_configs object."));
+ try (InputStream configStream = TestUtils.jsonToInputStream(json)) {
+ CertificateSourceUnavailableException exception =
+ assertThrows(
+ CertificateSourceUnavailableException.class,
+ () ->
+ WorkloadCertificateConfiguration.fromCertificateConfigurationStream(
+ configStream));
+ assertTrue(
+ exception
+ .getMessage()
+ .contains(
+ "A workload certificate configuration must be provided in the cert_configs object."));
+ }
}
@Test
void workloadCertificateConfig_fromStreamMissingCertConfig_Fails() throws IOException {
GenericJson json = new GenericJson();
- InputStream configStream = TestUtils.jsonToInputStream(json);
-
- IllegalArgumentException exception =
- assertThrows(
- IllegalArgumentException.class,
- () ->
- WorkloadCertificateConfiguration.fromCertificateConfigurationStream(configStream));
- assertTrue(
- exception
- .getMessage()
- .contains(
- "The cert_configs object must be provided in the certificate configuration file."));
+ try (InputStream configStream = TestUtils.jsonToInputStream(json)) {
+ IllegalArgumentException exception =
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ WorkloadCertificateConfiguration.fromCertificateConfigurationStream(
+ configStream));
+ assertTrue(
+ exception
+ .getMessage()
+ .contains(
+ "The cert_configs object must be provided in the certificate configuration file."));
+ }
}
static InputStream writeWorkloadCertificateConfigStream(String certPath, String privateKeyPath)
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/mtls/X509ProviderTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/mtls/X509ProviderTest.java
index 7f3927654f80..5ddd1a169d29 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/mtls/X509ProviderTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/mtls/X509ProviderTest.java
@@ -36,73 +36,44 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import java.io.ByteArrayInputStream;
+import com.google.auth.oauth2.SystemPropertyProvider;
+import com.google.auth.oauth2.TestEnvironmentProvider;
+import com.google.auth.oauth2.TestPropertyProvider;
import java.io.File;
-import java.io.FileNotFoundException;
+import java.io.FileInputStream;
import java.io.IOException;
-import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
-import java.util.HashMap;
-import java.util.Map;
import org.junit.jupiter.api.Test;
class X509ProviderTest {
- private static final String TEST_CERT =
- "-----BEGIN CERTIFICATE-----\n"
- + "MIICGzCCAYSgAwIBAgIIWrt6xtmHPs4wDQYJKoZIhvcNAQEFBQAwMzExMC8GA1UE\n"
- + "AxMoMTAwOTEyMDcyNjg3OC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbTAeFw0x\n"
- + "MjEyMDExNjEwNDRaFw0yMjExMjkxNjEwNDRaMDMxMTAvBgNVBAMTKDEwMDkxMjA3\n"
- + "MjY4NzguYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20wgZ8wDQYJKoZIhvcNAQEB\n"
- + "BQADgY0AMIGJAoGBAL1SdY8jTUVU7O4/XrZLYTw0ON1lV6MQRGajFDFCqD2Fd9tQ\n"
- + "GLW8Iftx9wfXe1zuaehJSgLcyCxazfyJoN3RiONBihBqWY6d3lQKqkgsRTNZkdFJ\n"
- + "Wdzl/6CxhK9sojh2p0r3tydtv9iwq5fuuWIvtODtT98EgphhncQAqkKoF3zVAgMB\n"
- + "AAGjODA2MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQM\n"
- + "MAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4GBAD8XQEqzGePa9VrvtEGpf+R4\n"
- + "fkxKbcYAzqYq202nKu0kfjhIYkYSBj6gi348YaxE64yu60TVl42l5HThmswUheW4\n"
- + "uQIaq36JvwvsDP5Zoj5BgiNSnDAFQp+jJFBRUA5vooJKgKgMDf/r/DCOsbO6VJF1\n"
- + "kWwa9n19NFiV0z3m6isj\n"
- + "-----END CERTIFICATE-----\n";
-
- private static final String TEST_PRIVATE_KEY =
- "-----BEGIN PRIVATE KEY-----\n"
- + "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAL1SdY8jTUVU7O4/\n"
- + "XrZLYTw0ON1lV6MQRGajFDFCqD2Fd9tQGLW8Iftx9wfXe1zuaehJSgLcyCxazfyJ\n"
- + "oN3RiONBihBqWY6d3lQKqkgsRTNZkdFJWdzl/6CxhK9sojh2p0r3tydtv9iwq5fu\n"
- + "uWIvtODtT98EgphhncQAqkKoF3zVAgMBAAECgYB51B9cXe4yiGTzJ4pOKpHGySAy\n"
- + "sC1F/IjXt2eeD3PuKv4m/hL4l7kScpLx0+NJuQ4j8U2UK/kQOdrGANapB1ZbMZAK\n"
- + "/q0xmIUzdNIDiGSoTXGN2mEfdsEpQ/Xiv0lyhYBBPC/K4sYIpHccnhSRQUZlWLLY\n"
- + "lE5cFNKC9b7226mNvQJBAPt0hfCNIN0kUYOA9jdLtx7CE4ySGMPf5KPBuzPd8ty1\n"
- + "fxaFm9PB7B76VZQYmHcWy8rT5XjoLJHrmGW1ZvP+iDsCQQDAvnKoarPOGb5iJfkq\n"
- + "RrA4flf1TOlf+1+uqIOJ94959jkkJeb0gv/TshDnm6/bWn+1kJylQaKygCizwPwB\n"
- + "Z84vAkA0Duur4YvsPJijoQ9YY1SGCagCcjyuUKwFOxaGpmyhRPIKt56LOJqpzyno\n"
- + "fy8ReKa4VyYq4eZYT249oFCwMwIBAkAROPNF2UL3x5UbcAkznd1hLujtIlI4IV4L\n"
- + "XUNjsJtBap7we/KHJq11XRPlniO4lf2TW7iji5neGVWJulTKS1xBAkAerktk4Hsw\n"
- + "ErUaUG1s/d+Sgc8e/KMeBElV+NxGhcWEeZtfHMn/6VOlbzY82JyvC9OKC80A5CAE\n"
- + "VUV6b25kqrcu\n"
- + "-----END PRIVATE KEY-----";
+ private static final String TEST_CERT_PATH = "testresources/mtls/test_cert.pem";
+ private static final String TEST_CONFIG_PATH = "testresources/mtls/certificate_config.json";
@Test
void x509Provider_fileDoesntExist_throws() {
String certConfigPath = "badfile.txt";
- X509Provider testProvider = new TestX509Provider(certConfigPath);
- String expectedErrorMessage = "File does not exist.";
-
+ X509Provider testProvider = new X509Provider(certConfigPath);
+ String expectedErrorMessage =
+ "Certificate configuration file does not exist or is not a file: "
+ + new File(certConfigPath).getAbsolutePath();
CertificateSourceUnavailableException exception =
assertThrows(CertificateSourceUnavailableException.class, testProvider::getKeyStore);
- assertTrue(exception.getMessage().contains(expectedErrorMessage));
+ assertEquals(expectedErrorMessage, exception.getMessage());
}
@Test
- void x509Provider_emptyFile_throws() {
- String certConfigPath = "certConfig.txt";
- InputStream certConfigStream = new ByteArrayInputStream("".getBytes());
- TestX509Provider testProvider = new TestX509Provider(certConfigPath);
- testProvider.addFile(certConfigPath, certConfigStream);
+ void x509Provider_emptyFile_throws() throws IOException {
+ Path emptyConfig = Files.createTempFile("emptyConfig", ".txt");
+ emptyConfig.toFile().deleteOnExit();
+
+ X509Provider testProvider = new X509Provider(emptyConfig.toString());
String expectedErrorMessage = "no JSON input found";
IllegalArgumentException exception =
@@ -112,21 +83,13 @@ void x509Provider_emptyFile_throws() {
@Test
void x509Provider_succeeds() throws IOException, KeyStoreException, CertificateException {
- String certConfigPath = "certConfig.txt";
- String certPath = "cert.crt";
- String keyPath = "key.crt";
- InputStream certConfigStream =
- WorkloadCertificateConfigurationTest.writeWorkloadCertificateConfigStream(
- certPath, keyPath);
-
- TestX509Provider testProvider = new TestX509Provider(certConfigPath);
- testProvider.addFile(certConfigPath, certConfigStream);
- testProvider.addFile(certPath, new ByteArrayInputStream(TEST_CERT.getBytes()));
- testProvider.addFile(keyPath, new ByteArrayInputStream(TEST_PRIVATE_KEY.getBytes()));
+ X509Provider testProvider = new X509Provider(TEST_CONFIG_PATH);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
- Certificate expectedCert =
- cf.generateCertificate(new ByteArrayInputStream(TEST_CERT.getBytes()));
+ Certificate expectedCert;
+ try (FileInputStream fis = new FileInputStream(new File(TEST_CERT_PATH))) {
+ expectedCert = cf.generateCertificate(fis);
+ }
// Assert that the store has the expected certificate and only the expected certificate.
KeyStore store = testProvider.getKeyStore();
@@ -137,22 +100,17 @@ void x509Provider_succeeds() throws IOException, KeyStoreException, CertificateE
@Test
void x509Provider_succeeds_withEnvVariable()
throws IOException, KeyStoreException, CertificateException {
- String certConfigPath = "certConfig.txt";
- String certPath = "cert.crt";
- String keyPath = "key.crt";
- InputStream certConfigStream =
- WorkloadCertificateConfigurationTest.writeWorkloadCertificateConfigStream(
- certPath, keyPath);
-
- TestX509Provider testProvider = new TestX509Provider();
- testProvider.setEnv("GOOGLE_API_CERTIFICATE_CONFIG", certConfigPath);
- testProvider.addFile(certConfigPath, certConfigStream);
- testProvider.addFile(certPath, new ByteArrayInputStream(TEST_CERT.getBytes()));
- testProvider.addFile(keyPath, new ByteArrayInputStream(TEST_PRIVATE_KEY.getBytes()));
+ TestEnvironmentProvider envProvider = new TestEnvironmentProvider();
+ envProvider.setEnv("GOOGLE_API_CERTIFICATE_CONFIG", TEST_CONFIG_PATH);
+
+ X509Provider testProvider =
+ new X509Provider(envProvider, SystemPropertyProvider.getInstance(), null);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
- Certificate expectedCert =
- cf.generateCertificate(new ByteArrayInputStream(TEST_CERT.getBytes()));
+ Certificate expectedCert;
+ try (FileInputStream fis = new FileInputStream(new File(TEST_CERT_PATH))) {
+ expectedCert = cf.generateCertificate(fis);
+ }
// Assert that the store has the expected certificate and only the expected certificate.
KeyStore store = testProvider.getKeyStore();
@@ -163,22 +121,17 @@ void x509Provider_succeeds_withEnvVariable()
@Test
void x509Provider_succeeds_withWellKnownPath()
throws IOException, KeyStoreException, CertificateException {
- String certConfigPath = "certConfig.txt";
- String certPath = "cert.crt";
- String keyPath = "key.crt";
- InputStream certConfigStream =
- WorkloadCertificateConfigurationTest.writeWorkloadCertificateConfigStream(
- certPath, keyPath);
-
- TestX509Provider testProvider = new TestX509Provider();
- testProvider.setEnv("GOOGLE_API_CERTIFICATE_CONFIG", certConfigPath);
- testProvider.addFile(certConfigPath, certConfigStream);
- testProvider.addFile(certPath, new ByteArrayInputStream(TEST_CERT.getBytes()));
- testProvider.addFile(keyPath, new ByteArrayInputStream(TEST_PRIVATE_KEY.getBytes()));
+ TestEnvironmentProvider envProvider = new TestEnvironmentProvider();
+ envProvider.setEnv("CLOUDSDK_CONFIG", "testresources/mtls/");
+
+ X509Provider testProvider =
+ new X509Provider(envProvider, SystemPropertyProvider.getInstance(), null);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
- Certificate expectedCert =
- cf.generateCertificate(new ByteArrayInputStream(TEST_CERT.getBytes()));
+ Certificate expectedCert;
+ try (FileInputStream fis = new FileInputStream(new File(TEST_CERT_PATH))) {
+ expectedCert = cf.generateCertificate(fis);
+ }
// Assert that the store has the expected certificate and only the expected certificate.
KeyStore store = testProvider.getKeyStore();
@@ -186,53 +139,73 @@ void x509Provider_succeeds_withWellKnownPath()
assertNotNull(store.getCertificateAlias(expectedCert));
}
- static class TestX509Provider extends X509Provider {
- private final Map files;
- private final Map variables;
- private final Map properties;
+ @Test
+ void x509Provider_succeeds_withWindowsPath()
+ throws IOException, KeyStoreException, CertificateException {
+ Path windowsTempDir = Files.createTempDirectory("windowsTempDir");
+ windowsTempDir.toFile().deleteOnExit();
+ Path gcloudDir = windowsTempDir.resolve("gcloud");
+ Files.createDirectory(gcloudDir);
+ Path configPath = gcloudDir.resolve("certificate_config.json");
- TestX509Provider() {
- this(null);
- }
+ // Copy the valid config to this new temp location
+ Files.copy(new File(TEST_CONFIG_PATH).toPath(), configPath);
- TestX509Provider(String filePathOverride) {
- super(filePathOverride);
- this.files = new HashMap<>();
- this.variables = new HashMap<>();
- this.properties = new HashMap<>();
- }
+ TestEnvironmentProvider envProvider = new TestEnvironmentProvider();
+ envProvider.setEnv("APPDATA", windowsTempDir.toString());
- void addFile(String file, InputStream stream) {
- files.put(file, stream);
- }
+ TestPropertyProvider propProvider = new TestPropertyProvider();
+ propProvider.setProperty("os.name", "Windows 10");
- @Override
- String getEnv(String name) {
- return variables.get(name);
- }
+ X509Provider testProvider = new X509Provider(envProvider, propProvider, null);
- void setEnv(String name, String value) {
- variables.put(name, value);
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ Certificate expectedCert;
+ try (FileInputStream fis = new FileInputStream(new File(TEST_CERT_PATH))) {
+ expectedCert = cf.generateCertificate(fis);
}
- @Override
- String getProperty(String property, String def) {
- String value = properties.get(property);
- return value == null ? def : value;
- }
+ KeyStore store = testProvider.getKeyStore();
+ assertEquals(1, store.size());
+ assertNotNull(store.getCertificateAlias(expectedCert));
+ }
- @Override
- boolean isFile(File file) {
- return files.containsKey(file.getPath());
- }
+ @Test
+ void x509Provider_certFileDoesntExist_throws() throws IOException {
+ Path tempConfig = Files.createTempFile("config", ".json");
+ tempConfig.toFile().deleteOnExit();
+ Path nonExistentCert = tempConfig.getParent().resolve("non_existent_cert.pem");
- @Override
- InputStream createInputStream(File file) throws FileNotFoundException {
- InputStream stream = files.get(file.getPath());
- if (stream == null) {
- throw new FileNotFoundException(file.getPath());
- }
- return stream;
- }
+ Files.write(
+ tempConfig,
+ ("{\"cert_configs\":{\"workload\":{\"cert_path\":\""
+ + nonExistentCert.toString()
+ + "\",\"key_path\":\"key.pem\"}}}")
+ .getBytes());
+
+ X509Provider testProvider = new X509Provider(tempConfig.toString());
+
+ assertThrows(IOException.class, testProvider::getKeyStore);
+ }
+
+ @Test
+ void x509Provider_malformedCert_throws() throws IOException {
+ Path tempConfig = Files.createTempFile("config", ".json");
+ tempConfig.toFile().deleteOnExit();
+ Path malformedCert = Files.createTempFile("badcert", ".pem");
+ malformedCert.toFile().deleteOnExit();
+
+ Files.write(malformedCert, "This is not a valid certificate".getBytes());
+
+ Files.write(
+ tempConfig,
+ ("{\"cert_configs\":{\"workload\":{\"cert_path\":\""
+ + malformedCert.toString()
+ + "\",\"key_path\":\"key.pem\"}}}")
+ .getBytes());
+
+ X509Provider testProvider = new X509Provider(tempConfig.toString());
+
+ assertThrows(Exception.class, testProvider::getKeyStore);
}
}
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/AccessTokenTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/AccessTokenTest.java
index d93e2c98f53e..f9ebaa2bb94c 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/AccessTokenTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/AccessTokenTest.java
@@ -32,14 +32,14 @@
package com.google.auth.oauth2;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertSame;
-import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.junit.jupiter.api.Test;
@@ -92,7 +92,7 @@ void builder() {
.setTokenValue(TOKEN)
.setScopes("dummy")
.build();
- assertEquals(Arrays.asList("dummy"), accessToken.getScopes());
+ assertEquals(Collections.singletonList("dummy"), accessToken.getScopes());
// empty scope
accessToken =
@@ -105,7 +105,7 @@ void builder() {
}
@Test
- void equals_true() throws IOException {
+ void equals_true() {
AccessToken accessToken =
AccessToken.newBuilder()
.setExpirationTime(EXPIRATION_DATE)
@@ -121,12 +121,12 @@ void equals_true() throws IOException {
.setScopes(SCOPES)
.build();
- assertTrue(accessToken.equals(otherAccessToken));
- assertTrue(otherAccessToken.equals(accessToken));
+ assertEquals(accessToken, otherAccessToken);
+ assertEquals(otherAccessToken, accessToken);
}
@Test
- void equals_false_scopes() throws IOException {
+ void equals_false_scopes() {
AccessToken accessToken =
AccessToken.newBuilder()
.setExpirationTime(EXPIRATION_DATE)
@@ -138,15 +138,15 @@ void equals_false_scopes() throws IOException {
AccessToken.newBuilder()
.setExpirationTime(EXPIRATION_DATE)
.setTokenValue(TOKEN)
- .setScopes(Arrays.asList("scope1"))
+ .setScopes(Collections.singletonList("scope1"))
.build();
- assertFalse(accessToken.equals(otherAccessToken));
- assertFalse(otherAccessToken.equals(accessToken));
+ assertNotEquals(accessToken, otherAccessToken);
+ assertNotEquals(otherAccessToken, accessToken);
}
@Test
- void equals_false_token() throws IOException {
+ void equals_false_token() {
AccessToken accessToken =
AccessToken.newBuilder()
.setExpirationTime(EXPIRATION_DATE)
@@ -161,12 +161,12 @@ void equals_false_token() throws IOException {
.setScopes(SCOPES)
.build();
- assertFalse(accessToken.equals(otherAccessToken));
- assertFalse(otherAccessToken.equals(accessToken));
+ assertNotEquals(accessToken, otherAccessToken);
+ assertNotEquals(otherAccessToken, accessToken);
}
@Test
- void equals_false_expirationDate() throws IOException {
+ void equals_false_expirationDate() {
AccessToken accessToken =
AccessToken.newBuilder()
.setExpirationTime(EXPIRATION_DATE)
@@ -181,8 +181,8 @@ void equals_false_expirationDate() throws IOException {
.setScopes(SCOPES)
.build();
- assertFalse(accessToken.equals(otherAccessToken));
- assertFalse(otherAccessToken.equals(accessToken));
+ assertNotEquals(accessToken, otherAccessToken);
+ assertNotEquals(otherAccessToken, accessToken);
}
@Test
@@ -201,7 +201,7 @@ void toString_containsFields() {
}
@Test
- void hashCode_equals() throws IOException {
+ void hashCode_equals() {
AccessToken accessToken =
AccessToken.newBuilder()
.setExpirationTime(EXPIRATION_DATE)
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/AppEngineCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/AppEngineCredentialsTest.java
index 43139e2bed2b..eb885d184c17 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/AppEngineCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/AppEngineCredentialsTest.java
@@ -37,8 +37,8 @@
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import com.google.common.collect.ImmutableMap;
import java.io.IOException;
@@ -77,18 +77,15 @@ void constructor_usesAppIdentityService() throws IOException {
@Test
void constructor_noAppEngineRuntime_throwsHelpfulLoadError() {
- try {
- new TestAppEngineCredentialsNoSdk();
- fail("Credential expected to fail to load if credential class not present.");
- } catch (IOException e) {
- String message = e.getMessage();
- assertTrue(message.contains("Check that the App Engine SDK is deployed."));
- assertInstanceOf(ClassNotFoundException.class, e.getCause());
- assertTrue(
- e.getCause()
- .getMessage()
- .contains(AppEngineCredentials.APP_IDENTITY_SERVICE_FACTORY_CLASS));
- }
+ IOException exception = assertThrows(IOException.class, TestAppEngineCredentialsNoSdk::new);
+ String message = exception.getMessage();
+ assertTrue(message.contains("Check that the App Engine SDK is deployed."));
+ assertInstanceOf(ClassNotFoundException.class, exception.getCause());
+ assertTrue(
+ exception
+ .getCause()
+ .getMessage()
+ .contains(AppEngineCredentials.APP_IDENTITY_SERVICE_FACTORY_CLASS));
}
@Test
@@ -115,12 +112,7 @@ void sign_sameAs() throws IOException {
void createScoped_clonesWithScopes() throws IOException {
TestAppEngineCredentials credentials = new TestAppEngineCredentials(null);
assertTrue(credentials.createScopedRequired());
- try {
- credentials.refreshAccessToken();
- fail("Should not be able to use credential without scopes.");
- } catch (Exception expected) {
- // Expected
- }
+ assertThrows(IOException.class, credentials::refreshAccessToken);
GoogleCredentials scopedCredentials = credentials.createScoped(SCOPES);
assertNotSame(credentials, scopedCredentials);
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/AwsCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/AwsCredentialsTest.java
index 4764d27ec38f..e401ae853771 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/AwsCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/AwsCredentialsTest.java
@@ -32,12 +32,13 @@
package com.google.auth.oauth2;
import static com.google.auth.Credentials.GOOGLE_DEFAULT_UNIVERSE;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import com.google.api.client.json.GenericJson;
import com.google.api.client.json.JsonParser;
@@ -55,7 +56,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.function.Supplier;
import org.junit.jupiter.api.Test;
/** Tests for {@link AwsCredentials}. */
@@ -86,7 +86,6 @@ class AwsCredentialsTest extends BaseSerializationTest {
}
};
- private static final Map EMPTY_METADATA_HEADERS = Collections.emptyMap();
private static final Map EMPTY_STRING_HEADERS = Collections.emptyMap();
private static final AwsCredentialSource AWS_CREDENTIAL_SOURCE =
@@ -110,13 +109,13 @@ class AwsCredentialsTest extends BaseSerializationTest {
@Test
void test_awsCredentialSource() {
- String keys[] = {"region_url", "url", "imdsv2_session_token_url"};
+ String[] keys = {"region_url", "url", "imdsv2_session_token_url"};
for (String key : keys) {
Map credentialSourceWithInvalidUrl = buildAwsIpv6CredentialSourceMap();
credentialSourceWithInvalidUrl.put(key, "https://badhost.com/fake");
// Should succeed as no validation is done.
- new AwsCredentialSource(credentialSourceWithInvalidUrl);
+ assertDoesNotThrow(() -> new AwsCredentialSource(credentialSourceWithInvalidUrl));
}
}
@@ -190,7 +189,7 @@ void refreshAccessToken_withServiceAccountImpersonationOptions() throws IOExcept
.setServiceAccountImpersonationUrl(
transportFactory.transport.getServiceAccountImpersonationUrl())
.setServiceAccountImpersonationOptions(
- ExternalAccountCredentialsTest.buildServiceAccountImpersonationOptions(2800))
+ ExternalAccountCredentialsTest.buildServiceAccountImpersonationOptions())
.build();
AccessToken accessToken = awsCredential.refreshAccessToken();
@@ -199,17 +198,17 @@ void refreshAccessToken_withServiceAccountImpersonationOptions() throws IOExcept
transportFactory.transport.getServiceAccountAccessToken(), accessToken.getTokenValue());
// Validate that default lifetime was set correctly on the request.
- GenericJson query =
- OAuth2Utils.JSON_FACTORY
- .createJsonParser(transportFactory.transport.getLastRequest().getContentAsString())
- .parseAndClose(GenericJson.class);
-
- assertEquals("2800s", query.get("lifetime"));
-
- // Validate metrics header is set correctly on the sts request.
- Map> headers =
- transportFactory.transport.getRequests().get(6).getHeaders();
- ExternalAccountCredentialsTest.validateMetricsHeader(headers, "aws", true, true);
+ try (JsonParser jsonParser =
+ OAuth2Utils.JSON_FACTORY.createJsonParser(
+ transportFactory.transport.getLastRequest().getContentAsString())) {
+ GenericJson query = jsonParser.parseAndClose(GenericJson.class);
+ assertEquals("2800s", query.get("lifetime"));
+
+ // Validate metrics header is set correctly on the sts request.
+ Map> headers =
+ transportFactory.transport.getRequests().get(6).getHeaders();
+ ExternalAccountCredentialsTest.validateMetricsHeader(headers, "aws", true, true);
+ }
}
@Test
@@ -485,12 +484,8 @@ void retrieveSubjectToken_noRegion_expectThrows() {
.setCredentialSource(buildAwsCredentialSource(transportFactory))
.build();
- try {
- awsCredential.retrieveSubjectToken();
- fail("Should not be able to use credential without exception.");
- } catch (IOException exception) {
- assertEquals("Failed to retrieve AWS region.", exception.getMessage());
- }
+ IOException exception = assertThrows(IOException.class, awsCredential::retrieveSubjectToken);
+ assertEquals("Failed to retrieve AWS region.", exception.getMessage());
List requests = transportFactory.transport.getRequests();
assertEquals(1, requests.size());
@@ -514,12 +509,8 @@ void retrieveSubjectToken_noRole_expectThrows() {
.setCredentialSource(buildAwsCredentialSource(transportFactory))
.build();
- try {
- awsCredential.retrieveSubjectToken();
- fail("Should not be able to use credential without exception.");
- } catch (IOException exception) {
- assertEquals("Failed to retrieve AWS IAM role.", exception.getMessage());
- }
+ IOException exception = assertThrows(IOException.class, awsCredential::retrieveSubjectToken);
+ assertEquals("Failed to retrieve AWS IAM role.", exception.getMessage());
List requests = transportFactory.transport.getRequests();
assertEquals(2, requests.size());
@@ -546,12 +537,8 @@ void retrieveSubjectToken_noCredentials_expectThrows() {
.setCredentialSource(buildAwsCredentialSource(transportFactory))
.build();
- try {
- awsCredential.retrieveSubjectToken();
- fail("Should not be able to use credential without exception.");
- } catch (IOException exception) {
- assertEquals("Failed to retrieve AWS credentials.", exception.getMessage());
- }
+ IOException exception = assertThrows(IOException.class, awsCredential::retrieveSubjectToken);
+ assertEquals("Failed to retrieve AWS credentials.", exception.getMessage());
List requests = transportFactory.transport.getRequests();
assertEquals(3, requests.size());
@@ -581,15 +568,11 @@ void retrieveSubjectToken_noRegionUrlProvided() {
.setCredentialSource(new AwsCredentialSource(credentialSource))
.build();
- try {
- awsCredential.retrieveSubjectToken();
- fail("Should not be able to use credential without exception.");
- } catch (IOException exception) {
- assertEquals(
- "Unable to determine the AWS region. The credential source does not "
- + "contain the region URL.",
- exception.getMessage());
- }
+ IOException exception = assertThrows(IOException.class, awsCredential::retrieveSubjectToken);
+ assertEquals(
+ "Unable to determine the AWS region. The credential source does not "
+ + "contain the region URL.",
+ exception.getMessage());
// No requests because the credential source does not contain region URL.
List requests = transportFactory.transport.getRequests();
@@ -679,7 +662,7 @@ void retrieveSubjectToken_withProgrammaticRefreshSessionToken() throws IOExcepti
}
@Test
- void retrieveSubjectToken_passesContext() throws IOException {
+ void retrieveSubjectToken_passesContext() {
MockExternalAccountCredentialsTransportFactory transportFactory =
new MockExternalAccountCredentialsTransportFactory();
@@ -705,11 +688,11 @@ void retrieveSubjectToken_passesContext() throws IOException {
.setSubjectTokenType("subjectTokenType")
.build();
- awsCredential.retrieveSubjectToken();
+ assertDoesNotThrow(awsCredential::retrieveSubjectToken);
}
@Test
- void retrieveSubjectToken_withProgrammaticRefreshThrowsError() throws IOException {
+ void retrieveSubjectToken_withProgrammaticRefreshThrowsError() {
MockExternalAccountCredentialsTransportFactory transportFactory =
new MockExternalAccountCredentialsTransportFactory();
@@ -727,12 +710,8 @@ void retrieveSubjectToken_withProgrammaticRefreshThrowsError() throws IOExceptio
.setSubjectTokenType("subjectTokenType")
.build();
- try {
- String subjectToken = URLDecoder.decode(awsCredential.retrieveSubjectToken(), "UTF-8");
- fail("retrieveSubjectToken should not succeed");
- } catch (IOException e) {
- assertEquals("test", e.getMessage());
- }
+ IOException exception = assertThrows(IOException.class, awsCredential::retrieveSubjectToken);
+ assertEquals("test", exception.getMessage());
}
@Test
@@ -853,14 +832,13 @@ void getAwsSecurityCredentials_fromMetadataServer_noUrlProvided() {
.setCredentialSource(new AwsCredentialSource(credentialSource))
.build();
- try {
- awsCredential.getAwsSecurityCredentialsSupplier().getCredentials(emptyContext);
- fail("Should not be able to use credential without exception.");
- } catch (IOException exception) {
- assertEquals(
- "Unable to determine the AWS IAM role name. The credential source does not contain the url field.",
- exception.getMessage());
- }
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () -> awsCredential.getAwsSecurityCredentialsSupplier().getCredentials(emptyContext));
+ assertEquals(
+ "Unable to determine the AWS IAM role name. The credential source does not contain the url field.",
+ exception.getMessage());
// No requests because url field is not present in credential source.
List requests = transportFactory.transport.getRequests();
@@ -946,7 +924,7 @@ void getAwsRegion_metadataServer() throws IOException {
}
@Test
- void createdScoped_clonedCredentialWithAddedScopes() throws IOException {
+ void createdScoped_clonedCredentialWithAddedScopes() {
AwsCredentials credentials =
AwsCredentials.newBuilder(AWS_CREDENTIAL)
.setServiceAccountImpersonationUrl(SERVICE_ACCOUNT_IMPERSONATION_URL)
@@ -982,12 +960,10 @@ void credentialSource_invalidAwsEnvironmentId() {
credentialSource.put("regional_cred_verification_url", GET_CALLER_IDENTITY_URL);
credentialSource.put("environment_id", "azure1");
- try {
- new AwsCredentialSource(credentialSource);
- fail("Exception should be thrown.");
- } catch (IllegalArgumentException e) {
- assertEquals("Invalid AWS environment ID.", e.getMessage());
- }
+ IllegalArgumentException exception =
+ assertThrows(
+ IllegalArgumentException.class, () -> new AwsCredentialSource(credentialSource));
+ assertEquals("Invalid AWS environment ID.", exception.getMessage());
}
@Test
@@ -997,31 +973,27 @@ void credentialSource_invalidAwsEnvironmentVersion() {
credentialSource.put("regional_cred_verification_url", GET_CALLER_IDENTITY_URL);
credentialSource.put("environment_id", "aws" + environmentVersion);
- try {
- new AwsCredentialSource(credentialSource);
- fail("Exception should be thrown.");
- } catch (IllegalArgumentException e) {
- assertEquals(
- String.format(
- "AWS version %s is not supported in the current build.", environmentVersion),
- e.getMessage());
- }
+ IllegalArgumentException exception =
+ assertThrows(
+ IllegalArgumentException.class, () -> new AwsCredentialSource(credentialSource));
+ assertEquals(
+ String.format("AWS version %s is not supported in the current build.", environmentVersion),
+ exception.getMessage());
}
@Test
void credentialSource_missingRegionalCredVerificationUrl() {
- try {
- new AwsCredentialSource(new HashMap());
- fail("Exception should be thrown.");
- } catch (IllegalArgumentException e) {
- assertEquals(
- "A regional_cred_verification_url representing the GetCallerIdentity action URL must be specified.",
- e.getMessage());
- }
+ HashMap credentialSourceMap = new HashMap<>();
+ IllegalArgumentException exception =
+ assertThrows(
+ IllegalArgumentException.class, () -> new AwsCredentialSource(credentialSourceMap));
+ assertEquals(
+ "A regional_cred_verification_url representing the GetCallerIdentity action URL must be specified.",
+ exception.getMessage());
}
@Test
- void builder_allFields() throws IOException {
+ void builder_allFields() {
List scopes = Arrays.asList("scope1", "scope2");
AwsCredentials credentials =
@@ -1057,7 +1029,7 @@ void builder_allFields() throws IOException {
}
@Test
- void builder_missingUniverseDomain_defaults() throws IOException {
+ void builder_missingUniverseDomain_defaults() {
List scopes = Arrays.asList("scope1", "scope2");
AwsCredentials credentials =
@@ -1094,7 +1066,7 @@ void builder_missingUniverseDomain_defaults() throws IOException {
}
@Test
- void newBuilder_allFields() throws IOException {
+ void newBuilder_allFields() {
List scopes = Arrays.asList("scope1", "scope2");
AwsCredentials credentials =
@@ -1132,7 +1104,7 @@ void newBuilder_allFields() throws IOException {
}
@Test
- void newBuilder_noUniverseDomain_defaults() throws IOException {
+ void newBuilder_noUniverseDomain_defaults() {
List scopes = Arrays.asList("scope1", "scope2");
AwsCredentials credentials =
@@ -1169,7 +1141,7 @@ void newBuilder_noUniverseDomain_defaults() throws IOException {
}
@Test
- void builder_defaultRegionalCredentialVerificationUrlOverride() throws IOException {
+ void builder_defaultRegionalCredentialVerificationUrlOverride() {
List scopes = Arrays.asList("scope1", "scope2");
AwsSecurityCredentialsSupplier supplier =
@@ -1197,63 +1169,55 @@ void builder_defaultRegionalCredentialVerificationUrlOverride() throws IOExcepti
}
@Test
- void builder_supplierAndCredSourceThrows() throws IOException {
+ void builder_supplierAndCredSourceThrows() {
List scopes = Arrays.asList("scope1", "scope2");
AwsSecurityCredentialsSupplier supplier =
new TestAwsSecurityCredentialsSupplier("region", null, null, null);
- try {
- AwsCredentials credentials =
- AwsCredentials.newBuilder()
- .setAwsSecurityCredentialsSupplier(supplier)
- .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
- .setAudience("audience")
- .setSubjectTokenType("subjectTokenType")
- .setTokenUrl(STS_URL)
- .setTokenInfoUrl("tokenInfoUrl")
- .setCredentialSource(AWS_CREDENTIAL_SOURCE)
- .setServiceAccountImpersonationUrl(SERVICE_ACCOUNT_IMPERSONATION_URL)
- .setQuotaProjectId("quotaProjectId")
- .setClientId("clientId")
- .setClientSecret("clientSecret")
- .setScopes(scopes)
- .build();
- fail("Should not be able to continue without exception.");
- } catch (IllegalArgumentException exception) {
- assertEquals(
- "AwsCredentials cannot have both an awsSecurityCredentialsSupplier and a credentialSource.",
- exception.getMessage());
- }
+ AwsCredentials.Builder builder =
+ AwsCredentials.newBuilder()
+ .setAwsSecurityCredentialsSupplier(supplier)
+ .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
+ .setAudience("audience")
+ .setSubjectTokenType("subjectTokenType")
+ .setTokenUrl(STS_URL)
+ .setTokenInfoUrl("tokenInfoUrl")
+ .setCredentialSource(AWS_CREDENTIAL_SOURCE)
+ .setServiceAccountImpersonationUrl(SERVICE_ACCOUNT_IMPERSONATION_URL)
+ .setQuotaProjectId("quotaProjectId")
+ .setClientId("clientId")
+ .setClientSecret("clientSecret")
+ .setScopes(scopes);
+ IllegalArgumentException exception =
+ assertThrows(IllegalArgumentException.class, builder::build);
+ assertEquals(
+ "AwsCredentials cannot have both an awsSecurityCredentialsSupplier and a credentialSource.",
+ exception.getMessage());
}
@Test
- void builder_noSupplieOrCredSourceThrows() throws IOException {
+ void builder_noSupplieOrCredSourceThrows() {
List scopes = Arrays.asList("scope1", "scope2");
- Supplier testSupplier = () -> null;
-
- try {
- AwsCredentials credentials =
- AwsCredentials.newBuilder()
- .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
- .setAudience("audience")
- .setSubjectTokenType("subjectTokenType")
- .setTokenUrl(STS_URL)
- .setTokenInfoUrl("tokenInfoUrl")
- .setTokenInfoUrl("tokenInfoUrl")
- .setServiceAccountImpersonationUrl(SERVICE_ACCOUNT_IMPERSONATION_URL)
- .setQuotaProjectId("quotaProjectId")
- .setClientId("clientId")
- .setClientSecret("clientSecret")
- .setScopes(scopes)
- .build();
- fail("Should not be able to continue without exception.");
- } catch (IllegalArgumentException exception) {
- assertEquals(
- "An awsSecurityCredentialsSupplier or a credentialSource must be provided.",
- exception.getMessage());
- }
+ AwsCredentials.Builder builder =
+ AwsCredentials.newBuilder()
+ .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
+ .setAudience("audience")
+ .setSubjectTokenType("subjectTokenType")
+ .setTokenUrl(STS_URL)
+ .setTokenInfoUrl("tokenInfoUrl")
+ .setTokenInfoUrl("tokenInfoUrl")
+ .setServiceAccountImpersonationUrl(SERVICE_ACCOUNT_IMPERSONATION_URL)
+ .setQuotaProjectId("quotaProjectId")
+ .setClientId("clientId")
+ .setClientSecret("clientSecret")
+ .setScopes(scopes);
+ IllegalArgumentException exception =
+ assertThrows(IllegalArgumentException.class, builder::build);
+ assertEquals(
+ "An awsSecurityCredentialsSupplier or a credentialSource must be provided.",
+ exception.getMessage());
}
@Test
@@ -1281,7 +1245,7 @@ void serialize() throws IOException, ClassNotFoundException {
assertEquals(testCredentials, deserializedCredentials);
assertEquals(testCredentials.hashCode(), deserializedCredentials.hashCode());
assertEquals(testCredentials.toString(), deserializedCredentials.toString());
- assertSame(deserializedCredentials.clock, Clock.SYSTEM);
+ assertSame(Clock.SYSTEM, deserializedCredentials.clock);
}
private static void ValidateRequest(
@@ -1353,12 +1317,12 @@ static InputStream writeAwsCredentialsStream(String stsUrl, String regionUrl, St
return TestUtils.jsonToInputStream(json);
}
- class TestAwsSecurityCredentialsSupplier implements AwsSecurityCredentialsSupplier {
+ static class TestAwsSecurityCredentialsSupplier implements AwsSecurityCredentialsSupplier {
- private String region;
- private AwsSecurityCredentials credentials;
- private IOException credentialException;
- private ExternalAccountSupplierContext expectedContext;
+ private final String region;
+ private final AwsSecurityCredentials credentials;
+ private final IOException credentialException;
+ private final ExternalAccountSupplierContext expectedContext;
TestAwsSecurityCredentialsSupplier(
String region,
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/AwsRequestSignerTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/AwsRequestSignerTest.java
index a1125edef760..750390aeaec2 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/AwsRequestSignerTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/AwsRequestSignerTest.java
@@ -49,8 +49,9 @@
/**
* Tests for {@link AwsRequestSigner}.
*
- * Examples of sigv4 signed requests:
- * https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
+ *
Examples
+ * of sigv4 signed requests
*/
class AwsRequestSignerTest {
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/CertificateIdentityPoolSubjectTokenSupplierTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/CertificateIdentityPoolSubjectTokenSupplierTest.java
index 9ff8f7f5f9f6..dfb81281db53 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/CertificateIdentityPoolSubjectTokenSupplierTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/CertificateIdentityPoolSubjectTokenSupplierTest.java
@@ -32,6 +32,7 @@
package com.google.auth.oauth2;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -254,8 +255,9 @@ void getSubjectToken_trustChainWrongOrder_throwsIllegalArgumentException() {
Throwable cause = exception.getCause();
assertNotNull(cause, "Exception cause should not be null");
- assertTrue(
- cause instanceof IllegalArgumentException,
+ assertInstanceOf(
+ IllegalArgumentException.class,
+ cause,
"Exception cause should be an IllegalArgumentException");
assertEquals(expectedRootErrorMessage, cause.getMessage());
}
@@ -301,7 +303,7 @@ void getSubjectToken_trustChainFileNotFound_throwsIOException() {
assertThrows(IOException.class, () -> supplier.getSubjectToken(mockContext));
// Check that the cause is NoSuchFileException from readTrustChain.
- assertTrue(exception.getCause() instanceof NoSuchFileException);
+ assertInstanceOf(NoSuchFileException.class, exception.getCause());
// Check the outer exception message added in getSubjectToken.
assertEquals("Trust chain file not found: " + nonExistentPath, exception.getMessage());
@@ -328,7 +330,7 @@ void getSubjectToken_trustChainInvalidFormat_throwsIOException() throws Exceptio
exception.getMessage());
// Check that the cause is CertificateException from readTrustChain
- assertTrue(exception.getCause() instanceof CertificateException);
+ assertInstanceOf(CertificateException.class, exception.getCause());
// Verify the cause's message specifically points to the trust chain parsing failure
// and includes the path of the invalid trust chain file.
@@ -357,8 +359,8 @@ void getSubjectToken_leafCertFileNotFound_throwsIOException() {
// Check that the cause is the original NoSuchFileException.
assertNotNull(exception.getCause(), "Exception should have a cause");
- assertTrue(
- exception.getCause() instanceof NoSuchFileException, "Cause should be NoSuchFileException");
+ assertInstanceOf(
+ NoSuchFileException.class, exception.getCause(), "Cause should be NoSuchFileException");
// Check the message of the cause (which is the path) in a platform-agnostic way.
Path expectedCausePath = Paths.get(nonExistentPath);
@@ -385,7 +387,7 @@ void getSubjectToken_leafCertInvalidFormat_throwsIOException() throws Exception
// Check that the cause is CertificateException from parseCertificate (via
// loadLeafCertificate)
- assertTrue(exception.getCause() instanceof CertificateException);
+ assertInstanceOf(CertificateException.class, exception.getCause());
assertEquals("Failed to parse X.509 certificate data.", exception.getCause().getMessage());
// Check the outer exception message
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ClientIdTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ClientIdTest.java
index c002cf7e4fe5..eaceca0eaf3a 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ClientIdTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ClientIdTest.java
@@ -31,6 +31,7 @@
package com.google.auth.oauth2;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -57,9 +58,8 @@ void constructor() {
@Test
void constructor_nullClientId_throws() {
- assertThrows(
- NullPointerException.class,
- () -> ClientId.newBuilder().setClientSecret(CLIENT_SECRET).build());
+ ClientId.Builder builder = ClientId.newBuilder().setClientSecret(CLIENT_SECRET);
+ assertThrows(NullPointerException.class, builder::build);
}
@Test
@@ -100,21 +100,21 @@ void fromJson_installedNoSecret() throws IOException {
}
@Test
- void fromJson_invalidType_throws() throws IOException {
+ void fromJson_invalidType_throws() {
GenericJson json = writeClientIdJson("invalid", CLIENT_ID, null);
assertThrows(IOException.class, () -> ClientId.fromJson(json));
}
@Test
- void fromJson_noClientId_throws() throws IOException {
+ void fromJson_noClientId_throws() {
GenericJson json = writeClientIdJson("web", null, null);
assertThrows(IOException.class, () -> ClientId.fromJson(json));
}
@Test
- void fromJson_zeroLengthClientId_throws() throws IOException {
+ void fromJson_zeroLengthClientId_throws() {
GenericJson json = writeClientIdJson("web", "", null);
assertThrows(IOException.class, () -> ClientId.fromJson(json));
@@ -129,7 +129,7 @@ void fromResource() throws IOException {
}
@Test
- void fromResource_badResource() throws IOException {
+ void fromResource_badResource() {
assertThrows(
NullPointerException.class,
() -> ClientId.fromResource(ClientIdTest.class, "invalid.json"));
@@ -168,9 +168,9 @@ void fromStream_invalidJson_doesNotThrow() throws IOException {
+ CLIENT_SECRET
+ "\""
+ "}"; // No closing brace
- InputStream stream = TestUtils.stringToInputStream(invalidJson);
-
- ClientId.fromStream(stream);
+ try (InputStream stream = TestUtils.stringToInputStream(invalidJson)) {
+ assertDoesNotThrow(() -> ClientId.fromStream(stream));
+ }
}
private GenericJson writeClientIdJson(String type, String clientId, String clientSecret) {
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/CloudShellCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/CloudShellCredentialsTest.java
index 2f0dde620679..21abe335f3f5 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/CloudShellCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/CloudShellCredentialsTest.java
@@ -32,9 +32,8 @@
package com.google.auth.oauth2;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
-import static org.junit.jupiter.api.Assertions.assertTrue;
import com.google.api.client.util.Clock;
import java.io.BufferedReader;
@@ -50,63 +49,57 @@ class CloudShellCredentialsTest extends BaseSerializationTest {
@Test
void refreshAccessToken() throws IOException {
- final ServerSocket authSocket = new ServerSocket(0);
- try {
+ try (ServerSocket authSocket = new ServerSocket(0)) {
Runnable serverTask =
- new Runnable() {
- @Override
- public void run() {
- try {
- Socket clientSocket = authSocket.accept();
- BufferedReader input =
- new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
- String lines = input.readLine();
- lines += '\n' + input.readLine();
- assertEquals(lines, CloudShellCredentials.GET_AUTH_TOKEN_REQUEST);
-
- PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
- out.println("32\n[\"email\", \"project-id\", \"token\"]");
- } catch (Exception reThrown) {
- throw new RuntimeException(reThrown);
- }
+ () -> {
+ try {
+ Socket clientSocket = authSocket.accept();
+ BufferedReader input =
+ new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
+ String lines = input.readLine();
+ lines += '\n' + input.readLine();
+ assertEquals(CloudShellCredentials.GET_AUTH_TOKEN_REQUEST, lines);
+
+ PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
+ out.println("32\n[\"email\", \"project-id\", \"token\"]");
+ } catch (Exception reThrown) {
+ throw new RuntimeException(reThrown);
}
};
Thread serverThread = new Thread(serverTask);
serverThread.start();
- GoogleCredentials creds =
+ GoogleCredentials credentials =
CloudShellCredentials.newBuilder().setAuthPort(authSocket.getLocalPort()).build();
- assertEquals("token", creds.refreshAccessToken().getTokenValue());
- } finally {
- authSocket.close();
+ assertEquals("token", credentials.refreshAccessToken().getTokenValue());
}
}
@Test
- void equals_true() throws IOException {
+ void equals_true() {
GoogleCredentials credentials = CloudShellCredentials.newBuilder().setAuthPort(42).build();
GoogleCredentials otherCredentials = CloudShellCredentials.newBuilder().setAuthPort(42).build();
- assertTrue(credentials.equals(otherCredentials));
- assertTrue(otherCredentials.equals(credentials));
+ assertEquals(credentials, otherCredentials);
+ assertEquals(otherCredentials, credentials);
}
@Test
- void equals_false_authPort() throws IOException {
+ void equals_false_authPort() {
GoogleCredentials credentials = CloudShellCredentials.newBuilder().setAuthPort(42).build();
GoogleCredentials otherCredentials = CloudShellCredentials.newBuilder().setAuthPort(43).build();
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
- void toString_containsFields() throws IOException {
+ void toString_containsFields() {
String expectedToString = String.format("CloudShellCredentials{authPort=%d}", 42);
GoogleCredentials credentials = CloudShellCredentials.newBuilder().setAuthPort(42).build();
assertEquals(expectedToString, credentials.toString());
}
@Test
- void hashCode_equals() throws IOException {
+ void hashCode_equals() {
GoogleCredentials credentials = CloudShellCredentials.newBuilder().setAuthPort(42).build();
GoogleCredentials otherCredentials = CloudShellCredentials.newBuilder().setAuthPort(42).build();
assertEquals(credentials.hashCode(), otherCredentials.hashCode());
@@ -119,7 +112,7 @@ void serialize() throws IOException, ClassNotFoundException {
assertEquals(credentials, deserializedCredentials);
assertEquals(credentials.hashCode(), deserializedCredentials.hashCode());
assertEquals(credentials.toString(), deserializedCredentials.toString());
- assertSame(deserializedCredentials.clock, Clock.SYSTEM);
+ assertSame(Clock.SYSTEM, deserializedCredentials.clock);
}
@Test
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java
index 2f9b4b7e2836..82240171d9af 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java
@@ -36,12 +36,13 @@
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import com.google.api.client.http.HttpStatusCodes;
import com.google.api.client.http.HttpTransport;
@@ -151,7 +152,7 @@ void buildTokenUrlWithScopes_empty_scopes() {
@Test
void buildTokenUrlWithScopes_single_scope() {
ComputeEngineCredentials credentials =
- ComputeEngineCredentials.newBuilder().setScopes(Arrays.asList("foo")).build();
+ ComputeEngineCredentials.newBuilder().setScopes(Collections.singletonList("foo")).build();
String tokenUrlWithScopes = credentials.createTokenUrlWithScopes();
Collection scopes = credentials.getScopes();
@@ -295,11 +296,11 @@ void buildTokenUrlHardDirectPathBound_alts_transport() {
}
@Test
- void buildScoped_scopesPresent() throws IOException {
+ void buildScoped_scopesPresent() {
ComputeEngineCredentials credentials =
ComputeEngineCredentials.newBuilder().setScopes(null).build();
ComputeEngineCredentials scopedCredentials =
- (ComputeEngineCredentials) credentials.createScoped(Arrays.asList("foo"));
+ (ComputeEngineCredentials) credentials.createScoped(Collections.singletonList("foo"));
Collection scopes = scopedCredentials.getScopes();
assertEquals(1, scopes.size());
@@ -307,11 +308,11 @@ void buildScoped_scopesPresent() throws IOException {
}
@Test
- void buildScoped_correctMargins() throws IOException {
+ void buildScoped_correctMargins() {
ComputeEngineCredentials credentials =
ComputeEngineCredentials.newBuilder().setScopes(null).build();
ComputeEngineCredentials scopedCredentials =
- (ComputeEngineCredentials) credentials.createScoped(Arrays.asList("foo"));
+ (ComputeEngineCredentials) credentials.createScoped(Collections.singletonList("foo"));
assertEquals(
ComputeEngineCredentials.COMPUTE_EXPIRATION_MARGIN,
@@ -328,7 +329,7 @@ void buildScoped_explicitUniverse() throws IOException {
.setUniverseDomain("some-universe")
.build();
ComputeEngineCredentials scopedCredentials =
- (ComputeEngineCredentials) credentials.createScoped(Arrays.asList("foo"));
+ (ComputeEngineCredentials) credentials.createScoped(Collections.singletonList("foo"));
assertEquals("some-universe", scopedCredentials.getUniverseDomain());
assertTrue(scopedCredentials.isExplicitUniverseDomain());
@@ -337,7 +338,7 @@ void buildScoped_explicitUniverse() throws IOException {
@Test
void createScoped_defaultScopes() {
GoogleCredentials credentials =
- ComputeEngineCredentials.create().createScoped(null, Arrays.asList("foo"));
+ ComputeEngineCredentials.create().createScoped(null, Collections.singletonList("foo"));
Collection scopes = ((ComputeEngineCredentials) credentials).getScopes();
assertEquals(1, scopes.size());
@@ -345,14 +346,14 @@ void createScoped_defaultScopes() {
}
@Test
- void buildScoped_quotaProjectId() throws IOException {
+ void buildScoped_quotaProjectId() {
ComputeEngineCredentials credentials =
ComputeEngineCredentials.newBuilder()
.setScopes(null)
.setQuotaProjectId("some-project-id")
.build();
ComputeEngineCredentials scopedCredentials =
- (ComputeEngineCredentials) credentials.createScoped(Arrays.asList("foo"));
+ (ComputeEngineCredentials) credentials.createScoped(Collections.singletonList("foo"));
assertEquals("some-project-id", scopedCredentials.getQuotaProjectId());
}
@@ -365,7 +366,7 @@ void buildDefaultScoped_explicitUniverse() throws IOException {
.setUniverseDomain("some-universe")
.build();
ComputeEngineCredentials scopedCredentials =
- (ComputeEngineCredentials) credentials.createScoped(null, Arrays.asList("foo"));
+ (ComputeEngineCredentials) credentials.createScoped(null, Collections.singletonList("foo"));
assertEquals("some-universe", scopedCredentials.getUniverseDomain());
assertTrue(scopedCredentials.isExplicitUniverseDomain());
@@ -374,7 +375,7 @@ void buildDefaultScoped_explicitUniverse() throws IOException {
@Test
void create_scoped_correctMargins() {
GoogleCredentials credentials =
- ComputeEngineCredentials.create().createScoped(null, Arrays.asList("foo"));
+ ComputeEngineCredentials.create().createScoped(null, Collections.singletonList("foo"));
assertEquals(
ComputeEngineCredentials.COMPUTE_EXPIRATION_MARGIN, credentials.getExpirationMargin());
@@ -425,15 +426,12 @@ void getRequestMetadata_missingServiceAccount_throws() {
transportFactory.transport.setServiceAccountEmail("SA_CLIENT_EMAIL");
ComputeEngineCredentials credentials =
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(transportFactory).build();
- try {
- credentials.getRequestMetadata(CALL_URI);
- fail("Expected error refreshing token.");
- } catch (IOException expected) {
- String message = expected.getMessage();
- assertTrue(message.contains(Integer.toString(HttpStatusCodes.STATUS_CODE_NOT_FOUND)));
- // Message should mention scopes are missing on the VM.
- assertTrue(message.contains("scope"));
- }
+ IOException exception =
+ assertThrows(IOException.class, () -> credentials.getRequestMetadata(CALL_URI));
+ String message = exception.getMessage();
+ assertTrue(message.contains(Integer.toString(HttpStatusCodes.STATUS_CODE_NOT_FOUND)));
+ // Message should mention scopes are missing on the VM.
+ assertTrue(message.contains("scope"));
}
@Test
@@ -443,14 +441,11 @@ void getRequestMetadata_serverError_throws() {
transportFactory.transport.setServiceAccountEmail("SA_CLIENT_EMAIL");
ComputeEngineCredentials credentials =
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(transportFactory).build();
- try {
- credentials.getRequestMetadata(CALL_URI);
- fail("Expected error refreshing token.");
- } catch (IOException expected) {
- String message = expected.getMessage();
- assertTrue(message.contains(Integer.toString(HttpStatusCodes.STATUS_CODE_SERVER_ERROR)));
- assertTrue(message.contains("Unexpected"));
- }
+ IOException exception =
+ assertThrows(IOException.class, () -> credentials.getRequestMetadata(CALL_URI));
+ String message = exception.getMessage();
+ assertTrue(message.contains(Integer.toString(HttpStatusCodes.STATUS_CODE_SERVER_ERROR)));
+ assertTrue(message.contains("Unexpected"));
}
@Test
@@ -464,19 +459,19 @@ void equals_true() throws IOException {
ComputeEngineCredentials otherCredentials =
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(transportFactory).build();
assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, otherCredentials.getUniverseDomain());
- assertFalse(explicitUniverseCredentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(explicitUniverseCredentials));
+ assertNotEquals(explicitUniverseCredentials, otherCredentials);
+ assertNotEquals(otherCredentials, explicitUniverseCredentials);
ComputeEngineCredentials otherExplicitUniverseCredentials =
ComputeEngineCredentials.newBuilder()
.setUniverseDomain(Credentials.GOOGLE_DEFAULT_UNIVERSE)
.setHttpTransportFactory(transportFactory)
.build();
- assertTrue(explicitUniverseCredentials.equals(otherExplicitUniverseCredentials));
- assertTrue(otherExplicitUniverseCredentials.equals(explicitUniverseCredentials));
+ assertEquals(explicitUniverseCredentials, otherExplicitUniverseCredentials);
+ assertEquals(otherExplicitUniverseCredentials, explicitUniverseCredentials);
}
@Test
- void equals_false_transportFactory() throws IOException {
+ void equals_false_transportFactory() {
MockHttpTransportFactory httpTransportFactory = new MockHttpTransportFactory();
MockMetadataServerTransportFactory serverTransportFactory =
new MockMetadataServerTransportFactory();
@@ -486,12 +481,12 @@ void equals_false_transportFactory() throws IOException {
.build();
ComputeEngineCredentials otherCredentials =
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(httpTransportFactory).build();
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
- void toString_explicit_containsFields() throws IOException {
+ void toString_explicit_containsFields() {
MockMetadataServerTransportFactory serverTransportFactory =
new MockMetadataServerTransportFactory();
String expectedToString =
@@ -513,7 +508,7 @@ void toString_explicit_containsFields() throws IOException {
}
@Test
- void hashCode_equals() throws IOException {
+ void hashCode_equals() {
MockMetadataServerTransportFactory serverTransportFactory =
new MockMetadataServerTransportFactory();
ComputeEngineCredentials credentials =
@@ -552,17 +547,17 @@ void serialize() throws IOException, ClassNotFoundException {
assertEquals(credentials, deserializedCredentials);
assertEquals(credentials.hashCode(), deserializedCredentials.hashCode());
assertEquals(credentials.toString(), deserializedCredentials.toString());
- assertSame(deserializedCredentials.clock, Clock.SYSTEM);
+ assertSame(Clock.SYSTEM, deserializedCredentials.clock);
credentials = ComputeEngineCredentials.newBuilder().build();
deserializedCredentials = serializeAndDeserialize(credentials);
assertEquals(credentials, deserializedCredentials);
assertEquals(credentials.hashCode(), deserializedCredentials.hashCode());
assertEquals(credentials.toString(), deserializedCredentials.toString());
- assertSame(deserializedCredentials.clock, Clock.SYSTEM);
+ assertSame(Clock.SYSTEM, deserializedCredentials.clock);
}
@Test
- void getAccount_sameAs() throws IOException {
+ void getAccount_sameAs() {
MockMetadataServerTransportFactory transportFactory = new MockMetadataServerTransportFactory();
String defaultAccountEmail = "mail@mail.com";
@@ -603,14 +598,10 @@ public LowLevelHttpResponse execute() throws IOException {
ComputeEngineCredentials credentials =
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(transportFactory).build();
- try {
- credentials.getAccount();
- fail("Fetching default service account should have failed");
- } catch (RuntimeException e) {
- assertEquals("Failed to get service account", e.getMessage());
- assertNotNull(e.getCause());
- assertTrue(e.getCause().getMessage().contains("404"));
- }
+ RuntimeException exception = assertThrows(RuntimeException.class, credentials::getAccount);
+ assertEquals("Failed to get service account", exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertTrue(exception.getCause().getMessage().contains("404"));
}
@Test
@@ -638,14 +629,10 @@ public LowLevelHttpResponse execute() throws IOException {
ComputeEngineCredentials credentials =
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(transportFactory).build();
- try {
- credentials.getAccount();
- fail("Fetching default service account should have failed");
- } catch (RuntimeException e) {
- assertEquals("Failed to get service account", e.getMessage());
- assertNotNull(e.getCause());
- assertTrue(e.getCause().getMessage().contains("Empty content"));
- }
+ RuntimeException exception = assertThrows(RuntimeException.class, credentials::getAccount);
+ assertEquals("Failed to get service account", exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertTrue(exception.getCause().getMessage().contains("Empty content"));
}
@Test
@@ -793,9 +780,9 @@ public LowLevelHttpResponse execute() throws IOException {
ComputeEngineCredentials credentials =
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(transportFactory).build();
- IOException exception = assertThrows(IOException.class, () -> credentials.refreshAccessToken());
+ IOException exception = assertThrows(IOException.class, credentials::refreshAccessToken);
assertTrue(exception.getCause().getMessage().contains("503"));
- assertTrue(exception instanceof GoogleAuthException);
+ assertInstanceOf(GoogleAuthException.class, exception);
assertTrue(((GoogleAuthException) exception).isRetryable());
}
@@ -803,7 +790,7 @@ public LowLevelHttpResponse execute() throws IOException {
void refresh_non503_ioexception_throws() {
MockMetadataServerTransportFactory transportFactory = new MockMetadataServerTransportFactory();
final Queue responseSequence = new ArrayDeque<>();
- IntStream.rangeClosed(400, 600).forEach(i -> responseSequence.add(i));
+ IntStream.rangeClosed(400, 600).forEach(responseSequence::add);
while (!responseSequence.isEmpty()) {
if (responseSequence.peek() == 503) {
@@ -829,8 +816,7 @@ public LowLevelHttpResponse execute() throws IOException {
ComputeEngineCredentials credentials =
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(transportFactory).build();
- IOException exception =
- assertThrows(IOException.class, () -> credentials.refreshAccessToken());
+ IOException exception = assertThrows(IOException.class, credentials::refreshAccessToken);
assertFalse(exception instanceof GoogleAuthException);
}
}
@@ -859,7 +845,7 @@ public LowLevelHttpResponse execute() throws IOException {
String universeDomain = credentials.getUniverseDomain();
assertEquals("some-universe.xyz", universeDomain);
- assertEquals(false, credentials.isExplicitUniverseDomain());
+ assertFalse(credentials.isExplicitUniverseDomain());
}
@Test
@@ -886,7 +872,7 @@ public LowLevelHttpResponse execute() throws IOException {
String universeDomain = credentials.getUniverseDomain();
assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, universeDomain);
- assertEquals(false, credentials.isExplicitUniverseDomain());
+ assertFalse(credentials.isExplicitUniverseDomain());
}
@Test
@@ -913,7 +899,7 @@ public LowLevelHttpResponse execute() throws IOException {
String universeDomain = credentials.getUniverseDomain();
assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, universeDomain);
- assertEquals(false, credentials.isExplicitUniverseDomain());
+ assertFalse(credentials.isExplicitUniverseDomain());
}
@Test
@@ -929,7 +915,7 @@ void getUniverseDomain_explicitSet_NoMdsCall() throws IOException {
String universeDomain = credentials.getUniverseDomain();
assertEquals("explicit.universe", universeDomain);
- assertEquals(true, credentials.isExplicitUniverseDomain());
+ assertTrue(credentials.isExplicitUniverseDomain());
assertEquals(0, transportFactory.transport.getRequestCount());
}
@@ -946,14 +932,13 @@ void getUniverseDomain_explicitGduSet_NoMdsCall() throws IOException {
String universeDomain = credentials.getUniverseDomain();
assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, universeDomain);
- assertEquals(true, credentials.isExplicitUniverseDomain());
+ assertTrue(credentials.isExplicitUniverseDomain());
assertEquals(0, transportFactory.transport.getRequestCount());
}
@Test
- void getUniverseDomain_fromMetadata_non404error_throws() throws IOException {
+ void getUniverseDomain_fromMetadata_non404error_throws() {
MockMetadataServerTransportFactory transportFactory = new MockMetadataServerTransportFactory();
- MockMetadataServerTransport transport = transportFactory.transport;
ComputeEngineCredentials credentials =
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(transportFactory).build();
@@ -963,13 +948,10 @@ void getUniverseDomain_fromMetadata_non404error_throws() throws IOException {
if (status == 404) {
continue;
}
- try {
- transportFactory.transport.setStatusCode(status);
- credentials.getUniverseDomain();
- fail("Should not be able to use credential without exception.");
- } catch (GoogleAuthException ex) {
- assertTrue(ex.isRetryable());
- }
+ transportFactory.transport.setStatusCode(status);
+ GoogleAuthException ex =
+ assertThrows(GoogleAuthException.class, credentials::getUniverseDomain);
+ assertTrue(ex.isRetryable());
}
}
@@ -985,7 +967,7 @@ public LowLevelHttpRequest buildRequest(String method, String url) throws IOExce
if (isSignRequestUrl(url)) {
return new MockLowLevelHttpRequest(url) {
@Override
- public LowLevelHttpResponse execute() throws IOException {
+ public LowLevelHttpResponse execute() {
return new MockLowLevelHttpResponse()
.setStatusCode(HttpStatusCodes.STATUS_CODE_OK);
}
@@ -1061,7 +1043,7 @@ void idTokenWithAudience_full() throws IOException {
IdTokenCredentials.newBuilder()
.setIdTokenProvider(credentials)
.setTargetAudience(targetAudience)
- .setOptions(Arrays.asList(IdTokenProvider.Option.FORMAT_FULL))
+ .setOptions(Collections.singletonList(IdTokenProvider.Option.FORMAT_FULL))
.build();
tokenCredential.refresh();
Payload p = tokenCredential.getIdToken().getJsonWebSignature().getPayload();
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/CredentialAccessBoundaryTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/CredentialAccessBoundaryTest.java
index 0dee7011e4ee..04abd3d9d23c 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/CredentialAccessBoundaryTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/CredentialAccessBoundaryTest.java
@@ -33,7 +33,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.auth.oauth2.CredentialAccessBoundary.AccessBoundaryRule;
import com.google.auth.oauth2.CredentialAccessBoundary.AccessBoundaryRule.AvailabilityCondition;
@@ -90,22 +90,17 @@ void credentialAccessBoundary() {
@Test
void credentialAccessBoundary_nullRules_throws() {
- try {
- CredentialAccessBoundary.newBuilder().build();
- fail("Should fail.");
- } catch (NullPointerException e) {
- // Expected.
- }
+ CredentialAccessBoundary.Builder builder = CredentialAccessBoundary.newBuilder();
+ assertThrows(NullPointerException.class, builder::build);
}
@Test
void credentialAccessBoundary_withoutRules_throws() {
- try {
- CredentialAccessBoundary.newBuilder().setRules(new ArrayList()).build();
- fail("Should fail.");
- } catch (IllegalArgumentException e) {
- assertEquals("At least one access boundary rule must be provided.", e.getMessage());
- }
+ CredentialAccessBoundary.Builder builder =
+ CredentialAccessBoundary.newBuilder().setRules(new ArrayList<>());
+ IllegalArgumentException exception =
+ assertThrows(IllegalArgumentException.class, builder::build);
+ assertEquals("At least one access boundary rule must be provided.", exception.getMessage());
}
@Test
@@ -121,12 +116,10 @@ void credentialAccessBoundary_ruleCountExceeded_throws() {
builder.addRule(rule);
}
- try {
- builder.build();
- fail("Should fail.");
- } catch (IllegalArgumentException e) {
- assertEquals("The provided list has more than 10 access boundary rules.", e.getMessage());
- }
+ IllegalArgumentException exception =
+ assertThrows(IllegalArgumentException.class, builder::build);
+ assertEquals(
+ "The provided list has more than 10 access boundary rules.", exception.getMessage());
}
@Test
@@ -204,74 +197,58 @@ void accessBoundaryRule_requiredFields() {
@Test
void accessBoundaryRule_withEmptyAvailableResource_throws() {
- try {
- AccessBoundaryRule.newBuilder()
- .setAvailableResource("")
- .addAvailablePermission("permission")
- .build();
- fail("Should fail.");
- } catch (IllegalArgumentException e) {
- assertEquals("The provided availableResource is empty.", e.getMessage());
- }
+ AccessBoundaryRule.Builder builder =
+ AccessBoundaryRule.newBuilder()
+ .setAvailableResource("")
+ .addAvailablePermission("permission");
+ IllegalArgumentException exception =
+ assertThrows(IllegalArgumentException.class, builder::build);
+ assertEquals("The provided availableResource is empty.", exception.getMessage());
}
@Test
void accessBoundaryRule_withoutAvailableResource_throws() {
- try {
- AccessBoundaryRule.newBuilder().addAvailablePermission("permission").build();
- fail("Should fail.");
- } catch (NullPointerException e) {
- // Expected.
- }
+ AccessBoundaryRule.Builder builder =
+ AccessBoundaryRule.newBuilder().addAvailablePermission("permission");
+ assertThrows(NullPointerException.class, builder::build);
}
@Test
void accessBoundaryRule_withoutAvailablePermissions_throws() {
- try {
- AccessBoundaryRule.newBuilder().setAvailableResource("resource").build();
- fail("Should fail.");
- } catch (NullPointerException e) {
- // Expected.
- }
+ AccessBoundaryRule.Builder builder =
+ AccessBoundaryRule.newBuilder().setAvailableResource("resource");
+ assertThrows(NullPointerException.class, builder::build);
}
@Test
void accessBoundaryRule_withEmptyAvailablePermissions_throws() {
- try {
- AccessBoundaryRule.newBuilder()
- .setAvailableResource("resource")
- .setAvailablePermissions(new ArrayList())
- .build();
- fail("Should fail.");
- } catch (IllegalArgumentException e) {
- assertEquals("The list of provided availablePermissions is empty.", e.getMessage());
- }
+ AccessBoundaryRule.Builder builder =
+ AccessBoundaryRule.newBuilder()
+ .setAvailableResource("resource")
+ .setAvailablePermissions(new ArrayList<>());
+ IllegalArgumentException exception =
+ assertThrows(IllegalArgumentException.class, builder::build);
+ assertEquals("The list of provided availablePermissions is empty.", exception.getMessage());
}
@Test
void accessBoundaryRule_withNullAvailablePermissions_throws() {
- try {
- AccessBoundaryRule.newBuilder()
- .setAvailableResource("resource")
- .addAvailablePermission(null)
- .build();
- fail("Should fail.");
- } catch (IllegalArgumentException e) {
- assertEquals("One of the provided available permissions is null.", e.getMessage());
- }
+ AccessBoundaryRule.Builder builder =
+ AccessBoundaryRule.newBuilder()
+ .setAvailableResource("resource")
+ .addAvailablePermission(null);
+ IllegalArgumentException exception =
+ assertThrows(IllegalArgumentException.class, builder::build);
+ assertEquals("One of the provided available permissions is null.", exception.getMessage());
}
@Test
void accessBoundaryRule_withEmptyAvailablePermission_throws() {
- try {
- AccessBoundaryRule.newBuilder()
- .setAvailableResource("resource")
- .addAvailablePermission("")
- .build();
- fail("Should fail.");
- } catch (IllegalArgumentException e) {
- assertEquals("One of the provided available permissions is empty.", e.getMessage());
- }
+ AccessBoundaryRule.Builder builder =
+ AccessBoundaryRule.newBuilder().setAvailableResource("resource").addAvailablePermission("");
+ IllegalArgumentException exception =
+ assertThrows(IllegalArgumentException.class, builder::build);
+ assertEquals("One of the provided available permissions is empty.", exception.getMessage());
}
@Test
@@ -300,21 +277,15 @@ void availabilityCondition_expressionOnly() {
@Test
void availabilityCondition_nullExpression_throws() {
- try {
- AvailabilityCondition.newBuilder().setExpression(null).build();
- fail("Should fail.");
- } catch (NullPointerException e) {
- // Expected.
- }
+ AvailabilityCondition.Builder builder = AvailabilityCondition.newBuilder().setExpression(null);
+ assertThrows(NullPointerException.class, builder::build);
}
@Test
void availabilityCondition_emptyExpression_throws() {
- try {
- AvailabilityCondition.newBuilder().setExpression("").build();
- fail("Should fail.");
- } catch (IllegalArgumentException e) {
- assertEquals("The provided expression is empty.", e.getMessage());
- }
+ AvailabilityCondition.Builder builder = AvailabilityCondition.newBuilder().setExpression("");
+ IllegalArgumentException exception =
+ assertThrows(IllegalArgumentException.class, builder::build);
+ assertEquals("The provided expression is empty.", exception.getMessage());
}
}
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/DefaultCredentialsProviderTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/DefaultCredentialsProviderTest.java
index 1852629ee6cb..d0447871b01a 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/DefaultCredentialsProviderTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/DefaultCredentialsProviderTest.java
@@ -33,11 +33,13 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.LowLevelHttpRequest;
@@ -83,7 +85,7 @@ class DefaultCredentialsProviderTest {
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;
@@ -94,7 +96,7 @@ class DefaultCredentialsProviderTest {
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_SA_API_AUDIENCE = URI.create("https://gdch-api-audience");
+ private static final String GDCH_SA_API_AUDIENCE = "https://gdch-api-audience";
private static final Collection SCOPES = Collections.singletonList("dummy.scope");
private static final URI CALL_URI = URI.create("http://googleapis.com/testapi/v1/foo");
private static final String QUOTA_PROJECT = "sample-quota-project-id";
@@ -107,28 +109,22 @@ void getDefaultCredentials_noCredentials_throws() {
MockHttpTransportFactory transportFactory = new MockHttpTransportFactory();
TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider();
- try {
- testProvider.getDefaultCredentials(transportFactory);
- fail("No credential expected.");
- } catch (IOException e) {
- String message = e.getMessage();
- assertTrue(message.equals(DefaultCredentialsProvider.CLOUDSDK_MISSING_CREDENTIALS));
- }
+ IOException e =
+ assertThrows(IOException.class, () -> testProvider.getDefaultCredentials(transportFactory));
+ String message = e.getMessage();
+ assertEquals(DefaultCredentialsProvider.CLOUDSDK_MISSING_CREDENTIALS, message);
}
@Test
void getDefaultCredentials_noCredentialsSandbox_throwsNonSecurity() {
MockHttpTransportFactory transportFactory = new MockHttpTransportFactory();
TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider();
- testProvider.setFileSandbox(true);
-
- try {
- testProvider.getDefaultCredentials(transportFactory);
- fail("No credential expected.");
- } catch (IOException e) {
- String message = e.getMessage();
- assertTrue(message.equals(DefaultCredentialsProvider.CLOUDSDK_MISSING_CREDENTIALS));
- }
+ testProvider.setFileSandbox();
+
+ IOException e =
+ assertThrows(IOException.class, () -> testProvider.getDefaultCredentials(transportFactory));
+ String message = e.getMessage();
+ assertEquals(DefaultCredentialsProvider.CLOUDSDK_MISSING_CREDENTIALS, message);
}
@Test
@@ -138,18 +134,15 @@ void getDefaultCredentials_envValidSandbox_throwsNonSecurity() throws Exception
UserCredentialsTest.writeUserStream(
USER_CLIENT_ID, USER_CLIENT_SECRET, REFRESH_TOKEN, QUOTA_PROJECT);
TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider();
- testProvider.setFileSandbox(true);
+ testProvider.setFileSandbox();
String userPath = tempFilePath("user.json");
testProvider.addFile(userPath, userStream);
testProvider.setEnv(DefaultCredentialsProvider.CREDENTIAL_ENV_VAR, userPath);
- try {
- testProvider.getDefaultCredentials(transportFactory);
- fail("No credential expected.");
- } catch (IOException e) {
- String message = e.getMessage();
- assertTrue(message.equals(DefaultCredentialsProvider.CLOUDSDK_MISSING_CREDENTIALS));
- }
+ IOException e =
+ assertThrows(IOException.class, () -> testProvider.getDefaultCredentials(transportFactory));
+ String message = e.getMessage();
+ assertEquals(DefaultCredentialsProvider.CLOUDSDK_MISSING_CREDENTIALS, message);
}
@Test
@@ -158,70 +151,47 @@ void getDefaultCredentials_noCredentials_singleGceTestRequest() {
new MockRequestCountingTransportFactory();
TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider();
- try {
- testProvider.getDefaultCredentials(transportFactory);
- fail("No credential expected.");
- } catch (IOException expected) {
- String message = expected.getMessage();
- assertTrue(message.equals(DefaultCredentialsProvider.CLOUDSDK_MISSING_CREDENTIALS));
- }
+ IOException expected =
+ assertThrows(IOException.class, () -> testProvider.getDefaultCredentials(transportFactory));
+ String message = expected.getMessage();
+ assertEquals(DefaultCredentialsProvider.CLOUDSDK_MISSING_CREDENTIALS, message);
assertEquals(
- transportFactory.transport.getRequestCount(),
- ComputeEngineCredentials.MAX_COMPUTE_PING_TRIES);
- try {
- testProvider.getDefaultCredentials(transportFactory);
- fail("No credential expected.");
- } catch (IOException expected) {
- // Expected
- }
+ ComputeEngineCredentials.MAX_COMPUTE_PING_TRIES,
+ transportFactory.transport.getRequestCount());
+ assertThrows(IOException.class, () -> testProvider.getDefaultCredentials(transportFactory));
assertEquals(
- transportFactory.transport.getRequestCount(),
- ComputeEngineCredentials.MAX_COMPUTE_PING_TRIES);
+ ComputeEngineCredentials.MAX_COMPUTE_PING_TRIES,
+ transportFactory.transport.getRequestCount());
}
@Test
- void getDefaultCredentials_noCredentials_linuxNotGce() throws IOException {
- TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider();
- testProvider.setProperty("os.name", "Linux");
- String productFilePath = SMBIOS_PATH_LINUX;
- InputStream productStream = new ByteArrayInputStream("test".getBytes());
- testProvider.addFile(productFilePath, productStream);
-
- assertFalse(ComputeEngineCredentials.checkStaticGceDetection(testProvider));
+ void getDefaultCredentials_noCredentials_linuxNotGce() {
+ checkStaticGceDetection("linux", "test", false);
}
@Test
- void getDefaultCredentials_static_linux() throws IOException {
- TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider();
- testProvider.setProperty("os.name", "Linux");
- String productFilePath = SMBIOS_PATH_LINUX;
- File productFile = new File(productFilePath);
- InputStream productStream = new ByteArrayInputStream("Googlekdjsfhg".getBytes());
- testProvider.addFile(productFile.getAbsolutePath(), productStream);
-
- assertTrue(ComputeEngineCredentials.checkStaticGceDetection(testProvider));
+ void getDefaultCredentials_static_linux() {
+ checkStaticGceDetection("linux", "Googlekdjsfhg", true);
}
@Test
- void getDefaultCredentials_static_windows_configuredAsLinux_notGce() throws IOException {
- TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider();
- testProvider.setProperty("os.name", "windows");
- String productFilePath = SMBIOS_PATH_LINUX;
- InputStream productStream = new ByteArrayInputStream("Googlekdjsfhg".getBytes());
- testProvider.addFile(productFilePath, productStream);
-
- assertFalse(ComputeEngineCredentials.checkStaticGceDetection(testProvider));
+ void getDefaultCredentials_static_windows_configuredAsLinux_notGce() {
+ checkStaticGceDetection("windows", "Googlekdjsfhg", false);
}
@Test
- void getDefaultCredentials_static_unsupportedPlatform_notGce() throws IOException {
+ void getDefaultCredentials_static_unsupportedPlatform_notGce() {
+ checkStaticGceDetection("macos", "Googlekdjsfhg", false);
+ }
+
+ private void checkStaticGceDetection(String osName, String productContent, boolean expected) {
TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider();
- testProvider.setProperty("os.name", "macos");
+ testProvider.setProperty("os.name", osName);
String productFilePath = SMBIOS_PATH_LINUX;
- InputStream productStream = new ByteArrayInputStream("Googlekdjsfhg".getBytes());
+ InputStream productStream = new ByteArrayInputStream(productContent.getBytes());
testProvider.addFile(productFilePath, productStream);
- assertFalse(ComputeEngineCredentials.checkStaticGceDetection(testProvider));
+ assertEquals(expected, ComputeEngineCredentials.checkStaticGceDetection(testProvider));
}
@Test
@@ -253,49 +223,40 @@ void getDefaultCredentials_caches() throws IOException {
void getDefaultCredentials_appEngineClassWithoutRuntime_NotFoundError() {
MockHttpTransportFactory transportFactory = new MockHttpTransportFactory();
TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider();
- testProvider.addType(
- DefaultCredentialsProvider.APP_ENGINE_SIGNAL_CLASS, MockOffAppEngineSystemProperty.class);
+ testProvider.addType(MockOffAppEngineSystemProperty.class);
testProvider.setProperty("isOnGAEStandard7", "true");
- try {
- testProvider.getDefaultCredentials(transportFactory);
- fail("No credential expected when not on App Engine.");
- } catch (IOException e) {
- String message = e.getMessage();
- assertTrue(message.equals(DefaultCredentialsProvider.CLOUDSDK_MISSING_CREDENTIALS));
- }
+ IOException e =
+ assertThrows(IOException.class, () -> testProvider.getDefaultCredentials(transportFactory));
+ String message = e.getMessage();
+ assertEquals(DefaultCredentialsProvider.CLOUDSDK_MISSING_CREDENTIALS, message);
}
@Test
void getDefaultCredentials_appEngineRuntimeWithoutClass_throwsHelpfulLoadError() {
MockHttpTransportFactory transportFactory = new MockHttpTransportFactory();
TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider();
- testProvider.addType(
- DefaultCredentialsProvider.APP_ENGINE_SIGNAL_CLASS, MockAppEngineSystemProperty.class);
+ testProvider.addType(MockAppEngineSystemProperty.class);
testProvider.setProperty("isOnGAEStandard7", "true");
- try {
- testProvider.getDefaultCredentials(transportFactory);
- fail("Credential expected to fail to load if credential class not present.");
- } catch (IOException e) {
- String message = e.getMessage();
- assertFalse(message.equals(DefaultCredentialsProvider.CLOUDSDK_MISSING_CREDENTIALS));
- assertTrue(message.contains("Check that the App Engine SDK is deployed."));
- }
+ IOException e =
+ assertThrows(IOException.class, () -> testProvider.getDefaultCredentials(transportFactory));
+ String message = e.getMessage();
+ assertNotEquals(DefaultCredentialsProvider.CLOUDSDK_MISSING_CREDENTIALS, message);
+ assertTrue(message.contains("Check that the App Engine SDK is deployed."));
}
@Test
void getDefaultCredentials_appEngineSkipWorks_retrievesCloudShellCredential() throws IOException {
MockHttpTransportFactory transportFactory = new MockHttpTransportFactory();
TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider();
- testProvider.addType(
- DefaultCredentialsProvider.APP_ENGINE_SIGNAL_CLASS, MockOffAppEngineSystemProperty.class);
+ testProvider.addType(MockOffAppEngineSystemProperty.class);
testProvider.setEnv(DefaultCredentialsProvider.CLOUD_SHELL_ENV_VAR, "9090");
testProvider.setEnv(DefaultCredentialsProvider.SKIP_APP_ENGINE_ENV_VAR, "true");
testProvider.setProperty("isOnGAEStanadard7", "true");
GoogleCredentials credentials = testProvider.getDefaultCredentials(transportFactory);
assertNotNull(credentials);
- assertTrue(credentials instanceof CloudShellCredentials);
+ assertInstanceOf(CloudShellCredentials.class, credentials);
}
@Test
@@ -319,8 +280,8 @@ void getDefaultCredentials_cloudshell() throws IOException {
GoogleCredentials defaultCredentials = testProvider.getDefaultCredentials(transportFactory);
- assertTrue(defaultCredentials instanceof CloudShellCredentials);
- assertEquals(((CloudShellCredentials) defaultCredentials).getAuthPort(), 4);
+ assertInstanceOf(CloudShellCredentials.class, defaultCredentials);
+ assertEquals(4, ((CloudShellCredentials) defaultCredentials).getAuthPort());
}
@Test
@@ -331,8 +292,8 @@ void getDefaultCredentials_cloudshell_withComputCredentialsPresent() throws IOEx
GoogleCredentials defaultCredentials = testProvider.getDefaultCredentials(transportFactory);
- assertTrue(defaultCredentials instanceof CloudShellCredentials);
- assertEquals(((CloudShellCredentials) defaultCredentials).getAuthPort(), 4);
+ assertInstanceOf(CloudShellCredentials.class, defaultCredentials);
+ assertEquals(4, ((CloudShellCredentials) defaultCredentials).getAuthPort());
}
@Test
@@ -342,14 +303,11 @@ void getDefaultCredentials_envMissingFile_throws() {
TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider();
testProvider.setEnv(DefaultCredentialsProvider.CREDENTIAL_ENV_VAR, invalidPath);
- try {
- testProvider.getDefaultCredentials(transportFactory);
- fail("Non existent credential should throw exception");
- } catch (IOException e) {
- String message = e.getMessage();
- assertTrue(message.contains(DefaultCredentialsProvider.CREDENTIAL_ENV_VAR));
- assertTrue(message.contains(invalidPath));
- }
+ IOException e =
+ assertThrows(IOException.class, () -> testProvider.getDefaultCredentials(transportFactory));
+ String message = e.getMessage();
+ assertTrue(message.contains(DefaultCredentialsProvider.CREDENTIAL_ENV_VAR));
+ assertTrue(message.contains(invalidPath));
}
@Test
@@ -382,7 +340,7 @@ void getDefaultCredentials_envUser_providesToken() throws IOException {
testProvider.addFile(userPath, userStream);
testProvider.setEnv(DefaultCredentialsProvider.CREDENTIAL_ENV_VAR, userPath);
- testUserProvidesToken(testProvider, USER_CLIENT_ID, USER_CLIENT_SECRET, REFRESH_TOKEN);
+ testUserProvidesToken(testProvider, USER_CLIENT_ID);
}
@Test
@@ -390,7 +348,7 @@ void getDefaultCredentials_GdchServiceAccount() throws IOException {
MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
InputStream gdchServiceAccountStream =
GdchCredentialsTest.writeGdchServiceAccountStream(
- GDCH_SA_FORMAT_VERSION,
+ GdchCredentials.SUPPORTED_JSON_FORMAT_VERSION,
GDCH_SA_PROJECT_ID,
GDCH_SA_PRIVATE_KEY_ID,
GDCH_SA_PRIVATE_KEY_PKC8,
@@ -405,7 +363,7 @@ void getDefaultCredentials_GdchServiceAccount() throws IOException {
GoogleCredentials defaultCredentials = testProvider.getDefaultCredentials(transportFactory);
assertNotNull(defaultCredentials);
- assertTrue(defaultCredentials instanceof GdchCredentials);
+ assertInstanceOf(GdchCredentials.class, defaultCredentials);
assertEquals(GDCH_SA_PROJECT_ID, defaultCredentials.getProjectId());
assertEquals(
GDCH_SA_SERVICE_IDENTITY_NAME,
@@ -418,7 +376,7 @@ void getDefaultCredentials_GdchServiceAccount() throws IOException {
defaultCredentials =
((GdchCredentials) defaultCredentials).createWithGdchAudience(GDCH_SA_API_AUDIENCE);
assertNotNull(defaultCredentials);
- assertTrue(defaultCredentials instanceof GdchCredentials);
+ assertInstanceOf(GdchCredentials.class, defaultCredentials);
assertEquals(GDCH_SA_PROJECT_ID, defaultCredentials.getProjectId());
assertEquals(
GDCH_SA_SERVICE_IDENTITY_NAME,
@@ -451,7 +409,7 @@ void getDefaultCredentials_quota_project() throws IOException {
credentials = credentials.toBuilder().setQuotaProjectId(QUOTA_PROJECT_EXPLICIT).build();
assertEquals(QUOTA_PROJECT_EXPLICIT, credentials.getQuotaProjectId());
- testUserProvidesToken(testProvider, USER_CLIENT_ID, USER_CLIENT_SECRET, REFRESH_TOKEN);
+ testUserProvidesToken(testProvider, USER_CLIENT_ID);
}
@Test
@@ -463,7 +421,7 @@ void getDefaultCredentials_compute_quotaProject() throws IOException {
GoogleCredentials defaultCredentials = testProvider.getDefaultCredentials(transportFactory);
- assertTrue(defaultCredentials instanceof ComputeEngineCredentials);
+ assertInstanceOf(ComputeEngineCredentials.class, defaultCredentials);
assertEquals(QUOTA_PROJECT_FROM_ENVIRONMENT, defaultCredentials.getQuotaProjectId());
// verify metrics header
@@ -482,44 +440,33 @@ void getDefaultCredentials_cloudshell_quotaProject() throws IOException {
GoogleCredentials defaultCredentials = testProvider.getDefaultCredentials(transportFactory);
- assertTrue(defaultCredentials instanceof CloudShellCredentials);
+ assertInstanceOf(CloudShellCredentials.class, defaultCredentials);
assertEquals(QUOTA_PROJECT_FROM_ENVIRONMENT, defaultCredentials.getQuotaProjectId());
}
@Test
- void getDefaultCredentials_envNoGceCheck_noGceRequest() throws IOException {
+ void getDefaultCredentials_envNoGceCheck_noGceRequest() {
MockRequestCountingTransportFactory transportFactory =
new MockRequestCountingTransportFactory();
TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider();
testProvider.setEnv(DefaultCredentialsProvider.NO_GCE_CHECK_ENV_VAR, "true");
- try {
- testProvider.getDefaultCredentials(transportFactory);
- fail("No credential expected.");
- } catch (IOException expected) {
- // Expected
- }
- assertEquals(transportFactory.transport.getRequestCount(), 0);
+ assertThrows(IOException.class, () -> testProvider.getDefaultCredentials(transportFactory));
+ assertEquals(0, transportFactory.transport.getRequestCount());
}
@Test
- void getDefaultCredentials_linuxSetup_envNoGceCheck_noGce() throws IOException {
+ void getDefaultCredentials_linuxSetup_envNoGceCheck_noGce() {
MockRequestCountingTransportFactory transportFactory =
new MockRequestCountingTransportFactory();
TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider();
testProvider.setEnv(DefaultCredentialsProvider.NO_GCE_CHECK_ENV_VAR, "true");
testProvider.setProperty("os.name", "Linux");
- String productFilePath = SMBIOS_PATH_LINUX;
- File productFile = new File(productFilePath);
+ File productFile = new File(SMBIOS_PATH_LINUX);
InputStream productStream = new ByteArrayInputStream("Googlekdjsfhg".getBytes());
testProvider.addFile(productFile.getAbsolutePath(), productStream);
- try {
- testProvider.getDefaultCredentials(transportFactory);
- fail("No credential expected.");
- } catch (IOException expected) {
- // Expected
- }
- assertEquals(transportFactory.transport.getRequestCount(), 0);
+ assertThrows(IOException.class, () -> testProvider.getDefaultCredentials(transportFactory));
+ assertEquals(0, transportFactory.transport.getRequestCount());
}
@Test
@@ -527,7 +474,7 @@ void getDefaultCredentials_envGceMetadataHost_setsMetadataServerUrl() {
String testUrl = "192.0.2.0";
TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider();
testProvider.setEnv(DefaultCredentialsProvider.GCE_METADATA_HOST_ENV_VAR, testUrl);
- assertEquals(ComputeEngineCredentials.getMetadataServerUrl(testProvider), "http://" + testUrl);
+ assertEquals("http://" + testUrl, ComputeEngineCredentials.getMetadataServerUrl(testProvider));
}
@Test
@@ -536,8 +483,8 @@ void getDefaultCredentials_envGceMetadataHost_setsTokenServerUrl() {
TestDefaultCredentialsProvider testProvider = new TestDefaultCredentialsProvider();
testProvider.setEnv(DefaultCredentialsProvider.GCE_METADATA_HOST_ENV_VAR, testUrl);
assertEquals(
- ComputeEngineCredentials.getTokenServerEncodedUrl(testProvider),
- "http://" + testUrl + "/computeMetadata/v1/instance/service-accounts/default/token");
+ "http://" + testUrl + "/computeMetadata/v1/instance/service-accounts/default/token",
+ ComputeEngineCredentials.getTokenServerEncodedUrl(testProvider));
}
@Test
@@ -552,7 +499,7 @@ void getDefaultCredentials_wellKnownFileEnv_providesToken() throws IOException {
testProvider.setEnv("CLOUDSDK_CONFIG", cloudConfigDir.getAbsolutePath());
testProvider.addFile(wellKnownFile.getAbsolutePath(), userStream);
- testUserProvidesToken(testProvider, USER_CLIENT_ID, USER_CLIENT_SECRET, REFRESH_TOKEN);
+ testUserProvidesToken(testProvider, USER_CLIENT_ID);
}
@Test
@@ -570,7 +517,7 @@ void getDefaultCredentials_wellKnownFileNonWindows_providesToken() throws IOExce
testProvider.setProperty("user.home", homeDir.getAbsolutePath());
testProvider.addFile(wellKnownFile.getAbsolutePath(), userStream);
- testUserProvidesToken(testProvider, USER_CLIENT_ID, USER_CLIENT_SECRET, REFRESH_TOKEN);
+ testUserProvidesToken(testProvider, USER_CLIENT_ID);
}
@Test
@@ -587,7 +534,7 @@ void getDefaultCredentials_wellKnownFileWindows_providesToken() throws IOExcepti
testProvider.setEnv("APPDATA", homeDir.getAbsolutePath());
testProvider.addFile(wellKnownFile.getAbsolutePath(), userStream);
- testUserProvidesToken(testProvider, USER_CLIENT_ID, USER_CLIENT_SECRET, REFRESH_TOKEN);
+ testUserProvidesToken(testProvider, USER_CLIENT_ID);
}
@Test
@@ -629,12 +576,12 @@ private String tempFilePath(String filename) {
return Paths.get(System.getProperty("java.io.tmpdir"), filename).toString();
}
- private class LogHandler extends Handler {
+ private static class LogHandler extends Handler {
LogRecord lastRecord;
@Override
- public void publish(LogRecord record) {
- lastRecord = record;
+ public void publish(LogRecord logRecord) {
+ this.lastRecord = logRecord;
}
public LogRecord getRecord() {
@@ -642,10 +589,14 @@ public LogRecord getRecord() {
}
@Override
- public void close() {}
+ public void close() {
+ // Test implementation. Nothing to close
+ }
@Override
- public void flush() {}
+ public void flush() {
+ // Test implementation. Nothing to flush
+ }
}
@Test
@@ -653,8 +604,7 @@ void getDefaultCredentials_wellKnownFile_logsGcloudWarning() throws IOException
LogRecord message = getCredentialsAndReturnLogMessage(false, true);
assertNotNull(message);
assertEquals(Level.WARNING, message.getLevel());
- assertTrue(
- message.getMessage().equals(DefaultCredentialsProvider.CLOUDSDK_CREDENTIALS_WARNING));
+ assertEquals(DefaultCredentialsProvider.CLOUDSDK_CREDENTIALS_WARNING, message.getMessage());
}
@Test
@@ -690,13 +640,12 @@ private LogRecord getCredentialsAndReturnLogMessage(boolean suppressWarning, boo
testProvider.setProperty("os.name", "linux");
testProvider.setProperty("user.home", homeDir.getAbsolutePath());
if (isGce) {
- String productFilePath = SMBIOS_PATH_LINUX;
- File productFile = new File(productFilePath);
+ File productFile = new File(SMBIOS_PATH_LINUX);
InputStream productStream = new ByteArrayInputStream("Googlekdjsfhg".getBytes());
testProvider.addFile(productFile.getAbsolutePath(), productStream);
}
testProvider.addFile(wellKnownFile.getAbsolutePath(), userStream);
- testUserProvidesToken(testProvider, GCLOUDSDK_CLIENT_ID, USER_CLIENT_SECRET, REFRESH_TOKEN);
+ testUserProvidesToken(testProvider, GCLOUDSDK_CLIENT_ID);
return handler.getRecord();
}
@@ -704,15 +653,13 @@ private static File getTempDirectory() {
return new File(System.getProperty("java.io.tmpdir"));
}
- private void testUserProvidesToken(
- TestDefaultCredentialsProvider testProvider,
- String clientId,
- String clientSecret,
- String refreshToken)
+ private void testUserProvidesToken(TestDefaultCredentialsProvider testProvider, String clientId)
throws IOException {
MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
- transportFactory.transport.addClient(clientId, clientSecret);
- transportFactory.transport.addRefreshToken(refreshToken, ACCESS_TOKEN);
+ transportFactory.transport.addClient(
+ clientId, DefaultCredentialsProviderTest.USER_CLIENT_SECRET);
+ transportFactory.transport.addRefreshToken(
+ DefaultCredentialsProviderTest.REFRESH_TOKEN, ACCESS_TOKEN);
testUserProvidesToken(testProvider, transportFactory, ACCESS_TOKEN);
}
@@ -755,7 +702,7 @@ void getDefaultCredentials_envVarSet_serviceAccountCredentials_correctCredential
GoogleCredentials credentials = testProvider.getDefaultCredentials(transportFactory);
assertNotNull(credentials);
- assertTrue(credentials instanceof ServiceAccountCredentials);
+ assertInstanceOf(ServiceAccountCredentials.class, credentials);
Map credentialInfo = credentials.getCredentialInfo();
assertEquals(
String.format(
@@ -780,7 +727,7 @@ void getDefaultCredentials_envVarSet_userCredential_correctCredentialInfo() thro
GoogleCredentials credentials = testProvider.getDefaultCredentials(transportFactory);
assertNotNull(credentials);
- assertTrue(credentials instanceof UserCredentials);
+ assertInstanceOf(UserCredentials.class, credentials);
Map credentialInfo = credentials.getCredentialInfo();
assertEquals(
String.format(
@@ -808,7 +755,7 @@ void getDefaultCredentials_wellKnownFile_userCredential_correctCredentialInfo()
GoogleCredentials credentials = testProvider.getDefaultCredentials(transportFactory);
assertNotNull(credentials);
- assertTrue(credentials instanceof UserCredentials);
+ assertInstanceOf(UserCredentials.class, credentials);
Map credentialInfo = credentials.getCredentialInfo();
assertEquals(
String.format("Well Known File at %s", wellKnownFile.getCanonicalPath()),
@@ -827,7 +774,7 @@ void getDefaultCredentials_computeEngineCredentials_defaultMDSUrl_correctCredent
GoogleCredentials credentials = testProvider.getDefaultCredentials(transportFactory);
assertNotNull(credentials);
- assertTrue(credentials instanceof ComputeEngineCredentials);
+ assertInstanceOf(ComputeEngineCredentials.class, credentials);
Map credentialInfo = credentials.getCredentialInfo();
assertEquals(
String.format(
@@ -849,7 +796,7 @@ void getDefaultCredentials_computeEngineCredentials_customMDSUrl_correctCredenti
GoogleCredentials credentials = testProvider.getDefaultCredentials(transportFactory);
assertNotNull(credentials);
- assertTrue(credentials instanceof ComputeEngineCredentials);
+ assertInstanceOf(ComputeEngineCredentials.class, credentials);
Map credentialInfo = credentials.getCredentialInfo();
assertEquals(
String.format("Metadata Server URL set to http://%s", gceMetadataHost),
@@ -868,7 +815,7 @@ private static class MockAppEngineSystemProperty {
@SuppressWarnings("unused")
public static final MockEnvironment environment =
- new MockEnvironment(MockEnvironmentEnum.Production);
+ new MockEnvironment(MockEnvironmentEnum.PRODUCTION);
}
private static class MockOffAppEngineSystemProperty {
@@ -878,13 +825,13 @@ private static class MockOffAppEngineSystemProperty {
}
private enum MockEnvironmentEnum {
- Production,
- Development;
+ PRODUCTION,
+ DEVELOPMENT;
}
public static class MockEnvironment {
- private MockEnvironmentEnum innerValue;
+ private final MockEnvironmentEnum innerValue;
MockEnvironment(MockEnvironmentEnum value) {
this.innerValue = value;
@@ -934,8 +881,8 @@ void addFile(String file, InputStream stream) {
files.put(file, stream);
}
- void addType(String className, Class> type) {
- types.put(className, type);
+ void addType(Class> type) {
+ types.put(DefaultCredentialsProvider.APP_ENGINE_SIGNAL_CLASS, type);
}
@Override
@@ -991,8 +938,8 @@ InputStream readStream(File file) throws FileNotFoundException {
return stream;
}
- void setFileSandbox(boolean fileSandbox) {
- this.fileSandbox = fileSandbox;
+ void setFileSandbox() {
+ this.fileSandbox = true;
}
}
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/DefaultPKCEProviderTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/DefaultPKCEProviderTest.java
index 114e27298b3f..34e9be380841 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/DefaultPKCEProviderTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/DefaultPKCEProviderTest.java
@@ -54,11 +54,11 @@ void testPkceExpected() throws NoSuchAlgorithmException {
String expectedCodeChallengeMethod = "S256";
assertEquals(pkce.getCodeChallenge(), expectedCodeChallenge);
- assertEquals(pkce.getCodeChallengeMethod(), expectedCodeChallengeMethod);
+ assertEquals(expectedCodeChallengeMethod, pkce.getCodeChallengeMethod());
}
@Test
- void testNoBase64Padding() throws NoSuchAlgorithmException {
+ void testNoBase64Padding() {
PKCEProvider pkce = new DefaultPKCEProvider();
assertFalse(pkce.getCodeChallenge().endsWith("="));
assertFalse(pkce.getCodeChallenge().contains("="));
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/DownscopedCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/DownscopedCredentialsTest.java
index 31c4e776e3f8..34a52b4154fb 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/DownscopedCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/DownscopedCredentialsTest.java
@@ -35,7 +35,7 @@
import static com.google.auth.oauth2.OAuth2Utils.TOKEN_EXCHANGE_URL_FORMAT;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.api.client.http.HttpTransport;
import com.google.auth.TestUtils;
@@ -188,38 +188,25 @@ void refreshAccessToken_cantRefreshSourceCredentials_throws() throws IOException
.setHttpTransportFactory(transportFactory)
.build();
- try {
- downscopedCredentials.refreshAccessToken();
- fail("Should fail as the source credential should not be able to be refreshed.");
- } catch (IOException e) {
- assertEquals("Unable to refresh the provided source credential.", e.getMessage());
- }
+ IOException e = assertThrows(IOException.class, downscopedCredentials::refreshAccessToken);
+ assertEquals("Unable to refresh the provided source credential.", e.getMessage());
}
@Test
void builder_noSourceCredential_throws() {
- try {
- DownscopedCredentials.newBuilder()
- .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
- .setCredentialAccessBoundary(CREDENTIAL_ACCESS_BOUNDARY)
- .build();
- fail("Should fail as the source credential is null.");
- } catch (NullPointerException e) {
- // Expected.
- }
+ DownscopedCredentials.Builder builder =
+ DownscopedCredentials.newBuilder()
+ .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY);
+ assertThrows(NullPointerException.class, builder::build);
}
@Test
void builder_noCredentialAccessBoundary_throws() throws IOException {
- try {
- DownscopedCredentials.newBuilder()
- .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
- .setSourceCredential(getServiceAccountSourceCredentials(/* canRefresh= */ true))
- .build();
- fail("Should fail as no access boundary was provided.");
- } catch (NullPointerException e) {
- // Expected.
- }
+ DownscopedCredentials.Builder builder =
+ DownscopedCredentials.newBuilder()
+ .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
+ .setSourceCredential(getServiceAccountSourceCredentials(/* canRefresh= */ true));
+ assertThrows(NullPointerException.class, builder::build);
}
@Test
@@ -263,37 +250,31 @@ void builder_universeDomainMismatch_throws() throws IOException {
GoogleCredentials sourceCredentials =
getServiceAccountSourceCredentials(/* canRefresh= */ true);
- try {
- DownscopedCredentials.newBuilder()
- .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
- .setSourceCredential(sourceCredentials)
- .setCredentialAccessBoundary(CREDENTIAL_ACCESS_BOUNDARY)
- .setUniverseDomain("differentUniverseDomain")
- .build();
- fail("Should fail with universe domain mismatch.");
- } catch (IllegalArgumentException e) {
- assertEquals(
- "The downscoped credential's universe domain must be the same as the source credential.",
- e.getMessage());
- }
+ DownscopedCredentials.Builder builder =
+ DownscopedCredentials.newBuilder()
+ .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
+ .setSourceCredential(sourceCredentials)
+ .setCredentialAccessBoundary(CREDENTIAL_ACCESS_BOUNDARY)
+ .setUniverseDomain("differentUniverseDomain");
+ IllegalArgumentException e = assertThrows(IllegalArgumentException.class, builder::build);
+ assertEquals(
+ "The downscoped credential's universe domain must be the same as the source credential.",
+ e.getMessage());
}
@Test
- void builder_sourceUniverseDomainUnavailable_throws() throws IOException {
+ void builder_sourceUniverseDomainUnavailable_throws() {
GoogleCredentials sourceCredentials = new MockSourceCredentialWithoutUniverseDomain();
- try {
- DownscopedCredentials.newBuilder()
- .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
- .setSourceCredential(sourceCredentials)
- .setCredentialAccessBoundary(CREDENTIAL_ACCESS_BOUNDARY)
- .build();
- fail("Should fail to retrieve source credential universe domain.");
- } catch (IllegalStateException e) {
- assertEquals(
- "Error occurred when attempting to retrieve source credential universe domain.",
- e.getMessage());
- }
+ DownscopedCredentials.Builder builder =
+ DownscopedCredentials.newBuilder()
+ .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
+ .setSourceCredential(sourceCredentials)
+ .setCredentialAccessBoundary(CREDENTIAL_ACCESS_BOUNDARY);
+ IllegalStateException e = assertThrows(IllegalStateException.class, builder::build);
+ assertEquals(
+ "Error occurred when attempting to retrieve source credential universe domain.",
+ e.getMessage());
}
private static GoogleCredentials getServiceAccountSourceCredentials(boolean canRefresh)
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ExecutableResponseTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ExecutableResponseTest.java
index da7ea8cc6e5b..d9923e968a16 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ExecutableResponseTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ExecutableResponseTest.java
@@ -34,8 +34,8 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import com.google.api.client.json.GenericJson;
import java.io.IOException;
@@ -128,129 +128,107 @@ void constructor_validErrorResponse() throws IOException {
}
@Test
- void constructor_errorResponseMissingCode_throws() throws IOException {
+ void constructor_errorResponseMissingCode_throws() {
GenericJson jsonResponse = buildErrorResponse();
Object[] values = new Object[] {null, ""};
for (Object value : values) {
jsonResponse.put("code", value);
- try {
- new ExecutableResponse(jsonResponse);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException exception) {
- assertEquals(
- "Error code INVALID_EXECUTABLE_RESPONSE: The executable response must contain "
- + "`error` and `message` fields when unsuccessful.",
- exception.getMessage());
- }
+ PluggableAuthException exception =
+ assertThrows(PluggableAuthException.class, () -> new ExecutableResponse(jsonResponse));
+ assertEquals(
+ "Error code INVALID_EXECUTABLE_RESPONSE: The executable response must contain "
+ + "`error` and `message` fields when unsuccessful.",
+ exception.getMessage());
}
}
@Test
- void constructor_errorResponseMissingMessage_throws() throws IOException {
+ void constructor_errorResponseMissingMessage_throws() {
GenericJson jsonResponse = buildErrorResponse();
Object[] values = new Object[] {null, ""};
for (Object value : values) {
jsonResponse.put("message", value);
- try {
- new ExecutableResponse(jsonResponse);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException exception) {
- assertEquals(
- "Error code INVALID_EXECUTABLE_RESPONSE: The executable response must contain "
- + "`error` and `message` fields when unsuccessful.",
- exception.getMessage());
- }
+ PluggableAuthException exception =
+ assertThrows(PluggableAuthException.class, () -> new ExecutableResponse(jsonResponse));
+ assertEquals(
+ "Error code INVALID_EXECUTABLE_RESPONSE: The executable response must contain "
+ + "`error` and `message` fields when unsuccessful.",
+ exception.getMessage());
}
}
@Test
- void constructor_successResponseMissingVersionField_throws() throws IOException {
+ void constructor_successResponseMissingVersionField_throws() {
GenericJson jsonResponse = buildOidcResponse();
jsonResponse.remove("version");
- try {
- new ExecutableResponse(jsonResponse);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException exception) {
- assertEquals(
- "Error code INVALID_EXECUTABLE_RESPONSE: The executable response is missing the "
- + "`version` field.",
- exception.getMessage());
- }
+ PluggableAuthException exception =
+ assertThrows(PluggableAuthException.class, () -> new ExecutableResponse(jsonResponse));
+ assertEquals(
+ "Error code INVALID_EXECUTABLE_RESPONSE: The executable response is missing the "
+ + "`version` field.",
+ exception.getMessage());
}
@Test
- void constructor_successResponseMissingSuccessField_throws() throws Exception {
+ void constructor_successResponseMissingSuccessField_throws() {
GenericJson jsonResponse = buildOidcResponse();
jsonResponse.remove("success");
- try {
- new ExecutableResponse(jsonResponse);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException exception) {
- assertEquals(
- "Error code INVALID_EXECUTABLE_RESPONSE: The executable response is missing the "
- + "`success` field.",
- exception.getMessage());
- }
+ PluggableAuthException exception =
+ assertThrows(PluggableAuthException.class, () -> new ExecutableResponse(jsonResponse));
+ assertEquals(
+ "Error code INVALID_EXECUTABLE_RESPONSE: The executable response is missing the "
+ + "`success` field.",
+ exception.getMessage());
}
@Test
- void constructor_successResponseMissingTokenTypeField_throws() throws IOException {
+ void constructor_successResponseMissingTokenTypeField_throws() {
GenericJson jsonResponse = buildOidcResponse();
jsonResponse.remove("token_type");
- try {
- new ExecutableResponse(jsonResponse);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException exception) {
- assertEquals(
- "Error code INVALID_EXECUTABLE_RESPONSE: The executable response is missing the "
- + "`token_type` field.",
- exception.getMessage());
- }
+ PluggableAuthException exception =
+ assertThrows(PluggableAuthException.class, () -> new ExecutableResponse(jsonResponse));
+ assertEquals(
+ "Error code INVALID_EXECUTABLE_RESPONSE: The executable response is missing the "
+ + "`token_type` field.",
+ exception.getMessage());
}
@Test
- void constructor_samlResponseMissingSubjectToken_throws() throws IOException {
+ void constructor_samlResponseMissingSubjectToken_throws() {
GenericJson jsonResponse = buildSamlResponse();
Object[] values = new Object[] {null, ""};
for (Object value : values) {
jsonResponse.put("saml_response", value);
-
- try {
- new ExecutableResponse(jsonResponse);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException exception) {
- assertEquals(
- "Error code INVALID_EXECUTABLE_RESPONSE: The executable response does not "
- + "contain a valid token.",
- exception.getMessage());
- }
+ PluggableAuthException exception =
+ assertThrows(PluggableAuthException.class, () -> new ExecutableResponse(jsonResponse));
+ assertEquals(
+ "Error code INVALID_EXECUTABLE_RESPONSE: The executable response does not "
+ + "contain a valid token.",
+ exception.getMessage());
}
}
@Test
- void constructor_oidcResponseMissingSubjectToken_throws() throws IOException {
+ void constructor_oidcResponseMissingSubjectToken_throws() {
GenericJson jsonResponse = buildOidcResponse();
Object[] values = new Object[] {null, ""};
for (Object value : values) {
jsonResponse.put("id_token", value);
- try {
- new ExecutableResponse(jsonResponse);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException exception) {
- assertEquals(
- "Error code INVALID_EXECUTABLE_RESPONSE: The executable response does not "
- + "contain a valid token.",
- exception.getMessage());
- }
+ PluggableAuthException exception =
+ assertThrows(PluggableAuthException.class, () -> new ExecutableResponse(jsonResponse));
+ assertEquals(
+ "Error code INVALID_EXECUTABLE_RESPONSE: The executable response does not "
+ + "contain a valid token.",
+ exception.getMessage());
}
}
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ExternalAccountAuthorizedUserCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ExternalAccountAuthorizedUserCredentialsTest.java
index 4913e5aec53e..78bb6811953e 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ExternalAccountAuthorizedUserCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ExternalAccountAuthorizedUserCredentialsTest.java
@@ -39,7 +39,6 @@
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.GenericJson;
@@ -51,12 +50,12 @@
import com.google.auth.oauth2.GoogleCredentials.GoogleCredentialsInfo;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import com.google.common.io.BaseEncoding;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
+import java.util.Base64;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
@@ -84,8 +83,8 @@ class ExternalAccountAuthorizedUserCredentialsTest extends BaseSerializationTest
private static final String BASIC_AUTH =
String.format(
"Basic %s",
- BaseEncoding.base64()
- .encode(
+ Base64.getEncoder()
+ .encodeToString(
String.format("%s:%s", CLIENT_ID, CLIENT_SECRET)
.getBytes(StandardCharsets.UTF_8)));
@@ -246,70 +245,59 @@ void builder_accessTokenWithMissingRefreshFields() {
@Test
void builder_accessAndRefreshTokenNull_throws() {
- try {
- ExternalAccountAuthorizedUserCredentials.newBuilder().build();
- fail("Should not be able to continue without exception.");
- } catch (IllegalStateException exception) {
- assertEquals(
- "ExternalAccountAuthorizedUserCredentials must be initialized with "
- + "an access token or fields to enable refresh: "
- + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
- exception.getMessage());
- }
+ ExternalAccountAuthorizedUserCredentials.Builder builder =
+ ExternalAccountAuthorizedUserCredentials.newBuilder();
+ IllegalStateException exception = assertThrows(IllegalStateException.class, builder::build);
+ assertEquals(
+ "ExternalAccountAuthorizedUserCredentials must be initialized with "
+ + "an access token or fields to enable refresh: "
+ + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
+ exception.getMessage());
}
@Test
void builder_missingTokenUrl_throws() {
- try {
- ExternalAccountAuthorizedUserCredentials.newBuilder()
- .setRefreshToken(REFRESH_TOKEN)
- .setClientId(CLIENT_ID)
- .setClientSecret(CLIENT_SECRET)
- .build();
- fail("Should not be able to continue without exception.");
- } catch (IllegalStateException exception) {
- assertEquals(
- "ExternalAccountAuthorizedUserCredentials must be initialized with "
- + "an access token or fields to enable refresh: "
- + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
- exception.getMessage());
- }
+ ExternalAccountAuthorizedUserCredentials.Builder builder =
+ ExternalAccountAuthorizedUserCredentials.newBuilder()
+ .setRefreshToken(REFRESH_TOKEN)
+ .setClientId(CLIENT_ID)
+ .setClientSecret(CLIENT_SECRET);
+ IllegalStateException exception = assertThrows(IllegalStateException.class, builder::build);
+ assertEquals(
+ "ExternalAccountAuthorizedUserCredentials must be initialized with "
+ + "an access token or fields to enable refresh: "
+ + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
+ exception.getMessage());
}
@Test
void builder_missingClientId_throws() {
- try {
- ExternalAccountAuthorizedUserCredentials.newBuilder()
- .setRefreshToken(REFRESH_TOKEN)
- .setTokenUrl(TOKEN_URL)
- .setClientSecret(CLIENT_SECRET)
- .build();
- fail("Should not be able to continue without exception.");
- } catch (IllegalStateException exception) {
- assertEquals(
- "ExternalAccountAuthorizedUserCredentials must be initialized with "
- + "an access token or fields to enable refresh: "
- + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
- exception.getMessage());
- }
+ ExternalAccountAuthorizedUserCredentials.Builder builder =
+ ExternalAccountAuthorizedUserCredentials.newBuilder()
+ .setRefreshToken(REFRESH_TOKEN)
+ .setTokenUrl(TOKEN_URL)
+ .setClientSecret(CLIENT_SECRET);
+ IllegalStateException exception = assertThrows(IllegalStateException.class, builder::build);
+ assertEquals(
+ "ExternalAccountAuthorizedUserCredentials must be initialized with "
+ + "an access token or fields to enable refresh: "
+ + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
+ exception.getMessage());
}
@Test
void builder_missingClientSecret_throws() {
- try {
- ExternalAccountAuthorizedUserCredentials.newBuilder()
- .setRefreshToken(REFRESH_TOKEN)
- .setTokenUrl(TOKEN_URL)
- .setClientId(CLIENT_ID)
- .build();
- fail("Should not be able to continue without exception.");
- } catch (IllegalStateException exception) {
- assertEquals(
- "ExternalAccountAuthorizedUserCredentials must be initialized with "
- + "an access token or fields to enable refresh: "
- + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
- exception.getMessage());
- }
+ ExternalAccountAuthorizedUserCredentials.Builder builder =
+ ExternalAccountAuthorizedUserCredentials.newBuilder()
+ .setRefreshToken(REFRESH_TOKEN)
+ .setTokenUrl(TOKEN_URL)
+ .setClientId(CLIENT_ID);
+ IllegalStateException exception = assertThrows(IllegalStateException.class, builder::build);
+ assertEquals(
+ "ExternalAccountAuthorizedUserCredentials must be initialized with "
+ + "an access token or fields to enable refresh: "
+ + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
+ exception.getMessage());
}
@Test
@@ -421,84 +409,89 @@ void fromJson_minimumRequiredFieldsForRefresh() throws IOException {
}
@Test
- void fromJson_accessTokenOnly_notSupported() throws IOException {
+ void fromJson_accessTokenOnly_notSupported() {
GenericJson json = new GenericJson();
json.put("access_token", ACCESS_TOKEN);
- try {
- ExternalAccountAuthorizedUserCredentials.fromJson(json, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- fail("Should not be able to continue without exception.");
- } catch (IllegalStateException exception) {
- assertEquals(
- "ExternalAccountAuthorizedUserCredentials must be initialized with "
- + "an access token or fields to enable refresh: "
- + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
- exception.getMessage());
- }
+ IllegalStateException exception =
+ assertThrows(
+ IllegalStateException.class,
+ () ->
+ ExternalAccountAuthorizedUserCredentials.fromJson(
+ json, OAuth2Utils.HTTP_TRANSPORT_FACTORY));
+ assertEquals(
+ "ExternalAccountAuthorizedUserCredentials must be initialized with "
+ + "an access token or fields to enable refresh: "
+ + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
+ exception.getMessage());
}
@Test
- void fromJson_missingRefreshToken_throws() throws IOException {
- try {
- GenericJson json = buildJsonCredentials();
- json.remove("refresh_token");
- ExternalAccountAuthorizedUserCredentials.fromJson(json, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- fail("Should not be able to continue without exception.");
- } catch (IllegalStateException exception) {
- assertEquals(
- "ExternalAccountAuthorizedUserCredentials must be initialized with "
- + "an access token or fields to enable refresh: "
- + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
- exception.getMessage());
- }
+ void fromJson_missingRefreshToken_throws() {
+ GenericJson json = buildJsonCredentials();
+ json.remove("refresh_token");
+ IllegalStateException exception =
+ assertThrows(
+ IllegalStateException.class,
+ () ->
+ ExternalAccountAuthorizedUserCredentials.fromJson(
+ json, OAuth2Utils.HTTP_TRANSPORT_FACTORY));
+ assertEquals(
+ "ExternalAccountAuthorizedUserCredentials must be initialized with "
+ + "an access token or fields to enable refresh: "
+ + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
+ exception.getMessage());
}
@Test
- void fromJson_missingTokenUrl_throws() throws IOException {
- try {
- GenericJson json = buildJsonCredentials();
- json.remove("token_url");
- ExternalAccountAuthorizedUserCredentials.fromJson(json, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- fail("Should not be able to continue without exception.");
- } catch (IllegalStateException exception) {
- assertEquals(
- "ExternalAccountAuthorizedUserCredentials must be initialized with "
- + "an access token or fields to enable refresh: "
- + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
- exception.getMessage());
- }
+ void fromJson_missingTokenUrl_throws() {
+ GenericJson json = buildJsonCredentials();
+ json.remove("token_url");
+ IllegalStateException exception =
+ assertThrows(
+ IllegalStateException.class,
+ () ->
+ ExternalAccountAuthorizedUserCredentials.fromJson(
+ json, OAuth2Utils.HTTP_TRANSPORT_FACTORY));
+ assertEquals(
+ "ExternalAccountAuthorizedUserCredentials must be initialized with "
+ + "an access token or fields to enable refresh: "
+ + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
+ exception.getMessage());
}
@Test
- void fromJson_missingClientId_throws() throws IOException {
- try {
- GenericJson json = buildJsonCredentials();
- json.remove("client_id");
- ExternalAccountAuthorizedUserCredentials.fromJson(json, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- fail("Should not be able to continue without exception.");
- } catch (IllegalStateException exception) {
- assertEquals(
- "ExternalAccountAuthorizedUserCredentials must be initialized with "
- + "an access token or fields to enable refresh: "
- + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
- exception.getMessage());
- }
+ void fromJson_missingClientId_throws() {
+ GenericJson json = buildJsonCredentials();
+ json.remove("client_id");
+ IllegalStateException exception =
+ assertThrows(
+ IllegalStateException.class,
+ () ->
+ ExternalAccountAuthorizedUserCredentials.fromJson(
+ json, OAuth2Utils.HTTP_TRANSPORT_FACTORY));
+ assertEquals(
+ "ExternalAccountAuthorizedUserCredentials must be initialized with "
+ + "an access token or fields to enable refresh: "
+ + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
+ exception.getMessage());
}
@Test
- void fromJson_missingClientSecret_throws() throws IOException {
- try {
- GenericJson json = buildJsonCredentials();
- json.remove("client_secret");
- ExternalAccountAuthorizedUserCredentials.fromJson(json, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- fail("Should not be able to continue without exception.");
- } catch (IllegalStateException exception) {
- assertEquals(
- "ExternalAccountAuthorizedUserCredentials must be initialized with "
- + "an access token or fields to enable refresh: "
- + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
- exception.getMessage());
- }
+ void fromJson_missingClientSecret_throws() {
+ GenericJson json = buildJsonCredentials();
+ json.remove("client_secret");
+ IllegalStateException exception =
+ assertThrows(
+ IllegalStateException.class,
+ () ->
+ ExternalAccountAuthorizedUserCredentials.fromJson(
+ json, OAuth2Utils.HTTP_TRANSPORT_FACTORY));
+ assertEquals(
+ "ExternalAccountAuthorizedUserCredentials must be initialized with "
+ + "an access token or fields to enable refresh: "
+ + "('refresh_token', 'token_url', 'client_id', 'client_secret').",
+ exception.getMessage());
}
@Test
@@ -567,10 +560,11 @@ void fromStream_accessTokenOnly_notSupported() throws IOException {
json.put("access_token", ACCESS_TOKEN);
json.put(
"type", GoogleCredentialsInfo.EXTERNAL_ACCOUNT_AUTHORIZED_USER_CREDENTIALS.getFileType());
- try {
- ExternalAccountAuthorizedUserCredentials.fromStream(TestUtils.jsonToInputStream(json));
- fail("Should not be able to continue without exception.");
- } catch (IllegalStateException exception) {
+ try (InputStream credentialsStream = TestUtils.jsonToInputStream(json)) {
+ IllegalStateException exception =
+ assertThrows(
+ IllegalStateException.class,
+ () -> ExternalAccountAuthorizedUserCredentials.fromStream(credentialsStream));
assertEquals(
"ExternalAccountAuthorizedUserCredentials must be initialized with "
+ "an access token or fields to enable refresh: "
@@ -581,12 +575,13 @@ void fromStream_accessTokenOnly_notSupported() throws IOException {
@Test
void fromStream_missingRefreshToken_throws() throws IOException {
- try {
- GenericJson json = buildJsonCredentials();
- json.remove("refresh_token");
- ExternalAccountAuthorizedUserCredentials.fromStream(TestUtils.jsonToInputStream(json));
- fail("Should not be able to continue without exception.");
- } catch (IllegalStateException exception) {
+ GenericJson json = buildJsonCredentials();
+ json.remove("refresh_token");
+ try (InputStream credentialsStream = TestUtils.jsonToInputStream(json)) {
+ IllegalStateException exception =
+ assertThrows(
+ IllegalStateException.class,
+ () -> ExternalAccountAuthorizedUserCredentials.fromStream(credentialsStream));
assertEquals(
"ExternalAccountAuthorizedUserCredentials must be initialized with "
+ "an access token or fields to enable refresh: "
@@ -597,12 +592,13 @@ void fromStream_missingRefreshToken_throws() throws IOException {
@Test
void fromStream_missingTokenUrl_throws() throws IOException {
- try {
- GenericJson json = buildJsonCredentials();
- json.remove("token_url");
- ExternalAccountAuthorizedUserCredentials.fromStream(TestUtils.jsonToInputStream(json));
- fail("Should not be able to continue without exception.");
- } catch (IllegalStateException exception) {
+ GenericJson json = buildJsonCredentials();
+ json.remove("token_url");
+ try (InputStream credentialsStream = TestUtils.jsonToInputStream(json)) {
+ IllegalStateException exception =
+ assertThrows(
+ IllegalStateException.class,
+ () -> ExternalAccountAuthorizedUserCredentials.fromStream(credentialsStream));
assertEquals(
"ExternalAccountAuthorizedUserCredentials must be initialized with "
+ "an access token or fields to enable refresh: "
@@ -613,12 +609,13 @@ void fromStream_missingTokenUrl_throws() throws IOException {
@Test
void fromStream_missingClientId_throws() throws IOException {
- try {
- GenericJson json = buildJsonCredentials();
- json.remove("client_id");
- ExternalAccountAuthorizedUserCredentials.fromStream(TestUtils.jsonToInputStream(json));
- fail("Should not be able to continue without exception.");
- } catch (IllegalStateException exception) {
+ GenericJson json = buildJsonCredentials();
+ json.remove("client_id");
+ try (InputStream credentialsStream = TestUtils.jsonToInputStream(json)) {
+ IllegalStateException exception =
+ assertThrows(
+ IllegalStateException.class,
+ () -> ExternalAccountAuthorizedUserCredentials.fromStream(credentialsStream));
assertEquals(
"ExternalAccountAuthorizedUserCredentials must be initialized with "
+ "an access token or fields to enable refresh: "
@@ -629,12 +626,13 @@ void fromStream_missingClientId_throws() throws IOException {
@Test
void fromStream_missingClientSecret_throws() throws IOException {
- try {
- GenericJson json = buildJsonCredentials();
- json.remove("client_secret");
- ExternalAccountAuthorizedUserCredentials.fromStream(TestUtils.jsonToInputStream(json));
- fail("Should not be able to continue without exception.");
- } catch (IllegalStateException exception) {
+ GenericJson json = buildJsonCredentials();
+ json.remove("client_secret");
+ try (InputStream credentialsStream = TestUtils.jsonToInputStream(json)) {
+ IllegalStateException exception =
+ assertThrows(
+ IllegalStateException.class,
+ () -> ExternalAccountAuthorizedUserCredentials.fromStream(credentialsStream));
assertEquals(
"ExternalAccountAuthorizedUserCredentials must be initialized with "
+ "an access token or fields to enable refresh: "
@@ -664,12 +662,13 @@ void fromStream_missingUniverseDomain_defaults() throws IOException {
@Test
void fromStream_invalidInputStream_throws() throws IOException {
- try {
- GenericJson json = buildJsonCredentials();
- json.put("audience", new HashMap<>());
- ExternalAccountAuthorizedUserCredentials.fromStream(TestUtils.jsonToInputStream(json));
- fail("Should not be able to continue without exception.");
- } catch (CredentialFormatException e) {
+ GenericJson json = buildJsonCredentials();
+ json.put("audience", new HashMap<>());
+ try (InputStream credentialsStream = TestUtils.jsonToInputStream(json)) {
+ CredentialFormatException e =
+ assertThrows(
+ CredentialFormatException.class,
+ () -> ExternalAccountAuthorizedUserCredentials.fromStream(credentialsStream));
assertEquals("Invalid input stream provided.", e.getMessage());
}
}
@@ -720,8 +719,8 @@ void getRequestMetadata_withQuotaProjectId() throws IOException {
assertTrue(metadata.containsKey(GoogleCredentials.QUOTA_PROJECT_ID_HEADER_KEY));
assertEquals(
- metadata.get(GoogleCredentials.QUOTA_PROJECT_ID_HEADER_KEY),
- Collections.singletonList(QUOTA_PROJECT));
+ Collections.singletonList(QUOTA_PROJECT),
+ metadata.get(GoogleCredentials.QUOTA_PROJECT_ID_HEADER_KEY));
validateAuthHeader(transportFactory.transport.getRequest());
}
@@ -775,13 +774,9 @@ void refreshAccessToken_genericAuthError_throws() throws IOException {
ExternalAccountAuthorizedUserCredentials credentials =
ExternalAccountAuthorizedUserCredentials.fromJson(buildJsonCredentials(), transportFactory);
- try {
- credentials.refreshAccessToken();
- fail("");
- } catch (OAuthException e) {
- assertEquals("invalid_request", e.getErrorCode());
- assertEquals("Invalid request.", e.getErrorDescription());
- }
+ OAuthException e = assertThrows(OAuthException.class, credentials::refreshAccessToken);
+ assertEquals("invalid_request", e.getErrorCode());
+ assertEquals("Invalid request.", e.getErrorDescription());
}
@Test
@@ -791,11 +786,11 @@ void refreshAccessToken_genericIOError_throws() throws IOException {
ExternalAccountAuthorizedUserCredentials credentials =
ExternalAccountAuthorizedUserCredentials.fromJson(buildJsonCredentials(), transportFactory);
- assertThrows(IOException.class, () -> credentials.refreshAccessToken());
+ assertThrows(IOException.class, credentials::refreshAccessToken);
}
@Test
- void refreshAccessToken_missingRefreshFields_throws() throws IOException {
+ void refreshAccessToken_missingRefreshFields_throws() {
ExternalAccountAuthorizedUserCredentials credentials =
ExternalAccountAuthorizedUserCredentials.newBuilder()
.setClientId(CLIENT_ID)
@@ -805,7 +800,7 @@ void refreshAccessToken_missingRefreshFields_throws() throws IOException {
.setHttpTransportFactory(transportFactory)
.build();
- assertThrows(IllegalStateException.class, () -> credentials.refreshAccessToken());
+ assertThrows(IllegalStateException.class, credentials::refreshAccessToken);
}
@Test
@@ -1238,7 +1233,7 @@ void serialize() throws IOException, ClassNotFoundException {
assertEquals(credentials, deserializedCredentials);
assertEquals(credentials.hashCode(), deserializedCredentials.hashCode());
assertEquals(credentials.toString(), deserializedCredentials.toString());
- assertSame(deserializedCredentials.clock, Clock.SYSTEM);
+ assertSame(Clock.SYSTEM, deserializedCredentials.clock);
}
static GenericJson buildJsonCredentials() {
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ExternalAccountCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ExternalAccountCredentialsTest.java
index d45979cfb985..1338c0d68fe9 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ExternalAccountCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ExternalAccountCredentialsTest.java
@@ -32,15 +32,18 @@
package com.google.auth.oauth2;
import static com.google.auth.oauth2.MockExternalAccountCredentialsTransport.SERVICE_ACCOUNT_IMPERSONATION_URL;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.GenericJson;
+import com.google.api.client.json.JsonParser;
import com.google.api.client.util.Clock;
import com.google.auth.TestUtils;
import com.google.auth.http.HttpTransportFactory;
@@ -97,7 +100,7 @@ void fromStream_identityPoolCredentials() throws IOException {
ExternalAccountCredentials credential =
ExternalAccountCredentials.fromStream(TestUtils.jsonToInputStream(json));
- assertTrue(credential instanceof IdentityPoolCredentials);
+ assertInstanceOf(IdentityPoolCredentials.class, credential);
}
@Test
@@ -107,7 +110,7 @@ void fromStream_awsCredentials() throws IOException {
ExternalAccountCredentials credential =
ExternalAccountCredentials.fromStream(TestUtils.jsonToInputStream(json));
- assertTrue(credential instanceof AwsCredentials);
+ assertInstanceOf(AwsCredentials.class, credential);
}
@Test
@@ -117,32 +120,29 @@ void fromStream_pluggableAuthCredentials() throws IOException {
ExternalAccountCredentials credential =
ExternalAccountCredentials.fromStream(TestUtils.jsonToInputStream(json));
- assertTrue(credential instanceof PluggableAuthCredentials);
+ assertInstanceOf(PluggableAuthCredentials.class, credential);
}
@Test
- void fromStream_invalidStream_throws() throws IOException {
+ void fromStream_invalidStream_throws() {
GenericJson json = buildJsonAwsCredential();
json.put("audience", new HashMap<>());
- try {
- ExternalAccountCredentials.fromStream(TestUtils.jsonToInputStream(json));
- fail("Should fail.");
- } catch (CredentialFormatException e) {
- assertEquals("An invalid input stream was provided.", e.getMessage());
- }
+ CredentialFormatException e =
+ assertThrows(
+ CredentialFormatException.class,
+ () -> ExternalAccountCredentials.fromStream(TestUtils.jsonToInputStream(json)));
+ assertEquals("An invalid input stream was provided.", e.getMessage());
}
@Test
- void fromStream_nullTransport_throws() throws IOException {
- try {
- ExternalAccountCredentials.fromStream(
- new ByteArrayInputStream("foo".getBytes()), /* transportFactory= */ null);
- fail("NullPointerException should be thrown.");
- } catch (NullPointerException e) {
- // Expected.
- }
+ void fromStream_nullTransport_throws() {
+ ByteArrayInputStream credentialsStream = new ByteArrayInputStream("foo".getBytes());
+ assertThrows(
+ NullPointerException.class,
+ () ->
+ ExternalAccountCredentials.fromStream(credentialsStream, /* transportFactory= */ null));
}
@Test
@@ -164,36 +164,32 @@ void fromStream_nullOptionalField() throws IOException {
}
@Test
- void fromStream_nullStream_throws() throws IOException {
- try {
- ExternalAccountCredentials.fromStream(
- /* credentialsStream= */ null, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- fail("NullPointerException should be thrown.");
- } catch (NullPointerException e) {
- // Expected.
- }
+ void fromStream_nullStream_throws() {
+ assertThrows(
+ NullPointerException.class,
+ () ->
+ ExternalAccountCredentials.fromStream(
+ /* credentialsStream= */ null, OAuth2Utils.HTTP_TRANSPORT_FACTORY));
}
@Test
- void fromStream_invalidWorkloadAudience_throws() throws IOException {
- try {
- GenericJson json = buildJsonIdentityPoolWorkforceCredential();
- json.put("audience", "invalidAudience");
- ExternalAccountCredentials credential =
- ExternalAccountCredentials.fromStream(TestUtils.jsonToInputStream(json));
- fail("CredentialFormatException should be thrown.");
- } catch (CredentialFormatException e) {
- assertEquals("An invalid input stream was provided.", e.getMessage());
- }
+ void fromStream_invalidWorkloadAudience_throws() {
+ GenericJson json = buildJsonIdentityPoolWorkforceCredential();
+ json.put("audience", "invalidAudience");
+ CredentialFormatException e =
+ assertThrows(
+ CredentialFormatException.class,
+ () -> ExternalAccountCredentials.fromStream(TestUtils.jsonToInputStream(json)));
+ assertEquals("An invalid input stream was provided.", e.getMessage());
}
@Test
- void fromJson_identityPoolCredentialsWorkload() throws IOException {
+ void fromJson_identityPoolCredentialsWorkload() {
ExternalAccountCredentials credential =
ExternalAccountCredentials.fromJson(
buildJsonIdentityPoolCredential(), OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- assertTrue(credential instanceof IdentityPoolCredentials);
+ assertInstanceOf(IdentityPoolCredentials.class, credential);
assertEquals(
"//iam.googleapis.com/projects/123/locations/global/workloadIdentityPools/pool/providers/provider",
credential.getAudience());
@@ -205,12 +201,12 @@ void fromJson_identityPoolCredentialsWorkload() throws IOException {
}
@Test
- void fromJson_identityPoolCredentialsWorkforce() throws IOException {
+ void fromJson_identityPoolCredentialsWorkforce() {
ExternalAccountCredentials credential =
ExternalAccountCredentials.fromJson(
buildJsonIdentityPoolWorkforceCredential(), OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- assertTrue(credential instanceof IdentityPoolCredentials);
+ assertInstanceOf(IdentityPoolCredentials.class, credential);
assertEquals(
"//iam.googleapis.com/locations/global/workforcePools/pool/providers/provider",
credential.getAudience());
@@ -223,16 +219,16 @@ void fromJson_identityPoolCredentialsWorkforce() throws IOException {
}
@Test
- void fromJson_identityPoolCredentialsWithServiceAccountImpersonationOptions() throws IOException {
+ void fromJson_identityPoolCredentialsWithServiceAccountImpersonationOptions() {
GenericJson identityPoolCredentialJson = buildJsonIdentityPoolCredential();
identityPoolCredentialJson.set(
- "service_account_impersonation", buildServiceAccountImpersonationOptions(2800));
+ "service_account_impersonation", buildServiceAccountImpersonationOptions());
ExternalAccountCredentials credential =
ExternalAccountCredentials.fromJson(
identityPoolCredentialJson, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- assertTrue(credential instanceof IdentityPoolCredentials);
+ assertInstanceOf(IdentityPoolCredentials.class, credential);
assertEquals(
"//iam.googleapis.com/projects/123/locations/global/workloadIdentityPools/pool/providers/provider",
credential.getAudience());
@@ -245,7 +241,7 @@ void fromJson_identityPoolCredentialsWithServiceAccountImpersonationOptions() th
}
@Test
- void fromJson_identityPoolCredentialsWithUniverseDomain() throws IOException {
+ void fromJson_identityPoolCredentialsWithUniverseDomain() {
GenericJson identityPoolCredentialJson = buildJsonIdentityPoolCredential();
identityPoolCredentialJson.set("universe_domain", "universeDomain");
@@ -253,7 +249,7 @@ void fromJson_identityPoolCredentialsWithUniverseDomain() throws IOException {
ExternalAccountCredentials.fromJson(
identityPoolCredentialJson, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- assertTrue(credential instanceof IdentityPoolCredentials);
+ assertInstanceOf(IdentityPoolCredentials.class, credential);
assertNotNull(credential.getCredentialSource());
assertEquals(
"//iam.googleapis.com/projects/123/locations/global/workloadIdentityPools/pool/providers/provider",
@@ -265,12 +261,12 @@ void fromJson_identityPoolCredentialsWithUniverseDomain() throws IOException {
}
@Test
- void fromJson_awsCredentials() throws IOException {
+ void fromJson_awsCredentials() {
ExternalAccountCredentials credential =
ExternalAccountCredentials.fromJson(
buildJsonAwsCredential(), OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- assertTrue(credential instanceof AwsCredentials);
+ assertInstanceOf(AwsCredentials.class, credential);
assertEquals("audience", credential.getAudience());
assertEquals("subjectTokenType", credential.getSubjectTokenType());
assertEquals(STS_URL, credential.getTokenUrl());
@@ -280,15 +276,15 @@ void fromJson_awsCredentials() throws IOException {
}
@Test
- void fromJson_awsCredentialsWithServiceAccountImpersonationOptions() throws IOException {
+ void fromJson_awsCredentialsWithServiceAccountImpersonationOptions() {
GenericJson awsCredentialJson = buildJsonAwsCredential();
awsCredentialJson.set(
- "service_account_impersonation", buildServiceAccountImpersonationOptions(2800));
+ "service_account_impersonation", buildServiceAccountImpersonationOptions());
ExternalAccountCredentials credential =
ExternalAccountCredentials.fromJson(awsCredentialJson, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- assertTrue(credential instanceof AwsCredentials);
+ assertInstanceOf(AwsCredentials.class, credential);
assertEquals("audience", credential.getAudience());
assertEquals("subjectTokenType", credential.getSubjectTokenType());
assertEquals(STS_URL, credential.getTokenUrl());
@@ -299,14 +295,14 @@ void fromJson_awsCredentialsWithServiceAccountImpersonationOptions() throws IOEx
}
@Test
- void fromJson_awsCredentialsWithUniverseDomain() throws IOException {
+ void fromJson_awsCredentialsWithUniverseDomain() {
GenericJson awsCredentialJson = buildJsonAwsCredential();
awsCredentialJson.set("universe_domain", "universeDomain");
ExternalAccountCredentials credential =
ExternalAccountCredentials.fromJson(awsCredentialJson, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- assertTrue(credential instanceof AwsCredentials);
+ assertInstanceOf(AwsCredentials.class, credential);
assertEquals("audience", credential.getAudience());
assertEquals("subjectTokenType", credential.getSubjectTokenType());
assertEquals(STS_URL, credential.getTokenUrl());
@@ -316,12 +312,12 @@ void fromJson_awsCredentialsWithUniverseDomain() throws IOException {
}
@Test
- void fromJson_pluggableAuthCredentials() throws IOException {
+ void fromJson_pluggableAuthCredentials() {
ExternalAccountCredentials credential =
ExternalAccountCredentials.fromJson(
buildJsonPluggableAuthCredential(), OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- assertTrue(credential instanceof PluggableAuthCredentials);
+ assertInstanceOf(PluggableAuthCredentials.class, credential);
assertEquals("audience", credential.getAudience());
assertEquals("subjectTokenType", credential.getSubjectTokenType());
assertEquals(STS_URL, credential.getTokenUrl());
@@ -337,12 +333,12 @@ void fromJson_pluggableAuthCredentials() throws IOException {
}
@Test
- void fromJson_pluggableAuthCredentialsWorkforce() throws IOException {
+ void fromJson_pluggableAuthCredentialsWorkforce() {
ExternalAccountCredentials credential =
ExternalAccountCredentials.fromJson(
buildJsonPluggableAuthWorkforceCredential(), OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- assertTrue(credential instanceof PluggableAuthCredentials);
+ assertInstanceOf(PluggableAuthCredentials.class, credential);
assertEquals(
"//iam.googleapis.com/locations/global/workforcePools/pool/providers/provider",
credential.getAudience());
@@ -363,7 +359,7 @@ void fromJson_pluggableAuthCredentialsWorkforce() throws IOException {
@Test
@SuppressWarnings("unchecked")
- void fromJson_pluggableAuthCredentials_allExecutableOptionsSet() throws IOException {
+ void fromJson_pluggableAuthCredentials_allExecutableOptionsSet() {
GenericJson json = buildJsonPluggableAuthCredential();
Map credentialSourceMap = (Map) json.get("credential_source");
// Add optional params to the executable config (timeout, output file path).
@@ -375,7 +371,7 @@ void fromJson_pluggableAuthCredentials_allExecutableOptionsSet() throws IOExcept
ExternalAccountCredentials credential =
ExternalAccountCredentials.fromJson(json, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- assertTrue(credential instanceof PluggableAuthCredentials);
+ assertInstanceOf(PluggableAuthCredentials.class, credential);
assertEquals("audience", credential.getAudience());
assertEquals("subjectTokenType", credential.getSubjectTokenType());
assertEquals(STS_URL, credential.getTokenUrl());
@@ -391,17 +387,16 @@ void fromJson_pluggableAuthCredentials_allExecutableOptionsSet() throws IOExcept
}
@Test
- void fromJson_pluggableAuthCredentialsWithServiceAccountImpersonationOptions()
- throws IOException {
+ void fromJson_pluggableAuthCredentialsWithServiceAccountImpersonationOptions() {
GenericJson pluggableAuthCredentialJson = buildJsonPluggableAuthCredential();
pluggableAuthCredentialJson.set(
- "service_account_impersonation", buildServiceAccountImpersonationOptions(2800));
+ "service_account_impersonation", buildServiceAccountImpersonationOptions());
ExternalAccountCredentials credential =
ExternalAccountCredentials.fromJson(
pluggableAuthCredentialJson, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- assertTrue(credential instanceof PluggableAuthCredentials);
+ assertInstanceOf(PluggableAuthCredentials.class, credential);
assertEquals("audience", credential.getAudience());
assertEquals("subjectTokenType", credential.getSubjectTokenType());
assertEquals(STS_URL, credential.getTokenUrl());
@@ -419,7 +414,7 @@ void fromJson_pluggableAuthCredentialsWithServiceAccountImpersonationOptions()
@Test
@SuppressWarnings("unchecked")
- void fromJson_pluggableAuthCredentials_withUniverseDomain() throws IOException {
+ void fromJson_pluggableAuthCredentials_withUniverseDomain() {
GenericJson json = buildJsonPluggableAuthCredential();
json.set("universe_domain", "universeDomain");
@@ -433,7 +428,7 @@ void fromJson_pluggableAuthCredentials_withUniverseDomain() throws IOException {
ExternalAccountCredentials credential =
ExternalAccountCredentials.fromJson(json, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- assertTrue(credential instanceof PluggableAuthCredentials);
+ assertInstanceOf(PluggableAuthCredentials.class, credential);
assertEquals("audience", credential.getAudience());
assertEquals("subjectTokenType", credential.getSubjectTokenType());
assertEquals(STS_URL, credential.getTokenUrl());
@@ -449,7 +444,7 @@ void fromJson_pluggableAuthCredentials_withUniverseDomain() throws IOException {
}
@Test
- void fromJson_pluggableAuthCredentialsWithUniverseDomain() throws IOException {
+ void fromJson_pluggableAuthCredentialsWithUniverseDomain() {
GenericJson pluggableAuthCredentialJson = buildJsonPluggableAuthCredential();
pluggableAuthCredentialJson.set("universe_domain", "universeDomain");
@@ -457,7 +452,7 @@ void fromJson_pluggableAuthCredentialsWithUniverseDomain() throws IOException {
ExternalAccountCredentials.fromJson(
pluggableAuthCredentialJson, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- assertTrue(credential instanceof PluggableAuthCredentials);
+ assertInstanceOf(PluggableAuthCredentials.class, credential);
assertEquals("audience", credential.getAudience());
assertEquals("subjectTokenType", credential.getSubjectTokenType());
assertEquals(STS_URL, credential.getTokenUrl());
@@ -473,31 +468,26 @@ void fromJson_pluggableAuthCredentialsWithUniverseDomain() throws IOException {
}
@Test
- void fromJson_nullJson_throws() throws IOException {
- try {
- ExternalAccountCredentials.fromJson(/* json= */ null, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- fail("Exception should be thrown.");
- } catch (NullPointerException e) {
- // Expected.
- }
+ void fromJson_nullJson_throws() {
+ assertThrows(
+ NullPointerException.class,
+ () ->
+ ExternalAccountCredentials.fromJson(
+ /* json= */ null, OAuth2Utils.HTTP_TRANSPORT_FACTORY));
}
@Test
- void fromJson_nullTransport_throws() throws IOException {
- try {
- ExternalAccountCredentials.fromJson(
- new HashMap(), /* transportFactory= */ null);
- fail("Exception should be thrown.");
- } catch (NullPointerException e) {
- // Expected.
- }
+ void fromJson_nullTransport_throws() {
+ HashMap json = new HashMap<>();
+ assertThrows(NullPointerException.class, () -> ExternalAccountCredentials.fromJson(json, null));
}
@Test
- void fromJson_invalidWorkforceAudiences_throws() throws IOException {
+ void fromJson_invalidWorkforceAudiences_throws() {
List invalidAudiences =
Arrays.asList(
- "//iam.googleapis.com/locations/global/workloadIdentityPools/pool/providers/provider",
+ "",
+ "//iam.googleapis.com/projects/x23/locations/global/workloadIdentityPools/pool/providers/provider",
"//iam.googleapis.com/locations/global/workforcepools/pool/providers/provider",
"//iam.googleapis.com/locations/global/workforcePools/providers/provider",
"//iam.googleapis.com/locations/global/workforcePools/providers",
@@ -507,23 +497,25 @@ void fromJson_invalidWorkforceAudiences_throws() throws IOException {
"//iam.googleapis.com/locations/global/workforce/providers");
for (String audience : invalidAudiences) {
- try {
- GenericJson json = buildJsonIdentityPoolCredential();
- json.put("audience", audience);
- json.put("workforce_pool_user_project", "userProject");
-
- ExternalAccountCredentials.fromJson(json, OAuth2Utils.HTTP_TRANSPORT_FACTORY);
- fail("Exception should be thrown.");
- } catch (IllegalArgumentException e) {
- assertEquals(
- "The workforce_pool_user_project parameter should only be provided for a Workforce Pool configuration.",
- e.getMessage());
- }
+ GenericJson json = buildJsonIdentityPoolCredential();
+ json.put("audience", audience);
+ json.put("workforce_pool_user_project", "userProject");
+
+ IllegalArgumentException e =
+ assertThrows(
+ IllegalArgumentException.class,
+ (org.junit.jupiter.api.function.Executable)
+ () ->
+ ExternalAccountCredentials.fromJson(
+ json, OAuth2Utils.HTTP_TRANSPORT_FACTORY));
+ assertEquals(
+ "The workforce_pool_user_project parameter should only be provided for a Workforce Pool configuration.",
+ e.getMessage());
}
}
@Test
- void constructor_builder() throws IOException {
+ void constructor_builder() {
HashMap credentialSource = new HashMap<>();
credentialSource.put("file", "file");
@@ -617,37 +609,37 @@ void constructor_builder_subjectTokenTypeEnum() {
@Test
void constructor_builder_invalidTokenUrl() {
- try {
- ExternalAccountCredentials.Builder builder =
- TestExternalAccountCredentials.newBuilder()
- .setHttpTransportFactory(transportFactory)
- .setAudience("audience")
- .setSubjectTokenType("subjectTokenType")
- .setTokenUrl("tokenUrl")
- .setCredentialSource(new TestCredentialSource(FILE_CREDENTIAL_SOURCE_MAP));
- new TestExternalAccountCredentials(builder);
- fail("Should not be able to continue without exception.");
- } catch (IllegalArgumentException exception) {
- assertEquals("The provided token URL is invalid.", exception.getMessage());
- }
+ ExternalAccountCredentials.Builder builder =
+ TestExternalAccountCredentials.newBuilder()
+ .setHttpTransportFactory(transportFactory)
+ .setAudience("audience")
+ .setSubjectTokenType("subjectTokenType")
+ .setTokenUrl("tokenUrl")
+ .setCredentialSource(new TestCredentialSource(FILE_CREDENTIAL_SOURCE_MAP));
+ IllegalArgumentException exception =
+ assertThrows(
+ IllegalArgumentException.class,
+ (org.junit.jupiter.api.function.Executable)
+ () -> new TestExternalAccountCredentials(builder));
+ assertEquals("The provided token URL is invalid.", exception.getMessage());
}
@Test
void constructor_builder_invalidServiceAccountImpersonationUrl() {
- try {
- ExternalAccountCredentials.Builder builder =
- TestExternalAccountCredentials.newBuilder()
- .setHttpTransportFactory(transportFactory)
- .setAudience("audience")
- .setSubjectTokenType("subjectTokenType")
- .setTokenUrl("tokenUrl")
- .setCredentialSource(new TestCredentialSource(FILE_CREDENTIAL_SOURCE_MAP))
- .setServiceAccountImpersonationUrl("serviceAccountImpersonationUrl");
- new TestExternalAccountCredentials(builder);
- fail("Should not be able to continue without exception.");
- } catch (IllegalArgumentException exception) {
- assertEquals("The provided token URL is invalid.", exception.getMessage());
- }
+ ExternalAccountCredentials.Builder builder =
+ TestExternalAccountCredentials.newBuilder()
+ .setHttpTransportFactory(transportFactory)
+ .setAudience("audience")
+ .setSubjectTokenType("subjectTokenType")
+ .setTokenUrl("tokenUrl")
+ .setCredentialSource(new TestCredentialSource(FILE_CREDENTIAL_SOURCE_MAP))
+ .setServiceAccountImpersonationUrl("serviceAccountImpersonationUrl");
+ IllegalArgumentException exception =
+ assertThrows(
+ IllegalArgumentException.class,
+ (org.junit.jupiter.api.function.Executable)
+ () -> new TestExternalAccountCredentials(builder));
+ assertEquals("The provided token URL is invalid.", exception.getMessage());
}
@Test
@@ -667,21 +659,22 @@ void constructor_builderWithInvalidWorkforceAudiences_throws() {
HashMap credentialSource = new HashMap<>();
credentialSource.put("file", "file");
for (String audience : invalidAudiences) {
- try {
- TestExternalAccountCredentials.newBuilder()
- .setWorkforcePoolUserProject("workforcePoolUserProject")
- .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
- .setAudience(audience)
- .setSubjectTokenType("subjectTokenType")
- .setTokenUrl(STS_URL)
- .setCredentialSource(new TestCredentialSource(credentialSource))
- .build();
- fail("Should not be able to continue without exception.");
- } catch (IllegalArgumentException exception) {
- assertEquals(
- "The workforce_pool_user_project parameter should only be provided for a Workforce Pool configuration.",
- exception.getMessage());
- }
+ IllegalArgumentException exception =
+ assertThrows(
+ IllegalArgumentException.class,
+ (org.junit.jupiter.api.function.Executable)
+ () ->
+ TestExternalAccountCredentials.newBuilder()
+ .setWorkforcePoolUserProject("workforcePoolUserProject")
+ .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
+ .setAudience(audience)
+ .setSubjectTokenType("subjectTokenType")
+ .setTokenUrl(STS_URL)
+ .setCredentialSource(new TestCredentialSource(credentialSource))
+ .build());
+ assertEquals(
+ "The workforce_pool_user_project parameter should only be provided for a Workforce Pool configuration.",
+ exception.getMessage());
}
}
@@ -690,14 +683,16 @@ void constructor_builderWithEmptyWorkforceUserProjectAndWorkforceAudience() {
HashMap credentialSource = new HashMap<>();
credentialSource.put("file", "file");
// No exception should be thrown.
- TestExternalAccountCredentials.newBuilder()
- .setWorkforcePoolUserProject("")
- .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
- .setAudience("//iam.googleapis.com/locations/global/workforcePools/pool/providers/provider")
- .setSubjectTokenType("subjectTokenType")
- .setTokenUrl(STS_URL)
- .setCredentialSource(new TestCredentialSource(credentialSource))
- .build();
+ ExternalAccountCredentials.Builder builder =
+ TestExternalAccountCredentials.newBuilder()
+ .setWorkforcePoolUserProject("")
+ .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
+ .setAudience(
+ "//iam.googleapis.com/locations/global/workforcePools/pool/providers/provider")
+ .setSubjectTokenType("subjectTokenType")
+ .setTokenUrl(STS_URL)
+ .setCredentialSource(new TestCredentialSource(credentialSource));
+ assertDoesNotThrow(builder::build);
}
@Test
@@ -705,31 +700,32 @@ void constructor_builder_invalidTokenLifetime_throws() {
Map invalidOptionsMap = new HashMap();
invalidOptionsMap.put("token_lifetime_seconds", "thisIsAString");
- try {
- IdentityPoolCredentials.newBuilder()
- .setHttpTransportFactory(transportFactory)
- .setAudience(
- "//iam.googleapis.com/locations/global/workforcePools/pool/providers/provider")
- .setSubjectTokenType("subjectTokenType")
- .setTokenUrl(STS_URL)
- .setTokenInfoUrl("https://tokeninfo.com")
- .setServiceAccountImpersonationUrl(SERVICE_ACCOUNT_IMPERSONATION_URL)
- .setCredentialSource(new TestCredentialSource(FILE_CREDENTIAL_SOURCE_MAP))
- .setScopes(Arrays.asList("scope1", "scope2"))
- .setQuotaProjectId("projectId")
- .setClientId("clientId")
- .setClientSecret("clientSecret")
- .setWorkforcePoolUserProject("workforcePoolUserProject")
- .setUniverseDomain("universeDomain")
- .setServiceAccountImpersonationOptions(invalidOptionsMap)
- .build();
- fail("Should not be able to continue without exception.");
- } catch (IllegalArgumentException exception) {
- assertEquals(
- "Value of \"token_lifetime_seconds\" field could not be parsed into an integer.",
- exception.getMessage());
- assertEquals(NumberFormatException.class, exception.getCause().getClass());
- }
+ IllegalArgumentException exception =
+ assertThrows(
+ IllegalArgumentException.class,
+ (org.junit.jupiter.api.function.Executable)
+ () ->
+ IdentityPoolCredentials.newBuilder()
+ .setHttpTransportFactory(transportFactory)
+ .setAudience(
+ "//iam.googleapis.com/locations/global/workforcePools/pool/providers/provider")
+ .setSubjectTokenType("subjectTokenType")
+ .setTokenUrl(STS_URL)
+ .setTokenInfoUrl("https://tokeninfo.com")
+ .setServiceAccountImpersonationUrl(SERVICE_ACCOUNT_IMPERSONATION_URL)
+ .setCredentialSource(new TestCredentialSource(FILE_CREDENTIAL_SOURCE_MAP))
+ .setScopes(Arrays.asList("scope1", "scope2"))
+ .setQuotaProjectId("projectId")
+ .setClientId("clientId")
+ .setClientSecret("clientSecret")
+ .setWorkforcePoolUserProject("workforcePoolUserProject")
+ .setUniverseDomain("universeDomain")
+ .setServiceAccountImpersonationOptions(invalidOptionsMap)
+ .build());
+ assertEquals(
+ "Value of \"token_lifetime_seconds\" field could not be parsed into an integer.",
+ exception.getMessage());
+ assertEquals(NumberFormatException.class, exception.getCause().getClass());
}
@Test
@@ -789,7 +785,7 @@ void constructor_builder_bigDecimalTokenLifetime() {
@Test
void constructor_builder_integerTokenLifetime() {
Map optionsMap = new HashMap();
- optionsMap.put("token_lifetime_seconds", Integer.valueOf(2800));
+ optionsMap.put("token_lifetime_seconds", 2800);
ExternalAccountCredentials credentials =
IdentityPoolCredentials.newBuilder()
@@ -818,59 +814,61 @@ void constructor_builder_lowTokenLifetime_throws() {
Map optionsMap = new HashMap();
optionsMap.put("token_lifetime_seconds", 599);
- try {
- IdentityPoolCredentials.newBuilder()
- .setHttpTransportFactory(transportFactory)
- .setAudience(
- "//iam.googleapis.com/locations/global/workforcePools/pool/providers/provider")
- .setSubjectTokenType("subjectTokenType")
- .setTokenUrl(STS_URL)
- .setTokenInfoUrl("https://tokeninfo.com")
- .setServiceAccountImpersonationUrl(SERVICE_ACCOUNT_IMPERSONATION_URL)
- .setCredentialSource(new TestCredentialSource(FILE_CREDENTIAL_SOURCE_MAP))
- .setScopes(Arrays.asList("scope1", "scope2"))
- .setQuotaProjectId("projectId")
- .setClientId("clientId")
- .setClientSecret("clientSecret")
- .setWorkforcePoolUserProject("workforcePoolUserProject")
- .setUniverseDomain("universeDomain")
- .setServiceAccountImpersonationOptions(optionsMap)
- .build();
- } catch (IllegalArgumentException e) {
- assertEquals(
- "The \"token_lifetime_seconds\" field must be between 600 and 43200 seconds.",
- e.getMessage());
- }
+ IllegalArgumentException e =
+ assertThrows(
+ IllegalArgumentException.class,
+ (org.junit.jupiter.api.function.Executable)
+ () ->
+ IdentityPoolCredentials.newBuilder()
+ .setHttpTransportFactory(transportFactory)
+ .setAudience(
+ "//iam.googleapis.com/locations/global/workforcePools/pool/providers/provider")
+ .setSubjectTokenType("subjectTokenType")
+ .setTokenUrl(STS_URL)
+ .setTokenInfoUrl("https://tokeninfo.com")
+ .setServiceAccountImpersonationUrl(SERVICE_ACCOUNT_IMPERSONATION_URL)
+ .setCredentialSource(new TestCredentialSource(FILE_CREDENTIAL_SOURCE_MAP))
+ .setScopes(Arrays.asList("scope1", "scope2"))
+ .setQuotaProjectId("projectId")
+ .setClientId("clientId")
+ .setClientSecret("clientSecret")
+ .setWorkforcePoolUserProject("workforcePoolUserProject")
+ .setUniverseDomain("universeDomain")
+ .setServiceAccountImpersonationOptions(optionsMap)
+ .build());
+ assertEquals(
+ "The \"token_lifetime_seconds\" field must be between 600 and 43200 seconds.",
+ e.getMessage());
}
@Test
void constructor_builder_highTokenLifetime_throws() {
- Map optionsMap = new HashMap();
+ Map optionsMap = new HashMap<>();
optionsMap.put("token_lifetime_seconds", 43201);
- try {
- IdentityPoolCredentials.newBuilder()
- .setHttpTransportFactory(transportFactory)
- .setAudience(
- "//iam.googleapis.com/locations/global/workforcePools/pool/providers/provider")
- .setSubjectTokenType("subjectTokenType")
- .setTokenUrl(STS_URL)
- .setTokenInfoUrl("https://tokeninfo.com")
- .setServiceAccountImpersonationUrl(SERVICE_ACCOUNT_IMPERSONATION_URL)
- .setCredentialSource(new TestCredentialSource(FILE_CREDENTIAL_SOURCE_MAP))
- .setScopes(Arrays.asList("scope1", "scope2"))
- .setQuotaProjectId("projectId")
- .setClientId("clientId")
- .setClientSecret("clientSecret")
- .setWorkforcePoolUserProject("workforcePoolUserProject")
- .setUniverseDomain("universeDomain")
- .setServiceAccountImpersonationOptions(optionsMap)
- .build();
- } catch (IllegalArgumentException e) {
- assertEquals(
- "The \"token_lifetime_seconds\" field must be between 600 and 43200 seconds.",
- e.getMessage());
- }
+ IdentityPoolCredentials.Builder builder =
+ IdentityPoolCredentials.newBuilder()
+ .setHttpTransportFactory(transportFactory)
+ .setAudience(
+ "//iam.googleapis.com/locations/global/workforcePools/pool/providers/provider")
+ .setSubjectTokenType("subjectTokenType")
+ .setTokenUrl(STS_URL)
+ .setTokenInfoUrl("https://tokeninfo.com")
+ .setServiceAccountImpersonationUrl(SERVICE_ACCOUNT_IMPERSONATION_URL)
+ .setCredentialSource(new TestCredentialSource(FILE_CREDENTIAL_SOURCE_MAP))
+ .setScopes(Arrays.asList("scope1", "scope2"))
+ .setQuotaProjectId("projectId")
+ .setClientId("clientId")
+ .setClientSecret("clientSecret")
+ .setWorkforcePoolUserProject("workforcePoolUserProject")
+ .setUniverseDomain("universeDomain");
+ IllegalArgumentException e =
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> builder.setServiceAccountImpersonationOptions(optionsMap));
+ assertEquals(
+ "The \"token_lifetime_seconds\" field must be between 600 and 43200 seconds.",
+ e.getMessage());
}
@Test
@@ -1006,17 +1004,18 @@ void exchangeExternalCredentialForAccessToken_withServiceAccountImpersonation()
transportFactory.transport.getServiceAccountAccessToken(), returnedToken.getTokenValue());
// Validate that default lifetime was set correctly on the request.
- GenericJson query =
- OAuth2Utils.JSON_FACTORY
- .createJsonParser(transportFactory.transport.getLastRequest().getContentAsString())
- .parseAndClose(GenericJson.class);
+ try (JsonParser jsonParser =
+ OAuth2Utils.JSON_FACTORY.createJsonParser(
+ transportFactory.transport.getLastRequest().getContentAsString())) {
+ GenericJson query = jsonParser.parseAndClose(GenericJson.class);
- assertEquals("3600s", query.get("lifetime"));
+ assertEquals("3600s", query.get("lifetime"));
- // Validate metrics header is set correctly on the sts request.
- Map> headers =
- transportFactory.transport.getRequests().get(1).getHeaders();
- validateMetricsHeader(headers, "url", true, false);
+ // Validate metrics header is set correctly on the sts request.
+ Map> headers =
+ transportFactory.transport.getRequests().get(1).getHeaders();
+ validateMetricsHeader(headers, "url", true, false);
+ }
}
@Test
@@ -1030,7 +1029,7 @@ void exchangeExternalCredentialForAccessToken_withServiceAccountImpersonationOpt
transportFactory.transport.getStsUrl(),
transportFactory.transport.getMetadataUrl(),
transportFactory.transport.getServiceAccountImpersonationUrl(),
- buildServiceAccountImpersonationOptions(2800)),
+ buildServiceAccountImpersonationOptions()),
transportFactory);
StsTokenExchangeRequest stsTokenExchangeRequest =
@@ -1043,16 +1042,16 @@ void exchangeExternalCredentialForAccessToken_withServiceAccountImpersonationOpt
transportFactory.transport.getServiceAccountAccessToken(), returnedToken.getTokenValue());
// Validate that lifetime was set correctly on the request.
- GenericJson query =
- OAuth2Utils.JSON_FACTORY
- .createJsonParser(transportFactory.transport.getLastRequest().getContentAsString())
- .parseAndClose(GenericJson.class);
-
- // Validate metrics header is set correctly on the sts request.
- Map> headers =
- transportFactory.transport.getRequests().get(1).getHeaders();
- validateMetricsHeader(headers, "url", true, true);
- assertEquals("2800s", query.get("lifetime"));
+ try (JsonParser jsonParser =
+ OAuth2Utils.JSON_FACTORY.createJsonParser(
+ transportFactory.transport.getLastRequest().getContentAsString())) {
+ GenericJson query = jsonParser.parseAndClose(GenericJson.class);
+ // Validate metrics header is set correctly on the sts request.
+ Map> headers =
+ transportFactory.transport.getRequests().get(1).getHeaders();
+ validateMetricsHeader(headers, "url", true, true);
+ assertEquals("2800s", query.get("lifetime"));
+ }
}
@Test
@@ -1069,19 +1068,18 @@ void exchangeExternalCredentialForAccessToken_throws() throws IOException {
StsTokenExchangeRequest stsTokenExchangeRequest =
StsTokenExchangeRequest.newBuilder("credential", "subjectTokenType").build();
- try {
- credential.exchangeExternalCredentialForAccessToken(stsTokenExchangeRequest);
- fail("Exception should be thrown.");
- } catch (OAuthException e) {
- assertEquals(errorCode, e.getErrorCode());
- assertEquals(errorDescription, e.getErrorDescription());
- assertEquals(errorUri, e.getErrorUri());
- }
+ OAuthException e =
+ assertThrows(
+ OAuthException.class,
+ (org.junit.jupiter.api.function.Executable)
+ () -> credential.exchangeExternalCredentialForAccessToken(stsTokenExchangeRequest));
+ assertEquals(errorCode, e.getErrorCode());
+ assertEquals(errorDescription, e.getErrorDescription());
+ assertEquals(errorUri, e.getErrorUri());
}
@Test
- void exchangeExternalCredentialForAccessToken_invalidImpersonatedCredentialsThrows()
- throws IOException {
+ void exchangeExternalCredentialForAccessToken_invalidImpersonatedCredentialsThrows() {
GenericJson json = buildJsonIdentityPoolCredential();
json.put("service_account_impersonation_url", "https://iamcredentials.googleapis.com");
ExternalAccountCredentials credential =
@@ -1090,14 +1088,13 @@ void exchangeExternalCredentialForAccessToken_invalidImpersonatedCredentialsThro
StsTokenExchangeRequest stsTokenExchangeRequest =
StsTokenExchangeRequest.newBuilder("credential", "subjectTokenType").build();
- try {
- credential.exchangeExternalCredentialForAccessToken(stsTokenExchangeRequest);
- fail("Exception should be thrown.");
- } catch (IllegalArgumentException e) {
- assertEquals(
- "Unable to determine target principal from service account impersonation URL.",
- e.getMessage());
- }
+ IllegalArgumentException e =
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> credential.exchangeExternalCredentialForAccessToken(stsTokenExchangeRequest));
+ assertEquals(
+ "Unable to determine target principal from service account impersonation URL.",
+ e.getMessage());
}
@Test
@@ -1147,7 +1144,7 @@ void serialize() throws IOException, ClassNotFoundException {
assertEquals(
testCredentials.getServiceAccountImpersonationOptions().getLifetime(),
deserializedCredentials.getServiceAccountImpersonationOptions().getLifetime());
- assertSame(deserializedCredentials.clock, Clock.SYSTEM);
+ assertSame(Clock.SYSTEM, deserializedCredentials.clock);
assertEquals(
MockExternalAccountCredentialsTransportFactory.class,
deserializedCredentials.toBuilder().getHttpTransportFactory().getClass());
@@ -1189,12 +1186,11 @@ void validateTokenUrl_invalidUrls() {
"https://us- -1.sts.googleapis.com");
for (String url : invalidUrls) {
- try {
- ExternalAccountCredentials.validateTokenUrl(url);
- fail("Should have failed since an invalid URL was passed.");
- } catch (IllegalArgumentException e) {
- assertEquals("The provided token URL is invalid.", e.getMessage());
- }
+ IllegalArgumentException e =
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> ExternalAccountCredentials.validateTokenUrl(url));
+ assertEquals("The provided token URL is invalid.", e.getMessage());
}
}
@@ -1235,12 +1231,12 @@ void validateServiceAccountImpersonationUrls_invalidUrls() {
"https://us- -1.iamcredentials.googleapis.com");
for (String url : invalidUrls) {
- try {
- ExternalAccountCredentials.validateServiceAccountImpersonationInfoUrl(url);
- fail("Should have failed since an invalid URL was passed.");
- } catch (IllegalArgumentException e) {
- assertEquals("The provided service account impersonation URL is invalid.", e.getMessage());
- }
+ IllegalArgumentException e =
+ assertThrows(
+ IllegalArgumentException.class,
+ (org.junit.jupiter.api.function.Executable)
+ () -> ExternalAccountCredentials.validateServiceAccountImpersonationInfoUrl(url));
+ assertEquals("The provided service account impersonation URL is invalid.", e.getMessage());
}
}
@@ -1318,10 +1314,9 @@ private GenericJson buildJsonPluggableAuthWorkforceCredential() {
return json;
}
- static Map buildServiceAccountImpersonationOptions(Integer lifetime) {
+ static Map buildServiceAccountImpersonationOptions() {
Map map = new HashMap();
- map.put("token_lifetime_seconds", lifetime);
-
+ map.put("token_lifetime_seconds", 2800);
return map;
}
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/GdchCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/GdchCredentialsTest.java
index b555149167f1..ace74dd67e63 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/GdchCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/GdchCredentialsTest.java
@@ -32,18 +32,21 @@
package com.google.auth.oauth2;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import com.google.api.client.json.GenericJson;
+import com.google.api.client.json.Json;
import com.google.api.client.json.JsonFactory;
+import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.json.webtoken.JsonWebSignature;
import com.google.api.client.json.webtoken.JsonWebToken;
import com.google.api.client.testing.http.FixedClock;
+import com.google.api.client.testing.http.MockLowLevelHttpResponse;
import com.google.api.client.util.Clock;
import com.google.auth.TestUtils;
import com.google.auth.oauth2.GoogleCredentials.GoogleCredentialsInfo;
@@ -52,27 +55,35 @@
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Files;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.security.spec.ECGenParameterSpec;
+import java.util.Base64;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
/** Test case for {@link GdchCredentials}. */
class GdchCredentialsTest extends BaseSerializationTest {
- private static final String FORMAT_VERSION = GdchCredentials.SUPPORTED_FORMAT_VERSION;
+ private static final String FORMAT_VERSION = GdchCredentials.SUPPORTED_JSON_FORMAT_VERSION;
private static final String PRIVATE_KEY_ID = "d84a4fefcf50791d4a90f2d7af17469d6282df9d";
static final String PRIVATE_KEY_PKCS8 =
"-----BEGIN PRIVATE KEY-----\n"
- + "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALX0PQoe1igW12i"
- + "kv1bN/r9lN749y2ijmbc/mFHPyS3hNTyOCjDvBbXYbDhQJzWVUikh4mvGBA07qTj79Xc3yBDfKP2IeyYQIFe0t0"
- + "zkd7R9Zdn98Y2rIQC47aAbDfubtkU1U72t4zL11kHvoa0/RuFZjncvlr42X7be7lYh4p3NAgMBAAECgYASk5wDw"
- + "4Az2ZkmeuN6Fk/y9H+Lcb2pskJIXjrL533vrDWGOC48LrsThMQPv8cxBky8HFSEklPpkfTF95tpD43iVwJRB/Gr"
- + "CtGTw65IfJ4/tI09h6zGc4yqvIo1cHX/LQ+SxKLGyir/dQM925rGt/VojxY5ryJR7GLbCzxPnJm/oQJBANwOCO6"
- + "D2hy1LQYJhXh7O+RLtA/tSnT1xyMQsGT+uUCMiKS2bSKx2wxo9k7h3OegNJIu1q6nZ6AbxDK8H3+d0dUCQQDTrP"
- + "SXagBxzp8PecbaCHjzNRSQE2in81qYnrAFNB4o3DpHyMMY6s5ALLeHKscEWnqP8Ur6X4PvzZecCWU9BKAZAkAut"
- + "LPknAuxSCsUOvUfS1i87ex77Ot+w6POp34pEX+UWb+u5iFn2cQacDTHLV1LtE80L8jVLSbrbrlH43H0DjU5AkEA"
- + "gidhycxS86dxpEljnOMCw8CKoUBd5I880IUahEiUltk7OLJYS/Ts1wbn3kPOVX3wyJs8WBDtBkFrDHW2ezth2QJ"
- + "ADj3e1YhMVdjJW5jqwlD/VNddGjgzyunmiZg0uOXsHXbytYmsA545S8KRQFaJKFXYYFo2kOjqOiC1T2cAzMDjCQ"
- + "==\n-----END PRIVATE KEY-----\n";
+ + "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgyITXsUvRm1C3lnyz\n"
+ + "OaMY7TNXZois4NH0bkMwqTAnVbqhRANCAASk5+U9skHVTo+sEVd2/yKY7A2eYn8K\n"
+ + "Cygd3bQalfWs533aTu93XwVx0YNN310aFquv3/VIiFofm1JEBAhUiG8e\n"
+ + "-----END PRIVATE KEY-----";
+
+ // Generated using OpenSSL:
+ // openssl ecparam -name prime256v1 -genkey -noout -out ec-sec1.pem
+ static final String PRIVATE_KEY_SEC1 =
+ "-----BEGIN EC PRIVATE KEY-----\n"
+ + "MHcCAQEEIK+G0KyJyJPDK/tyYsF0RyFW+X1GMsWbrlWn8TbLAI0doAoGCCqGSM49\n"
+ + "AwEHoUQDQgAEmGMJNcYyb9IfS4ngfvSf+c0sxOdcRfPNnZajry4bLgs++2VpQn8e\n"
+ + "l27zuFvF8jrM2/XyG5y9heE8YSjfLMy0Rw==\n"
+ + "-----END EC PRIVATE KEY-----";
private static final String PROJECT_ID = "project-id";
private static final String SERVICE_IDENTITY_NAME = "service-identity-name";
private static final String ACCESS_TOKEN = "1/MkSJoj1xsli0AccessToken_NKPY2";
@@ -81,7 +92,7 @@ class GdchCredentialsTest extends BaseSerializationTest {
private static final String CA_CERT_FILE_NAME = "cert.pem";
private static final String CA_CERT_PATH =
GdchCredentialsTest.class.getClassLoader().getResource(CA_CERT_FILE_NAME).getPath();
- private static final URI API_AUDIENCE = URI.create("https://gdch-api-audience");
+ private static final String API_AUDIENCE = "https://gdch-api-audience";
private static final URI CALL_URI = URI.create("http://googleapis.com/testapi/v1/foo");
@Test
@@ -100,6 +111,23 @@ void fromJSON_getProjectId() throws IOException {
assertEquals(PROJECT_ID, credentials.getProjectId());
}
+ @Test
+ void fromJSON_sec1Key() throws IOException {
+ GenericJson json =
+ writeGdchServiceAccountJson(
+ FORMAT_VERSION,
+ PROJECT_ID,
+ PRIVATE_KEY_ID,
+ PRIVATE_KEY_SEC1,
+ SERVICE_IDENTITY_NAME,
+ CA_CERT_PATH,
+ TOKEN_SERVER_URI);
+ GdchCredentials credentials = GdchCredentials.fromJson(json);
+
+ assertNotNull(credentials);
+ assertEquals(PROJECT_ID, credentials.getProjectId());
+ }
+
@Test
void fromJSON_getServiceIdentityName() throws IOException {
GenericJson json =
@@ -149,7 +177,7 @@ void fromJSON_getTokenServerUri() throws IOException {
}
@Test
- void fromJSON_nullFormatVersion() throws IOException {
+ void fromJSON_nullFormatVersion() {
GenericJson json =
writeGdchServiceAccountJson(
null,
@@ -160,22 +188,18 @@ void fromJSON_nullFormatVersion() throws IOException {
CA_CERT_PATH,
TOKEN_SERVER_URI);
- try {
- GdchCredentials credentials = GdchCredentials.fromJson(json);
- fail("Should not be able to create GDCH credential without exception.");
- } catch (IOException ex) {
- assertTrue(
- ex.getMessage()
- .contains(
- String.format(
- "Error reading GDCH service account credential from JSON, "
- + "%s is misconfigured.",
- "format_version")));
- }
+ IOException ex = assertThrows(IOException.class, () -> GdchCredentials.fromJson(json));
+ assertTrue(
+ ex.getMessage()
+ .contains(
+ String.format(
+ "Error reading GDCH service account credential from JSON, "
+ + "%s is misconfigured.",
+ "format_version")));
}
@Test
- void fromJSON_nullProjectId() throws IOException {
+ void fromJSON_nullProjectId() {
GenericJson json =
writeGdchServiceAccountJson(
FORMAT_VERSION,
@@ -186,22 +210,18 @@ void fromJSON_nullProjectId() throws IOException {
CA_CERT_PATH,
TOKEN_SERVER_URI);
- try {
- GdchCredentials credentials = GdchCredentials.fromJson(json);
- fail("Should not be able to create GDCH credential without exception.");
- } catch (IOException ex) {
- assertTrue(
- ex.getMessage()
- .contains(
- String.format(
- "Error reading GDCH service account credential from JSON, "
- + "%s is misconfigured.",
- "project")));
- }
+ IOException ex = assertThrows(IOException.class, () -> GdchCredentials.fromJson(json));
+ assertTrue(
+ ex.getMessage()
+ .contains(
+ String.format(
+ "Error reading GDCH service account credential from JSON, "
+ + "%s is misconfigured.",
+ "project")));
}
@Test
- void fromJSON_nullPrivateKeyId() throws IOException {
+ void fromJSON_nullPrivateKeyId() {
GenericJson json =
writeGdchServiceAccountJson(
FORMAT_VERSION,
@@ -212,22 +232,18 @@ void fromJSON_nullPrivateKeyId() throws IOException {
CA_CERT_PATH,
TOKEN_SERVER_URI);
- try {
- GdchCredentials credentials = GdchCredentials.fromJson(json);
- fail("Should not be able to create GDCH credential without exception.");
- } catch (IOException ex) {
- assertTrue(
- ex.getMessage()
- .contains(
- String.format(
- "Error reading GDCH service account credential from JSON, "
- + "%s is misconfigured.",
- "private_key_id")));
- }
+ IOException ex = assertThrows(IOException.class, () -> GdchCredentials.fromJson(json));
+ assertTrue(
+ ex.getMessage()
+ .contains(
+ String.format(
+ "Error reading GDCH service account credential from JSON, "
+ + "%s is misconfigured.",
+ "private_key_id")));
}
@Test
- void fromJSON_nullPrivateKey() throws IOException {
+ void fromJSON_nullPrivateKey() {
GenericJson json =
writeGdchServiceAccountJson(
FORMAT_VERSION,
@@ -238,22 +254,18 @@ void fromJSON_nullPrivateKey() throws IOException {
CA_CERT_PATH,
TOKEN_SERVER_URI);
- try {
- GdchCredentials credentials = GdchCredentials.fromJson(json);
- fail("Should not be able to create GDCH credential without exception.");
- } catch (IOException ex) {
- assertTrue(
- ex.getMessage()
- .contains(
- String.format(
- "Error reading GDCH service account credential from JSON, "
- + "%s is misconfigured.",
- "private_key")));
- }
+ IOException ex = assertThrows(IOException.class, () -> GdchCredentials.fromJson(json));
+ assertTrue(
+ ex.getMessage()
+ .contains(
+ String.format(
+ "Error reading GDCH service account credential from JSON, "
+ + "%s is misconfigured.",
+ "private_key")));
}
@Test
- void fromJSON_nullServiceIdentityName() throws IOException {
+ void fromJSON_nullServiceIdentityName() {
GenericJson json =
writeGdchServiceAccountJson(
FORMAT_VERSION,
@@ -264,18 +276,14 @@ void fromJSON_nullServiceIdentityName() throws IOException {
CA_CERT_PATH,
TOKEN_SERVER_URI);
- try {
- GdchCredentials credentials = GdchCredentials.fromJson(json);
- fail("Should not be able to create GDCH credential without exception.");
- } catch (IOException ex) {
- assertTrue(
- ex.getMessage()
- .contains(
- String.format(
- "Error reading GDCH service account credential from JSON, "
- + "%s is misconfigured.",
- "name")));
- }
+ IOException ex = assertThrows(IOException.class, () -> GdchCredentials.fromJson(json));
+ assertTrue(
+ ex.getMessage()
+ .contains(
+ String.format(
+ "Error reading GDCH service account credential from JSON, "
+ + "%s is misconfigured.",
+ "name")));
}
@Test
@@ -294,7 +302,7 @@ void fromJSON_nullCaCertPath() throws IOException {
}
@Test
- void fromJSON_nullTokenServerUri() throws IOException {
+ void fromJSON_nullTokenServerUri() {
GenericJson json =
writeGdchServiceAccountJson(
FORMAT_VERSION,
@@ -305,22 +313,18 @@ void fromJSON_nullTokenServerUri() throws IOException {
CA_CERT_PATH,
null);
- try {
- GdchCredentials credentials = GdchCredentials.fromJson(json);
- fail("Should not be able to create GDCH credential without exception.");
- } catch (IOException ex) {
- assertTrue(
- ex.getMessage()
- .contains(
- String.format(
- "Error reading GDCH service account credential from JSON, "
- + "%s is misconfigured.",
- "token_uri")));
- }
+ IOException ex = assertThrows(IOException.class, () -> GdchCredentials.fromJson(json));
+ assertTrue(
+ ex.getMessage()
+ .contains(
+ String.format(
+ "Error reading GDCH service account credential from JSON, "
+ + "%s is misconfigured.",
+ "token_uri")));
}
@Test
- void fromJSON_invalidFormatVersion() throws IOException {
+ void fromJSON_invalidFormatVersion() {
GenericJson json =
writeGdchServiceAccountJson(
"100",
@@ -331,18 +335,14 @@ void fromJSON_invalidFormatVersion() throws IOException {
CA_CERT_PATH,
TOKEN_SERVER_URI);
- try {
- GdchCredentials credentials = GdchCredentials.fromJson(json);
- fail("Should not be able to create GDCH credential without exception.");
- } catch (IOException ex) {
- assertTrue(
- ex.getMessage()
- .contains(String.format("Only format version %s is supported", FORMAT_VERSION)));
- }
+ IOException ex = assertThrows(IOException.class, () -> GdchCredentials.fromJson(json));
+ assertTrue(
+ ex.getMessage()
+ .contains(String.format("Only format version %s is supported", FORMAT_VERSION)));
}
@Test
- void fromJSON_invalidCaCertPath() throws IOException {
+ void fromJSON_invalidCaCertPath() {
GenericJson json =
writeGdchServiceAccountJson(
FORMAT_VERSION,
@@ -353,12 +353,8 @@ void fromJSON_invalidCaCertPath() throws IOException {
"/path/to/missing/file",
TOKEN_SERVER_URI);
- try {
- GdchCredentials credentials = GdchCredentials.fromJson(json);
- fail("Should not be able to create GDCH credential without exception.");
- } catch (IOException ex) {
- assertTrue(ex.getMessage().contains("Error reading certificate file from CA cert path"));
- }
+ IOException ex = assertThrows(IOException.class, () -> GdchCredentials.fromJson(json));
+ assertTrue(ex.getMessage().contains("Error reading certificate file from CA cert path"));
}
@Test
@@ -414,6 +410,73 @@ void fromJSON_hasAccessToken() throws IOException {
TestUtils.assertContainsBearerToken(metadata, ACCESS_TOKEN);
}
+ @Test
+ void fromStream_correct() throws IOException {
+ InputStream stream =
+ writeGdchServiceAccountStream(
+ FORMAT_VERSION,
+ PROJECT_ID,
+ PRIVATE_KEY_ID,
+ PRIVATE_KEY_PKCS8,
+ SERVICE_IDENTITY_NAME,
+ CA_CERT_PATH,
+ TOKEN_SERVER_URI);
+ GdchCredentials credentials = GdchCredentials.fromStream(stream);
+
+ assertEquals(PROJECT_ID, credentials.getProjectId());
+ assertEquals(SERVICE_IDENTITY_NAME, credentials.getServiceIdentityName());
+ }
+
+ @Test
+ void fromStream_invalidType() throws IOException {
+ GenericJson json =
+ writeGdchServiceAccountJson(
+ FORMAT_VERSION,
+ PROJECT_ID,
+ PRIVATE_KEY_ID,
+ PRIVATE_KEY_PKCS8,
+ SERVICE_IDENTITY_NAME,
+ CA_CERT_PATH,
+ TOKEN_SERVER_URI);
+ json.put("type", "invalid_type");
+ InputStream stream = TestUtils.jsonToInputStream(json);
+
+ IOException ex = assertThrows(IOException.class, () -> GdchCredentials.fromStream(stream));
+ assertTrue(ex.getMessage().contains("not recognized"));
+ }
+
+ @Test
+ void fromStream_withTransportFactory() throws IOException {
+ MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
+ InputStream stream =
+ writeGdchServiceAccountStream(
+ FORMAT_VERSION,
+ PROJECT_ID,
+ PRIVATE_KEY_ID,
+ PRIVATE_KEY_PKCS8,
+ SERVICE_IDENTITY_NAME,
+ CA_CERT_PATH,
+ TOKEN_SERVER_URI);
+ GdchCredentials credentials = GdchCredentials.fromStream(stream, transportFactory);
+
+ assertEquals(transportFactory, credentials.getTransportFactory());
+ }
+
+ @Test
+ void fromPem_correct() throws IOException {
+ GdchCredentials.Builder builder =
+ GdchCredentials.newBuilder()
+ .setProjectId(PROJECT_ID)
+ .setPrivateKeyId(PRIVATE_KEY_ID)
+ .setServiceIdentityName(SERVICE_IDENTITY_NAME)
+ .setTokenServerUri(TOKEN_SERVER_URI)
+ .setHttpTransportFactory(new MockTokenServerTransportFactory());
+
+ GdchCredentials credentials = GdchCredentials.fromPem(PRIVATE_KEY_PKCS8, builder);
+ assertNotNull(credentials.getPrivateKey());
+ assertEquals(PROJECT_ID, credentials.getProjectId());
+ }
+
@Test
void createWithGdchAudience_correct() throws IOException {
GenericJson json =
@@ -439,7 +502,7 @@ void createWithGdchAudience_correct() throws IOException {
assertEquals(SERVICE_IDENTITY_NAME, gdchWithAudience.getServiceIdentityName());
assertEquals(TOKEN_SERVER_URI, gdchWithAudience.getTokenServerUri());
assertEquals(CA_CERT_PATH, credentials.getCaCertPath());
- assertEquals(API_AUDIENCE, gdchWithAudience.getApiAudience());
+ assertEquals(API_AUDIENCE, gdchWithAudience.getGdchAudience());
}
@Test
@@ -455,12 +518,55 @@ void createWithGdchAudience_nullApiAudience() throws IOException {
TOKEN_SERVER_URI);
GdchCredentials credentials = GdchCredentials.fromJson(json);
- try {
- GdchCredentials gdchWithAudience = credentials.createWithGdchAudience(null);
- fail("Should not be able to create GDCH credential without exception.");
- } catch (NullPointerException ex) {
- assertTrue(ex.getMessage().contains("Audience are not configured for GDCH service account"));
- }
+ IllegalArgumentException ex =
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> credentials.createWithGdchAudience((String) null));
+ assertTrue(
+ ex.getMessage().contains("Audience cannot be null or empty for GDCH service account"));
+ }
+
+ @Test
+ void createWithGdchAudience_emptyApiAudience() throws IOException {
+ GenericJson json =
+ writeGdchServiceAccountJson(
+ FORMAT_VERSION,
+ PROJECT_ID,
+ PRIVATE_KEY_ID,
+ PRIVATE_KEY_PKCS8,
+ SERVICE_IDENTITY_NAME,
+ CA_CERT_PATH,
+ TOKEN_SERVER_URI);
+ GdchCredentials credentials = GdchCredentials.fromJson(json);
+
+ IllegalArgumentException ex =
+ assertThrows(IllegalArgumentException.class, () -> credentials.createWithGdchAudience(""));
+ assertTrue(
+ ex.getMessage().contains("Audience cannot be null or empty for GDCH service account"));
+ }
+
+ @Test
+ void getGdchAudience_vs_getApiAudience() throws IOException {
+ GenericJson json =
+ writeGdchServiceAccountJson(
+ FORMAT_VERSION,
+ PROJECT_ID,
+ PRIVATE_KEY_ID,
+ PRIVATE_KEY_PKCS8,
+ SERVICE_IDENTITY_NAME,
+ CA_CERT_PATH,
+ TOKEN_SERVER_URI);
+ GdchCredentials credentials = GdchCredentials.fromJson(json);
+
+ String validUri = "https://valid-audience.com";
+ GdchCredentials validCredentials = credentials.createWithGdchAudience(validUri);
+ assertEquals(validUri, validCredentials.getGdchAudience());
+ assertEquals(URI.create(validUri), validCredentials.getApiAudience());
+
+ String invalidUri = "invalid uri ^";
+ GdchCredentials invalidCredentials = credentials.createWithGdchAudience(invalidUri);
+ assertEquals(invalidUri, invalidCredentials.getGdchAudience());
+ assertNull(invalidCredentials.getApiAudience());
}
@Test
@@ -477,7 +583,7 @@ void createAssertion_correct() throws IOException {
GdchCredentials credentials = GdchCredentials.fromJson(json);
JsonFactory jsonFactory = OAuth2Utils.JSON_FACTORY;
long currentTimeMillis = Clock.SYSTEM.currentTimeMillis();
- String assertion = credentials.createAssertion(jsonFactory, currentTimeMillis, API_AUDIENCE);
+ String assertion = credentials.createAssertion(jsonFactory, currentTimeMillis);
JsonWebSignature signature = JsonWebSignature.parse(jsonFactory, assertion);
JsonWebToken.Payload payload = signature.getPayload();
@@ -548,30 +654,17 @@ void refreshAccessToken_nullApiAudience() throws IOException {
transportFactory.transport.addGdchServiceAccount(
GdchCredentials.getIssuerSubjectValue(PROJECT_ID, SERVICE_IDENTITY_NAME), tokenString);
transportFactory.transport.setTokenServerUri(TOKEN_SERVER_URI);
- try {
- AccessToken accessToken = credentials.refreshAccessToken();
- fail("Should not be able to refresh access token without exception.");
- } catch (NullPointerException ex) {
- assertTrue(
- ex.getMessage()
- .contains(
- "Audience are not configured for GDCH service account. Specify the "
- + "audience by calling createWithGDCHAudience"));
- }
+ NullPointerException ex =
+ assertThrows(NullPointerException.class, () -> credentials.refreshAccessToken());
+ assertTrue(
+ ex.getMessage()
+ .contains(
+ "Audience cannot be null or empty for GDCH service account credentials. "
+ + "Specify the audience by calling createWithGdchAudience"));
}
@Test
- void getIssuerSubjectValue_correct() throws IOException {
- GenericJson json =
- writeGdchServiceAccountJson(
- FORMAT_VERSION,
- PROJECT_ID,
- PRIVATE_KEY_ID,
- PRIVATE_KEY_PKCS8,
- SERVICE_IDENTITY_NAME,
- CA_CERT_PATH,
- TOKEN_SERVER_URI);
- GdchCredentials credentials = GdchCredentials.fromJson(json);
+ void getIssuerSubjectValue_correct() {
Object expectedIssSubValue =
String.format("system:serviceaccount:%s:%s", PROJECT_ID, SERVICE_IDENTITY_NAME);
assertEquals(
@@ -590,7 +683,7 @@ void equals_same() throws IOException {
SERVICE_IDENTITY_NAME,
CA_CERT_PATH,
TOKEN_SERVER_URI);
- OAuth2Credentials credentials = GdchCredentials.fromJson(json);
+ GdchCredentials credentials = GdchCredentials.fromJson(json);
GenericJson otherJson =
writeGdchServiceAccountJson(
FORMAT_VERSION,
@@ -600,14 +693,14 @@ void equals_same() throws IOException {
SERVICE_IDENTITY_NAME,
CA_CERT_PATH,
TOKEN_SERVER_URI);
- OAuth2Credentials otherCredentials = GdchCredentials.fromJson(otherJson);
- assertTrue(credentials.equals(otherCredentials));
- assertTrue(otherCredentials.equals(credentials));
+ GdchCredentials otherCredentials = GdchCredentials.fromJson(otherJson);
+ assertEquals(credentials, otherCredentials);
+ assertEquals(otherCredentials, credentials);
- credentials = ((GdchCredentials) credentials).createWithGdchAudience(API_AUDIENCE);
- otherCredentials = ((GdchCredentials) otherCredentials).createWithGdchAudience(API_AUDIENCE);
- assertTrue(credentials.equals(otherCredentials));
- assertTrue(otherCredentials.equals(credentials));
+ credentials = credentials.createWithGdchAudience(API_AUDIENCE);
+ otherCredentials = otherCredentials.createWithGdchAudience(API_AUDIENCE);
+ assertEquals(credentials, otherCredentials);
+ assertEquals(otherCredentials, credentials);
}
@Test
@@ -621,7 +714,7 @@ void equals_false_projectId() throws IOException {
SERVICE_IDENTITY_NAME,
CA_CERT_PATH,
TOKEN_SERVER_URI);
- OAuth2Credentials credentials = GdchCredentials.fromJson(json);
+ GdchCredentials credentials = GdchCredentials.fromJson(json);
GenericJson otherJson =
writeGdchServiceAccountJson(
FORMAT_VERSION,
@@ -631,14 +724,14 @@ void equals_false_projectId() throws IOException {
SERVICE_IDENTITY_NAME,
CA_CERT_PATH,
TOKEN_SERVER_URI);
- OAuth2Credentials otherCredentials = GdchCredentials.fromJson(otherJson);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ GdchCredentials otherCredentials = GdchCredentials.fromJson(otherJson);
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
- credentials = ((GdchCredentials) credentials).createWithGdchAudience(API_AUDIENCE);
- otherCredentials = ((GdchCredentials) otherCredentials).createWithGdchAudience(API_AUDIENCE);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ credentials = credentials.createWithGdchAudience(API_AUDIENCE);
+ otherCredentials = otherCredentials.createWithGdchAudience(API_AUDIENCE);
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
@@ -652,7 +745,7 @@ void equals_false_keyId() throws IOException {
SERVICE_IDENTITY_NAME,
CA_CERT_PATH,
TOKEN_SERVER_URI);
- OAuth2Credentials credentials = GdchCredentials.fromJson(json);
+ GdchCredentials credentials = GdchCredentials.fromJson(json);
GenericJson otherJson =
writeGdchServiceAccountJson(
FORMAT_VERSION,
@@ -662,14 +755,14 @@ void equals_false_keyId() throws IOException {
SERVICE_IDENTITY_NAME,
CA_CERT_PATH,
TOKEN_SERVER_URI);
- OAuth2Credentials otherCredentials = GdchCredentials.fromJson(otherJson);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ GdchCredentials otherCredentials = GdchCredentials.fromJson(otherJson);
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
- credentials = ((GdchCredentials) credentials).createWithGdchAudience(API_AUDIENCE);
- otherCredentials = ((GdchCredentials) otherCredentials).createWithGdchAudience(API_AUDIENCE);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ credentials = credentials.createWithGdchAudience(API_AUDIENCE);
+ otherCredentials = otherCredentials.createWithGdchAudience(API_AUDIENCE);
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
@@ -683,7 +776,7 @@ void equals_false_serviceIdentityName() throws IOException {
SERVICE_IDENTITY_NAME,
CA_CERT_PATH,
TOKEN_SERVER_URI);
- OAuth2Credentials credentials = GdchCredentials.fromJson(json);
+ GdchCredentials credentials = GdchCredentials.fromJson(json);
GenericJson otherJson =
writeGdchServiceAccountJson(
FORMAT_VERSION,
@@ -693,20 +786,22 @@ void equals_false_serviceIdentityName() throws IOException {
"otherServiceIdentityName",
CA_CERT_PATH,
TOKEN_SERVER_URI);
- OAuth2Credentials otherCredentials = GdchCredentials.fromJson(otherJson);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ GdchCredentials otherCredentials = GdchCredentials.fromJson(otherJson);
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
- credentials = ((GdchCredentials) credentials).createWithGdchAudience(API_AUDIENCE);
- otherCredentials = ((GdchCredentials) otherCredentials).createWithGdchAudience(API_AUDIENCE);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ credentials = credentials.createWithGdchAudience(API_AUDIENCE);
+ otherCredentials = otherCredentials.createWithGdchAudience(API_AUDIENCE);
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
void equals_false_caCertPath() throws IOException {
File tmpDirectory = Files.createTempDirectory("tmpDirectory").toFile();
+ tmpDirectory.deleteOnExit();
File testCaCertFile = File.createTempFile("testCert", ".pem", tmpDirectory);
+ testCaCertFile.deleteOnExit();
GenericJson json =
writeGdchServiceAccountJson(
FORMAT_VERSION,
@@ -716,7 +811,7 @@ void equals_false_caCertPath() throws IOException {
SERVICE_IDENTITY_NAME,
CA_CERT_PATH,
TOKEN_SERVER_URI);
- OAuth2Credentials credentials = GdchCredentials.fromJson(json);
+ GdchCredentials credentials = GdchCredentials.fromJson(json);
GenericJson otherJson =
writeGdchServiceAccountJson(
FORMAT_VERSION,
@@ -726,16 +821,14 @@ void equals_false_caCertPath() throws IOException {
SERVICE_IDENTITY_NAME,
testCaCertFile.getPath(),
TOKEN_SERVER_URI);
- OAuth2Credentials otherCredentials = GdchCredentials.fromJson(otherJson);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
-
- credentials = ((GdchCredentials) credentials).createWithGdchAudience(API_AUDIENCE);
- otherCredentials = ((GdchCredentials) otherCredentials).createWithGdchAudience(API_AUDIENCE);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ GdchCredentials otherCredentials = GdchCredentials.fromJson(otherJson);
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
- testCaCertFile.delete();
+ credentials = credentials.createWithGdchAudience(API_AUDIENCE);
+ otherCredentials = otherCredentials.createWithGdchAudience(API_AUDIENCE);
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
@@ -749,7 +842,7 @@ void equals_false_tokenServer() throws IOException {
SERVICE_IDENTITY_NAME,
CA_CERT_PATH,
TOKEN_SERVER_URI);
- OAuth2Credentials credentials = GdchCredentials.fromJson(json);
+ GdchCredentials credentials = GdchCredentials.fromJson(json);
GenericJson otherJson =
writeGdchServiceAccountJson(
FORMAT_VERSION,
@@ -759,19 +852,19 @@ void equals_false_tokenServer() throws IOException {
SERVICE_IDENTITY_NAME,
CA_CERT_PATH,
URI.create("https://foo1.com/bar"));
- OAuth2Credentials otherCredentials = GdchCredentials.fromJson(otherJson);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ GdchCredentials otherCredentials = GdchCredentials.fromJson(otherJson);
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
- credentials = ((GdchCredentials) credentials).createWithGdchAudience(API_AUDIENCE);
- otherCredentials = ((GdchCredentials) otherCredentials).createWithGdchAudience(API_AUDIENCE);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ credentials = credentials.createWithGdchAudience(API_AUDIENCE);
+ otherCredentials = otherCredentials.createWithGdchAudience(API_AUDIENCE);
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
void equals_false_apiAudience() throws IOException {
- URI otherApiAudience = URI.create("https://foo1.com/bar");
+ String otherApiAudience = URI.create("https://foo1.com/bar").toString();
GenericJson json =
writeGdchServiceAccountJson(
@@ -782,7 +875,7 @@ void equals_false_apiAudience() throws IOException {
SERVICE_IDENTITY_NAME,
CA_CERT_PATH,
TOKEN_SERVER_URI);
- OAuth2Credentials credentials = GdchCredentials.fromJson(json);
+ GdchCredentials credentials = GdchCredentials.fromJson(json);
GenericJson otherJson =
writeGdchServiceAccountJson(
FORMAT_VERSION,
@@ -792,13 +885,12 @@ void equals_false_apiAudience() throws IOException {
SERVICE_IDENTITY_NAME,
CA_CERT_PATH,
TOKEN_SERVER_URI);
- OAuth2Credentials otherCredentials = GdchCredentials.fromJson(otherJson);
+ GdchCredentials otherCredentials = GdchCredentials.fromJson(otherJson);
- credentials = ((GdchCredentials) credentials).createWithGdchAudience(API_AUDIENCE);
- otherCredentials =
- ((GdchCredentials) otherCredentials).createWithGdchAudience(otherApiAudience);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ credentials = credentials.createWithGdchAudience(API_AUDIENCE);
+ otherCredentials = otherCredentials.createWithGdchAudience(otherApiAudience);
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
@@ -812,8 +904,8 @@ void toString_containsFields() throws IOException {
SERVICE_IDENTITY_NAME,
CA_CERT_PATH,
TOKEN_SERVER_URI);
- OAuth2Credentials credentials = GdchCredentials.fromJson(json);
- credentials = ((GdchCredentials) credentials).createWithGdchAudience(API_AUDIENCE);
+ GdchCredentials credentials = GdchCredentials.fromJson(json);
+ credentials = credentials.createWithGdchAudience(API_AUDIENCE);
String expectedToString =
String.format(
"GdchCredentials{projectId=%s, privateKeyId=%s, serviceIdentityName=%s, "
@@ -839,7 +931,7 @@ void hashCode_equals() throws IOException {
SERVICE_IDENTITY_NAME,
CA_CERT_PATH,
TOKEN_SERVER_URI);
- OAuth2Credentials credentials = GdchCredentials.fromJson(json);
+ GdchCredentials credentials = GdchCredentials.fromJson(json);
GenericJson otherJson =
writeGdchServiceAccountJson(
FORMAT_VERSION,
@@ -849,11 +941,11 @@ void hashCode_equals() throws IOException {
SERVICE_IDENTITY_NAME,
CA_CERT_PATH,
TOKEN_SERVER_URI);
- OAuth2Credentials otherCredentials = GdchCredentials.fromJson(otherJson);
+ GdchCredentials otherCredentials = GdchCredentials.fromJson(otherJson);
assertEquals(credentials.hashCode(), otherCredentials.hashCode());
- credentials = ((GdchCredentials) credentials).createWithGdchAudience(API_AUDIENCE);
- otherCredentials = ((GdchCredentials) otherCredentials).createWithGdchAudience(API_AUDIENCE);
+ credentials = credentials.createWithGdchAudience(API_AUDIENCE);
+ otherCredentials = otherCredentials.createWithGdchAudience(API_AUDIENCE);
assertEquals(credentials.hashCode(), otherCredentials.hashCode());
}
@@ -876,12 +968,264 @@ void serialize_correct() throws IOException, ClassNotFoundException {
assertEquals(credentials, deserializedCredentials);
assertEquals(credentials.hashCode(), deserializedCredentials.hashCode());
assertEquals(credentials.toString(), deserializedCredentials.toString());
- assertSame(deserializedCredentials.clock, Clock.SYSTEM);
+ assertSame(Clock.SYSTEM, deserializedCredentials.clock);
assertEquals(
MockTokenServerTransportFactory.class,
deserializedCredentials.toBuilder().getHttpTransportFactory().getClass());
}
+ @Test
+ void refreshAccessToken_invalidResponse_missingAccessToken() throws IOException {
+ MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
+ GenericJson json =
+ writeGdchServiceAccountJson(
+ FORMAT_VERSION,
+ PROJECT_ID,
+ PRIVATE_KEY_ID,
+ PRIVATE_KEY_PKCS8,
+ SERVICE_IDENTITY_NAME,
+ CA_CERT_PATH,
+ TOKEN_SERVER_URI);
+ GdchCredentials credentials = GdchCredentials.fromJson(json, transportFactory);
+ GdchCredentials gdchWithAudience = credentials.createWithGdchAudience(API_AUDIENCE);
+
+ transportFactory.transport.addGdchServiceAccount(
+ GdchCredentials.getIssuerSubjectValue(PROJECT_ID, SERVICE_IDENTITY_NAME), null);
+ transportFactory.transport.setTokenServerUri(TOKEN_SERVER_URI);
+
+ IOException ex = assertThrows(IOException.class, () -> gdchWithAudience.refreshAccessToken());
+ assertEquals(
+ "Error parsing token refresh response. Expected value access_token not found.",
+ ex.getMessage());
+ }
+
+ @Test
+ void refreshAccessToken_invalidResponse_wrongTypeAccessToken() throws IOException {
+ refreshAccessToken_invalidResponse(
+ "{\"access_token\": 123, \"expires_in\": 3600}",
+ "Error parsing token refresh response. Expected string value access_token of wrong type.");
+ }
+
+ @Test
+ void refreshAccessToken_invalidResponse_missingExpiresIn() throws IOException {
+ refreshAccessToken_invalidResponse(
+ "{\"access_token\": \"token\"}",
+ "Error parsing token refresh response. Expected value expires_in not found.");
+ }
+
+ @Test
+ void refreshAccessToken_invalidResponse_wrongTypeExpiresIn() throws IOException {
+ refreshAccessToken_invalidResponse(
+ "{\"access_token\": \"token\", \"expires_in\": \"3600\"}",
+ "Error parsing token refresh response. Expected integer value expires_in of wrong type.");
+ }
+
+ private void refreshAccessToken_invalidResponse(
+ String responseContent, String expectedErrorMessage) throws IOException {
+ MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
+ GenericJson json =
+ writeGdchServiceAccountJson(
+ FORMAT_VERSION,
+ PROJECT_ID,
+ PRIVATE_KEY_ID,
+ PRIVATE_KEY_PKCS8,
+ SERVICE_IDENTITY_NAME,
+ CA_CERT_PATH,
+ TOKEN_SERVER_URI);
+ GdchCredentials credentials = GdchCredentials.fromJson(json, transportFactory);
+ GdchCredentials gdchWithAudience = credentials.createWithGdchAudience(API_AUDIENCE);
+
+ transportFactory.transport.addResponseSequence(
+ new MockLowLevelHttpResponse().setContentType(Json.MEDIA_TYPE).setContent(responseContent));
+
+ IOException ex = assertThrows(IOException.class, () -> gdchWithAudience.refreshAccessToken());
+ assertEquals(expectedErrorMessage, ex.getMessage());
+ }
+
+ @Test
+ void refreshAccessToken_serverError() throws IOException {
+ MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
+ GenericJson json =
+ writeGdchServiceAccountJson(
+ FORMAT_VERSION,
+ PROJECT_ID,
+ PRIVATE_KEY_ID,
+ PRIVATE_KEY_PKCS8,
+ SERVICE_IDENTITY_NAME,
+ CA_CERT_PATH,
+ TOKEN_SERVER_URI);
+ GdchCredentials credentials = GdchCredentials.fromJson(json, transportFactory);
+ GdchCredentials gdchWithAudience = credentials.createWithGdchAudience(API_AUDIENCE);
+
+ transportFactory.transport.addResponseSequence(
+ new MockLowLevelHttpResponse().setStatusCode(400).setReasonPhrase("Bad Request"));
+
+ GoogleAuthException ex =
+ assertThrows(GoogleAuthException.class, () -> gdchWithAudience.refreshAccessToken());
+ assertTrue(ex.getMessage().contains("Error getting access token for GDCH service account"));
+ assertTrue(ex.getMessage().contains("400 Bad Request"));
+ }
+
+ @Test
+ void refreshAccessToken_ioException() throws IOException {
+ MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
+ GenericJson json =
+ writeGdchServiceAccountJson(
+ FORMAT_VERSION,
+ PROJECT_ID,
+ PRIVATE_KEY_ID,
+ PRIVATE_KEY_PKCS8,
+ SERVICE_IDENTITY_NAME,
+ CA_CERT_PATH,
+ TOKEN_SERVER_URI);
+ GdchCredentials credentials = GdchCredentials.fromJson(json, transportFactory);
+ GdchCredentials gdchWithAudience = credentials.createWithGdchAudience(API_AUDIENCE);
+
+ transportFactory.transport.addResponseErrorSequence(new IOException("Connection reset"));
+
+ GoogleAuthException ex =
+ assertThrows(GoogleAuthException.class, () -> gdchWithAudience.refreshAccessToken());
+ assertTrue(ex.getMessage().contains("Error getting access token for GDCH service account"));
+ assertTrue(ex.getMessage().contains("Connection reset"));
+ }
+
+ @Test
+ void transcodeDerToConcat_withGeneratedSignature() throws Exception {
+ // Generate a new key pair and a signature.
+ KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
+ keyGen.initialize(new ECGenParameterSpec("secp256r1"));
+ KeyPair keyPair = keyGen.generateKeyPair();
+ Signature signer = Signature.getInstance("SHA256withECDSA");
+ signer.initSign(keyPair.getPrivate());
+ signer.update(new byte[] {1, 2, 3, 4});
+ byte[] derSignature = signer.sign();
+
+ // Transcode the signature and check length.
+ byte[] jwsSignature = GdchCredentials.transcodeDerToConcat(derSignature, 64);
+ assertEquals(64, jwsSignature.length);
+ }
+
+ @Test
+ void transcodeDerToConcat_invalidDerFormat() {
+ byte[] invalidDer = new byte[] {0x31, 0x00}; // Not a SEQUENCE
+ GoogleAuthException e =
+ assertThrows(
+ GoogleAuthException.class, () -> GdchCredentials.transcodeDerToConcat(invalidDer, 64));
+ assertEquals("Invalid DER signature format.", e.getMessage());
+ }
+
+ @Test
+ void transcodeDerToConcat_invalidLength() {
+ // SEQUENCE length doesn't match actual length
+ byte[] invalidDer = new byte[] {0x30, 0x05, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02};
+ GoogleAuthException e =
+ assertThrows(
+ GoogleAuthException.class, () -> GdchCredentials.transcodeDerToConcat(invalidDer, 64));
+ assertEquals("Invalid DER signature length.", e.getMessage());
+ }
+
+ @Test
+ void transcodeDerToConcat_invalidRInteger() {
+ // Uses BIT STRING (0x03) instead of INTEGER (0x02) for R
+ byte[] invalidDer = new byte[] {0x30, 0x06, 0x03, 0x01, 0x01, 0x02, 0x01, 0x02};
+ GoogleAuthException e =
+ assertThrows(
+ GoogleAuthException.class, () -> GdchCredentials.transcodeDerToConcat(invalidDer, 64));
+ assertEquals("Expected INTEGER for R.", e.getMessage());
+ }
+
+ @Test
+ void transcodeDerToConcat_invalidSInteger() {
+ // Uses BIT STRING (0x03) instead of INTEGER (0x02) for S
+ byte[] invalidDer = new byte[] {0x30, 0x06, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01};
+ GoogleAuthException e =
+ assertThrows(
+ GoogleAuthException.class, () -> GdchCredentials.transcodeDerToConcat(invalidDer, 64));
+ assertEquals("Expected INTEGER for S.", e.getMessage());
+ }
+
+ @Test
+ void signUsingEsSha256_producesVerifiableSignature() throws Exception {
+ KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
+ keyGen.initialize(new ECGenParameterSpec("secp256r1"));
+ KeyPair keyPair = keyGen.generateKeyPair();
+
+ JsonFactory jsonFactory = GsonFactory.getDefaultInstance();
+
+ JsonWebSignature.Header header = new JsonWebSignature.Header();
+ header.setAlgorithm("ES256");
+ header.setType("JWT");
+ header.setKeyId("test-key-id");
+
+ JsonWebToken.Payload payload = new JsonWebToken.Payload();
+ payload.setIssuer("test-issuer");
+ payload.setAudience("test-audience");
+
+ String signedJws =
+ GdchCredentials.signUsingEsSha256(keyPair.getPrivate(), jsonFactory, header, payload);
+
+ // Verify the signature.
+ JsonWebSignature jws = JsonWebSignature.parse(jsonFactory, signedJws);
+ assertTrue(jws.verifySignature(keyPair.getPublic()));
+ }
+
+ @Test
+ void signUsingEsSha256_validStructure() throws Exception {
+ PrivateKey privateKey =
+ OAuth2Utils.privateKeyFromPkcs8(PRIVATE_KEY_PKCS8, OAuth2Utils.Pkcs8Algorithm.EC);
+ JsonFactory jsonFactory = GsonFactory.getDefaultInstance();
+
+ JsonWebSignature.Header header = new JsonWebSignature.Header();
+ header.setAlgorithm("ES256");
+ header.setType("JWT");
+ header.setKeyId(PRIVATE_KEY_ID);
+
+ JsonWebToken.Payload payload = new JsonWebToken.Payload();
+ payload.setIssuer("test-issuer");
+ payload.setAudience("test-audience");
+ payload.setSubject("test-subject");
+ payload.setIssuedAtTimeSeconds(1000L);
+ payload.setExpirationTimeSeconds(2000L);
+
+ String signedJws = GdchCredentials.signUsingEsSha256(privateKey, jsonFactory, header, payload);
+
+ // Verify JWS structure
+ String[] parts = signedJws.split("\\.");
+ assertEquals(3, parts.length);
+
+ // Verify header
+ JsonWebSignature.Header decodedHeader =
+ jsonFactory.fromInputStream(
+ new java.io.ByteArrayInputStream(Base64.getUrlDecoder().decode(parts[0])),
+ JsonWebSignature.Header.class);
+ assertEquals("ES256", decodedHeader.getAlgorithm());
+ assertEquals("JWT", decodedHeader.getType());
+ assertEquals(PRIVATE_KEY_ID, decodedHeader.getKeyId());
+
+ // Verify payload
+ JsonWebToken.Payload decodedPayload =
+ jsonFactory.fromInputStream(
+ new java.io.ByteArrayInputStream(Base64.getUrlDecoder().decode(parts[1])),
+ JsonWebToken.Payload.class);
+ assertEquals("test-issuer", decodedPayload.getIssuer());
+ assertEquals("test-audience", decodedPayload.getAudience());
+ assertEquals("test-subject", decodedPayload.getSubject());
+
+ // Verify signature format (64 bytes for ES256)
+ byte[] signatureBytes = Base64.getUrlDecoder().decode(parts[2]);
+ assertEquals(64, signatureBytes.length);
+ }
+
+ @Test
+ void builder_setGdchAudience_nullString() {
+ GdchCredentials.Builder builder = GdchCredentials.newBuilder();
+ IllegalArgumentException ex =
+ assertThrows(IllegalArgumentException.class, () -> builder.setGdchAudience((String) null));
+ assertTrue(
+ ex.getMessage()
+ .contains("Audience cannot be null or empty for GDCH service account credentials."));
+ }
+
static GenericJson writeGdchServiceAccountJson(
String formatVersion,
String project,
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/GoogleAuthUtilsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/GoogleAuthUtilsTest.java
index 7c883df0fe73..de7077ef6277 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/GoogleAuthUtilsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/GoogleAuthUtilsTest.java
@@ -47,8 +47,9 @@ void getWellKnownCredentialsPath_correct() {
// the base folder will be an empty string using.
File homeDir = new File("");
File configDir = new File(homeDir, ".config");
- File cloudConfigDir = new File(configDir, provider.CLOUDSDK_CONFIG_DIRECTORY);
- File wellKnownFile = new File(cloudConfigDir, provider.WELL_KNOWN_CREDENTIALS_FILE);
+ File cloudConfigDir = new File(configDir, DefaultCredentialsProvider.CLOUDSDK_CONFIG_DIRECTORY);
+ File wellKnownFile =
+ new File(cloudConfigDir, DefaultCredentialsProvider.WELL_KNOWN_CREDENTIALS_FILE);
String obtainedPath = GoogleAuthUtils.getWellKnownCredentialsPath(provider);
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/GoogleCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/GoogleCredentialsTest.java
index 503c87d54207..74aa9fae9ccd 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/GoogleCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/GoogleCredentialsTest.java
@@ -33,12 +33,12 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import com.google.api.client.http.HttpStatusCodes;
import com.google.api.client.json.GenericJson;
@@ -71,7 +71,7 @@ class GoogleCredentialsTest extends BaseSerializationTest {
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;
@@ -82,7 +82,7 @@ class GoogleCredentialsTest extends BaseSerializationTest {
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 GDCH_API_AUDIENCE = "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";
@@ -100,13 +100,8 @@ class GoogleCredentialsTest extends BaseSerializationTest {
private static final String TPC_UNIVERSE = "foo.bar";
@Test
- void getApplicationDefault_nullTransport_throws() throws IOException {
- try {
- GoogleCredentials.getApplicationDefault(null);
- fail();
- } catch (NullPointerException expected) {
- // Expected
- }
+ void getApplicationDefault_nullTransport_throws() {
+ assertThrows(NullPointerException.class, () -> GoogleCredentials.getApplicationDefault(null));
}
@Test
@@ -114,29 +109,23 @@ 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) {
+ try (InputStream stream = TestUtils.jsonToInputStream(json)) {
+ IOException exception =
+ assertThrows(
+ IOException.class, () -> GoogleCredentials.fromStream(stream, transportFactory));
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));
+ assertTrue(exception.getMessage().contains(expectedError));
}
}
@Test
- void fromStream_nullTransport_throws() throws IOException {
+ void fromStream_nullTransport_throws() {
InputStream stream = new ByteArrayInputStream("foo".getBytes());
- try {
- GoogleCredentials.fromStream(stream, null);
- fail("Should throw if HttpTransportFactory is null");
- } catch (NullPointerException expected) {
- // Expected
- }
+ assertThrows(NullPointerException.class, () -> GoogleCredentials.fromStream(stream, null));
}
@Test
@@ -146,19 +135,17 @@ void fromStream_noType_throws() throws IOException {
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) {
+ try (InputStream stream = TestUtils.jsonToInputStream(json)) {
+ IOException exception =
+ assertThrows(
+ IOException.class, () -> GoogleCredentials.fromStream(stream, transportFactory));
String expectedError = "Error reading credentials from stream, 'type' field not specified.";
- assertEquals(expectedError, expected.getMessage());
+ assertEquals(expectedError, exception.getMessage());
}
}
@Test
void fromStream_nullStream_throws() {
- MockHttpTransportFactory transportFactory = new MockHttpTransportFactory();
assertThrows(NullPointerException.class, () -> GoogleCredentials.parseJsonInputStream(null));
}
@@ -175,7 +162,7 @@ void fromStream_serviceAccount_noUniverse_providesToken() throws IOException {
assertNotNull(credentials);
assertEquals(GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain());
- assertEquals(false, credentials.isExplicitUniverseDomain());
+ assertFalse(credentials.isExplicitUniverseDomain());
credentials = credentials.createScoped(SCOPES);
Map> metadata = credentials.getRequestMetadata(CALL_URI);
TestUtils.assertContainsBearerToken(metadata, ACCESS_TOKEN);
@@ -198,46 +185,62 @@ void fromStream_serviceAccount_Universe_noToken() throws IOException {
assertNotNull(credentials);
assertEquals(TPC_UNIVERSE, credentials.getUniverseDomain());
- assertEquals(true, credentials.isExplicitUniverseDomain());
+ assertTrue(credentials.isExplicitUniverseDomain());
credentials = credentials.createScoped(SCOPES);
- Map> metadata = credentials.getRequestMetadata(CALL_URI);
+ credentials.getRequestMetadata(CALL_URI);
assertNotNull(((ServiceAccountCredentials) credentials).getSelfSignedJwtCredentialsWithScope());
}
@Test
void fromStream_serviceAccountNoClientId_throws() throws IOException {
- InputStream serviceAccountStream =
+ try (InputStream serviceAccountStream =
ServiceAccountCredentialsTest.writeServiceAccountStream(
- null, SA_CLIENT_EMAIL, SA_PRIVATE_KEY_PKCS8, SA_PRIVATE_KEY_ID);
-
- testFromStreamException(serviceAccountStream, "client_id");
+ null, SA_CLIENT_EMAIL, SA_PRIVATE_KEY_PKCS8, SA_PRIVATE_KEY_ID)) {
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () -> GoogleCredentials.fromStream(serviceAccountStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("client_id"));
+ }
}
@Test
void fromStream_serviceAccountNoClientEmail_throws() throws IOException {
- InputStream serviceAccountStream =
+ try (InputStream serviceAccountStream =
ServiceAccountCredentialsTest.writeServiceAccountStream(
- SA_CLIENT_ID, null, SA_PRIVATE_KEY_PKCS8, SA_PRIVATE_KEY_ID);
-
- testFromStreamException(serviceAccountStream, "client_email");
+ SA_CLIENT_ID, null, SA_PRIVATE_KEY_PKCS8, SA_PRIVATE_KEY_ID)) {
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () -> GoogleCredentials.fromStream(serviceAccountStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("client_email"));
+ }
}
@Test
void fromStream_serviceAccountNoPrivateKey_throws() throws IOException {
- InputStream serviceAccountStream =
+ try (InputStream serviceAccountStream =
ServiceAccountCredentialsTest.writeServiceAccountStream(
- SA_CLIENT_ID, SA_CLIENT_EMAIL, null, SA_PRIVATE_KEY_ID);
-
- testFromStreamException(serviceAccountStream, "private_key");
+ SA_CLIENT_ID, SA_CLIENT_EMAIL, null, SA_PRIVATE_KEY_ID)) {
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () -> GoogleCredentials.fromStream(serviceAccountStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("private_key"));
+ }
}
@Test
void fromStream_serviceAccountNoPrivateKeyId_throws() throws IOException {
- InputStream serviceAccountStream =
+ try (InputStream serviceAccountStream =
ServiceAccountCredentialsTest.writeServiceAccountStream(
- SA_CLIENT_ID, SA_CLIENT_EMAIL, SA_PRIVATE_KEY_PKCS8, null);
-
- testFromStreamException(serviceAccountStream, "private_key_id");
+ SA_CLIENT_ID, SA_CLIENT_EMAIL, SA_PRIVATE_KEY_PKCS8, null)) {
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () -> GoogleCredentials.fromStream(serviceAccountStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("private_key_id"));
+ }
}
@Test
@@ -245,7 +248,7 @@ void fromStream_gdchServiceAccount_correct() throws IOException {
MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
InputStream gdchServiceAccountStream =
GdchCredentialsTest.writeGdchServiceAccountStream(
- GDCH_SA_FORMAT_VERSION,
+ GdchCredentials.SUPPORTED_JSON_FORMAT_VERSION,
GDCH_SA_PROJECT_ID,
GDCH_SA_PRIVATE_KEY_ID,
GDCH_SA_PRIVATE_KEY_PKC8,
@@ -256,8 +259,8 @@ void fromStream_gdchServiceAccount_correct() throws IOException {
GoogleCredentials.fromStream(gdchServiceAccountStream, transportFactory);
assertNotNull(credentials);
- assertTrue(credentials instanceof GdchCredentials);
- assertEquals(GDCH_SA_PROJECT_ID, ((GdchCredentials) credentials).getProjectId());
+ assertInstanceOf(GdchCredentials.class, credentials);
+ assertEquals(GDCH_SA_PROJECT_ID, credentials.getProjectId());
assertEquals(
GDCH_SA_SERVICE_IDENTITY_NAME, ((GdchCredentials) credentials).getServiceIdentityName());
assertEquals(GDCH_SA_TOKEN_SERVER_URI, ((GdchCredentials) credentials).getTokenServerUri());
@@ -267,8 +270,8 @@ void fromStream_gdchServiceAccount_correct() throws IOException {
credentials = ((GdchCredentials) credentials).createWithGdchAudience(GDCH_API_AUDIENCE);
assertNotNull(credentials);
- assertTrue(credentials instanceof GdchCredentials);
- assertEquals(GDCH_SA_PROJECT_ID, ((GdchCredentials) credentials).getProjectId());
+ assertTrue(true);
+ assertEquals(GDCH_SA_PROJECT_ID, credentials.getProjectId());
assertEquals(
GDCH_SA_SERVICE_IDENTITY_NAME, ((GdchCredentials) credentials).getServiceIdentityName());
assertEquals(GDCH_SA_TOKEN_SERVER_URI, ((GdchCredentials) credentials).getTokenServerUri());
@@ -278,7 +281,7 @@ void fromStream_gdchServiceAccount_correct() throws IOException {
@Test
void fromStream_gdchServiceAccountNoFormatVersion_throws() throws IOException {
- InputStream gdchServiceAccountStream =
+ try (InputStream gdchServiceAccountStream =
GdchCredentialsTest.writeGdchServiceAccountStream(
null,
GDCH_SA_PROJECT_ID,
@@ -286,89 +289,119 @@ void fromStream_gdchServiceAccountNoFormatVersion_throws() throws IOException {
GDCH_SA_PRIVATE_KEY_PKC8,
GDCH_SA_SERVICE_IDENTITY_NAME,
GDCH_SA_CA_CERT_PATH,
- GDCH_SA_TOKEN_SERVER_URI);
-
- testFromStreamException(gdchServiceAccountStream, "format_version");
+ GDCH_SA_TOKEN_SERVER_URI)) {
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () ->
+ GoogleCredentials.fromStream(gdchServiceAccountStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("format_version"));
+ }
}
@Test
void fromStream_gdchServiceAccountNoProjectId_throws() throws IOException {
- InputStream gdchServiceAccountStream =
+ try (InputStream gdchServiceAccountStream =
GdchCredentialsTest.writeGdchServiceAccountStream(
- GDCH_SA_FORMAT_VERSION,
+ GdchCredentials.SUPPORTED_JSON_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");
+ GDCH_SA_TOKEN_SERVER_URI)) {
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () ->
+ GoogleCredentials.fromStream(gdchServiceAccountStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("project"));
+ }
}
@Test
void fromStream_gdchServiceAccountNoPrivateKeyId_throws() throws IOException {
- InputStream gdchServiceAccountStream =
+ try (InputStream gdchServiceAccountStream =
GdchCredentialsTest.writeGdchServiceAccountStream(
- GDCH_SA_FORMAT_VERSION,
+ GdchCredentials.SUPPORTED_JSON_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");
+ GDCH_SA_TOKEN_SERVER_URI)) {
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () ->
+ GoogleCredentials.fromStream(gdchServiceAccountStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("private_key_id"));
+ }
}
@Test
void fromStream_gdchServiceAccountNoPrivateKey_throws() throws IOException {
- InputStream gdchServiceAccountStream =
+ try (InputStream gdchServiceAccountStream =
GdchCredentialsTest.writeGdchServiceAccountStream(
- GDCH_SA_FORMAT_VERSION,
+ GdchCredentials.SUPPORTED_JSON_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");
+ GDCH_SA_TOKEN_SERVER_URI)) {
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () ->
+ GoogleCredentials.fromStream(gdchServiceAccountStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("private_key"));
+ }
}
@Test
void fromStream_gdchServiceAccountNoServiceIdentityName_throws() throws IOException {
- InputStream gdchServiceAccountStream =
+ try (InputStream gdchServiceAccountStream =
GdchCredentialsTest.writeGdchServiceAccountStream(
- GDCH_SA_FORMAT_VERSION,
+ GdchCredentials.SUPPORTED_JSON_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");
+ GDCH_SA_TOKEN_SERVER_URI)) {
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () ->
+ GoogleCredentials.fromStream(gdchServiceAccountStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("name"));
+ }
}
@Test
void fromStream_gdchServiceAccountNoTokenServerUri_throws() throws IOException {
- InputStream gdchServiceAccountStream =
+ try (InputStream gdchServiceAccountStream =
GdchCredentialsTest.writeGdchServiceAccountStream(
- GDCH_SA_FORMAT_VERSION,
+ GdchCredentials.SUPPORTED_JSON_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");
+ null)) {
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () ->
+ GoogleCredentials.fromStream(gdchServiceAccountStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("token_uri"));
+ }
}
@Test
void fromStream_gdchServiceAccountInvalidFormatVersion_throws() throws IOException {
- InputStream gdchServiceAccountStream =
+ try (InputStream gdchServiceAccountStream =
GdchCredentialsTest.writeGdchServiceAccountStream(
"100",
GDCH_SA_PROJECT_ID,
@@ -376,28 +409,41 @@ void fromStream_gdchServiceAccountInvalidFormatVersion_throws() throws IOExcepti
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));
+ GDCH_SA_TOKEN_SERVER_URI)) {
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () ->
+ GoogleCredentials.fromStream(gdchServiceAccountStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(
+ exception
+ .getMessage()
+ .contains(
+ String.format(
+ "Only format version %s is supported",
+ GdchCredentials.SUPPORTED_JSON_FORMAT_VERSION)));
+ }
}
@Test
void fromStream_gdchServiceAccountInvalidCaCertPath_throws() throws IOException {
- InputStream gdchServiceAccountStream =
+ try (InputStream gdchServiceAccountStream =
GdchCredentialsTest.writeGdchServiceAccountStream(
- GDCH_SA_FORMAT_VERSION,
+ GdchCredentials.SUPPORTED_JSON_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"));
+ GDCH_SA_TOKEN_SERVER_URI)) {
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () ->
+ GoogleCredentials.fromStream(gdchServiceAccountStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(
+ exception.getMessage().contains("Error reading certificate file from CA cert path"));
+ }
}
@Test
@@ -430,27 +476,40 @@ void fromStream_userCredentials_defaultUniverse() throws IOException {
@Test
void fromStream_userCredentials_NoClientId_throws() throws IOException {
- InputStream userStream =
- UserCredentialsTest.writeUserStream(null, USER_CLIENT_SECRET, REFRESH_TOKEN, QUOTA_PROJECT);
-
- testFromStreamException(userStream, "client_id");
+ try (InputStream userStream =
+ UserCredentialsTest.writeUserStream(
+ null, USER_CLIENT_SECRET, REFRESH_TOKEN, QUOTA_PROJECT)) {
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () -> GoogleCredentials.fromStream(userStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("client_id"));
+ }
}
@Test
void fromStream_userCredentials_NoClientSecret_throws() throws IOException {
- InputStream userStream =
- UserCredentialsTest.writeUserStream(USER_CLIENT_ID, null, REFRESH_TOKEN, QUOTA_PROJECT);
-
- testFromStreamException(userStream, "client_secret");
+ try (InputStream userStream =
+ UserCredentialsTest.writeUserStream(USER_CLIENT_ID, null, REFRESH_TOKEN, QUOTA_PROJECT)) {
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () -> GoogleCredentials.fromStream(userStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("client_secret"));
+ }
}
@Test
void fromStream_userCredentials_NoRefreshToken_throws() throws IOException {
- InputStream userStream =
+ try (InputStream userStream =
UserCredentialsTest.writeUserStream(
- USER_CLIENT_ID, USER_CLIENT_SECRET, null, QUOTA_PROJECT);
-
- testFromStreamException(userStream, "refresh_token");
+ USER_CLIENT_ID, USER_CLIENT_SECRET, null, QUOTA_PROJECT)) {
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () -> GoogleCredentials.fromStream(userStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("refresh_token"));
+ }
}
@Test
@@ -723,7 +782,7 @@ void create_withoutUniverse() throws IOException {
GoogleCredentials credentials = GoogleCredentials.create(token);
assertEquals(GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain());
- assertEquals(false, credentials.isExplicitUniverseDomain());
+ assertFalse(credentials.isExplicitUniverseDomain());
}
@Test
@@ -732,7 +791,7 @@ void create_withUniverse() throws IOException {
GoogleCredentials credentials = GoogleCredentials.create("some-universe", token);
assertEquals("some-universe", credentials.getUniverseDomain());
- assertEquals(true, credentials.isExplicitUniverseDomain());
+ assertTrue(credentials.isExplicitUniverseDomain());
}
@Test
@@ -748,7 +807,7 @@ void buildWithQuotaProject() {
assertEquals("", withEmptyQuota.getQuotaProjectId());
GoogleCredentials sameCredentials = googleCredentials.createWithQuotaProject(null);
- assertEquals(null, sameCredentials.getQuotaProjectId());
+ assertNull(sameCredentials.getQuotaProjectId());
}
@Test
@@ -758,17 +817,17 @@ void buildWithUniverseDomain() throws IOException {
GoogleCredentials updated = original.toBuilder().setUniverseDomain("universe2").build();
assertEquals("universe1", original.getUniverseDomain());
- assertEquals(true, original.isExplicitUniverseDomain());
+ assertTrue(original.isExplicitUniverseDomain());
assertEquals("universe2", updated.getUniverseDomain());
- assertEquals(true, updated.isExplicitUniverseDomain());
+ assertTrue(updated.isExplicitUniverseDomain());
GoogleCredentials withEmpty = original.toBuilder().setUniverseDomain("").build();
assertEquals(GOOGLE_DEFAULT_UNIVERSE, withEmpty.getUniverseDomain());
- assertEquals(false, withEmpty.isExplicitUniverseDomain());
+ assertFalse(withEmpty.isExplicitUniverseDomain());
GoogleCredentials withNull = original.toBuilder().setUniverseDomain(null).build();
assertEquals(GOOGLE_DEFAULT_UNIVERSE, withNull.getUniverseDomain());
- assertEquals(false, withNull.isExplicitUniverseDomain());
+ assertFalse(withNull.isExplicitUniverseDomain());
}
@Test
@@ -778,22 +837,22 @@ void serialize() throws IOException, ClassNotFoundException {
assertEquals(testCredentials, deserializedCredentials);
assertEquals(testCredentials.hashCode(), deserializedCredentials.hashCode());
assertEquals(testCredentials.toString(), deserializedCredentials.toString());
- assertSame(deserializedCredentials.clock, Clock.SYSTEM);
+ assertSame(Clock.SYSTEM, deserializedCredentials.clock);
}
@Test
- void toString_containsFields() throws IOException {
+ void toString_containsFields() {
String expectedToString =
String.format(
"GoogleCredentials{quotaProjectId=%s, universeDomain=%s, isExplicitUniverseDomain=%s}",
- "some-project", "googleapis.com", false, "[some scope]");
+ "some-project", "googleapis.com", false);
GoogleCredentials credentials =
GoogleCredentials.newBuilder().setQuotaProjectId("some-project").build();
assertEquals(expectedToString, credentials.toString());
}
@Test
- void hashCode_equals() throws IOException {
+ void hashCode_equals() {
GoogleCredentials credentials =
GoogleCredentials.newBuilder().setUniverseDomain("some-domain").build();
GoogleCredentials otherCredentials =
@@ -802,24 +861,13 @@ void hashCode_equals() throws IOException {
}
@Test
- void equals_true() throws IOException {
+ void equals_true() {
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));
- }
+ assertEquals(credentials, otherCredentials);
+ assertEquals(otherCredentials, credentials);
}
@Test
@@ -854,7 +902,7 @@ void getCredentialInfo_userCredentials() throws IOException {
void getCredentialInfo_gdchCredentials() throws IOException {
InputStream gdchServiceAccountStream =
GdchCredentialsTest.writeGdchServiceAccountStream(
- GDCH_SA_FORMAT_VERSION,
+ GdchCredentials.SUPPORTED_JSON_FORMAT_VERSION,
GDCH_SA_PROJECT_ID,
GDCH_SA_PRIVATE_KEY_ID,
GDCH_SA_PRIVATE_KEY_PKC8,
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ITDownscopingTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ITDownscopingTest.java
index 2a04d771030d..5422760c4396 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ITDownscopingTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ITDownscopingTest.java
@@ -32,8 +32,8 @@
package com.google.auth.oauth2;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
@@ -122,12 +122,11 @@ public AccessToken refreshAccessToken() throws IOException {
// Attempt to retrieve the object that the downscoped token does not have access to. This should
// fail.
- try {
- retrieveObjectFromGcs(credentials, GCS_OBJECT_NAME_WITHOUT_PERMISSION);
- fail("Call to GCS should have failed.");
- } catch (HttpResponseException e) {
- assertEquals(403, e.getStatusCode());
- }
+ HttpResponseException e =
+ assertThrows(
+ HttpResponseException.class,
+ () -> retrieveObjectFromGcs(credentials, GCS_OBJECT_NAME_WITHOUT_PERMISSION));
+ assertEquals(403, e.getStatusCode());
}
private void retrieveObjectFromGcs(Credentials credentials, String objectName)
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ITWorkloadIdentityFederationTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ITWorkloadIdentityFederationTest.java
index d1574a06a2fc..0f1cdd3092f6 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ITWorkloadIdentityFederationTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ITWorkloadIdentityFederationTest.java
@@ -312,13 +312,13 @@ private GenericJson buildIdentityPoolCredentialConfig() throws IOException {
private GenericJson buildPluggableCredentialConfig() throws IOException {
String idToken = generateGoogleIdToken(OIDC_AUDIENCE);
- Instant expiration_time = Instant.now().plusSeconds(60 * 60);
+ Instant expirationTime = Instant.now().plusSeconds(60 * 60);
GenericJson executableJson = new GenericJson();
executableJson.setFactory(OAuth2Utils.JSON_FACTORY);
executableJson.put("success", true);
executableJson.put("version", 1);
- executableJson.put("expiration_time", expiration_time.toEpochMilli());
+ executableJson.put("expirationTime", expirationTime.toEpochMilli());
executableJson.put("token_type", "urn:ietf:params:oauth:token-type:jwt");
executableJson.put("id_token", idToken);
@@ -403,8 +403,8 @@ private void callGcs(GoogleCredentials credentials) throws IOException {
}
/**
- * Generates a Google ID token using the iamcredentials generateIdToken API.
- * https://cloud.google.com/iam/docs/creating-short-lived-service-account-credentials#sa-credentials-oidc
+ * Generates a Google ID token using the iamcredentials generateIdToken API. ...
*/
private String generateGoogleIdToken(String audience) throws IOException {
GoogleCredentials googleCredentials =
@@ -451,10 +451,10 @@ private String getXmlValueByTagName(String rawXml, String tagName) {
return null;
}
- private class ITAwsSecurityCredentialsProvider implements AwsSecurityCredentialsSupplier {
+ private static class ITAwsSecurityCredentialsProvider implements AwsSecurityCredentialsSupplier {
- private String region;
- private AwsSecurityCredentials credentials;
+ private final String region;
+ private final AwsSecurityCredentials credentials;
ITAwsSecurityCredentialsProvider(String region, AwsSecurityCredentials credentials) {
this.region = region;
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/IdTokenTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/IdTokenTest.java
index 52fa2c00885e..6ab42fa49e2f 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/IdTokenTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/IdTokenTest.java
@@ -32,8 +32,7 @@
package com.google.auth.oauth2;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
import java.io.IOException;
import java.util.Date;
@@ -61,16 +60,16 @@ void constructor() throws IOException {
void equals_true() throws IOException {
IdToken accessToken = IdToken.create(TOKEN_1);
IdToken otherAccessToken = IdToken.create(TOKEN_1);
- assertTrue(accessToken.equals(otherAccessToken));
- assertTrue(otherAccessToken.equals(accessToken));
+ assertEquals(accessToken, otherAccessToken);
+ assertEquals(otherAccessToken, accessToken);
}
@Test
void equals_false_token() throws IOException {
IdToken accessToken = IdToken.create(TOKEN_1);
IdToken otherAccessToken = IdToken.create(TOKEN_2);
- assertFalse(accessToken.equals(otherAccessToken));
- assertFalse(otherAccessToken.equals(accessToken));
+ assertNotEquals(accessToken, otherAccessToken);
+ assertNotEquals(otherAccessToken, accessToken);
}
@Test
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/IdentityPoolCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/IdentityPoolCredentialsTest.java
index 6997c79b0ef2..674d523e5090 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/IdentityPoolCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/IdentityPoolCredentialsTest.java
@@ -34,14 +34,12 @@
import static com.google.auth.Credentials.GOOGLE_DEFAULT_UNIVERSE;
import static com.google.auth.oauth2.MockExternalAccountCredentialsTransport.SERVICE_ACCOUNT_IMPERSONATION_URL;
import static com.google.auth.oauth2.OAuth2Utils.JSON_FACTORY;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.GenericJson;
@@ -78,7 +76,7 @@ class IdentityPoolCredentialsTest extends BaseSerializationTest {
(ExternalAccountSupplierContext context) -> "testSubjectToken";
@Test
- void createdScoped_clonedCredentialWithAddedScopes() throws IOException {
+ void createdScoped_clonedCredentialWithAddedScopes() {
IdentityPoolCredentials credentials =
IdentityPoolCredentials.newBuilder(createBaseFileSourcedCredentials())
.setServiceAccountImpersonationUrl(SERVICE_ACCOUNT_IMPERSONATION_URL)
@@ -188,12 +186,11 @@ void retrieveSubjectToken_fileSourcedWithNullFormat_throws() throws IOException
credentialSourceMap.put("file", file.getAbsolutePath());
credentialSourceMap.put("format", formatMap);
- try {
- new IdentityPoolCredentialSource(credentialSourceMap);
- fail("Exception should be thrown due to null format.");
- } catch (IllegalArgumentException e) {
- assertEquals("Invalid credential source format type: null.", e.getMessage());
- }
+ IllegalArgumentException e =
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> new IdentityPoolCredentialSource(credentialSourceMap));
+ assertEquals("Invalid credential source format type: null.", e.getMessage());
}
@Test
@@ -209,14 +206,10 @@ void retrieveSubjectToken_noFile_throws() {
.setCredentialSource(credentialSource)
.build();
- try {
- credentials.retrieveSubjectToken();
- fail("Exception should be thrown.");
- } catch (IOException e) {
- assertEquals(
- String.format("Invalid credential location. The file at %s does not exist.", path),
- e.getMessage());
- }
+ IOException e = assertThrows(IOException.class, credentials::retrieveSubjectToken);
+ assertEquals(
+ String.format("Invalid credential location. The file at %s does not exist.", path),
+ e.getMessage());
}
@Test
@@ -276,15 +269,11 @@ void retrieveSubjectToken_urlSourcedCredential_throws() {
buildUrlBasedCredentialSource(transportFactory.transport.getMetadataUrl()))
.build();
- try {
- credential.retrieveSubjectToken();
- fail("Exception should be thrown.");
- } catch (IOException e) {
- assertEquals(
- String.format(
- "Error getting subject token from metadata server: %s", response.getMessage()),
- e.getMessage());
- }
+ IOException e = assertThrows(IOException.class, credential::retrieveSubjectToken);
+ assertEquals(
+ String.format(
+ "Error getting subject token from metadata server: %s", response.getMessage()),
+ e.getMessage());
}
@Test
@@ -303,7 +292,7 @@ void retrieveSubjectToken_provider() throws IOException {
}
@Test
- void retrieveSubjectToken_providerThrowsError() throws IOException {
+ void retrieveSubjectToken_providerThrowsError() {
IOException testException = new IOException("test");
IdentityPoolSubjectTokenSupplier errorProvider =
@@ -316,12 +305,8 @@ void retrieveSubjectToken_providerThrowsError() throws IOException {
.setSubjectTokenSupplier(errorProvider)
.build();
- try {
- String subjectToken = credentials.retrieveSubjectToken();
- fail("retrieveSubjectToken should fail.");
- } catch (IOException e) {
- assertEquals("test", e.getMessage());
- }
+ IOException e = assertThrows(IOException.class, credentials::retrieveSubjectToken);
+ assertEquals("test", e.getMessage());
}
@Test
@@ -458,7 +443,7 @@ void refreshAccessToken_withServiceAccountImpersonationOptions() throws IOExcept
.setCredentialSource(
buildUrlBasedCredentialSource(transportFactory.transport.getMetadataUrl()))
.setServiceAccountImpersonationOptions(
- ExternalAccountCredentialsTest.buildServiceAccountImpersonationOptions(2800))
+ ExternalAccountCredentialsTest.buildServiceAccountImpersonationOptions())
.build();
AccessToken accessToken = credential.refreshAccessToken();
@@ -590,7 +575,7 @@ void refreshAccessToken_workforceWithServiceAccountImpersonationOptions() throws
buildUrlBasedCredentialSource(transportFactory.transport.getMetadataUrl()))
.setWorkforcePoolUserProject("userProject")
.setServiceAccountImpersonationOptions(
- ExternalAccountCredentialsTest.buildServiceAccountImpersonationOptions(2800))
+ ExternalAccountCredentialsTest.buildServiceAccountImpersonationOptions())
.build();
AccessToken accessToken = credential.refreshAccessToken();
@@ -646,7 +631,7 @@ void identityPoolCredentialSource_validFormats() {
credentialSourceMapWithUrlJsonTextSource);
for (Map source : sources) {
// Should not throw.
- new IdentityPoolCredentialSource(source);
+ assertDoesNotThrow(() -> new IdentityPoolCredentialSource(source));
}
}
@@ -689,20 +674,20 @@ void identityPoolCredentialSource_caseInsensitive() {
credentialSourceMapWithUrlJsonTextSource);
for (Map source : sources) {
// Should not throw.
- new IdentityPoolCredentialSource(source);
+ assertDoesNotThrow(() -> new IdentityPoolCredentialSource(source));
}
}
@Test
void identityPoolCredentialSource_invalidSourceType() {
- try {
- new IdentityPoolCredentialSource(new HashMap<>());
- fail("Should not be able to continue without exception.");
- } catch (IllegalArgumentException exception) {
- assertEquals(
- "Missing credential source file location, URL, or certificate. At least one must be specified.",
- exception.getMessage());
- }
+ HashMap credentialSourceMap = new HashMap<>();
+ IllegalArgumentException e =
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> new IdentityPoolCredentialSource(credentialSourceMap));
+ assertEquals(
+ "Missing credential source file location, URL, or certificate. At least one must be specified.",
+ e.getMessage());
}
@Test
@@ -714,12 +699,11 @@ void identityPoolCredentialSource_invalidFormatType() {
format.put("type", "unsupportedType");
credentialSourceMap.put("format", format);
- try {
- new IdentityPoolCredentialSource(credentialSourceMap);
- fail("Exception should be thrown.");
- } catch (IllegalArgumentException e) {
- assertEquals("Invalid credential source format type: unsupportedType.", e.getMessage());
- }
+ IllegalArgumentException e =
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> new IdentityPoolCredentialSource(credentialSourceMap));
+ assertEquals("Invalid credential source format type: unsupportedType.", e.getMessage());
}
@Test
@@ -731,12 +715,11 @@ void identityPoolCredentialSource_nullFormatType() {
format.put("type", null);
credentialSourceMap.put("format", format);
- try {
- new IdentityPoolCredentialSource(credentialSourceMap);
- fail("Exception should be thrown.");
- } catch (IllegalArgumentException e) {
- assertEquals("Invalid credential source format type: null.", e.getMessage());
- }
+ IllegalArgumentException e =
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> new IdentityPoolCredentialSource(credentialSourceMap));
+ assertEquals("Invalid credential source format type: null.", e.getMessage());
}
@Test
@@ -748,18 +731,17 @@ void identityPoolCredentialSource_subjectTokenFieldNameUnset() {
format.put("type", "json");
credentialSourceMap.put("format", format);
- try {
- new IdentityPoolCredentialSource(credentialSourceMap);
- fail("Exception should be thrown.");
- } catch (IllegalArgumentException e) {
- assertEquals(
- "When specifying a JSON credential type, the subject_token_field_name must be set.",
- e.getMessage());
- }
+ IllegalArgumentException e =
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> new IdentityPoolCredentialSource(credentialSourceMap));
+ assertEquals(
+ "When specifying a JSON credential type, the subject_token_field_name must be set.",
+ e.getMessage());
}
@Test
- void builder_allFields() throws IOException {
+ void builder_allFields() {
List scopes = Arrays.asList("scope1", "scope2");
IdentityPoolCredentialSource credentialSource = createFileCredentialSource();
@@ -831,23 +813,20 @@ void builder_invalidWorkforceAudiences_throws() {
"//iam.googleapis.com/locations/global/workforce/providers");
for (String audience : invalidAudiences) {
- try {
- IdentityPoolCredentials.newBuilder()
- .setWorkforcePoolUserProject("workforcePoolUserProject")
- .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
- .setAudience(audience)
- .setSubjectTokenType("subjectTokenType")
- .setTokenUrl(STS_URL)
- .setTokenInfoUrl("tokenInfoUrl")
- .setCredentialSource(createFileCredentialSource())
- .setQuotaProjectId("quotaProjectId")
- .build();
- fail("Exception should be thrown.");
- } catch (IllegalArgumentException e) {
- assertEquals(
- "The workforce_pool_user_project parameter should only be provided for a Workforce Pool configuration.",
- e.getMessage());
- }
+ IdentityPoolCredentials.Builder builder =
+ IdentityPoolCredentials.newBuilder()
+ .setWorkforcePoolUserProject("workforcePoolUserProject")
+ .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
+ .setAudience(audience)
+ .setSubjectTokenType("subjectTokenType")
+ .setTokenUrl(STS_URL)
+ .setTokenInfoUrl("tokenInfoUrl")
+ .setCredentialSource(createFileCredentialSource())
+ .setQuotaProjectId("quotaProjectId");
+ IllegalArgumentException e = assertThrows(IllegalArgumentException.class, builder::build);
+ assertEquals(
+ "The workforce_pool_user_project parameter should only be provided for a Workforce Pool configuration.",
+ e.getMessage());
}
}
@@ -872,44 +851,37 @@ void builder_emptyWorkforceUserProjectWithWorkforceAudience() {
@Test
void builder_supplierAndCredSourceThrows() {
- try {
- IdentityPoolCredentials credentials =
- IdentityPoolCredentials.newBuilder()
- .setSubjectTokenSupplier(testProvider)
- .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
- .setAudience("audience")
- .setSubjectTokenType("subjectTokenType")
- .setTokenUrl(STS_URL)
- .setCredentialSource(createFileCredentialSource())
- .build();
- fail("Should not be able to continue without exception.");
- } catch (IllegalArgumentException exception) {
- assertEquals(
- "IdentityPoolCredentials cannot have both a subjectTokenSupplier and a credentialSource.",
- exception.getMessage());
- }
+ IdentityPoolCredentials.Builder builder =
+ IdentityPoolCredentials.newBuilder()
+ .setSubjectTokenSupplier(testProvider)
+ .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
+ .setAudience("audience")
+ .setSubjectTokenType("subjectTokenType")
+ .setTokenUrl(STS_URL)
+ .setCredentialSource(createFileCredentialSource());
+ IllegalArgumentException exception =
+ assertThrows(IllegalArgumentException.class, builder::build);
+ assertEquals(
+ "IdentityPoolCredentials cannot have both a subjectTokenSupplier and a credentialSource.",
+ exception.getMessage());
}
@Test
- void builder_noSupplierOrCredSourceThrows() throws IOException {
-
- try {
- IdentityPoolCredentials credentials =
- IdentityPoolCredentials.newBuilder()
- .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
- .setAudience("audience")
- .setSubjectTokenType("subjectTokenType")
- .setTokenUrl(STS_URL)
- .build();
- fail("Should not be able to continue without exception.");
- } catch (IllegalArgumentException exception) {
- assertEquals(
- "A subjectTokenSupplier or a credentialSource must be provided.", exception.getMessage());
- }
+ void builder_noSupplierOrCredSourceThrows() {
+ IdentityPoolCredentials.Builder builder =
+ IdentityPoolCredentials.newBuilder()
+ .setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
+ .setAudience("audience")
+ .setSubjectTokenType("subjectTokenType")
+ .setTokenUrl(STS_URL);
+ IllegalArgumentException exception =
+ assertThrows(IllegalArgumentException.class, builder::build);
+ assertEquals(
+ "A subjectTokenSupplier or a credentialSource must be provided.", exception.getMessage());
}
@Test
- void builder_missingUniverseDomain_defaults() throws IOException {
+ void builder_missingUniverseDomain_defaults() {
List scopes = Arrays.asList("scope1", "scope2");
IdentityPoolCredentialSource credentialSource = createFileCredentialSource();
@@ -944,7 +916,7 @@ void builder_missingUniverseDomain_defaults() throws IOException {
}
@Test
- void newBuilder_allFields() throws IOException {
+ void newBuilder_allFields() {
List scopes = Arrays.asList("scope1", "scope2");
IdentityPoolCredentials credentials =
@@ -986,7 +958,7 @@ void newBuilder_allFields() throws IOException {
}
@Test
- void newBuilder_noUniverseDomain_defaults() throws IOException {
+ void newBuilder_noUniverseDomain_defaults() {
List scopes = Arrays.asList("scope1", "scope2");
IdentityPoolCredentials credentials =
@@ -1045,14 +1017,42 @@ void serialize() throws IOException, ClassNotFoundException {
}
@Test
- void build_withCertificateSourceAndCustomX509Provider_success()
- throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException {
- // Create an empty KeyStore and a spy on a custom X509Provider.
- KeyStore keyStore = KeyStore.getInstance("JKS");
- keyStore.load(null, null);
- TestX509Provider x509Provider =
- spy(new TestX509Provider(keyStore, "/path/to/certificate.json"));
+ void build_withCertificateSource_succeeds() throws Exception {
+ // Set up credential source for certificate type.
+ Map certificateMap = new HashMap<>();
+ certificateMap.put("use_default_certificate_config", false);
+ certificateMap.put("certificate_config_location", "testresources/mtls/certificate_config.json");
+ Map credentialSourceMap = new HashMap<>();
+ credentialSourceMap.put("certificate", certificateMap);
+ IdentityPoolCredentialSource credentialSource =
+ new IdentityPoolCredentialSource(credentialSourceMap);
+ MockExternalAccountCredentialsTransportFactory mockTransportFactory =
+ new MockExternalAccountCredentialsTransportFactory();
+ // Build credentials.
+ IdentityPoolCredentials credentials =
+ IdentityPoolCredentials.newBuilder()
+ .setHttpTransportFactory(mockTransportFactory)
+ .setAudience("test-audience")
+ .setSubjectTokenType("test-token-type")
+ .setCredentialSource(credentialSource)
+ .build();
+
+ // Verify successful creation and correct internal setup.
+ assertNotNull(credentials, "Credentials should be successfully created");
+ assertTrue(
+ credentials.getIdentityPoolSubjectTokenSupplier()
+ instanceof CertificateIdentityPoolSubjectTokenSupplier,
+ "Subject token supplier should be for certificates");
+ assertEquals(
+ IdentityPoolCredentials.CERTIFICATE_METRICS_HEADER_VALUE,
+ credentials.getCredentialSourceType(),
+ "Metrics header should indicate certificate source");
+ }
+
+ @Test
+ void build_withDefaultCertificateConfig_success()
+ throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException {
// Set up credential source for certificate type.
Map certificateMap = new HashMap<>();
certificateMap.put("use_default_certificate_config", true);
@@ -1063,11 +1063,18 @@ void build_withCertificateSourceAndCustomX509Provider_success()
MockExternalAccountCredentialsTransportFactory mockTransportFactory =
new MockExternalAccountCredentialsTransportFactory();
- // Build credentials with the custom provider.
+ // Use the pre-existing test configuration file to bypass well-known path resolution.
+ EnvironmentProvider mockEnvProvider =
+ name ->
+ "GOOGLE_API_CERTIFICATE_CONFIG".equals(name)
+ ? new File("testresources/mtls/certificate_config.json").getAbsolutePath()
+ : null;
+
+ // Build credentials using the default provider (no setX509Provider).
IdentityPoolCredentials credentials =
IdentityPoolCredentials.newBuilder()
- .setX509Provider(x509Provider)
.setHttpTransportFactory(mockTransportFactory)
+ .setEnvironmentProvider(mockEnvProvider)
.setAudience("test-audience")
.setSubjectTokenType("test-token-type")
.setCredentialSource(credentialSource)
@@ -1083,10 +1090,6 @@ void build_withCertificateSourceAndCustomX509Provider_success()
IdentityPoolCredentials.CERTIFICATE_METRICS_HEADER_VALUE,
credentials.getCredentialSourceType(),
"Metrics header should indicate certificate source");
-
- // Verify the custom provider methods were called during build.
- verify(x509Provider).getKeyStore();
- verify(x509Provider).getCertificatePath();
}
@Test
@@ -1148,15 +1151,17 @@ void build_withCustomProvider_throwsOnGetKeyStore()
@Test
void build_withCustomProvider_throwsOnGetCertificatePath()
throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException {
- // Simulate a scenario where the X509Provider cannot access or read the certificate
- // configuration file needed to determine the certificate path, resulting in an IOException.
+ // Simulate a scenario where path resolution fails during build with a custom
+ // provider.
+ // We achieve this by passing a non-existent configuration path which causes
+ // MtlsUtils to throw
+ // IOException.
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(null, null);
TestX509Provider x509Provider = new TestX509Provider(keyStore, "/path/to/certificate.json");
- x509Provider.setShouldThrowOnGetCertificatePath(true); // Configure to throw
Map certificateMap = new HashMap<>();
- certificateMap.put("certificate_config_location", "/path/to/certificate.json");
+ certificateMap.put("certificate_config_location", "/non/existent/path.json");
// Expect RuntimeException because the constructor wraps the IOException.
RuntimeException exception =
@@ -1164,10 +1169,9 @@ void build_withCustomProvider_throwsOnGetCertificatePath()
RuntimeException.class,
() -> createCredentialsWithCertificate(x509Provider, certificateMap));
- // Verify the cause is the expected IOException from the mock.
+ // Verify the cause is the expected IOException (or subclass) from MtlsUtils.
assertNotNull(exception.getCause());
assertTrue(exception.getCause() instanceof IOException);
- assertEquals("Simulated IOException on certificate path", exception.getCause().getMessage());
// Verify the wrapper exception message
assertEquals(
@@ -1276,7 +1280,6 @@ private static class TestX509Provider extends X509Provider {
private final KeyStore keyStore;
private final String certificatePath;
private boolean shouldThrowOnGetKeyStore = false;
- private boolean shouldThrowOnGetCertificatePath = false;
TestX509Provider(KeyStore keyStore, String certificatePath) {
super();
@@ -1292,20 +1295,8 @@ public KeyStore getKeyStore() throws IOException {
return keyStore;
}
- @Override
- public String getCertificatePath() throws IOException {
- if (shouldThrowOnGetCertificatePath) {
- throw new IOException("Simulated IOException on certificate path");
- }
- return certificatePath;
- }
-
void setShouldThrowOnGetKeyStore(boolean shouldThrow) {
this.shouldThrowOnGetKeyStore = shouldThrow;
}
-
- void setShouldThrowOnGetCertificatePath(boolean shouldThrow) {
- this.shouldThrowOnGetCertificatePath = shouldThrow;
- }
}
}
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ImpersonatedCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ImpersonatedCredentialsTest.java
index 0a70c1ec7839..044aa0ce6755 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ImpersonatedCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ImpersonatedCredentialsTest.java
@@ -34,12 +34,12 @@
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -48,6 +48,7 @@
import com.google.api.client.json.GenericJson;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.JsonGenerator;
+import com.google.api.client.json.JsonParser;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.json.webtoken.JsonWebToken.Payload;
import com.google.api.client.testing.http.MockLowLevelHttpRequest;
@@ -123,10 +124,6 @@ class ImpersonatedCredentialsTest extends BaseSerializationTest {
private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
private static final String TEST_UNIVERSE_DOMAIN = "test.xyz";
- private static final String OLD_IMPERSONATION_URL =
- "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/"
- + IMPERSONATED_CLIENT_EMAIL
- + ":generateAccessToken";
public static final String DEFAULT_IMPERSONATION_URL =
String.format(
IamUtils.IAM_ACCESS_TOKEN_ENDPOINT_FORMAT,
@@ -194,8 +191,7 @@ void fromJson_userAsSource_WithQuotaProjectId() throws IOException {
assertEquals(DELEGATES, credentials.getDelegates());
assertEquals(IMMUTABLE_SCOPES_LIST, credentials.getScopes());
assertEquals(3600, credentials.getLifetime());
- GoogleCredentials sourceCredentials = credentials.getSourceCredentials();
- assertTrue(sourceCredentials instanceof UserCredentials);
+ assertInstanceOf(UserCredentials.class, credentials.getSourceCredentials());
}
@Test()
@@ -217,8 +213,7 @@ void fromJson_userAsSource_WithoutQuotaProjectId() throws IOException {
assertEquals(DELEGATES, credentials.getDelegates());
assertEquals(IMMUTABLE_SCOPES_LIST, credentials.getScopes());
assertEquals(3600, credentials.getLifetime());
- GoogleCredentials sourceCredentials = credentials.getSourceCredentials();
- assertTrue(sourceCredentials instanceof UserCredentials);
+ assertInstanceOf(UserCredentials.class, credentials.getSourceCredentials());
}
@Test()
@@ -241,8 +236,7 @@ void fromJson_userAsSource_MissingDelegatesField() throws IOException {
assertEquals(new ArrayList(), credentials.getDelegates());
assertEquals(IMMUTABLE_SCOPES_LIST, credentials.getScopes());
assertEquals(3600, credentials.getLifetime());
- GoogleCredentials sourceCredentials = credentials.getSourceCredentials();
- assertTrue(sourceCredentials instanceof UserCredentials);
+ assertInstanceOf(UserCredentials.class, credentials.getSourceCredentials());
}
@Test()
@@ -258,19 +252,17 @@ void fromJson_ServiceAccountAsSource() throws IOException {
assertEquals(DELEGATES, credentials.getDelegates());
assertEquals(IMMUTABLE_SCOPES_LIST, credentials.getScopes());
assertEquals(3600, credentials.getLifetime());
- GoogleCredentials sourceCredentials = credentials.getSourceCredentials();
- assertTrue(sourceCredentials instanceof ServiceAccountCredentials);
+ assertInstanceOf(ServiceAccountCredentials.class, credentials.getSourceCredentials());
}
@Test()
- void fromJson_InvalidFormat() throws IOException {
+ void fromJson_InvalidFormat() {
GenericJson json = buildInvalidCredentialsJson();
- try {
- ImpersonatedCredentials.fromJson(json, mockTransportFactory);
- fail("An exception should be thrown.");
- } catch (CredentialFormatException e) {
- assertEquals("An invalid input stream was provided.", e.getMessage());
- }
+ CredentialFormatException e =
+ assertThrows(
+ CredentialFormatException.class,
+ () -> ImpersonatedCredentials.fromJson(json, mockTransportFactory));
+ assertEquals("An invalid input stream was provided.", e.getMessage());
}
@Test()
@@ -280,7 +272,7 @@ void createScopedRequired_True() {
sourceCredentials,
IMPERSONATED_CLIENT_EMAIL,
null,
- new ArrayList(),
+ new ArrayList<>(),
VALID_LIFETIME,
mockTransportFactory);
assertTrue(targetCredentials.createScopedRequired());
@@ -311,15 +303,15 @@ void createScoped() {
mockTransportFactory,
QUOTA_PROJECT_ID);
- ImpersonatedCredentials scoped_credentials =
+ ImpersonatedCredentials scopedCredentials =
(ImpersonatedCredentials) targetCredentials.createScoped(IMMUTABLE_SCOPES_LIST);
- assertEquals(targetCredentials.getAccount(), scoped_credentials.getAccount());
- assertEquals(targetCredentials.getDelegates(), scoped_credentials.getDelegates());
- assertEquals(targetCredentials.getLifetime(), scoped_credentials.getLifetime());
+ assertEquals(targetCredentials.getAccount(), scopedCredentials.getAccount());
+ assertEquals(targetCredentials.getDelegates(), scopedCredentials.getDelegates());
+ assertEquals(targetCredentials.getLifetime(), scopedCredentials.getLifetime());
assertEquals(
- targetCredentials.getSourceCredentials(), scoped_credentials.getSourceCredentials());
- assertEquals(targetCredentials.getQuotaProjectId(), scoped_credentials.getQuotaProjectId());
- assertEquals(Arrays.asList("scope1", "scope2"), scoped_credentials.getScopes());
+ targetCredentials.getSourceCredentials(), scopedCredentials.getSourceCredentials());
+ assertEquals(targetCredentials.getQuotaProjectId(), scopedCredentials.getQuotaProjectId());
+ assertEquals(Arrays.asList("scope1", "scope2"), scopedCredentials.getScopes());
}
@Test
@@ -341,10 +333,10 @@ void createScoped_existingAccessTokenInvalidated() throws IOException {
targetCredentials.refresh();
assertEquals(ACCESS_TOKEN, targetCredentials.getAccessToken().getTokenValue());
- ImpersonatedCredentials scoped_credentials =
+ ImpersonatedCredentials scopedCredentials =
(ImpersonatedCredentials) targetCredentials.createScoped(IMMUTABLE_SCOPES_LIST);
- assertNull(scoped_credentials.getAccessToken());
+ assertNull(scopedCredentials.getAccessToken());
}
@Test
@@ -359,15 +351,15 @@ void createScopedWithImmutableScopes() {
mockTransportFactory,
QUOTA_PROJECT_ID);
- ImpersonatedCredentials scoped_credentials =
+ ImpersonatedCredentials scopedCredentials =
(ImpersonatedCredentials) targetCredentials.createScoped(IMMUTABLE_SCOPES_SET);
- assertEquals(targetCredentials.getAccount(), scoped_credentials.getAccount());
- assertEquals(targetCredentials.getDelegates(), scoped_credentials.getDelegates());
- assertEquals(targetCredentials.getLifetime(), scoped_credentials.getLifetime());
+ assertEquals(targetCredentials.getAccount(), scopedCredentials.getAccount());
+ assertEquals(targetCredentials.getDelegates(), scopedCredentials.getDelegates());
+ assertEquals(targetCredentials.getLifetime(), scopedCredentials.getLifetime());
assertEquals(
- targetCredentials.getSourceCredentials(), scoped_credentials.getSourceCredentials());
- assertEquals(targetCredentials.getQuotaProjectId(), scoped_credentials.getQuotaProjectId());
- assertEquals(Arrays.asList("scope1", "scope2"), scoped_credentials.getScopes());
+ targetCredentials.getSourceCredentials(), scopedCredentials.getSourceCredentials());
+ assertEquals(targetCredentials.getQuotaProjectId(), scopedCredentials.getQuotaProjectId());
+ assertEquals(Arrays.asList("scope1", "scope2"), scopedCredentials.getScopes());
}
@Test
@@ -383,10 +375,10 @@ void createScopedWithIamEndpointOverride() {
QUOTA_PROJECT_ID,
IMPERSONATION_OVERRIDE_URL);
- ImpersonatedCredentials scoped_credentials =
+ ImpersonatedCredentials scopedCredentials =
(ImpersonatedCredentials) targetCredentials.createScoped(IMMUTABLE_SCOPES_SET);
assertEquals(
- targetCredentials.getIamEndpointOverride(), scoped_credentials.getIamEndpointOverride());
+ targetCredentials.getIamEndpointOverride(), scopedCredentials.getIamEndpointOverride());
}
@Test
@@ -409,13 +401,9 @@ void refreshAccessToken_unauthorized() throws IOException {
VALID_LIFETIME,
mockTransportFactory);
- try {
- targetCredentials.refreshAccessToken().getTokenValue();
- fail(String.format("Should throw exception with message containing '%s'", expectedMessage));
- } catch (IOException expected) {
- assertEquals("Error requesting access token", expected.getMessage());
- assertTrue(expected.getCause().getMessage().contains(expectedMessage));
- }
+ IOException expected = assertThrows(IOException.class, targetCredentials::refreshAccessToken);
+ assertEquals("Error requesting access token", expected.getMessage());
+ assertTrue(expected.getCause().getMessage().contains(expectedMessage));
}
@Test()
@@ -439,13 +427,9 @@ void refreshAccessToken_malformedTarget() throws IOException {
VALID_LIFETIME,
mockTransportFactory);
- try {
- targetCredentials.refreshAccessToken().getTokenValue();
- fail(String.format("Should throw exception with message containing '%s'", expectedMessage));
- } catch (IOException expected) {
- assertEquals("Error requesting access token", expected.getMessage());
- assertTrue(expected.getCause().getMessage().contains(expectedMessage));
- }
+ IOException expected = assertThrows(IOException.class, targetCredentials::refreshAccessToken);
+ assertEquals("Error requesting access token", expected.getMessage());
+ assertTrue(expected.getCause().getMessage().contains(expectedMessage));
}
@Test()
@@ -457,28 +441,22 @@ void credential_with_zero_lifetime() throws IllegalStateException {
}
@Test()
- void credential_with_invalid_lifetime() throws IOException, IllegalStateException {
-
- try {
- ImpersonatedCredentials targetCredentials =
- ImpersonatedCredentials.create(
- sourceCredentials,
- IMPERSONATED_CLIENT_EMAIL,
- null,
- IMMUTABLE_SCOPES_LIST,
- INVALID_LIFETIME);
- targetCredentials.refreshAccessToken().getTokenValue();
- fail(
- String.format(
- "Should throw exception with message containing '%s'",
- "lifetime must be less than or equal to 43200"));
- } catch (IllegalStateException expected) {
- assertTrue(expected.getMessage().contains("lifetime must be less than or equal to 43200"));
- }
+ void credential_with_invalid_lifetime() throws IllegalStateException {
+ IllegalStateException expected =
+ assertThrows(
+ IllegalStateException.class,
+ () ->
+ ImpersonatedCredentials.create(
+ sourceCredentials,
+ IMPERSONATED_CLIENT_EMAIL,
+ null,
+ IMMUTABLE_SCOPES_LIST,
+ INVALID_LIFETIME));
+ assertTrue(expected.getMessage().contains("lifetime must be less than or equal to 43200"));
}
@Test()
- void credential_with_invalid_scope() throws IOException, IllegalStateException {
+ void credential_with_invalid_scope() throws IllegalStateException {
assertThrows(
NullPointerException.class,
() ->
@@ -667,12 +645,8 @@ void refreshAccessToken_invalidDate() throws IllegalStateException {
VALID_LIFETIME,
mockTransportFactory);
- try {
- targetCredentials.refreshAccessToken().getTokenValue();
- fail(String.format("Should throw exception with message containing '%s'", expectedMessage));
- } catch (IOException expected) {
- assertTrue(expected.getMessage().contains(expectedMessage));
- }
+ IOException expected = assertThrows(IOException.class, targetCredentials::refreshAccessToken);
+ assertTrue(expected.getMessage().contains(expectedMessage));
}
@Test
@@ -738,13 +712,13 @@ void sign_requestIncludesDelegates() throws IOException {
assertArrayEquals(expectedSignature, targetCredentials.sign(expectedSignature));
MockLowLevelHttpRequest request = mockTransportFactory.getTransport().getRequest();
- GenericJson body =
- JSON_FACTORY
- .createJsonParser(request.getContentAsString())
- .parseAndClose(GenericJson.class);
- List delegates = new ArrayList<>();
- delegates.add("delegate@example.com");
- assertEquals(delegates, body.get("delegates"));
+
+ try (JsonParser jsonParser = JSON_FACTORY.createJsonParser(request.getContentAsString())) {
+ GenericJson body = jsonParser.parseAndClose(GenericJson.class);
+ List delegates = new ArrayList<>();
+ delegates.add("delegate@example.com");
+ assertEquals(delegates, body.get("delegates"));
+ }
}
@Test
@@ -752,7 +726,7 @@ void sign_usesSourceCredentials() {
Calendar c = Calendar.getInstance();
c.add(Calendar.DATE, 1);
Date expiry = c.getTime();
- GoogleCredentials sourceCredentials =
+ GoogleCredentials sourceCred =
new GoogleCredentials.Builder()
.setAccessToken(new AccessToken("source-token", expiry))
.build();
@@ -763,7 +737,7 @@ void sign_usesSourceCredentials() {
mockTransportFactory.getTransport().addStatusCodeAndMessage(HttpStatusCodes.STATUS_CODE_OK, "");
ImpersonatedCredentials targetCredentials =
ImpersonatedCredentials.create(
- sourceCredentials,
+ sourceCred,
IMPERSONATED_CLIENT_EMAIL,
ImmutableList.of("delegate@example.com"),
IMMUTABLE_SCOPES_LIST,
@@ -803,15 +777,11 @@ void sign_accessDenied_throws() {
.getTransport()
.addStatusCodeAndMessage(HttpStatusCodes.STATUS_CODE_FORBIDDEN, "Sign Error");
- try {
- byte[] bytes = {0xD, 0xE, 0xA, 0xD};
- targetCredentials.sign(bytes);
- fail("Signing should have failed");
- } catch (SigningException e) {
- assertEquals("Failed to sign the provided bytes", e.getMessage());
- assertNotNull(e.getCause());
- assertTrue(e.getCause().getMessage().contains("403"));
- }
+ SigningException e =
+ assertThrows(SigningException.class, () -> targetCredentials.sign(expectedSignature));
+ assertEquals("Failed to sign the provided bytes", e.getMessage());
+ assertNotNull(e.getCause());
+ assertTrue(e.getCause().getMessage().contains("403"));
}
@Test
@@ -836,15 +806,11 @@ void sign_serverError_throws() {
.getTransport()
.addStatusCodeAndMessage(HttpStatusCodes.STATUS_CODE_NOT_FOUND, "Sign Error");
- try {
- byte[] bytes = {0xD, 0xE, 0xA, 0xD};
- targetCredentials.sign(bytes);
- fail("Signing should have failed");
- } catch (SigningException e) {
- assertEquals("Failed to sign the provided bytes", e.getMessage());
- assertNotNull(e.getCause());
- assertTrue(e.getCause().getMessage().contains("404"));
- }
+ SigningException e =
+ assertThrows(SigningException.class, () -> targetCredentials.sign(expectedSignature));
+ assertEquals("Failed to sign the provided bytes", e.getMessage());
+ assertNotNull(e.getCause());
+ assertTrue(e.getCause().getMessage().contains("404"));
}
@Test
@@ -1039,12 +1005,8 @@ void idToken_withServerError() {
.setIdTokenProvider(targetCredentials)
.setTargetAudience(targetAudience)
.build();
- try {
- tokenCredential.refresh();
- fail("Should not be able to use credential without exception.");
- } catch (IOException e) {
- assertTrue(e.getMessage().contains("Error code 500 trying to getIDToken"));
- }
+ IOException e = assertThrows(IOException.class, tokenCredential::refresh);
+ assertTrue(e.getMessage().contains("Error code 500 trying to getIDToken"));
}
@Test
@@ -1073,12 +1035,8 @@ void idToken_withOtherError() {
.setIdTokenProvider(targetCredentials)
.setTargetAudience(targetAudience)
.build();
- try {
- tokenCredential.refresh();
- fail("Should not be able to use credential without exception.");
- } catch (IOException e) {
- assertTrue(e.getMessage().contains("Unexpected Error code 301 trying to getIDToken"));
- }
+ IOException e = assertThrows(IOException.class, tokenCredential::refresh);
+ assertTrue(e.getMessage().contains("Unexpected Error code 301 trying to getIDToken"));
}
@Test
@@ -1115,22 +1073,20 @@ void universeDomain_getFromSourceCredentials() throws IOException {
}
@Test
- void universeDomain_whenExplicit_notAllowedIfNotMatchToSourceUD() throws IOException {
+ void universeDomain_whenExplicit_notAllowedIfNotMatchToSourceUD() {
GoogleCredentials sourceCredentialsNonGDU =
sourceCredentials.toBuilder().setUniverseDomain("source.domain.xyz").build();
+ GoogleCredentials.Builder builder =
+ ImpersonatedCredentials.newBuilder()
+ .setSourceCredentials(sourceCredentialsNonGDU)
+ .setTargetPrincipal(IMPERSONATED_CLIENT_EMAIL)
+ .setDelegates(null)
+ .setScopes(IMMUTABLE_SCOPES_LIST)
+ .setLifetime(VALID_LIFETIME)
+ .setHttpTransportFactory(mockTransportFactory)
+ .setUniverseDomain("explicit.domain.com");
IllegalStateException illegalStateException =
- assertThrows(
- IllegalStateException.class,
- () ->
- ImpersonatedCredentials.newBuilder()
- .setSourceCredentials(sourceCredentialsNonGDU)
- .setTargetPrincipal(IMPERSONATED_CLIENT_EMAIL)
- .setDelegates(null)
- .setScopes(IMMUTABLE_SCOPES_LIST)
- .setLifetime(VALID_LIFETIME)
- .setHttpTransportFactory(mockTransportFactory)
- .setUniverseDomain("explicit.domain.com")
- .build());
+ assertThrows(IllegalStateException.class, builder::build);
assertEquals(
"Universe domain source.domain.xyz in source credentials"
+ " does not match explicit.domain.com universe domain set for impersonated credentials.",
@@ -1195,7 +1151,7 @@ void scopes_userConfiguredAndFromJson() throws IOException {
}
@Test
- void hashCode_equals() throws IOException {
+ void hashCode_equals() {
mockTransportFactory.getTransport().setTargetPrincipal(IMPERSONATED_CLIENT_EMAIL);
mockTransportFactory.getTransport().setAccessToken(ACCESS_TOKEN);
mockTransportFactory.getTransport().setExpireTime(getDefaultExpireTime());
@@ -1240,7 +1196,7 @@ void serialize() throws IOException, ClassNotFoundException {
assertEquals(targetCredentials, deserializedCredentials);
assertEquals(targetCredentials.hashCode(), deserializedCredentials.hashCode());
assertEquals(targetCredentials.toString(), deserializedCredentials.toString());
- assertSame(deserializedCredentials.clock, Clock.SYSTEM);
+ assertSame(Clock.SYSTEM, deserializedCredentials.clock);
}
/**
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/JwtCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/JwtCredentialsTest.java
index 95a4e3f4d81a..dc93eede2141 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/JwtCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/JwtCredentialsTest.java
@@ -35,7 +35,7 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
-import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
@@ -95,51 +95,38 @@ void serialize() throws IOException, ClassNotFoundException {
assertEquals(credentials, deserializedCredentials);
assertEquals(credentials.hashCode(), deserializedCredentials.hashCode());
assertEquals(credentials.toString(), deserializedCredentials.toString());
- assertSame(deserializedCredentials.getClock(), Clock.SYSTEM);
+ assertSame(Clock.SYSTEM, deserializedCredentials.getClock());
}
@Test
void builder_requiresPrivateKey() {
- try {
- JwtClaims claims =
- JwtClaims.newBuilder()
- .setAudience("some-audience")
- .setIssuer("some-issuer")
- .setSubject("some-subject")
- .build();
- JwtCredentials.newBuilder().setJwtClaims(claims).setPrivateKeyId(PRIVATE_KEY_ID).build();
- fail("Should throw exception");
- } catch (NullPointerException ex) {
- // expected
- }
+ JwtClaims claims =
+ JwtClaims.newBuilder()
+ .setAudience("some-audience")
+ .setIssuer("some-issuer")
+ .setSubject("some-subject")
+ .build();
+ JwtCredentials.Builder builder =
+ JwtCredentials.newBuilder().setJwtClaims(claims).setPrivateKeyId(PRIVATE_KEY_ID);
+ assertThrows(NullPointerException.class, builder::build);
}
@Test
void builder_requiresClaims() {
- try {
- JwtCredentials.newBuilder()
- .setPrivateKeyId(PRIVATE_KEY_ID)
- .setPrivateKey(getPrivateKey())
- .build();
- fail("Should throw exception");
- } catch (NullPointerException ex) {
- // expected
- }
+ JwtCredentials.Builder builder =
+ JwtCredentials.newBuilder().setPrivateKeyId(PRIVATE_KEY_ID).setPrivateKey(getPrivateKey());
+ assertThrows(NullPointerException.class, builder::build);
}
@Test
void builder_requiresCompleteClaims() {
- try {
- JwtClaims claims = JwtClaims.newBuilder().build();
- JwtCredentials.newBuilder()
- .setJwtClaims(claims)
- .setPrivateKeyId(PRIVATE_KEY_ID)
- .setPrivateKey(getPrivateKey())
- .build();
- fail("Should throw exception");
- } catch (IllegalStateException ex) {
- // expected
- }
+ JwtClaims claims = JwtClaims.newBuilder().build();
+ JwtCredentials.Builder builder =
+ JwtCredentials.newBuilder()
+ .setJwtClaims(claims)
+ .setPrivateKeyId(PRIVATE_KEY_ID)
+ .setPrivateKey(getPrivateKey());
+ assertThrows(IllegalStateException.class, builder::build);
}
@Test
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockExternalAccountCredentialsTransport.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockExternalAccountCredentialsTransport.java
index fc9f8ba3e80b..7719b08d2e7b 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockExternalAccountCredentialsTransport.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockExternalAccountCredentialsTransport.java
@@ -84,11 +84,11 @@ public class MockExternalAccountCredentialsTransport extends MockHttpTransport {
static final String IAM_ENDPOINT = "https://iamcredentials.googleapis.com";
- private Queue responseSequence = new ArrayDeque<>();
- private Queue responseErrorSequence = new ArrayDeque<>();
- private Queue refreshTokenSequence = new ArrayDeque<>();
- private Queue> scopeSequence = new ArrayDeque<>();
- private List requests = new ArrayList<>();
+ private final Queue responseSequence = new ArrayDeque<>();
+ private final Queue responseErrorSequence = new ArrayDeque<>();
+ private final Queue refreshTokenSequence = new ArrayDeque<>();
+ private final Queue> scopeSequence = new ArrayDeque<>();
+ private final List requests = new ArrayList<>();
private String expireTime;
private String metadataServerContentType;
private String stsContent;
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockIAMCredentialsServiceTransportFactory.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockIAMCredentialsServiceTransportFactory.java
index a1df56b4b21a..c21a42f376cd 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockIAMCredentialsServiceTransportFactory.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockIAMCredentialsServiceTransportFactory.java
@@ -35,7 +35,7 @@
import com.google.auth.http.HttpTransportFactory;
public class MockIAMCredentialsServiceTransportFactory implements HttpTransportFactory {
- private MockIAMCredentialsServiceTransport transport;
+ private final MockIAMCredentialsServiceTransport transport;
MockIAMCredentialsServiceTransportFactory() {
this(Credentials.GOOGLE_DEFAULT_UNIVERSE);
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockMetadataServerTransport.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockMetadataServerTransport.java
index 725a124fcd15..1b218b73ef45 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockMetadataServerTransport.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockMetadataServerTransport.java
@@ -44,8 +44,7 @@
import com.google.common.io.BaseEncoding;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
-import java.net.MalformedURLException;
-import java.net.URL;
+import java.net.URI;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;
@@ -168,10 +167,9 @@ public LowLevelHttpResponse execute() throws IOException {
GenericJson signContents = new GenericJson();
signContents.setFactory(OAuth2Utils.JSON_FACTORY);
signContents.put("signedBlob", BaseEncoding.base64().encode(signature));
-
- String signature = signContents.toPrettyString();
-
- return new MockLowLevelHttpResponse().setContentType(Json.MEDIA_TYPE).setContent(signature);
+ return new MockLowLevelHttpResponse()
+ .setContentType(Json.MEDIA_TYPE)
+ .setContent(signContents.toPrettyString());
}
};
}
@@ -228,7 +226,7 @@ public LowLevelHttpResponse execute() throws IOException {
}
private MockLowLevelHttpRequest getMockRequestForIdentityDocument(String url)
- throws MalformedURLException, UnsupportedEncodingException {
+ throws UnsupportedEncodingException {
if (statusCode != null && statusCode != HttpStatusCodes.STATUS_CODE_OK) {
return new MockLowLevelHttpRequest(url) {
@Override
@@ -254,7 +252,7 @@ public LowLevelHttpResponse execute() {
// https://cloud.google.com/compute/docs/instances/verifying-instance-identity#token_format
Map queryPairs = new HashMap();
- String query = (new URL(url)).getQuery();
+ String query = (URI.create(url)).getQuery();
String[] pairs = query.split("&");
for (String pair : pairs) {
int idx = pair.indexOf("=");
@@ -263,33 +261,29 @@ public LowLevelHttpResponse execute() {
URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
}
- if (queryPairs.containsKey("format")) {
- if (((String) queryPairs.get("format")).equals("full")) {
-
- // return licenses only if format=full is set
- if (queryPairs.containsKey("licenses")) {
- // The metadata server defaults to false and matches "on", "off" and ::absl::SimpleAtob.
- // See https://abseil.io/docs/cpp/guides/strings#numericConversion for more information.
- if (BOOL_PARAMETER_VALUE.matcher((String) queryPairs.get("licenses")).matches()) {
- return new MockLowLevelHttpRequest(url) {
- @Override
- public LowLevelHttpResponse execute() throws IOException {
- return new MockLowLevelHttpResponse()
- .setContent(ComputeEngineCredentialsTest.FULL_ID_TOKEN_WITH_LICENSES);
- }
- };
- }
- }
- // otherwise return full format
+ if (queryPairs.containsKey("format") && queryPairs.get("format").equals("full")) {
+ // return licenses only if format=full is set
+ if (queryPairs.containsKey("licenses")
+ && BOOL_PARAMETER_VALUE.matcher(queryPairs.get("licenses")).matches()) {
return new MockLowLevelHttpRequest(url) {
@Override
public LowLevelHttpResponse execute() throws IOException {
return new MockLowLevelHttpResponse()
- .setContent(ComputeEngineCredentialsTest.FULL_ID_TOKEN);
+ .setContent(ComputeEngineCredentialsTest.FULL_ID_TOKEN_WITH_LICENSES);
}
};
}
+
+ // otherwise return full format
+ return new MockLowLevelHttpRequest(url) {
+ @Override
+ public LowLevelHttpResponse execute() throws IOException {
+ return new MockLowLevelHttpResponse()
+ .setContent(ComputeEngineCredentialsTest.FULL_ID_TOKEN);
+ }
+ };
}
+
// Return default format if nothing is set
return new MockLowLevelHttpRequest(url) {
@Override
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockTokenCheckingTransport.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockTokenCheckingTransport.java
index 3ef4df2fe942..11af02041343 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockTokenCheckingTransport.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockTokenCheckingTransport.java
@@ -44,8 +44,8 @@ public class MockTokenCheckingTransport extends HttpTransport {
public static final String SUCCESS_CONTENT = "{\"key\":\"value\"}";
- private MockTokenServerTransport tokenServer;
- private String refreshToken;
+ private final MockTokenServerTransport tokenServer;
+ private final String refreshToken;
public MockTokenCheckingTransport(MockTokenServerTransport tokenServer, String refreshToken) {
this.tokenServer = tokenServer;
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockTokenServerTransport.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockTokenServerTransport.java
index a61c185b5704..5a6cd2e5d1a8 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockTokenServerTransport.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockTokenServerTransport.java
@@ -75,7 +75,6 @@ public class MockTokenServerTransport extends MockHttpTransport {
private final Queue> responseSequence = new ArrayDeque<>();
private int expiresInSeconds = 3600;
private MockLowLevelHttpRequest request;
- private ClientAuthenticationType clientAuthenticationType;
private PKCEProvider pkceProvider;
public MockTokenServerTransport() {}
@@ -88,9 +87,7 @@ public void setTokenServerUri(URI tokenServerUri) {
this.tokenServerUri = tokenServerUri;
}
- public void setClientAuthType(ClientAuthenticationType type) {
- this.clientAuthenticationType = type;
- }
+ public void setClientAuthType(ClientAuthenticationType type) {}
public void setPkceProvider(PKCEProvider pkceProvider) {
this.pkceProvider = pkceProvider;
@@ -141,9 +138,9 @@ public void setError(IOException error) {
this.error = error;
}
- public void addResponseErrorSequence(IOException... errors) {
- for (IOException error : errors) {
- responseSequence.add(Futures.immediateFailedFuture(error));
+ public void addResponseErrorSequence(IOException... ioExceptions) {
+ for (IOException ioException : ioExceptions) {
+ responseSequence.add(Futures.immediateFailedFuture(ioException));
}
}
@@ -173,7 +170,6 @@ public LowLevelHttpRequest buildRequest(String method, String url) throws IOExce
}
int questionMarkPos = url.indexOf('?');
final String urlWithoutQuery = (questionMarkPos > 0) ? url.substring(0, questionMarkPos) : url;
- final String query = (questionMarkPos > 0) ? url.substring(questionMarkPos + 1) : "";
if (!responseSequence.isEmpty()) {
request =
@@ -213,7 +209,7 @@ public LowLevelHttpResponse execute() throws IOException {
}
String content = this.getContentAsString();
- Map query = TestUtils.parseQuery(content);
+ Map query = parseRequestContent(content);
String accessToken = null;
String refreshToken = null;
String grantedScopesString = null;
@@ -255,16 +251,18 @@ public LowLevelHttpResponse execute() throws IOException {
} else if (query.containsKey("grant_type")) {
String grantType = query.get("grant_type");
String assertion = query.get("assertion");
+ if (assertion == null) {
+ assertion = query.get("subject_token");
+ }
JsonWebSignature signature = JsonWebSignature.parse(JSON_FACTORY, assertion);
if (OAuth2Utils.GRANT_TYPE_JWT_BEARER.equals(grantType)) {
String foundEmail = signature.getPayload().getIssuer();
- if (!serviceAccounts.containsKey(foundEmail)) {}
accessToken = serviceAccounts.get(foundEmail);
String foundTargetAudience =
(String) signature.getPayload().get("target_audience");
String foundScopes = (String) signature.getPayload().get("scope");
- if ((foundScopes == null || foundScopes.length() == 0)
- && (foundTargetAudience == null || foundTargetAudience.length() == 0)) {
+ if ((foundScopes == null || foundScopes.isEmpty())
+ && (foundTargetAudience == null || foundTargetAudience.isEmpty())) {
throw new IOException("Either target_audience or scopes must be specified.");
}
@@ -284,7 +282,10 @@ public LowLevelHttpResponse execute() throws IOException {
"GDCH Service Account Service Identity Name not found as issuer.");
}
accessToken = gdchServiceAccounts.get(foundServiceIdentityName);
- String foundApiAudience = (String) signature.getPayload().get("api_audience");
+ String foundApiAudience = query.get("audience");
+ if (foundApiAudience == null || foundApiAudience.isEmpty()) {
+ foundApiAudience = (String) signature.getPayload().get("api_audience");
+ }
if ((foundApiAudience == null || foundApiAudience.length() == 0)) {
throw new IOException("Api_audience must be specified.");
}
@@ -326,7 +327,7 @@ public LowLevelHttpResponse execute() throws IOException {
new MockLowLevelHttpRequest(url) {
@Override
public LowLevelHttpResponse execute() throws IOException {
- Map parameters = TestUtils.parseQuery(this.getContentAsString());
+ Map parameters = parseRequestContent(this.getContentAsString());
String token = parameters.get("token");
if (token == null) {
throw new IOException("Token to revoke not found.");
@@ -358,7 +359,7 @@ public LowLevelHttpResponse execute() throws IOException {
}
String content = this.getContentAsString();
- Map query = TestUtils.parseQuery(content);
+ Map query = parseRequestContent(content);
// Validate required fields.
if (!query.containsKey("code")
@@ -414,6 +415,13 @@ public LowLevelHttpResponse execute() throws IOException {
return super.buildRequest(method, url);
}
+ private Map parseRequestContent(String content) throws IOException {
+ if (content != null && content.trim().startsWith("{")) {
+ return TestUtils.parseJson(content);
+ }
+ return TestUtils.parseQuery(content);
+ }
+
private void validateAdditionalParameters(Map query) {
if (additionalParameters.containsKey(query.get("code"))) {
Map additionalParametersMap = additionalParameters.get(query.get("code"));
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/OAuth2CredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/OAuth2CredentialsTest.java
index a54765abcbbb..c726006180ca 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/OAuth2CredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/OAuth2CredentialsTest.java
@@ -32,14 +32,15 @@
package com.google.auth.oauth2;
import static java.util.concurrent.TimeUnit.HOURS;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import com.google.api.client.util.Clock;
import com.google.auth.TestClock;
@@ -100,7 +101,7 @@ void tearDown() {
void constructor_storesAccessToken() {
OAuth2Credentials credentials =
OAuth2Credentials.newBuilder().setAccessToken(new AccessToken(ACCESS_TOKEN, null)).build();
- assertEquals(credentials.getAccessToken().getTokenValue(), ACCESS_TOKEN);
+ assertEquals(ACCESS_TOKEN, credentials.getAccessToken().getTokenValue());
}
@Test
@@ -169,7 +170,7 @@ public AccessToken refreshAccessToken() throws IOException {
assertEquals(lastMetadata, callback.awaitResult());
waitForRefreshTaskCompletion(credentials);
assertEquals(1, refreshCount.get());
- lastMetadata = credentials.getRequestMetadata();
+ credentials.getRequestMetadata();
refreshCount.set(0);
// Fast forward to expired
@@ -181,7 +182,7 @@ public AccessToken refreshAccessToken() throws IOException {
TestUtils.assertContainsBearerToken(callback.awaitResult(), newToken.getTokenValue());
assertEquals(1, refreshCount.get());
waitForRefreshTaskCompletion(credentials);
- lastMetadata = credentials.getRequestMetadata();
+ credentials.getRequestMetadata();
}
@Test
@@ -192,7 +193,7 @@ void getAuthenticationType_returnsOAuth2() {
.setClientSecret(CLIENT_SECRET)
.setRefreshToken(REFRESH_TOKEN)
.build();
- assertEquals(credentials.getAuthenticationType(), "OAuth2");
+ assertEquals("OAuth2", credentials.getAuthenticationType());
}
@Test
@@ -214,7 +215,7 @@ void hasRequestMetadataOnly_returnsTrue() {
.setClientSecret(CLIENT_SECRET)
.setRefreshToken(REFRESH_TOKEN)
.build();
- assertTrue(credentials.hasRequestMetadata());
+ assertTrue(credentials.hasRequestMetadataOnly());
}
@Test
@@ -331,13 +332,9 @@ void getRequestMetadata_blocking_cachesExpiringToken() throws IOException {
clock.addToCurrentTime(60 * 60 * 1000);
assertEquals(0, transportFactory.transport.buildRequestCount);
- try {
- credentials.getRequestMetadata(CALL_URI);
- fail("Should throw");
- } catch (IOException e) {
- assertSame(error, e.getCause());
- assertEquals(1, transportFactory.transport.buildRequestCount--);
- }
+ IOException e = assertThrows(IOException.class, () -> credentials.getRequestMetadata(CALL_URI));
+ assertSame(error, e.getCause());
+ assertEquals(1, transportFactory.transport.buildRequestCount--);
// Reset the error and try again
transportFactory.transport.setError(null);
@@ -347,7 +344,7 @@ void getRequestMetadata_blocking_cachesExpiringToken() throws IOException {
}
@Test
- void getRequestMetadata_async() throws IOException {
+ void getRequestMetadata_async() {
final String accessToken1 = "1/MkSJoj1xsli0AccessToken_NKPY2";
final String accessToken2 = "2/MkSJoj1xsli0AccessToken_NKPY2";
MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
@@ -668,12 +665,12 @@ public Map> call() throws Exception {
// Get the error that getRequestMetadata(uri) created
Throwable actualBlockingError =
- assertThrows(ExecutionException.class, () -> blockingCall.get()).getCause();
+ assertThrows(ExecutionException.class, blockingCall::get).getCause();
assertEquals(error, actualBlockingError);
RuntimeException actualAsyncError =
- assertThrows(RuntimeException.class, () -> callback1.awaitResult());
+ assertThrows(RuntimeException.class, callback1::awaitResult);
assertEquals(error, actualAsyncError);
}
@@ -692,12 +689,9 @@ public AccessToken refreshAccessToken() {
expectedStacktrace = expectedStacktrace.subList(1, expectedStacktrace.size());
AtomicReference actualError = new AtomicReference<>();
- try {
- creds.getRequestMetadata(CALL_URI);
- fail("Should not be able to use credential without exception.");
- } catch (Exception refreshError) {
- actualError.set(refreshError);
- }
+ Exception refreshError =
+ assertThrows(RuntimeException.class, () -> creds.getRequestMetadata(CALL_URI));
+ actualError.set(refreshError);
List actualStacktrace = Arrays.asList(actualError.get().getStackTrace());
actualStacktrace =
@@ -789,37 +783,37 @@ void refreshIfExpired_refreshesToken() throws IOException {
}
@Test
- void refresh_temporaryToken_throws() throws IOException {
+ void refresh_temporaryToken_throws() {
OAuth2Credentials credentials =
OAuth2Credentials.newBuilder().setAccessToken(new AccessToken(ACCESS_TOKEN, null)).build();
- assertThrows(IllegalStateException.class, () -> credentials.refresh());
+ assertThrows(IllegalStateException.class, credentials::refresh);
}
@Test
- void equals_true() throws IOException {
+ void equals_true() {
final String accessToken1 = "1/MkSJoj1xsli0AccessToken_NKPY2";
OAuth2Credentials credentials =
OAuth2Credentials.newBuilder().setAccessToken(new AccessToken(accessToken1, null)).build();
OAuth2Credentials otherCredentials =
OAuth2Credentials.newBuilder().setAccessToken(new AccessToken(accessToken1, null)).build();
- assertTrue(credentials.equals(otherCredentials));
- assertTrue(otherCredentials.equals(credentials));
+ assertEquals(credentials, otherCredentials);
+ assertEquals(otherCredentials, credentials);
}
@Test
- void equals_false_accessToken() throws IOException {
+ void equals_false_accessToken() {
final String accessToken1 = "1/MkSJoj1xsli0AccessToken_NKPY2";
final String accessToken2 = "2/MkSJoj1xsli0AccessToken_NKPY2";
OAuth2Credentials credentials =
OAuth2Credentials.newBuilder().setAccessToken(new AccessToken(accessToken1, null)).build();
OAuth2Credentials otherCredentials =
OAuth2Credentials.newBuilder().setAccessToken(new AccessToken(accessToken2, null)).build();
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
- void toString_containsFields() throws IOException {
+ void toString_containsFields() {
AccessToken accessToken = new AccessToken("1/MkSJoj1xsli0AccessToken_NKPY2", null);
OAuth2Credentials credentials =
OAuth2Credentials.newBuilder().setAccessToken(accessToken).build();
@@ -829,12 +823,12 @@ void toString_containsFields() throws IOException {
ImmutableMap.of(
AuthHttpConstants.AUTHORIZATION,
ImmutableList.of(OAuth2Utils.BEARER_PREFIX + accessToken.getTokenValue())),
- accessToken.toString());
+ accessToken);
assertEquals(expectedToString, credentials.toString());
}
@Test
- void hashCode_equals() throws IOException {
+ void hashCode_equals() {
final String accessToken = "1/MkSJoj1xsli0AccessToken_NKPY2";
OAuth2Credentials credentials =
OAuth2Credentials.newBuilder().setAccessToken(new AccessToken(accessToken, null)).build();
@@ -852,7 +846,7 @@ void serialize() throws IOException, ClassNotFoundException {
assertEquals(credentials, deserializedCredentials);
assertEquals(credentials.hashCode(), deserializedCredentials.hashCode());
assertEquals(credentials.toString(), deserializedCredentials.toString());
- assertSame(deserializedCredentials.clock, Clock.SYSTEM);
+ assertSame(Clock.SYSTEM, deserializedCredentials.clock);
}
@Test
@@ -862,65 +856,16 @@ void updateTokenValueBeforeWake() throws IOException, InterruptedException {
AccessToken refreshedToken = new AccessToken("2/MkSJoj1xsli0AccessToken_NKPY2", null);
refreshedTokenFuture.set(refreshedToken);
- final ListenableFutureTask task =
- ListenableFutureTask.create(
- new Callable() {
- @Override
- public OAuthValue call() throws Exception {
- return OAuthValue.create(refreshedToken, new HashMap<>());
- }
- });
-
- OAuth2Credentials creds =
- new OAuth2Credentials() {
- @Override
- public AccessToken refreshAccessToken() {
- synchronized (this) {
- // Wake up the main thread. This is done now because the child thread (t) is known to
- // have the refresh task. Now we want the main thread to wake up and create a future
- // in order to wait for the refresh to complete.
- this.notify();
- }
- RefreshTaskListener listener =
- new RefreshTaskListener(task) {
- @Override
- public void run() {
- try {
- // Sleep before setting accessToken to new accessToken. Refresh should not
- // complete before this, and the accessToken is `null` until it is.
- Thread.sleep(300);
- super.run();
- } catch (Exception e) {
- fail("Unexpected error. Exception: " + e);
- }
- }
- };
-
- this.refreshTask = new RefreshTask(task, listener);
-
- try {
- // Sleep for 100 milliseconds to give parent thread time to create a refresh future.
- Thread.sleep(100);
- return refreshedTokenFuture.get();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- };
+ OAuth2Credentials creds = getOAuth2Credentials(refreshedToken, refreshedTokenFuture);
Thread t =
new Thread(
- new Runnable() {
- @Override
- public void run() {
- try {
- creds.refresh();
- assertNotNull(creds.getAccessToken());
- } catch (Exception e) {
- fail("Unexpected error. Exception: " + e);
- }
- }
- });
+ () ->
+ assertDoesNotThrow(
+ () -> {
+ creds.refresh();
+ assertNotNull(creds.getAccessToken());
+ }));
t.start();
synchronized (creds) {
@@ -941,6 +886,47 @@ public void run() {
t.join();
}
+ private OAuth2Credentials getOAuth2Credentials(
+ AccessToken refreshedToken, SettableFuture refreshedTokenFuture) {
+ final ListenableFutureTask task =
+ ListenableFutureTask.create(() -> OAuthValue.create(refreshedToken, new HashMap<>()));
+
+ return new OAuth2Credentials() {
+ @Override
+ public AccessToken refreshAccessToken() {
+ synchronized (this) {
+ // Wake up the main thread. This is done now because the child thread (t) is known to
+ // have the refresh task. Now we want the main thread to wake up and create a future
+ // in order to wait for the refresh to complete.
+ this.notify();
+ }
+ RefreshTaskListener listener =
+ new RefreshTaskListener(task) {
+ @Override
+ public void run() {
+ assertDoesNotThrow(
+ () -> {
+ // Sleep before setting accessToken to new accessToken. Refresh should not
+ // complete before this, and the accessToken is `null` until it is.
+ Thread.sleep(300);
+ super.run();
+ });
+ }
+ };
+
+ this.refreshTask = new RefreshTask(task, listener);
+
+ try {
+ // Sleep for 100 milliseconds to give parent thread time to create a refresh future.
+ Thread.sleep(100);
+ return refreshedTokenFuture.get();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+
private void waitForRefreshTaskCompletion(OAuth2Credentials credentials)
throws TimeoutException, InterruptedException {
for (int i = 0; i < 100; i++) {
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/OAuth2CredentialsWithRefreshTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/OAuth2CredentialsWithRefreshTest.java
index 2c285c5491a8..a6b437eabc3b 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/OAuth2CredentialsWithRefreshTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/OAuth2CredentialsWithRefreshTest.java
@@ -33,8 +33,9 @@
import static com.google.auth.oauth2.OAuth2Credentials.DEFAULT_EXPIRATION_MARGIN;
import static com.google.auth.oauth2.OAuth2Credentials.DEFAULT_REFRESH_MARGIN;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.auth.TestUtils;
import java.io.IOException;
@@ -150,37 +151,24 @@ public AccessToken refreshAccessToken() {
@Test
void builder_noAccessToken() {
- OAuth2CredentialsWithRefresh.newBuilder()
- .setRefreshHandler(
- new OAuth2CredentialsWithRefresh.OAuth2RefreshHandler() {
- @Override
- public AccessToken refreshAccessToken() {
- return null;
- }
- })
- .build();
+ OAuth2CredentialsWithRefresh.Builder builder =
+ OAuth2CredentialsWithRefresh.newBuilder().setRefreshHandler(() -> null);
+ assertDoesNotThrow(builder::build);
}
@Test
void builder_noRefreshHandler_throws() {
- try {
- OAuth2CredentialsWithRefresh.newBuilder().setAccessToken(ACCESS_TOKEN).build();
- fail("Should fail as a refresh handler must be provided.");
- } catch (NullPointerException e) {
- // Expected.
- }
+ OAuth2CredentialsWithRefresh.Builder builder =
+ OAuth2CredentialsWithRefresh.newBuilder().setAccessToken(ACCESS_TOKEN);
+ assertThrows(NullPointerException.class, builder::build);
}
@Test
void builder_noExpirationTimeInAccessToken_throws() {
- try {
- OAuth2CredentialsWithRefresh.newBuilder()
- .setAccessToken(new AccessToken("accessToken", null))
- .build();
- fail("Should fail as a refresh handler must be provided.");
- } catch (IllegalArgumentException e) {
- // Expected.
- }
+ OAuth2CredentialsWithRefresh.Builder builder =
+ OAuth2CredentialsWithRefresh.newBuilder()
+ .setAccessToken(new AccessToken("accessToken", null));
+ assertThrows(IllegalArgumentException.class, builder::build);
}
@Test
@@ -189,13 +177,7 @@ void refreshAccessToken_delegateToRefreshHandler() throws IOException {
OAuth2CredentialsWithRefresh credentials =
OAuth2CredentialsWithRefresh.newBuilder()
.setAccessToken(ACCESS_TOKEN)
- .setRefreshHandler(
- new OAuth2CredentialsWithRefresh.OAuth2RefreshHandler() {
- @Override
- public AccessToken refreshAccessToken() {
- return refreshedToken;
- }
- })
+ .setRefreshHandler(() -> refreshedToken)
.build();
AccessToken accessToken = credentials.refreshAccessToken();
@@ -210,13 +192,7 @@ void getRequestMetadata() throws IOException {
OAuth2CredentialsWithRefresh credentials =
OAuth2CredentialsWithRefresh.newBuilder()
.setAccessToken(ACCESS_TOKEN)
- .setRefreshHandler(
- new OAuth2CredentialsWithRefresh.OAuth2RefreshHandler() {
- @Override
- public AccessToken refreshAccessToken() {
- return refreshedToken;
- }
- })
+ .setRefreshHandler(() -> refreshedToken)
.build();
Map> metadata = credentials.getRequestMetadata(uri);
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/PluggableAuthCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/PluggableAuthCredentialsTest.java
index 9832c78215c0..094b21f9dbb2 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/PluggableAuthCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/PluggableAuthCredentialsTest.java
@@ -36,7 +36,6 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.fail;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.GenericJson;
@@ -94,7 +93,7 @@ void retrieveSubjectToken_shouldDelegateToHandler() throws IOException {
.setExecutableHandler(options -> "pluggableAuthToken")
.build();
String subjectToken = credential.retrieveSubjectToken();
- assertEquals(subjectToken, "pluggableAuthToken");
+ assertEquals("pluggableAuthToken", subjectToken);
}
@Test
@@ -119,24 +118,24 @@ void retrieveSubjectToken_shouldPassAllOptionsToHandler() throws IOException {
String subjectToken = credential.retrieveSubjectToken();
- assertEquals(subjectToken, "pluggableAuthToken");
+ assertEquals("pluggableAuthToken", subjectToken);
// Validate that the correct options were passed to the executable handler.
ExecutableOptions options = providedOptions[0];
- assertEquals(options.getExecutableCommand(), command);
+ assertEquals(command, options.getExecutableCommand());
assertEquals(options.getExecutableTimeoutMs(), Integer.parseInt(timeout));
- assertEquals(options.getOutputFilePath(), outputFile);
+ assertEquals(outputFile, options.getOutputFilePath());
Map envMap = options.getEnvironmentMap();
- assertEquals(envMap.size(), 5);
+ assertEquals(5, envMap.size());
assertEquals(envMap.get("GOOGLE_EXTERNAL_ACCOUNT_AUDIENCE"), credential.getAudience());
assertEquals(
envMap.get("GOOGLE_EXTERNAL_ACCOUNT_TOKEN_TYPE"), credential.getSubjectTokenType());
- assertEquals(envMap.get("GOOGLE_EXTERNAL_ACCOUNT_INTERACTIVE"), "0");
+ assertEquals("0", envMap.get("GOOGLE_EXTERNAL_ACCOUNT_INTERACTIVE"));
assertEquals(
envMap.get("GOOGLE_EXTERNAL_ACCOUNT_IMPERSONATED_EMAIL"),
credential.getServiceAccountEmail());
- assertEquals(envMap.get("GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE"), outputFile);
+ assertEquals(outputFile, envMap.get("GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE"));
}
@Test
@@ -159,20 +158,20 @@ void retrieveSubjectToken_shouldPassMinimalOptionsToHandler() throws IOException
String subjectToken = credential.retrieveSubjectToken();
- assertEquals(subjectToken, "pluggableAuthToken");
+ assertEquals("pluggableAuthToken", subjectToken);
// Validate that the correct options were passed to the executable handler.
ExecutableOptions options = providedOptions[0];
- assertEquals(options.getExecutableCommand(), command);
- assertEquals(options.getExecutableTimeoutMs(), DEFAULT_EXECUTABLE_TIMEOUT_MS);
+ assertEquals(command, options.getExecutableCommand());
+ assertEquals(DEFAULT_EXECUTABLE_TIMEOUT_MS, options.getExecutableTimeoutMs());
assertNull(options.getOutputFilePath());
Map envMap = options.getEnvironmentMap();
- assertEquals(envMap.size(), 3);
+ assertEquals(3, envMap.size());
assertEquals(envMap.get("GOOGLE_EXTERNAL_ACCOUNT_AUDIENCE"), credential.getAudience());
assertEquals(
envMap.get("GOOGLE_EXTERNAL_ACCOUNT_TOKEN_TYPE"), credential.getSubjectTokenType());
- assertEquals(envMap.get("GOOGLE_EXTERNAL_ACCOUNT_INTERACTIVE"), "0");
+ assertEquals("0", envMap.get("GOOGLE_EXTERNAL_ACCOUNT_INTERACTIVE"));
assertNull(envMap.get("GOOGLE_EXTERNAL_ACCOUNT_IMPERSONATED_EMAIL"));
assertNull(envMap.get("GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE"));
}
@@ -198,7 +197,7 @@ void refreshAccessToken_withoutServiceAccountImpersonation() throws IOException
// Validate that the correct subject token was passed to STS.
Map query =
TestUtils.parseQuery(transportFactory.transport.getRequests().get(0).getContentAsString());
- assertEquals(query.get("subject_token"), "pluggableAuthToken");
+ assertEquals("pluggableAuthToken", query.get("subject_token"));
// Validate metrics header is set correctly on the sts request.
Map> headers =
@@ -239,7 +238,7 @@ void refreshAccessToken_withServiceAccountImpersonation() throws IOException {
// Validate that the correct subject token was passed to STS.
Map query =
TestUtils.parseQuery(transportFactory.transport.getRequests().get(0).getContentAsString());
- assertEquals(query.get("subject_token"), "pluggableAuthToken");
+ assertEquals("pluggableAuthToken", query.get("subject_token"));
// Validate metrics header is set correctly on the sts request.
Map> headers =
@@ -265,7 +264,7 @@ void refreshAccessToken_withServiceAccountImpersonationOptions() throws IOExcept
.setServiceAccountImpersonationUrl(
transportFactory.transport.getServiceAccountImpersonationUrl())
.setServiceAccountImpersonationOptions(
- ExternalAccountCredentialsTest.buildServiceAccountImpersonationOptions(2800))
+ ExternalAccountCredentialsTest.buildServiceAccountImpersonationOptions())
.setHttpTransportFactory(transportFactory)
.build();
@@ -304,9 +303,9 @@ void pluggableAuthCredentialSource_allFields() {
PluggableAuthCredentialSource credentialSource = new PluggableAuthCredentialSource(source);
- assertEquals(credentialSource.getCommand(), "/path/to/executable");
- assertEquals(credentialSource.getTimeoutMs(), 10000);
- assertEquals(credentialSource.getOutputFilePath(), "/path/to/output/file");
+ assertEquals("/path/to/executable", credentialSource.getCommand());
+ assertEquals(10000, credentialSource.getTimeoutMs());
+ assertEquals("/path/to/output/file", credentialSource.getOutputFilePath());
}
@Test
@@ -317,8 +316,8 @@ void pluggableAuthCredentialSource_noTimeoutProvided_setToDefault() {
executable.put("command", "command");
PluggableAuthCredentialSource credentialSource = new PluggableAuthCredentialSource(source);
- assertEquals(credentialSource.getCommand(), "command");
- assertEquals(credentialSource.getTimeoutMs(), DEFAULT_EXECUTABLE_TIMEOUT_MS);
+ assertEquals("command", credentialSource.getCommand());
+ assertEquals(DEFAULT_EXECUTABLE_TIMEOUT_MS, credentialSource.getTimeoutMs());
assertNull(credentialSource.getOutputFilePath());
}
@@ -335,16 +334,14 @@ void pluggableAuthCredentialSource_timeoutProvidedOutOfRange_throws() {
for (int value : possibleOutOfRangeValues) {
executable.put("timeout_millis", value);
- try {
- new PluggableAuthCredentialSource(source);
- fail("Should not be able to continue without exception.");
- } catch (IllegalArgumentException exception) {
- assertEquals(
- String.format(
- "The executable timeout must be between %s and %s milliseconds.",
- MINIMUM_EXECUTABLE_TIMEOUT_MS, MAXIMUM_EXECUTABLE_TIMEOUT_MS),
- exception.getMessage());
- }
+ IllegalArgumentException exception =
+ assertThrows(
+ IllegalArgumentException.class, () -> new PluggableAuthCredentialSource(source));
+ assertEquals(
+ String.format(
+ "The executable timeout must be between %s and %s milliseconds.",
+ MINIMUM_EXECUTABLE_TIMEOUT_MS, MAXIMUM_EXECUTABLE_TIMEOUT_MS),
+ exception.getMessage());
}
}
@@ -362,21 +359,21 @@ void pluggableAuthCredentialSource_validTimeoutProvided() {
executable.put("timeout_millis", value);
PluggableAuthCredentialSource credentialSource = new PluggableAuthCredentialSource(source);
- assertEquals(credentialSource.getCommand(), "command");
- assertEquals(credentialSource.getTimeoutMs(), 10000);
+ assertEquals("command", credentialSource.getCommand());
+ assertEquals(10000, credentialSource.getTimeoutMs());
assertNull(credentialSource.getOutputFilePath());
}
}
@Test
void pluggableAuthCredentialSource_missingExecutableField_throws() {
- try {
- new PluggableAuthCredentialSource(new HashMap<>());
- fail("Should not be able to continue without exception.");
- } catch (IllegalArgumentException exception) {
- assertEquals(
- "Invalid credential source for PluggableAuth credentials.", exception.getMessage());
- }
+ HashMap credentialSourceMap = new HashMap<>();
+ IllegalArgumentException exception =
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> new PluggableAuthCredentialSource(credentialSourceMap));
+ assertEquals(
+ "Invalid credential source for PluggableAuth credentials.", exception.getMessage());
}
@Test
@@ -385,18 +382,16 @@ void pluggableAuthCredentialSource_missingExecutableCommandField_throws() {
Map executable = new HashMap<>();
source.put("executable", executable);
- try {
- new PluggableAuthCredentialSource(source);
- fail("Should not be able to continue without exception.");
- } catch (IllegalArgumentException exception) {
- assertEquals(
- "The PluggableAuthCredentialSource is missing the required 'command' field.",
- exception.getMessage());
- }
+ IllegalArgumentException exception =
+ assertThrows(
+ IllegalArgumentException.class, () -> new PluggableAuthCredentialSource(source));
+ assertEquals(
+ "The PluggableAuthCredentialSource is missing the required 'command' field.",
+ exception.getMessage());
}
@Test
- void builder_allFields() throws IOException {
+ void builder_allFields() {
List scopes = Arrays.asList("scope1", "scope2");
PluggableAuthCredentialSource source = buildCredentialSource();
@@ -436,7 +431,7 @@ void builder_allFields() throws IOException {
}
@Test
- void builder_missingUniverseDomain_defaults() throws IOException {
+ void builder_missingUniverseDomain_defaults() {
List scopes = Arrays.asList("scope1", "scope2");
PluggableAuthCredentialSource source = buildCredentialSource();
@@ -475,7 +470,7 @@ void builder_missingUniverseDomain_defaults() throws IOException {
}
@Test
- void newBuilder_allFields() throws IOException {
+ void newBuilder_allFields() {
List scopes = Arrays.asList("scope1", "scope2");
PluggableAuthCredentialSource source = buildCredentialSource();
@@ -517,7 +512,7 @@ void newBuilder_allFields() throws IOException {
}
@Test
- void newBuilder_noUniverseDomain_defaults() throws IOException {
+ void newBuilder_noUniverseDomain_defaults() {
List scopes = Arrays.asList("scope1", "scope2");
PluggableAuthCredentialSource source = buildCredentialSource();
@@ -558,7 +553,7 @@ void newBuilder_noUniverseDomain_defaults() throws IOException {
}
@Test
- void createdScoped_clonedCredentialWithAddedScopes() throws IOException {
+ void createdScoped_clonedCredentialWithAddedScopes() {
PluggableAuthCredentials credentials =
PluggableAuthCredentials.newBuilder(CREDENTIAL)
.setExecutableHandler(options -> "pluggableAuthToken")
@@ -591,7 +586,7 @@ void createdScoped_clonedCredentialWithAddedScopes() throws IOException {
}
@Test
- void serialize() throws IOException, ClassNotFoundException {
+ void serialize() {
PluggableAuthCredentials testCredentials =
PluggableAuthCredentials.newBuilder(CREDENTIAL)
.setExecutableHandler(options -> "pluggableAuthToken")
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/PluggableAuthExceptionTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/PluggableAuthExceptionTest.java
index f924d4137724..534ad9f33a2b 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/PluggableAuthExceptionTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/PluggableAuthExceptionTest.java
@@ -39,8 +39,6 @@
/** Tests for {@link PluggableAuthException}. */
class PluggableAuthExceptionTest {
- private static final String MESSAGE_FORMAT = "Error code %s: %s";
-
@Test
void constructor() {
PluggableAuthException e = new PluggableAuthException("errorCode", "errorDescription");
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/PluggableAuthHandlerTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/PluggableAuthHandlerTest.java
index c31266d27360..1566c7eed418 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/PluggableAuthHandlerTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/PluggableAuthHandlerTest.java
@@ -33,8 +33,8 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
@@ -189,7 +189,7 @@ void retrieveTokenFromExecutable_samlResponse() throws IOException, InterruptedE
}
@Test
- void retrieveTokenFromExecutable_errorResponse_throws() throws InterruptedException, IOException {
+ void retrieveTokenFromExecutable_errorResponse_throws() throws InterruptedException {
TestEnvironmentProvider environmentProvider = new TestEnvironmentProvider();
environmentProvider.setEnv("GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES", "1");
@@ -211,13 +211,12 @@ void retrieveTokenFromExecutable_errorResponse_throws() throws InterruptedExcept
PluggableAuthHandler handler = new PluggableAuthHandler(environmentProvider, processBuilder);
// Call retrieveTokenFromExecutable().
- try {
- handler.retrieveTokenFromExecutable(DEFAULT_OPTIONS);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException e) {
- assertEquals("401", e.getErrorCode());
- assertEquals("Caller not authorized.", e.getErrorDescription());
- }
+ PluggableAuthException e =
+ assertThrows(
+ PluggableAuthException.class,
+ () -> handler.retrieveTokenFromExecutable(DEFAULT_OPTIONS));
+ assertEquals("401", e.getErrorCode());
+ assertEquals("Caller not authorized.", e.getErrorDescription());
}
@Test
@@ -281,7 +280,7 @@ void retrieveTokenFromExecutable_successResponseWithoutExpirationTimeField()
@Test
void
retrieveTokenFromExecutable_successResponseWithoutExpirationTimeFieldWithOutputFileSpecified_throws()
- throws InterruptedException, IOException {
+ throws InterruptedException {
TestEnvironmentProvider environmentProvider = new TestEnvironmentProvider();
environmentProvider.setEnv("GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES", "1");
@@ -333,19 +332,14 @@ public String getOutputFilePath() {
PluggableAuthHandler handler = new PluggableAuthHandler(environmentProvider, processBuilder);
- // Call retrieveTokenFromExecutable() should throw an exception as the STDOUT response
- // is missing
- // the `expiration_time` field and an output file was specified in the configuration.
- try {
- handler.retrieveTokenFromExecutable(options);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException exception) {
- assertEquals(
- "Error code INVALID_EXECUTABLE_RESPONSE: The executable response must contain the "
- + "`expiration_time` field for successful responses when an output_file has been specified in the"
- + " configuration.",
- exception.getMessage());
- }
+ PluggableAuthException exception =
+ assertThrows(
+ PluggableAuthException.class, () -> handler.retrieveTokenFromExecutable(options));
+ assertEquals(
+ "Error code INVALID_EXECUTABLE_RESPONSE: The executable response must contain the "
+ + "`expiration_time` field for successful responses when an output_file has been specified in the"
+ + " configuration.",
+ exception.getMessage());
verify(mockProcess, times(i + 1)).destroy();
verify(mockProcess, times(i + 1))
@@ -410,16 +404,14 @@ public String getOutputFilePath() {
// Call retrieveTokenFromExecutable() which should throw an exception as the output file
// response is missing
// the `expiration_time` field.
- try {
- handler.retrieveTokenFromExecutable(options);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException exception) {
- assertEquals(
- "Error code INVALID_EXECUTABLE_RESPONSE: The executable response must contain the "
- + "`expiration_time` field for successful responses when an output_file has been specified in the"
- + " configuration.",
- exception.getMessage());
- }
+ PluggableAuthException exception =
+ assertThrows(
+ PluggableAuthException.class, () -> handler.retrieveTokenFromExecutable(options));
+ assertEquals(
+ "Error code INVALID_EXECUTABLE_RESPONSE: The executable response must contain the "
+ + "`expiration_time` field for successful responses when an output_file has been specified in the"
+ + " configuration.",
+ exception.getMessage());
// Validate executable not invoked.
verify(mockProcess, times(0)).destroyForcibly();
@@ -485,8 +477,7 @@ public String getOutputFilePath() {
}
@Test
- void retrieveTokenFromExecutable_withInvalidOutputFile_throws()
- throws IOException, InterruptedException {
+ void retrieveTokenFromExecutable_withInvalidOutputFile_throws() throws IOException {
TestEnvironmentProvider environmentProvider = new TestEnvironmentProvider();
environmentProvider.setEnv("GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES", "1");
@@ -530,12 +521,10 @@ public String getOutputFilePath() {
PluggableAuthHandler handler = new PluggableAuthHandler(environmentProvider, processBuilder);
// Call retrieveTokenFromExecutable().
- try {
- handler.retrieveTokenFromExecutable(options);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException e) {
- assertEquals("INVALID_OUTPUT_FILE", e.getErrorCode());
- }
+ PluggableAuthException e =
+ assertThrows(
+ PluggableAuthException.class, () -> handler.retrieveTokenFromExecutable(options));
+ assertEquals("INVALID_OUTPUT_FILE", e.getErrorCode());
}
@Test
@@ -629,18 +618,16 @@ void retrieveTokenFromExecutable_expiredResponse_throws()
PluggableAuthHandler handler = new PluggableAuthHandler(environmentProvider, processBuilder);
// Call retrieveTokenFromExecutable().
- try {
- handler.retrieveTokenFromExecutable(DEFAULT_OPTIONS);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException e) {
- assertEquals("INVALID_RESPONSE", e.getErrorCode());
- assertEquals("The executable response is expired.", e.getErrorDescription());
- }
+ PluggableAuthException e =
+ assertThrows(
+ PluggableAuthException.class,
+ () -> handler.retrieveTokenFromExecutable(DEFAULT_OPTIONS));
+ assertEquals("INVALID_RESPONSE", e.getErrorCode());
+ assertEquals("The executable response is expired.", e.getErrorDescription());
}
@Test
- void retrieveTokenFromExecutable_invalidVersion_throws()
- throws InterruptedException, IOException {
+ void retrieveTokenFromExecutable_invalidVersion_throws() throws InterruptedException {
TestEnvironmentProvider environmentProvider = new TestEnvironmentProvider();
environmentProvider.setEnv("GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES", "1");
@@ -663,22 +650,20 @@ void retrieveTokenFromExecutable_invalidVersion_throws()
PluggableAuthHandler handler = new PluggableAuthHandler(environmentProvider, processBuilder);
// Call retrieveTokenFromExecutable().
- try {
- handler.retrieveTokenFromExecutable(DEFAULT_OPTIONS);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException e) {
- assertEquals("UNSUPPORTED_VERSION", e.getErrorCode());
- assertEquals(
- "The version of the executable response is not supported. "
- + String.format(
- "The maximum version currently supported is %s.",
- EXECUTABLE_SUPPORTED_MAX_VERSION),
- e.getErrorDescription());
- }
+ PluggableAuthException e =
+ assertThrows(
+ PluggableAuthException.class,
+ () -> handler.retrieveTokenFromExecutable(DEFAULT_OPTIONS));
+ assertEquals("UNSUPPORTED_VERSION", e.getErrorCode());
+ assertEquals(
+ "The version of the executable response is not supported. "
+ + String.format(
+ "The maximum version currently supported is %s.", EXECUTABLE_SUPPORTED_MAX_VERSION),
+ e.getErrorDescription());
}
@Test
- void retrieveTokenFromExecutable_allowExecutablesDisabled_throws() throws IOException {
+ void retrieveTokenFromExecutable_allowExecutablesDisabled_throws() {
// In order to use Pluggable Auth, GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES must be set to 1.
// If set to 0, a runtime exception should be thrown.
TestEnvironmentProvider environmentProvider = new TestEnvironmentProvider();
@@ -686,16 +671,15 @@ void retrieveTokenFromExecutable_allowExecutablesDisabled_throws() throws IOExce
PluggableAuthHandler handler = new PluggableAuthHandler(environmentProvider);
- try {
- handler.retrieveTokenFromExecutable(DEFAULT_OPTIONS);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException e) {
- assertEquals("PLUGGABLE_AUTH_DISABLED", e.getErrorCode());
- assertEquals(
- "Pluggable Auth executables need to be explicitly allowed to run by "
- + "setting the GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES environment variable to 1.",
- e.getErrorDescription());
- }
+ PluggableAuthException e =
+ assertThrows(
+ PluggableAuthException.class,
+ () -> handler.retrieveTokenFromExecutable(DEFAULT_OPTIONS));
+ assertEquals("PLUGGABLE_AUTH_DISABLED", e.getErrorCode());
+ assertEquals(
+ "Pluggable Auth executables need to be explicitly allowed to run by "
+ + "setting the GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES environment variable to 1.",
+ e.getErrorDescription());
}
@Test
@@ -853,7 +837,7 @@ void getExecutableResponse_errorResponse() throws IOException, InterruptedExcept
}
@Test
- void getExecutableResponse_timeoutExceeded_throws() throws InterruptedException, IOException {
+ void getExecutableResponse_timeoutExceeded_throws() throws InterruptedException {
TestEnvironmentProvider environmentProvider = new TestEnvironmentProvider();
environmentProvider.setEnv("GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES", "1");
@@ -867,14 +851,12 @@ void getExecutableResponse_timeoutExceeded_throws() throws InterruptedException,
PluggableAuthHandler handler = new PluggableAuthHandler(environmentProvider, processBuilder);
// Call getExecutableResponse().
- try {
- handler.getExecutableResponse(DEFAULT_OPTIONS);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException e) {
- assertEquals("TIMEOUT_EXCEEDED", e.getErrorCode());
- assertEquals(
- "The executable failed to finish within the timeout specified.", e.getErrorDescription());
- }
+ PluggableAuthException e =
+ assertThrows(
+ PluggableAuthException.class, () -> handler.getExecutableResponse(DEFAULT_OPTIONS));
+ assertEquals("TIMEOUT_EXCEEDED", e.getErrorCode());
+ assertEquals(
+ "The executable failed to finish within the timeout specified.", e.getErrorDescription());
verify(mockProcess, times(1))
.waitFor(
@@ -883,7 +865,7 @@ void getExecutableResponse_timeoutExceeded_throws() throws InterruptedException,
}
@Test
- void getExecutableResponse_nonZeroExitCode_throws() throws InterruptedException, IOException {
+ void getExecutableResponse_nonZeroExitCode_throws() throws InterruptedException {
TestEnvironmentProvider environmentProvider = new TestEnvironmentProvider();
environmentProvider.setEnv("GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES", "1");
@@ -899,15 +881,13 @@ void getExecutableResponse_nonZeroExitCode_throws() throws InterruptedException,
PluggableAuthHandler handler = new PluggableAuthHandler(environmentProvider, processBuilder);
// Call getExecutableResponse().
- try {
- handler.getExecutableResponse(DEFAULT_OPTIONS);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException e) {
- assertEquals("EXIT_CODE", e.getErrorCode());
- assertEquals(
- String.format("The executable failed with exit code %s.", EXIT_CODE_FAIL),
- e.getErrorDescription());
- }
+ PluggableAuthException e =
+ assertThrows(
+ PluggableAuthException.class, () -> handler.getExecutableResponse(DEFAULT_OPTIONS));
+ assertEquals("EXIT_CODE", e.getErrorCode());
+ assertEquals(
+ String.format("The executable failed with exit code %s.", EXIT_CODE_FAIL),
+ e.getErrorDescription());
verify(mockProcess, times(1))
.waitFor(
@@ -916,7 +896,7 @@ void getExecutableResponse_nonZeroExitCode_throws() throws InterruptedException,
}
@Test
- void getExecutableResponse_processInterrupted_throws() throws InterruptedException, IOException {
+ void getExecutableResponse_processInterrupted_throws() throws InterruptedException {
TestEnvironmentProvider environmentProvider = new TestEnvironmentProvider();
environmentProvider.setEnv("GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES", "1");
@@ -931,15 +911,13 @@ void getExecutableResponse_processInterrupted_throws() throws InterruptedExcepti
PluggableAuthHandler handler = new PluggableAuthHandler(environmentProvider, processBuilder);
// Call getExecutableResponse().
- try {
- handler.getExecutableResponse(DEFAULT_OPTIONS);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException e) {
- assertEquals("INTERRUPTED", e.getErrorCode());
- assertEquals(
- String.format("The execution was interrupted: %s.", new InterruptedException()),
- e.getErrorDescription());
- }
+ PluggableAuthException e =
+ assertThrows(
+ PluggableAuthException.class, () -> handler.getExecutableResponse(DEFAULT_OPTIONS));
+ assertEquals("INTERRUPTED", e.getErrorCode());
+ assertEquals(
+ String.format("The execution was interrupted: %s.", new InterruptedException()),
+ e.getErrorDescription());
verify(mockProcess, times(1))
.waitFor(
@@ -948,7 +926,7 @@ void getExecutableResponse_processInterrupted_throws() throws InterruptedExcepti
}
@Test
- void getExecutableResponse_invalidResponse_throws() throws InterruptedException, IOException {
+ void getExecutableResponse_invalidResponse_throws() throws InterruptedException {
TestEnvironmentProvider environmentProvider = new TestEnvironmentProvider();
environmentProvider.setEnv("GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES", "1");
@@ -969,15 +947,13 @@ void getExecutableResponse_invalidResponse_throws() throws InterruptedException,
PluggableAuthHandler handler = new PluggableAuthHandler(environmentProvider, processBuilder);
// Call getExecutableResponse().
- try {
- handler.getExecutableResponse(DEFAULT_OPTIONS);
- fail("Should not be able to continue without exception.");
- } catch (PluggableAuthException e) {
- assertEquals("INVALID_RESPONSE", e.getErrorCode());
- assertEquals(
- String.format("The executable returned an invalid response: %s.", badResponse),
- e.getErrorDescription());
- }
+ PluggableAuthException e =
+ assertThrows(
+ PluggableAuthException.class, () -> handler.getExecutableResponse(DEFAULT_OPTIONS));
+ assertEquals("INVALID_RESPONSE", e.getErrorCode());
+ assertEquals(
+ String.format("The executable returned an invalid response: %s.", badResponse),
+ e.getErrorDescription());
verify(mockProcess, times(1))
.waitFor(
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/SecureSessionAgentConfigTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/SecureSessionAgentConfigTest.java
index b9249517c640..3dc07f494c6d 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/SecureSessionAgentConfigTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/SecureSessionAgentConfigTest.java
@@ -35,7 +35,7 @@
import org.junit.jupiter.api.Test;
-/** Test cases for {@linkSecureSessionAgentConfig}. */
+/** Test cases for {@link SecureSessionAgentConfig}. */
class SecureSessionAgentConfigTest {
private static final String S2A_PLAINTEXT_ADDRESS = "plaintext";
private static final String S2A_MTLS_ADDRESS = "mtls";
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountCredentialsTest.java
index 2c516a9b2b4a..ed26a0af3c6f 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountCredentialsTest.java
@@ -32,6 +32,7 @@
package com.google.auth.oauth2;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
@@ -139,17 +140,14 @@ private static ServiceAccountCredentials.Builder createDefaultBuilderWithScopes(
private static ServiceAccountCredentials.Builder createDefaultBuilderWithKey(
PrivateKey privateKey) {
- ServiceAccountCredentials.Builder builder =
- ServiceAccountCredentials.newBuilder()
- .setClientId(CLIENT_ID)
- .setClientEmail(CLIENT_EMAIL)
- .setPrivateKey(privateKey)
- .setPrivateKeyId(PRIVATE_KEY_ID)
- .setProjectId(PROJECT_ID)
- .setQuotaProjectId(QUOTA_PROJECT)
- .setHttpTransportFactory(new MockHttpTransportFactory());
-
- return builder;
+ return ServiceAccountCredentials.newBuilder()
+ .setClientId(CLIENT_ID)
+ .setClientEmail(CLIENT_EMAIL)
+ .setPrivateKey(privateKey)
+ .setPrivateKeyId(PRIVATE_KEY_ID)
+ .setProjectId(PROJECT_ID)
+ .setQuotaProjectId(QUOTA_PROJECT)
+ .setHttpTransportFactory(new MockHttpTransportFactory());
}
static ServiceAccountCredentials.Builder createDefaultBuilder() throws IOException {
@@ -172,16 +170,11 @@ void setLifetime() throws IOException {
}
@Test
- void setLifetime_invalid_lifetime() throws IOException, IllegalStateException {
- try {
- createDefaultBuilder().setLifetime(INVALID_LIFETIME).build();
- fail(
- String.format(
- "Should throw exception with message containing '%s'",
- "lifetime must be less than or equal to 43200"));
- } catch (IllegalStateException expected) {
- assertTrue(expected.getMessage().contains("lifetime must be less than or equal to 43200"));
- }
+ void setLifetime_invalid_lifetime() throws IllegalStateException, IOException {
+ ServiceAccountCredentials.Builder builder =
+ createDefaultBuilder().setLifetime(INVALID_LIFETIME);
+ IllegalStateException exception = assertThrows(IllegalStateException.class, builder::build);
+ assertTrue(exception.getMessage().contains("lifetime must be less than or equal to 43200"));
}
@Test
@@ -300,7 +293,6 @@ void createAssertion_custom_lifetime() throws IOException {
@Test
void createAssertionForIdToken_correct() throws IOException {
- PrivateKey privateKey = OAuth2Utils.privateKeyFromPkcs8(PRIVATE_KEY_PKCS8);
ServiceAccountCredentials credentials =
createDefaultBuilder()
.setPrivateKeyId(PRIVATE_KEY_ID)
@@ -369,14 +361,11 @@ void createdScoped_withAud_noUniverse_jwtWithScopesDisabled_accessToken() throws
GoogleCredentials credentials = createDefaultBuilderWithToken(ACCESS_TOKEN).build();
// No aud, no scopes gives an exception.
- try {
- credentials.getRequestMetadata(null);
- fail("Should not be able to get token without scopes");
- } catch (IOException e) {
- assertTrue(
- e.getMessage().contains("Scopes and uri are not configured for service account"),
- "expected to fail with exception");
- }
+ IOException exception =
+ assertThrows(IOException.class, () -> credentials.getRequestMetadata(null));
+ assertTrue(
+ exception.getMessage().contains("Scopes and uri are not configured for service account"),
+ "expected to fail with exception");
GoogleCredentials scopedCredentials = credentials.createScoped(SCOPES);
assertEquals(false, credentials.isExplicitUniverseDomain());
@@ -389,15 +378,10 @@ void createdScoped_withAud_noUniverse_jwtWithScopesDisabled_accessToken() throws
void createdScoped_withUniverse_selfSignedJwt() throws IOException {
ServiceAccountCredentials credentials =
createDefaultBuilder().setUniverseDomain("foo.bar").build();
-
- try {
- credentials.getRequestMetadata(null);
- fail("Should not be able to get token without scopes");
- } catch (IOException e) {
- assertTrue(
- e.getMessage().contains("Scopes and uri are not configured for service account"),
- "expected to fail with exception");
- }
+ IOException exception =
+ assertThrows(IOException.class, () -> credentials.getRequestMetadata(null));
+ assertTrue(
+ exception.getMessage().contains("Scopes and uri are not configured for service account"));
GoogleCredentials scopedCredentials = credentials.createScoped("dummy.scope");
Map> metadata = scopedCredentials.getRequestMetadata(null);
@@ -429,14 +413,10 @@ void createdScoped_withUniverse_selfSignedJwt() throws IOException {
void noScopes_withUniverse_selfSignedJwt() throws IOException {
GoogleCredentials credentials = createDefaultBuilder().setUniverseDomain("foo.bar").build();
- try {
- credentials.getRequestMetadata(null);
- fail("Should not be able to get token without scopes");
- } catch (IOException e) {
- assertTrue(
- e.getMessage().contains("Scopes and uri are not configured for service account"),
- "expected to fail with exception");
- }
+ IOException exception =
+ assertThrows(IOException.class, () -> credentials.getRequestMetadata(null));
+ assertTrue(
+ exception.getMessage().contains("Scopes and uri are not configured for service account"));
Map> metadata = credentials.getRequestMetadata(CALL_URI);
assertNull(((ServiceAccountCredentials) credentials).getSelfSignedJwtCredentialsWithScope());
@@ -588,8 +568,8 @@ void fromJson_hasQuotaProjectId() throws IOException {
assertTrue(metadata.containsKey(GoogleCredentials.QUOTA_PROJECT_ID_HEADER_KEY));
assertEquals(
- metadata.get(GoogleCredentials.QUOTA_PROJECT_ID_HEADER_KEY),
- Collections.singletonList(QUOTA_PROJECT));
+ Collections.singletonList(QUOTA_PROJECT),
+ metadata.get(GoogleCredentials.QUOTA_PROJECT_ID_HEADER_KEY));
}
@Test
@@ -602,15 +582,15 @@ void getRequestMetadata_hasAccessToken() throws IOException {
@Test
void getRequestMetadata_customTokenServer_hasAccessToken() throws IOException {
- final URI TOKEN_SERVER = URI.create("https://foo.com/bar");
+ final URI tokenServerUri = URI.create("https://foo.com/bar");
MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
transportFactory.transport.addServiceAccount(CLIENT_EMAIL, ACCESS_TOKEN);
- transportFactory.transport.setTokenServerUri(TOKEN_SERVER);
+ transportFactory.transport.setTokenServerUri(tokenServerUri);
OAuth2Credentials credentials =
createDefaultBuilder()
.setScopes(SCOPES)
.setHttpTransportFactory(transportFactory)
- .setTokenServerUri(TOKEN_SERVER)
+ .setTokenServerUri(tokenServerUri)
.build();
Map> metadata = credentials.getRequestMetadata(CALL_URI);
@@ -672,7 +652,6 @@ void refreshAccessToken_IOException_Retry() throws IOException {
MockTokenServerTransport transport = transportFactory.transport;
ServiceAccountCredentials credentials =
createDefaultBuilder().setScopes(SCOPES).setHttpTransportFactory(transportFactory).build();
- ;
transport.addServiceAccount(CLIENT_EMAIL, accessToken1);
TestUtils.assertContainsBearerToken(credentials.getRequestMetadata(CALL_URI), accessToken1);
@@ -743,15 +722,11 @@ void refreshAccessToken_defaultRetriesDisabled() throws IOException {
MockLowLevelHttpResponse response429 = new MockLowLevelHttpResponse().setStatusCode(429);
transport.addServiceAccount(CLIENT_EMAIL, accessToken2);
- try {
- transport.addResponseSequence(response408, response429);
- credentials.refresh();
- fail("Should not be able to use credential without exception.");
- } catch (GoogleAuthException ex) {
- assertTrue(ex.getMessage().contains("Error getting access token for service account: 408"));
- assertTrue(ex.isRetryable());
- assertEquals(0, ex.getRetryCount());
- }
+ transport.addResponseSequence(response408, response429);
+ GoogleAuthException ex = assertThrows(GoogleAuthException.class, credentials::refresh);
+ assertTrue(ex.getMessage().contains("Error getting access token for service account: 408"));
+ assertTrue(ex.isRetryable());
+ assertEquals(0, ex.getRetryCount());
}
@Test
@@ -770,21 +745,17 @@ void refreshAccessToken_maxRetries_maxDelay() throws IOException {
MockLowLevelHttpResponse response503 = new MockLowLevelHttpResponse().setStatusCode(503);
Instant start = Instant.now();
- try {
- transport.addResponseSequence(response408, response429, response500, response503);
- credentials.refresh();
- fail("Should not be able to use credential without exception.");
- } catch (GoogleAuthException ex) {
- Instant finish = Instant.now();
- long timeElapsed = Duration.between(start, finish).toMillis();
-
- // we expect max retry time of 7 sec +/- jitter
- assertTrue(timeElapsed > 5500 && timeElapsed < 10000);
- assertTrue(ex.getMessage().contains("Error getting access token for service account: 503"));
- assertTrue(ex.isRetryable());
- assertEquals(3, ex.getRetryCount());
- assertTrue(ex.getCause() instanceof HttpResponseException);
- }
+ transport.addResponseSequence(response408, response429, response500, response503);
+ GoogleAuthException ex = assertThrows(GoogleAuthException.class, credentials::refresh);
+ Instant finish = Instant.now();
+ long timeElapsed = Duration.between(start, finish).toMillis();
+
+ // we expect max retry time of 7 sec +/- jitter
+ assertTrue(timeElapsed > 5500 && timeElapsed < 10000);
+ assertTrue(ex.getMessage().contains("Error getting access token for service account: 503"));
+ assertTrue(ex.isRetryable());
+ assertEquals(3, ex.getRetryCount());
+ assertTrue(ex.getCause() instanceof HttpResponseException);
}
@Test
@@ -801,24 +772,19 @@ void refreshAccessToken_RequestFailure_retried() throws IOException {
MockLowLevelHttpResponse response503 = new MockLowLevelHttpResponse().setStatusCode(503);
Instant start = Instant.now();
- try {
- transport.addResponseSequence(response503);
- transport.addResponseErrorSequence(error, error, error);
- credentials.refresh();
- fail("Should not be able to use credential without exception.");
- } catch (GoogleAuthException ex) {
- Instant finish = Instant.now();
- long timeElapsed = Duration.between(start, finish).toMillis();
-
- // we expect max retry time of 7 sec +/- jitter
- assertTrue(timeElapsed > 5500 && timeElapsed < 10000);
- assertTrue(
- ex.getMessage()
- .contains("Error getting access token for service account: Invalid grant"));
- assertTrue(ex.isRetryable());
- assertEquals(3, ex.getRetryCount());
- assertTrue(ex.getCause() instanceof IOException);
- }
+ transport.addResponseSequence(response503);
+ transport.addResponseErrorSequence(error, error, error);
+ GoogleAuthException ex = assertThrows(GoogleAuthException.class, credentials::refresh);
+ Instant finish = Instant.now();
+ long timeElapsed = Duration.between(start, finish).toMillis();
+
+ // we expect max retry time of 7 sec +/- jitter
+ assertTrue(timeElapsed > 5500 && timeElapsed < 10000);
+ assertTrue(
+ ex.getMessage().contains("Error getting access token for service account: Invalid grant"));
+ assertTrue(ex.isRetryable());
+ assertEquals(3, ex.getRetryCount());
+ assertTrue(ex.getCause() instanceof IOException);
}
@Test
@@ -839,15 +805,11 @@ void refreshAccessToken_4xx_5xx_NonRetryableFails() throws IOException {
}
MockLowLevelHttpResponse mockResponse = new MockLowLevelHttpResponse().setStatusCode(status);
- try {
- transport.addResponseSequence(mockResponse);
- transport.addServiceAccount(CLIENT_EMAIL, accessToken2);
- credentials.refresh();
- fail("Should not be able to use credential without exception.");
- } catch (GoogleAuthException ex) {
- assertFalse(ex.isRetryable());
- assertEquals(0, ex.getRetryCount());
- }
+ transport.addResponseSequence(mockResponse);
+ transport.addServiceAccount(CLIENT_EMAIL, accessToken2);
+ GoogleAuthException ex = assertThrows(GoogleAuthException.class, credentials::refresh);
+ assertFalse(ex.isRetryable());
+ assertEquals(0, ex.getRetryCount());
}
}
@@ -1071,8 +1033,8 @@ void equals_true() throws IOException {
SCOPES,
transportFactory,
tokenServer);
- assertTrue(credentials.equals(otherCredentials));
- assertTrue(otherCredentials.equals(credentials));
+ assertEquals(credentials, otherCredentials);
+ assertEquals(otherCredentials, credentials);
}
@Test
@@ -1097,8 +1059,8 @@ void equals_false_clientId() throws IOException {
SCOPES,
serverTransportFactory,
tokenServer1);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
@@ -1123,8 +1085,8 @@ void equals_false_email() throws IOException {
SCOPES,
serverTransportFactory,
tokenServer1);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
@@ -1152,8 +1114,8 @@ void equals_false_super() throws IOException {
.toBuilder()
.setUniverseDomain("universe.com")
.build();
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
@@ -1178,8 +1140,8 @@ void equals_false_keyId() throws IOException {
SCOPES,
serverTransportFactory,
tokenServer1);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
@@ -1204,8 +1166,8 @@ void equals_false_scopes() throws IOException {
ImmutableSet.of(),
serverTransportFactory,
tokenServer1);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
@@ -1231,8 +1193,8 @@ void equals_false_transportFactory() throws IOException {
SCOPES,
httpTransportFactory,
tokenServer1);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
@@ -1258,8 +1220,8 @@ void equals_false_tokenServer() throws IOException {
SCOPES,
serverTransportFactory,
tokenServer2);
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
@@ -1373,38 +1335,30 @@ void serialize() throws IOException, ClassNotFoundException {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
try (ObjectOutputStream output = new ObjectOutputStream(bytes)) {
output.writeObject(credentials);
- String s = output.toString();
}
ServiceAccountCredentials deserializedCredentials = serializeAndDeserialize(credentials);
assertEquals(credentials, deserializedCredentials);
assertEquals(credentials.hashCode(), deserializedCredentials.hashCode());
assertEquals(credentials.toString(), deserializedCredentials.toString());
- assertSame(deserializedCredentials.clock, Clock.SYSTEM);
+ assertSame(Clock.SYSTEM, deserializedCredentials.clock);
assertEquals(
MockTokenServerTransportFactory.class,
deserializedCredentials.toBuilder().getHttpTransportFactory().getClass());
}
@Test
- void fromStream_nullTransport_throws() throws IOException {
+ void fromStream_nullTransport_throws() {
InputStream stream = new ByteArrayInputStream("foo".getBytes());
- try {
- ServiceAccountCredentials.fromStream(stream, null);
- fail("Should throw if HttpTransportFactory is null");
- } catch (NullPointerException expected) {
- // Expected
- }
+ assertThrows(
+ NullPointerException.class, () -> ServiceAccountCredentials.fromStream(stream, null));
}
@Test
- void fromStream_nullStream_throws() throws IOException {
+ void fromStream_nullStream_throws() {
MockHttpTransportFactory transportFactory = new MockHttpTransportFactory();
- try {
- ServiceAccountCredentials.fromStream(null, transportFactory);
- fail("Should throw if InputStream is null");
- } catch (NullPointerException expected) {
- // Expected
- }
+ assertThrows(
+ NullPointerException.class,
+ () -> ServiceAccountCredentials.fromStream(null, transportFactory));
}
@Test
@@ -1428,7 +1382,13 @@ void fromStream_noClientId_throws() throws IOException {
InputStream serviceAccountStream =
writeServiceAccountStream(null, CLIENT_EMAIL, PRIVATE_KEY_PKCS8, PRIVATE_KEY_ID);
- testFromStreamException(serviceAccountStream, "client_id");
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () ->
+ ServiceAccountCredentials.fromStream(
+ serviceAccountStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("client_id"));
}
@Test
@@ -1436,7 +1396,13 @@ void fromStream_noClientEmail_throws() throws IOException {
InputStream serviceAccountStream =
writeServiceAccountStream(CLIENT_ID, null, PRIVATE_KEY_PKCS8, PRIVATE_KEY_ID);
- testFromStreamException(serviceAccountStream, "client_email");
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () ->
+ ServiceAccountCredentials.fromStream(
+ serviceAccountStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("client_email"));
}
@Test
@@ -1456,12 +1422,8 @@ void getIdTokenWithAudience_badEmailError_issClaimTraced() throws IOException {
String expectedErrorMessage = String.format("iss: %s", CLIENT_EMAIL);
- try {
- tokenCredential.refresh();
- fail("Should not be able to use credential without exception.");
- } catch (IOException expected) {
- assertTrue(expected.getMessage().contains(expectedErrorMessage));
- }
+ IOException exception = assertThrows(IOException.class, tokenCredential::refresh);
+ assertTrue(exception.getMessage().contains(expectedErrorMessage));
}
@Test
@@ -1469,7 +1431,13 @@ void fromStream_noPrivateKey_throws() throws IOException {
InputStream serviceAccountStream =
writeServiceAccountStream(CLIENT_ID, CLIENT_EMAIL, null, PRIVATE_KEY_ID);
- testFromStreamException(serviceAccountStream, "private_key");
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () ->
+ ServiceAccountCredentials.fromStream(
+ serviceAccountStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("private_key"));
}
@Test
@@ -1477,7 +1445,13 @@ void fromStream_noPrivateKeyId_throws() throws IOException {
InputStream serviceAccountStream =
writeServiceAccountStream(CLIENT_ID, CLIENT_EMAIL, PRIVATE_KEY_PKCS8, null);
- testFromStreamException(serviceAccountStream, "private_key_id");
+ IOException exception =
+ assertThrows(
+ IOException.class,
+ () ->
+ ServiceAccountCredentials.fromStream(
+ serviceAccountStream, DUMMY_TRANSPORT_FACTORY));
+ assertTrue(exception.getMessage().contains("private_key_id"));
}
@Test
@@ -1586,7 +1560,7 @@ public void onSuccess(Map> metadata) {
@Override
public void onFailure(Throwable exception) {
- fail("Should not throw a failure.");
+ // Test framework should fail if this is called and success.set(true) is not reached.
}
});
@@ -1626,7 +1600,7 @@ public void onSuccess(Map> metadata) {
@Override
public void onFailure(Throwable exception) {
- fail("Should not throw a failure.");
+ // Test framework should fail if this is called and success.set(true) is not reached.
}
});
@@ -1683,12 +1657,7 @@ void refreshAccessToken_withDomainDelegation_selfSignedJWT_disabled() throws IOE
Map> metadata = credentials.getRequestMetadata(CALL_URI);
TestUtils.assertContainsBearerToken(metadata, accessToken1);
- try {
- verifyJwtAccess(metadata, "dummy.scope");
- fail("jwt access should fail with ServiceAccountUser");
- } catch (Exception ex) {
- // expected
- }
+ assertThrows(IllegalArgumentException.class, () -> verifyJwtAccess(metadata, "dummy.scope"));
transport.addServiceAccount(CLIENT_EMAIL, accessToken2);
credentials.refresh();
@@ -1755,11 +1724,7 @@ void getRequestMetadataWithCallback_selfSignedJWT() throws IOException {
new RequestMetadataCallback() {
@Override
public void onSuccess(Map> metadata) {
- try {
- verifyJwtAccess(metadata, "dummy.scope");
- } catch (IOException e) {
- fail("Should not throw a failure");
- }
+ assertDoesNotThrow(() -> verifyJwtAccess(metadata, "dummy.scope"));
success.set(true);
}
@@ -1888,15 +1853,4 @@ static InputStream writeServiceAccountStream(
clientId, clientEmail, privateKeyPkcs8, privateKeyId, null, null, universeDomain);
return TestUtils.jsonToInputStream(json);
}
-
- private static void testFromStreamException(InputStream stream, String expectedMessageContent) {
- try {
- ServiceAccountCredentials.fromStream(stream, DUMMY_TRANSPORT_FACTORY);
- fail(
- String.format(
- "Should throw exception with message containing '%s'", expectedMessageContent));
- } catch (IOException expected) {
- assertTrue(expected.getMessage().contains(expectedMessageContent));
- }
- }
}
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountJwtAccessCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountJwtAccessCredentialsTest.java
index 8d696663132b..d961f7b1b685 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountJwtAccessCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountJwtAccessCredentialsTest.java
@@ -33,12 +33,14 @@
import static com.google.auth.Credentials.GOOGLE_DEFAULT_UNIVERSE;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
@@ -117,50 +119,44 @@ void constructor_allParameters_constructs() throws IOException {
@Test
void constructor_noClientId_constructs() throws IOException {
PrivateKey privateKey = OAuth2Utils.privateKeyFromPkcs8(SA_PRIVATE_KEY_PKCS8);
- ServiceAccountJwtAccessCredentials.newBuilder()
- .setClientEmail(SA_CLIENT_EMAIL)
- .setPrivateKey(privateKey)
- .setPrivateKeyId(SA_PRIVATE_KEY_ID)
- .build();
+ ServiceAccountJwtAccessCredentials.Builder builder =
+ ServiceAccountJwtAccessCredentials.newBuilder()
+ .setClientEmail(SA_CLIENT_EMAIL)
+ .setPrivateKey(privateKey)
+ .setPrivateKeyId(SA_PRIVATE_KEY_ID);
+ assertDoesNotThrow(builder::build);
}
@Test
void constructor_noPrivateKeyId_constructs() throws IOException {
PrivateKey privateKey = OAuth2Utils.privateKeyFromPkcs8(SA_PRIVATE_KEY_PKCS8);
- ServiceAccountJwtAccessCredentials.newBuilder()
- .setClientId(SA_CLIENT_ID)
- .setClientEmail(SA_CLIENT_EMAIL)
- .setPrivateKey(privateKey)
- .build();
+ ServiceAccountJwtAccessCredentials.Builder builder =
+ ServiceAccountJwtAccessCredentials.newBuilder()
+ .setClientId(SA_CLIENT_ID)
+ .setClientEmail(SA_CLIENT_EMAIL)
+ .setPrivateKey(privateKey);
+ assertDoesNotThrow(builder::build);
}
@Test
void constructor_noEmail_throws() throws IOException {
PrivateKey privateKey = OAuth2Utils.privateKeyFromPkcs8(SA_PRIVATE_KEY_PKCS8);
- try {
- ServiceAccountJwtAccessCredentials.newBuilder()
- .setClientId(SA_CLIENT_ID)
- .setPrivateKey(privateKey)
- .setPrivateKeyId(SA_PRIVATE_KEY_ID)
- .build();
- fail("exception expected");
- } catch (NullPointerException e) {
- // Expected
- }
+ ServiceAccountJwtAccessCredentials.Builder builder =
+ ServiceAccountJwtAccessCredentials.newBuilder()
+ .setClientId(SA_CLIENT_ID)
+ .setPrivateKey(privateKey)
+ .setPrivateKeyId(SA_PRIVATE_KEY_ID);
+ assertThrows(NullPointerException.class, builder::build);
}
@Test
void constructor_noPrivateKey_throws() {
- try {
- ServiceAccountJwtAccessCredentials.newBuilder()
- .setClientId(SA_CLIENT_ID)
- .setClientEmail(SA_CLIENT_EMAIL)
- .setPrivateKeyId(SA_PRIVATE_KEY_ID)
- .build();
- fail("exception expected");
- } catch (NullPointerException e) {
- // Expected
- }
+ ServiceAccountJwtAccessCredentials.Builder builder =
+ ServiceAccountJwtAccessCredentials.newBuilder()
+ .setClientId(SA_CLIENT_ID)
+ .setClientEmail(SA_CLIENT_EMAIL)
+ .setPrivateKeyId(SA_PRIVATE_KEY_ID);
+ assertThrows(NullPointerException.class, builder::build);
}
@Test
@@ -168,7 +164,7 @@ void getAuthenticationType_returnsJwtAccess() throws IOException {
Credentials credentials =
ServiceAccountJwtAccessCredentials.fromPkcs8(
SA_CLIENT_ID, SA_CLIENT_EMAIL, SA_PRIVATE_KEY_PKCS8, SA_PRIVATE_KEY_ID);
- assertEquals(credentials.getAuthenticationType(), "JWTAccess");
+ assertEquals("JWTAccess", credentials.getAuthenticationType());
}
@Test
@@ -200,7 +196,7 @@ void getRequestMetadata_blocking_hasJwtAccess() throws IOException {
Map> metadata = credentials.getRequestMetadata(CALL_URI);
- verifyJwtAccess(metadata, SA_CLIENT_EMAIL, CALL_URI, SA_PRIVATE_KEY_ID);
+ verifyJwtAccess(metadata, CALL_URI);
}
@Test
@@ -217,7 +213,7 @@ void getRequestMetadata_blocking_defaultURI_hasJwtAccess() throws IOException {
Map> metadata = credentials.getRequestMetadata();
- verifyJwtAccess(metadata, SA_CLIENT_EMAIL, CALL_URI, SA_PRIVATE_KEY_ID);
+ verifyJwtAccess(metadata, CALL_URI);
}
@Test
@@ -231,12 +227,7 @@ void getRequestMetadata_blocking_noURI_throws() throws IOException {
.setPrivateKeyId(SA_PRIVATE_KEY_ID)
.build();
- try {
- credentials.getRequestMetadata();
- fail("exception expected");
- } catch (IOException e) {
- // Expected
- }
+ assertThrows(IOException.class, credentials::getRequestMetadata);
}
@Test
@@ -305,7 +296,7 @@ void getRequestMetadata_async_hasJwtAccess() throws IOException {
credentials.getRequestMetadata(CALL_URI, executor, callback);
assertEquals(0, executor.numTasks());
assertNotNull(callback.metadata);
- verifyJwtAccess(callback.metadata, SA_CLIENT_EMAIL, CALL_URI, SA_PRIVATE_KEY_ID);
+ verifyJwtAccess(callback.metadata, CALL_URI);
}
@Test
@@ -325,7 +316,7 @@ void getRequestMetadata_async_defaultURI_hasJwtAccess() throws IOException {
credentials.getRequestMetadata(null, executor, callback);
assertEquals(0, executor.numTasks());
assertNotNull(callback.metadata);
- verifyJwtAccess(callback.metadata, SA_CLIENT_EMAIL, CALL_URI, SA_PRIVATE_KEY_ID);
+ verifyJwtAccess(callback.metadata, CALL_URI);
}
@Test
@@ -418,8 +409,8 @@ void getRequestMetadata_contains_quotaProjectId() throws IOException {
Map> metadata = credentials.getRequestMetadata(CALL_URI);
assertTrue(metadata.containsKey(GoogleCredentials.QUOTA_PROJECT_ID_HEADER_KEY));
assertEquals(
- metadata.get(GoogleCredentials.QUOTA_PROJECT_ID_HEADER_KEY),
- Collections.singletonList(QUOTA_PROJECT));
+ Collections.singletonList(QUOTA_PROJECT),
+ metadata.get(GoogleCredentials.QUOTA_PROJECT_ID_HEADER_KEY));
}
@Test
@@ -473,8 +464,8 @@ void equals_true() throws IOException {
.setPrivateKeyId(SA_PRIVATE_KEY_ID)
.setDefaultAudience(CALL_URI)
.build();
- assertTrue(credentials.equals(otherCredentials));
- assertTrue(otherCredentials.equals(credentials));
+ assertEquals(credentials, otherCredentials);
+ assertEquals(otherCredentials, credentials);
}
@Test
@@ -496,8 +487,8 @@ void equals_false_clientId() throws IOException {
.setPrivateKeyId(SA_PRIVATE_KEY_ID)
.setDefaultAudience(CALL_URI)
.build();
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
@@ -519,8 +510,8 @@ void equals_false_email() throws IOException {
.setPrivateKeyId(SA_PRIVATE_KEY_ID)
.setDefaultAudience(CALL_URI)
.build();
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
@@ -542,8 +533,8 @@ void equals_false_keyId() throws IOException {
.setPrivateKeyId("otherKeyId")
.setDefaultAudience(CALL_URI)
.build();
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
@@ -566,8 +557,8 @@ void equals_false_callUri() throws IOException {
.setPrivateKeyId(SA_PRIVATE_KEY_ID)
.setDefaultAudience(otherCallUri)
.build();
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
@@ -625,23 +616,19 @@ void serialize() throws IOException, ClassNotFoundException {
.build();
ServiceAccountJwtAccessCredentials deserializedCredentials =
serializeAndDeserialize(credentials);
- verifyJwtAccess(
- deserializedCredentials.getRequestMetadata(), SA_CLIENT_EMAIL, CALL_URI, SA_PRIVATE_KEY_ID);
+ verifyJwtAccess(deserializedCredentials.getRequestMetadata(), CALL_URI);
assertEquals(credentials, deserializedCredentials);
assertEquals(credentials.hashCode(), deserializedCredentials.hashCode());
assertEquals(credentials.toString(), deserializedCredentials.toString());
- assertSame(deserializedCredentials.clock, Clock.SYSTEM);
+ assertSame(Clock.SYSTEM, deserializedCredentials.clock);
}
@Test
- void fromStream_nullStream_throws() throws IOException {
+ void fromStream_nullStream_throws() {
MockHttpTransportFactory transportFactory = new MockHttpTransportFactory();
- try {
- ServiceAccountCredentials.fromStream(null, transportFactory);
- fail("Should throw if InputStream is null");
- } catch (NullPointerException expected) {
- // Expected
- }
+ assertThrows(
+ NullPointerException.class,
+ () -> ServiceAccountCredentials.fromStream(null, transportFactory));
}
@Test
@@ -654,7 +641,7 @@ void fromStream_hasJwtAccess() throws IOException {
assertNotNull(credentials);
Map> metadata = credentials.getRequestMetadata(CALL_URI);
- verifyJwtAccess(metadata, SA_CLIENT_EMAIL, CALL_URI, SA_PRIVATE_KEY_ID);
+ verifyJwtAccess(metadata, CALL_URI);
}
@Test
@@ -668,7 +655,7 @@ void fromStream_defaultURI_hasJwtAccess() throws IOException {
assertNotNull(credentials);
Map> metadata = credentials.getRequestMetadata(null);
- verifyJwtAccess(metadata, SA_CLIENT_EMAIL, CALL_URI, SA_PRIVATE_KEY_ID);
+ verifyJwtAccess(metadata, CALL_URI);
}
@Test
@@ -722,7 +709,7 @@ void jwtWithClaims_overrideAudience() throws IOException {
Map> metadata = withAudience.getRequestMetadata(CALL_URI);
- verifyJwtAccess(metadata, SA_CLIENT_EMAIL, URI.create("new-audience"), SA_PRIVATE_KEY_ID);
+ verifyJwtAccess(metadata, URI.create("new-audience"));
}
@Test
@@ -735,12 +722,8 @@ void jwtWithClaims_noAudience() throws IOException {
.setPrivateKey(privateKey)
.setPrivateKeyId(SA_PRIVATE_KEY_ID)
.build();
- try {
- credentials.jwtWithClaims(JwtClaims.newBuilder().build());
- fail("Expected to throw exception for missing audience");
- } catch (IllegalStateException ex) {
- // expected exception
- }
+ JwtClaims claims = JwtClaims.newBuilder().build();
+ assertThrows(IllegalStateException.class, () -> credentials.jwtWithClaims(claims));
}
@Test
@@ -757,7 +740,7 @@ void jwtWithClaims_defaultAudience() throws IOException {
Credentials withAudience = credentials.jwtWithClaims(JwtClaims.newBuilder().build());
Map> metadata = withAudience.getRequestMetadata(CALL_URI);
- verifyJwtAccess(metadata, SA_CLIENT_EMAIL, URI.create("default-audience"), SA_PRIVATE_KEY_ID);
+ verifyJwtAccess(metadata, URI.create("default-audience"));
}
@Test
@@ -832,15 +815,7 @@ public void onFailure(Throwable exception) {
@Test
void fromJSON_noUniverseDomain() throws IOException {
- GenericJson json =
- writeServiceAccountJson(
- SA_CLIENT_ID,
- SA_CLIENT_EMAIL,
- SA_PRIVATE_KEY_PKCS8,
- "test-project-id",
- SA_PRIVATE_KEY_ID,
- QUOTA_PROJECT,
- null);
+ GenericJson json = writeServiceAccountJson(null);
ServiceAccountJwtAccessCredentials credentials =
ServiceAccountJwtAccessCredentials.fromJson(json, URI.create("default-aud"));
assertEquals(SA_CLIENT_ID, credentials.getClientId());
@@ -853,15 +828,7 @@ void fromJSON_noUniverseDomain() throws IOException {
@Test
void fromJSON_UniverseDomainSet() throws IOException {
- GenericJson json =
- writeServiceAccountJson(
- SA_CLIENT_ID,
- SA_CLIENT_EMAIL,
- SA_PRIVATE_KEY_PKCS8,
- "test-project-id",
- SA_PRIVATE_KEY_ID,
- QUOTA_PROJECT,
- "example.com");
+ GenericJson json = writeServiceAccountJson("example.com");
ServiceAccountJwtAccessCredentials credentials =
ServiceAccountJwtAccessCredentials.fromJson(json, URI.create("default-aud"));
assertEquals(SA_CLIENT_ID, credentials.getClientId());
@@ -933,11 +900,7 @@ void builder_customUniverseDomain() throws IOException {
assertEquals("example.com", credentials.getUniverseDomain());
}
- private void verifyJwtAccess(
- Map> metadata,
- String expectedEmail,
- URI expectedAudience,
- String expectedKeyId)
+ private void verifyJwtAccess(Map> metadata, URI expectedAudience)
throws IOException {
assertNotNull(metadata);
List authorizations = metadata.get(AuthHttpConstants.AUTHORIZATION);
@@ -951,50 +914,32 @@ private void verifyJwtAccess(
}
assertNotNull(assertion, "Bearer assertion not found");
JsonWebSignature signature = JsonWebSignature.parse(JSON_FACTORY, assertion);
- assertEquals(expectedEmail, signature.getPayload().getIssuer());
- assertEquals(expectedEmail, signature.getPayload().getSubject());
+ assertEquals(
+ ServiceAccountJwtAccessCredentialsTest.SA_CLIENT_EMAIL, signature.getPayload().getIssuer());
+ assertEquals(
+ ServiceAccountJwtAccessCredentialsTest.SA_CLIENT_EMAIL,
+ signature.getPayload().getSubject());
assertEquals(expectedAudience.toString(), signature.getPayload().getAudience());
- assertEquals(expectedKeyId, signature.getHeader().getKeyId());
+ assertEquals(
+ ServiceAccountJwtAccessCredentialsTest.SA_PRIVATE_KEY_ID, signature.getHeader().getKeyId());
}
private static void testFromStreamException(InputStream stream, String expectedMessageContent) {
- try {
- ServiceAccountJwtAccessCredentials.fromStream(stream, CALL_URI);
- fail(
- String.format(
- "Should throw exception with message containing '%s'", expectedMessageContent));
- } catch (IOException expected) {
- assertTrue(expected.getMessage().contains(expectedMessageContent));
- }
+ IOException expected =
+ assertThrows(
+ IOException.class,
+ () -> ServiceAccountJwtAccessCredentials.fromStream(stream, CALL_URI));
+ assertTrue(expected.getMessage().contains(expectedMessageContent));
}
- private GenericJson writeServiceAccountJson(
- String clientId,
- String clientEmail,
- String privateKeyPkcs8,
- String privateKeyId,
- String projectId,
- String quotaProjectId,
- String universeDomain) {
+ private GenericJson writeServiceAccountJson(String universeDomain) {
GenericJson json = new GenericJson();
- if (clientId != null) {
- json.put("client_id", clientId);
- }
- if (clientEmail != null) {
- json.put("client_email", clientEmail);
- }
- if (privateKeyPkcs8 != null) {
- json.put("private_key", privateKeyPkcs8);
- }
- if (privateKeyId != null) {
- json.put("private_key_id", privateKeyId);
- }
- if (projectId != null) {
- json.put("project_id", projectId);
- }
- if (quotaProjectId != null) {
- json.put("quota_project_id", quotaProjectId);
- }
+ json.put("client_id", ServiceAccountJwtAccessCredentialsTest.SA_CLIENT_ID);
+ json.put("client_email", ServiceAccountJwtAccessCredentialsTest.SA_CLIENT_EMAIL);
+ json.put("private_key", ServiceAccountJwtAccessCredentialsTest.SA_PRIVATE_KEY_PKCS8);
+ json.put("private_key_id", "test-project-id");
+ json.put("project_id", ServiceAccountJwtAccessCredentialsTest.SA_PRIVATE_KEY_ID);
+ json.put("quota_project_id", ServiceAccountJwtAccessCredentialsTest.QUOTA_PROJECT);
if (universeDomain != null) {
json.put("universe_domain", universeDomain);
}
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/StsRequestHandlerTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/StsRequestHandlerTest.java
index 6607403a4d7a..a0e2090d2cc9 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/StsRequestHandlerTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/StsRequestHandlerTest.java
@@ -176,7 +176,7 @@ void exchangeToken_throwsException() throws IOException {
TestUtils.buildHttpResponseException(
"invalidRequest", /* errorDescription= */ null, /* errorUri= */ null));
- OAuthException e = assertThrows(OAuthException.class, () -> requestHandler.exchangeToken());
+ OAuthException e = assertThrows(OAuthException.class, requestHandler::exchangeToken);
assertEquals("invalidRequest", e.getErrorCode());
assertNull(e.getErrorDescription());
@@ -196,7 +196,7 @@ void exchangeToken_withOptionalParams_throwsException() throws IOException {
transport.addResponseErrorSequence(
TestUtils.buildHttpResponseException("invalidRequest", "errorDescription", "errorUri"));
- OAuthException e = assertThrows(OAuthException.class, () -> requestHandler.exchangeToken());
+ OAuthException e = assertThrows(OAuthException.class, requestHandler::exchangeToken);
assertEquals("invalidRequest", e.getErrorCode());
assertEquals("errorDescription", e.getErrorDescription());
@@ -216,8 +216,7 @@ void exchangeToken_ioException() {
IOException e = new IOException();
transport.addResponseErrorSequence(e);
- IOException thrownException =
- assertThrows(IOException.class, () -> requestHandler.exchangeToken());
+ IOException thrownException = assertThrows(IOException.class, requestHandler::exchangeToken);
assertEquals(e, thrownException);
}
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/TestEnvironmentProvider.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/TestEnvironmentProvider.java
index 9e6de11089fe..b7921b3a426c 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/TestEnvironmentProvider.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/TestEnvironmentProvider.java
@@ -1,9 +1,39 @@
+/*
+ * Copyright 2021, 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 java.util.HashMap;
import java.util.Map;
-final class TestEnvironmentProvider implements EnvironmentProvider {
+public final class TestEnvironmentProvider implements EnvironmentProvider {
private final Map environmentVariables = new HashMap<>();
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/TestPropertyProvider.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/TestPropertyProvider.java
new file mode 100644
index 000000000000..e84d6ba5c8e0
--- /dev/null
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/TestPropertyProvider.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * 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 LLC 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 java.util.HashMap;
+import java.util.Map;
+
+public class TestPropertyProvider implements PropertyProvider {
+ private final Map properties = new HashMap<>();
+
+ public TestPropertyProvider() {}
+
+ public void setProperty(String property, String value) {
+ properties.put(property, value);
+ }
+
+ @Override
+ public String getProperty(String property, String def) {
+ if (properties.containsKey(property)) {
+ return properties.get(property);
+ }
+ return def;
+ }
+}
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/TokenVerifierTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/TokenVerifierTest.java
index 6872214f05d7..81847ffd24f8 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/TokenVerifierTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/TokenVerifierTest.java
@@ -32,8 +32,8 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.LowLevelHttpRequest;
@@ -84,12 +84,9 @@ public long currentTimeMillis() {
void verifyExpiredToken() {
for (String token : ALL_TOKENS) {
TokenVerifier tokenVerifier = TokenVerifier.newBuilder().build();
- try {
- tokenVerifier.verify(token);
- fail("Should have thrown a VerificationException");
- } catch (TokenVerifier.VerificationException e) {
- assertTrue(e.getMessage().contains("expired"));
- }
+ VerificationException e =
+ assertThrows(VerificationException.class, () -> tokenVerifier.verify(token));
+ assertTrue(e.getMessage().contains("expired"));
}
}
@@ -98,12 +95,9 @@ void verifyExpectedAudience() {
TokenVerifier tokenVerifier =
TokenVerifier.newBuilder().setAudience("expected audience").build();
for (String token : ALL_TOKENS) {
- try {
- tokenVerifier.verify(token);
- fail("Should have thrown a VerificationException");
- } catch (TokenVerifier.VerificationException e) {
- assertTrue(e.getMessage().contains("audience does not match"));
- }
+ VerificationException e =
+ assertThrows(VerificationException.class, () -> tokenVerifier.verify(token));
+ assertTrue(e.getMessage().contains("audience does not match"));
}
}
@@ -111,12 +105,9 @@ void verifyExpectedAudience() {
void verifyExpectedIssuer() {
TokenVerifier tokenVerifier = TokenVerifier.newBuilder().setIssuer("expected issuer").build();
for (String token : ALL_TOKENS) {
- try {
- tokenVerifier.verify(token);
- fail("Should have thrown a VerificationException");
- } catch (TokenVerifier.VerificationException e) {
- assertTrue(e.getMessage().contains("issuer does not match"));
- }
+ VerificationException e =
+ assertThrows(VerificationException.class, () -> tokenVerifier.verify(token));
+ assertTrue(e.getMessage().contains("issuer does not match"));
}
}
@@ -151,13 +142,10 @@ public LowLevelHttpResponse execute() throws IOException {
.setHttpTransportFactory(httpTransportFactory)
.build();
- try {
- tokenVerifier.verify(ES256_TOKEN);
- fail("Should not be able to continue without exception.");
- } catch (TokenVerifier.VerificationException exception) {
- assertTrue(
- exception.getMessage().contains("Error fetching PublicKey from certificate location"));
- }
+ VerificationException exception =
+ assertThrows(VerificationException.class, () -> tokenVerifier.verify(ES256_TOKEN));
+ assertTrue(
+ exception.getMessage().contains("Error fetching PublicKey from certificate location"));
}
@Test
@@ -189,12 +177,9 @@ public LowLevelHttpResponse execute() throws IOException {
.setClock(FIXED_CLOCK)
.setHttpTransportFactory(httpTransportFactory)
.build();
- try {
- tokenVerifier.verify(ES256_TOKEN);
- fail("Should have failed verification");
- } catch (TokenVerifier.VerificationException e) {
- assertTrue(e.getMessage().contains("Error fetching PublicKey"));
- }
+ VerificationException e =
+ assertThrows(VerificationException.class, () -> tokenVerifier.verify(ES256_TOKEN));
+ assertTrue(e.getMessage().contains("Error fetching PublicKey"));
}
@Test
@@ -230,19 +215,12 @@ void verifyPublicKeyStoreIntermittentError() throws VerificationException, IOExc
.setHttpTransportFactory(transportFactory)
.build();
- try {
- tokenVerifier.verify(ES256_TOKEN);
- fail("Should not be able to continue without exception.");
- } catch (TokenVerifier.VerificationException exception) {
- assertTrue(exception.getMessage().contains("Error fetching PublicKey"));
- }
+ VerificationException exception =
+ assertThrows(VerificationException.class, () -> tokenVerifier.verify(ES256_TOKEN));
+ assertTrue(exception.getMessage().contains("Error fetching PublicKey"));
- try {
- tokenVerifier.verify(ES256_TOKEN);
- fail("Should not be able to continue without exception.");
- } catch (TokenVerifier.VerificationException exception) {
- assertTrue(exception.getCause().getMessage().contains("No valid public key"));
- }
+ exception = assertThrows(VerificationException.class, () -> tokenVerifier.verify(ES256_TOKEN));
+ assertTrue(exception.getCause().getMessage().contains("No valid public key"));
assertNotNull(tokenVerifier.verify(ES256_TOKEN));
}
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/UserAuthorizerTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/UserAuthorizerTest.java
index 050a9d199079..bcde55b0045a 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/UserAuthorizerTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/UserAuthorizerTest.java
@@ -40,7 +40,6 @@
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import com.google.auth.TestUtils;
import com.google.auth.http.HttpTransportFactory;
@@ -66,7 +65,7 @@ class UserAuthorizerTest {
private static final List GRANTED_SCOPES = Arrays.asList("scope1", "scope2");
private static final String GRANTED_SCOPES_STRING = String.join(" ", GRANTED_SCOPES);
private static final String DUMMY_SCOPE = "dummy_scope";
- private static final List DUMMY_SCOPES = Arrays.asList(DUMMY_SCOPE);
+ private static final List DUMMY_SCOPES = Collections.singletonList(DUMMY_SCOPE);
private static final Long EXPIRATION_TIME = 504000300L;
private static final AccessToken ACCESS_TOKEN =
AccessToken.newBuilder()
@@ -147,20 +146,15 @@ void constructorWithClientAuthenticationTypeNone() {
@Test
void constructorCommon_nullClientId_throws() {
- assertThrows(
- NullPointerException.class,
- () ->
- UserAuthorizer.newBuilder()
- .setScopes(DUMMY_SCOPES)
- .setCallbackUri(CALLBACK_URI)
- .build());
+ UserAuthorizer.Builder builder =
+ UserAuthorizer.newBuilder().setScopes(DUMMY_SCOPES).setCallbackUri(CALLBACK_URI);
+ assertThrows(NullPointerException.class, builder::build);
}
@Test
void constructorCommon_nullScopes_throws() {
- assertThrows(
- NullPointerException.class,
- () -> UserAuthorizer.newBuilder().setClientId(CLIENT_ID).build());
+ UserAuthorizer.Builder builder = UserAuthorizer.newBuilder().setClientId(CLIENT_ID);
+ assertThrows(NullPointerException.class, builder::build);
}
@Test
@@ -181,30 +175,30 @@ void getCallbackUri_relativeToBase() {
@Test
void getAuthorizationUrl() throws IOException {
- final String CUSTOM_STATE = "custom_state";
- final String PROTOCOL = "https";
- final String HOST = "accounts.test.com";
- final String PATH = "/o/o/oauth2/auth";
- final URI AUTH_URI = URI.create(PROTOCOL + "://" + HOST + PATH);
+ final String customState = "custom_state";
+ final String protocol = "https";
+ final String host = "accounts.test.com";
+ final String path = "/o/o/oauth2/auth";
+ final URI authUri = URI.create(protocol + "://" + host + path);
final String EXPECTED_CALLBACK = "http://example.com" + CALLBACK_URI.toString();
UserAuthorizer authorizer =
UserAuthorizer.newBuilder()
.setClientId(CLIENT_ID)
.setScopes(DUMMY_SCOPES)
.setCallbackUri(CALLBACK_URI)
- .setUserAuthUri(AUTH_URI)
+ .setUserAuthUri(authUri)
.setPKCEProvider(pkce)
.build();
- URL authorizationUrl = authorizer.getAuthorizationUrl(USER_ID, CUSTOM_STATE, BASE_URI);
+ URL authorizationUrl = authorizer.getAuthorizationUrl(USER_ID, customState, BASE_URI);
- assertEquals(PROTOCOL, authorizationUrl.getProtocol());
+ assertEquals(protocol, authorizationUrl.getProtocol());
assertEquals(-1, authorizationUrl.getPort());
- assertEquals(PATH, authorizationUrl.getPath());
- assertEquals(HOST, authorizationUrl.getHost());
+ assertEquals(path, authorizationUrl.getPath());
+ assertEquals(host, authorizationUrl.getHost());
String query = authorizationUrl.getQuery();
Map parameters = TestUtils.parseQuery(query);
- assertEquals(CUSTOM_STATE, parameters.get("state"));
+ assertEquals(customState, parameters.get("state"));
assertEquals(USER_ID, parameters.get("login_hint"));
assertEquals(EXPECTED_CALLBACK, parameters.get("redirect_uri"));
assertEquals(CLIENT_ID_VALUE, parameters.get("client_id"));
@@ -217,18 +211,17 @@ void getAuthorizationUrl() throws IOException {
@Test
void getAuthorizationUrl_additionalParameters() throws IOException {
- final String CUSTOM_STATE = "custom_state";
- final String PROTOCOL = "https";
- final String HOST = "accounts.test.com";
- final String PATH = "/o/o/oauth2/auth";
- final URI AUTH_URI = URI.create(PROTOCOL + "://" + HOST + PATH);
- final String EXPECTED_CALLBACK = "http://example.com" + CALLBACK_URI.toString();
+ final String customState = "custom_state";
+ final String protocol = "https";
+ final String host = "accounts.test.com";
+ final String path = "/o/o/oauth2/auth";
+ final URI authUri = URI.create(protocol + "://" + host + path);
UserAuthorizer authorizer =
UserAuthorizer.newBuilder()
.setClientId(CLIENT_ID)
.setScopes(DUMMY_SCOPES)
.setCallbackUri(CALLBACK_URI)
- .setUserAuthUri(AUTH_URI)
+ .setUserAuthUri(authUri)
.build();
Map additionalParameters = new HashMap();
additionalParameters.put("param1", "value1");
@@ -236,7 +229,7 @@ void getAuthorizationUrl_additionalParameters() throws IOException {
// Verify that the authorization URL doesn't include the additional parameters if they are not
// passed in.
- URL authorizationUrl = authorizer.getAuthorizationUrl(USER_ID, CUSTOM_STATE, BASE_URI);
+ URL authorizationUrl = authorizer.getAuthorizationUrl(USER_ID, customState, BASE_URI);
String query = authorizationUrl.getQuery();
Map parameters = TestUtils.parseQuery(query);
assertFalse(parameters.containsKey("param1"));
@@ -244,7 +237,7 @@ void getAuthorizationUrl_additionalParameters() throws IOException {
// Verify that the authorization URL includes the additional parameters if they are passed in.
authorizationUrl =
- authorizer.getAuthorizationUrl(USER_ID, CUSTOM_STATE, BASE_URI, additionalParameters);
+ authorizer.getAuthorizationUrl(USER_ID, customState, BASE_URI, additionalParameters);
query = authorizationUrl.getQuery();
parameters = TestUtils.parseQuery(query);
assertEquals("value1", parameters.get("param1"));
@@ -252,7 +245,7 @@ void getAuthorizationUrl_additionalParameters() throws IOException {
// Verify that the authorization URL doesn't include the additional parameters passed in the
// previous call to the authorizer
- authorizationUrl = authorizer.getAuthorizationUrl(USER_ID, CUSTOM_STATE, BASE_URI);
+ authorizationUrl = authorizer.getAuthorizationUrl(USER_ID, customState, BASE_URI);
query = authorizationUrl.getQuery();
parameters = TestUtils.parseQuery(query);
assertFalse(parameters.containsKey("param1"));
@@ -392,7 +385,7 @@ void testGetTokenResponseFromAuthCodeExchange_missingAuthCode_throws() {
}
@Test
- void testGetTokenResponseFromAuthCodeExchange_missingAccessToken_throws() throws IOException {
+ void testGetTokenResponseFromAuthCodeExchange_missingAccessToken_throws() {
MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
transportFactory.transport.addClient(CLIENT_ID_VALUE, CLIENT_SECRET);
// Missing access token.
@@ -452,7 +445,7 @@ void getCredentials_storedCredentials_returnsStored() throws IOException {
}
@Test
- void getCredentials_nullUserId_throws() throws IOException {
+ void getCredentials_nullUserId_throws() {
TokenStore tokenStore = new MemoryTokensStorage();
UserAuthorizer authorizer =
UserAuthorizer.newBuilder()
@@ -643,7 +636,7 @@ void getCredentialsFromCode_additionalParameters() throws IOException {
}
@Test
- void getCredentialsFromCode_nullCode_throws() throws IOException {
+ void getCredentialsFromCode_nullCode_throws() {
UserAuthorizer authorizer =
UserAuthorizer.newBuilder()
.setClientId(CLIENT_ID)
@@ -695,7 +688,7 @@ void getAndStoreCredentialsFromCode_getAndStoresCredentials() throws IOException
}
@Test
- void getAndStoreCredentialsFromCode_nullCode_throws() throws IOException {
+ void getAndStoreCredentialsFromCode_nullCode_throws() {
UserAuthorizer authorizer =
UserAuthorizer.newBuilder()
.setClientId(CLIENT_ID)
@@ -709,7 +702,7 @@ void getAndStoreCredentialsFromCode_nullCode_throws() throws IOException {
}
@Test
- void getAndStoreCredentialsFromCode_nullUserId_throws() throws IOException {
+ void getAndStoreCredentialsFromCode_nullUserId_throws() {
UserAuthorizer authorizer =
UserAuthorizer.newBuilder()
.setClientId(CLIENT_ID)
@@ -756,19 +749,14 @@ void revokeAuthorization_revokesAndClears() throws IOException {
authorizer.revokeAuthorization(USER_ID);
- try {
- credentials1.refresh();
- fail("Credentials should not refresh after revoke.");
- } catch (IOException expected) {
- // Expected
- }
+ assertThrows(IOException.class, credentials1::refresh);
UserCredentials credentials2 = authorizer.getCredentials(USER_ID);
assertNull(credentials2);
}
@Test
void nullCodeVerifierPKCEProvider() {
- PKCEProvider pkce =
+ PKCEProvider pkceProvider =
new PKCEProvider() {
@Override
public String getCodeVerifier() {
@@ -786,20 +774,17 @@ public String getCodeChallenge() {
}
};
- assertThrows(
- IllegalArgumentException.class,
- () ->
- UserAuthorizer.newBuilder()
- .setClientId(CLIENT_ID)
- .setScopes(DUMMY_SCOPES)
- .setTokenStore(new MemoryTokensStorage())
- .setPKCEProvider(pkce)
- .build());
+ UserAuthorizer.Builder builder =
+ UserAuthorizer.newBuilder()
+ .setClientId(CLIENT_ID)
+ .setScopes(DUMMY_SCOPES)
+ .setTokenStore(new MemoryTokensStorage());
+ assertThrows(IllegalArgumentException.class, () -> builder.setPKCEProvider(pkceProvider));
}
@Test
void nullCodeChallengePKCEProvider() {
- PKCEProvider pkce =
+ PKCEProvider pkceProvider =
new PKCEProvider() {
@Override
public String getCodeVerifier() {
@@ -817,20 +802,17 @@ public String getCodeChallenge() {
}
};
- assertThrows(
- IllegalArgumentException.class,
- () ->
- UserAuthorizer.newBuilder()
- .setClientId(CLIENT_ID)
- .setScopes(DUMMY_SCOPES)
- .setTokenStore(new MemoryTokensStorage())
- .setPKCEProvider(pkce)
- .build());
+ UserAuthorizer.Builder builder =
+ UserAuthorizer.newBuilder()
+ .setClientId(CLIENT_ID)
+ .setScopes(DUMMY_SCOPES)
+ .setTokenStore(new MemoryTokensStorage());
+ assertThrows(IllegalArgumentException.class, () -> builder.setPKCEProvider(pkceProvider));
}
@Test
void nullCodeChallengeMethodPKCEProvider() {
- PKCEProvider pkce =
+ PKCEProvider pkceProvider =
new PKCEProvider() {
@Override
public String getCodeVerifier() {
@@ -848,15 +830,12 @@ public String getCodeChallenge() {
}
};
- assertThrows(
- IllegalArgumentException.class,
- () ->
- UserAuthorizer.newBuilder()
- .setClientId(CLIENT_ID)
- .setScopes(DUMMY_SCOPES)
- .setTokenStore(new MemoryTokensStorage())
- .setPKCEProvider(pkce)
- .build());
+ UserAuthorizer.Builder builder =
+ UserAuthorizer.newBuilder()
+ .setClientId(CLIENT_ID)
+ .setScopes(DUMMY_SCOPES)
+ .setTokenStore(new MemoryTokensStorage());
+ assertThrows(IllegalArgumentException.class, () -> builder.setPKCEProvider(pkceProvider));
}
@Test
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/UserCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/UserCredentialsTest.java
index e5a6c658a320..aaabf4aeefec 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/UserCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/UserCredentialsTest.java
@@ -31,6 +31,7 @@
package com.google.auth.oauth2;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
@@ -85,13 +86,9 @@ class UserCredentialsTest extends BaseSerializationTest {
@Test
void constructor_accessAndRefreshTokenNull_throws() {
- assertThrows(
- IllegalStateException.class,
- () ->
- UserCredentials.newBuilder()
- .setClientId(CLIENT_ID)
- .setClientSecret(CLIENT_SECRET)
- .build());
+ UserCredentials.Builder builder =
+ UserCredentials.newBuilder().setClientId(CLIENT_ID).setClientSecret(CLIENT_SECRET);
+ assertThrows(IllegalStateException.class, builder::build);
}
@Test
@@ -180,8 +177,8 @@ void fromJson_hasQuotaProjectId() throws IOException {
Map> metadata = credentials.getRequestMetadata(CALL_URI);
assertTrue(metadata.containsKey(GoogleCredentials.QUOTA_PROJECT_ID_HEADER_KEY));
assertEquals(
- metadata.get(GoogleCredentials.QUOTA_PROJECT_ID_HEADER_KEY),
- Collections.singletonList(QUOTA_PROJECT));
+ Collections.singletonList(QUOTA_PROJECT),
+ metadata.get(GoogleCredentials.QUOTA_PROJECT_ID_HEADER_KEY));
}
@Test
@@ -203,7 +200,7 @@ void getRequestMetadata_initialToken_hasAccessToken() throws IOException {
}
@Test
- void getRequestMetadata_initialTokenRefreshed_throws() throws IOException {
+ void getRequestMetadata_initialTokenRefreshed_throws() {
MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
transportFactory.transport.addClient(CLIENT_ID, CLIENT_SECRET);
AccessToken accessToken = new AccessToken(ACCESS_TOKEN, null);
@@ -215,12 +212,7 @@ void getRequestMetadata_initialTokenRefreshed_throws() throws IOException {
.setHttpTransportFactory(transportFactory)
.build();
- try {
- userCredentials.refresh();
- fail("Should not be able to refresh without refresh token.");
- } catch (IllegalStateException expected) {
- // Expected
- }
+ assertThrows(IllegalStateException.class, userCredentials::refresh);
}
@Test
@@ -243,18 +235,18 @@ void getRequestMetadata_fromRefreshToken_hasAccessToken() throws IOException {
@Test
void getRequestMetadata_customTokenServer_hasAccessToken() throws IOException {
- final URI TOKEN_SERVER = URI.create("https://foo.com/bar");
+ final URI tokenServerUri = URI.create("https://foo.com/bar");
MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
transportFactory.transport.addClient(CLIENT_ID, CLIENT_SECRET);
transportFactory.transport.addRefreshToken(REFRESH_TOKEN, ACCESS_TOKEN);
- transportFactory.transport.setTokenServerUri(TOKEN_SERVER);
+ transportFactory.transport.setTokenServerUri(tokenServerUri);
UserCredentials userCredentials =
UserCredentials.newBuilder()
.setClientId(CLIENT_ID)
.setClientSecret(CLIENT_SECRET)
.setRefreshToken(REFRESH_TOKEN)
.setHttpTransportFactory(transportFactory)
- .setTokenServerUri(TOKEN_SERVER)
+ .setTokenServerUri(tokenServerUri)
.build();
Map> metadata = userCredentials.getRequestMetadata(CALL_URI);
@@ -263,7 +255,7 @@ void getRequestMetadata_customTokenServer_hasAccessToken() throws IOException {
}
@Test
- void equals_true() throws IOException {
+ void equals_true() {
final URI tokenServer = URI.create("https://foo.com/bar");
MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
AccessToken accessToken = new AccessToken(ACCESS_TOKEN, null);
@@ -287,12 +279,12 @@ void equals_true() throws IOException {
.setTokenServerUri(tokenServer)
.setQuotaProjectId(QUOTA_PROJECT)
.build();
- assertTrue(credentials.equals(otherCredentials));
- assertTrue(otherCredentials.equals(credentials));
+ assertEquals(credentials, otherCredentials);
+ assertEquals(otherCredentials, credentials);
}
@Test
- void equals_false_clientId() throws IOException {
+ void equals_false_clientId() {
final URI tokenServer1 = URI.create("https://foo1.com/bar");
AccessToken accessToken = new AccessToken(ACCESS_TOKEN, null);
MockHttpTransportFactory httpTransportFactory = new MockHttpTransportFactory();
@@ -314,12 +306,12 @@ void equals_false_clientId() throws IOException {
.setHttpTransportFactory(httpTransportFactory)
.setTokenServerUri(tokenServer1)
.build();
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
- void equals_false_clientSecret() throws IOException {
+ void equals_false_clientSecret() {
final URI tokenServer1 = URI.create("https://foo1.com/bar");
AccessToken accessToken = new AccessToken(ACCESS_TOKEN, null);
MockHttpTransportFactory httpTransportFactory = new MockHttpTransportFactory();
@@ -341,12 +333,12 @@ void equals_false_clientSecret() throws IOException {
.setHttpTransportFactory(httpTransportFactory)
.setTokenServerUri(tokenServer1)
.build();
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
- void equals_false_refreshToken() throws IOException {
+ void equals_false_refreshToken() {
final URI tokenServer1 = URI.create("https://foo1.com/bar");
AccessToken accessToken = new AccessToken(ACCESS_TOKEN, null);
MockHttpTransportFactory httpTransportFactory = new MockHttpTransportFactory();
@@ -368,12 +360,12 @@ void equals_false_refreshToken() throws IOException {
.setHttpTransportFactory(httpTransportFactory)
.setTokenServerUri(tokenServer1)
.build();
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
- void equals_false_accessToken() throws IOException {
+ void equals_false_accessToken() {
final URI tokenServer1 = URI.create("https://foo1.com/bar");
AccessToken accessToken = new AccessToken(ACCESS_TOKEN, null);
AccessToken otherAccessToken = new AccessToken("otherAccessToken", null);
@@ -396,13 +388,13 @@ void equals_false_accessToken() throws IOException {
.setHttpTransportFactory(httpTransportFactory)
.setTokenServerUri(tokenServer1)
.build();
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
assertNotEquals(credentials.hashCode(), otherAccessToken.hashCode());
}
@Test
- void equals_false_transportFactory() throws IOException {
+ void equals_false_transportFactory() {
final URI tokenServer1 = URI.create("https://foo1.com/bar");
AccessToken accessToken = new AccessToken(ACCESS_TOKEN, null);
MockHttpTransportFactory httpTransportFactory = new MockHttpTransportFactory();
@@ -425,12 +417,12 @@ void equals_false_transportFactory() throws IOException {
.setHttpTransportFactory(serverTransportFactory)
.setTokenServerUri(tokenServer1)
.build();
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
- void equals_false_tokenServer() throws IOException {
+ void equals_false_tokenServer() {
final URI tokenServer1 = URI.create("https://foo1.com/bar");
final URI tokenServer2 = URI.create("https://foo2.com/bar");
AccessToken accessToken = new AccessToken(ACCESS_TOKEN, null);
@@ -453,12 +445,12 @@ void equals_false_tokenServer() throws IOException {
.setHttpTransportFactory(httpTransportFactory)
.setTokenServerUri(tokenServer2)
.build();
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
- void equals_false_quotaProjectId() throws IOException {
+ void equals_false_quotaProjectId() {
final String quotaProject1 = "sample-id-1";
final String quotaProject2 = "sample-id-2";
AccessToken accessToken = new AccessToken(ACCESS_TOKEN, null);
@@ -481,12 +473,12 @@ void equals_false_quotaProjectId() throws IOException {
.setHttpTransportFactory(httpTransportFactory)
.setQuotaProjectId(quotaProject2)
.build();
- assertFalse(credentials.equals(otherCredentials));
- assertFalse(otherCredentials.equals(credentials));
+ assertNotEquals(credentials, otherCredentials);
+ assertNotEquals(otherCredentials, credentials);
}
@Test
- void toString_containsFields() throws IOException {
+ void toString_containsFields() {
AccessToken accessToken = new AccessToken(ACCESS_TOKEN, null);
final URI tokenServer = URI.create("https://foo.com/bar");
MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
@@ -518,7 +510,7 @@ void toString_containsFields() throws IOException {
}
@Test
- void hashCode_equals() throws IOException {
+ void hashCode_equals() {
final URI tokenServer = URI.create("https://foo.com/bar");
MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory();
AccessToken accessToken = new AccessToken(ACCESS_TOKEN, null);
@@ -563,29 +555,20 @@ void serialize() throws IOException, ClassNotFoundException {
assertEquals(credentials, deserializedCredentials);
assertEquals(credentials.hashCode(), deserializedCredentials.hashCode());
assertEquals(credentials.toString(), deserializedCredentials.toString());
- assertSame(deserializedCredentials.clock, Clock.SYSTEM);
+ assertSame(Clock.SYSTEM, deserializedCredentials.clock);
}
@Test
- void fromStream_nullTransport_throws() throws IOException {
+ void fromStream_nullTransport_throws() {
InputStream stream = new ByteArrayInputStream("foo".getBytes());
- try {
- UserCredentials.fromStream(stream, null);
- fail("Should throw if HttpTransportFactory is null");
- } catch (NullPointerException expected) {
- // Expected
- }
+ assertThrows(NullPointerException.class, () -> UserCredentials.fromStream(stream, null));
}
@Test
- void fromStream_nullStream_throws() throws IOException {
+ void fromStream_nullStream_throws() {
MockHttpTransportFactory transportFactory = new MockHttpTransportFactory();
- try {
- UserCredentials.fromStream(null, transportFactory);
- fail("Should throw if InputStream is null");
- } catch (NullPointerException expected) {
- // Expected
- }
+ assertThrows(
+ NullPointerException.class, () -> UserCredentials.fromStream(null, transportFactory));
}
@Test
@@ -607,25 +590,31 @@ void fromStream_user_providesToken() throws IOException {
void fromStream_userNoClientId_throws() throws IOException {
InputStream userStream = writeUserStream(null, CLIENT_SECRET, REFRESH_TOKEN, QUOTA_PROJECT);
- testFromStreamException(userStream, "client_id");
+ IOException exception =
+ assertThrows(IOException.class, () -> UserCredentials.fromStream(userStream));
+ assertTrue(exception.getMessage().contains("client_id"));
}
@Test
void fromStream_userNoClientSecret_throws() throws IOException {
InputStream userStream = writeUserStream(CLIENT_ID, null, REFRESH_TOKEN, QUOTA_PROJECT);
- testFromStreamException(userStream, "client_secret");
+ IOException exception =
+ assertThrows(IOException.class, () -> UserCredentials.fromStream(userStream));
+ assertTrue(exception.getMessage().contains("client_secret"));
}
@Test
void fromStream_userNoRefreshToken_throws() throws IOException {
InputStream userStream = writeUserStream(CLIENT_ID, CLIENT_SECRET, null, QUOTA_PROJECT);
- testFromStreamException(userStream, "refresh_token");
+ IOException exception =
+ assertThrows(IOException.class, () -> UserCredentials.fromStream(userStream));
+ assertTrue(exception.getMessage().contains("refresh_token"));
}
@Test
- void saveUserCredentials_saved_throws() throws IOException {
+ void saveUserCredentials_saved_doesNotThrow() throws IOException {
UserCredentials userCredentials =
UserCredentials.newBuilder()
.setClientId(CLIENT_ID)
@@ -636,11 +625,11 @@ void saveUserCredentials_saved_throws() throws IOException {
file.deleteOnExit();
String filePath = file.getAbsolutePath();
- userCredentials.save(filePath);
+ assertDoesNotThrow(() -> userCredentials.save(filePath));
}
@Test
- void saveAndRestoreUserCredential_saveAndRestored_throws() throws IOException {
+ void saveAndRestoreUserCredential_saveAndRestored_doesNotThrow() throws IOException {
UserCredentials userCredentials =
UserCredentials.newBuilder()
.setClientId(CLIENT_ID)
@@ -653,15 +642,14 @@ void saveAndRestoreUserCredential_saveAndRestored_throws() throws IOException {
String filePath = file.getAbsolutePath();
- userCredentials.save(filePath);
-
- FileInputStream inputStream = new FileInputStream(new File(filePath));
-
- UserCredentials restoredCredentials = UserCredentials.fromStream(inputStream);
+ assertDoesNotThrow(() -> userCredentials.save(filePath));
- assertEquals(userCredentials.getClientId(), restoredCredentials.getClientId());
- assertEquals(userCredentials.getClientSecret(), restoredCredentials.getClientSecret());
- assertEquals(userCredentials.getRefreshToken(), restoredCredentials.getRefreshToken());
+ try (FileInputStream inputStream = new FileInputStream(filePath)) {
+ UserCredentials restoredCredentials = UserCredentials.fromStream(inputStream);
+ assertEquals(userCredentials.getClientId(), restoredCredentials.getClientId());
+ assertEquals(userCredentials.getClientSecret(), restoredCredentials.getClientSecret());
+ assertEquals(userCredentials.getRefreshToken(), restoredCredentials.getRefreshToken());
+ }
}
@Test
@@ -791,15 +779,11 @@ void IdTokenCredentials_NoRetry_RetryableStatus_throws() throws IOException {
UserCredentials credentials = UserCredentials.fromStream(userStream, transportFactory);
- try {
- transportFactory.transport.addResponseSequence(response408, response429);
- credentials.refresh();
- fail("Should not be able to use credential without exception.");
- } catch (GoogleAuthException ex) {
- assertTrue(ex.getMessage().contains("com.google.api.client.http.HttpResponseException: 408"));
- assertTrue(ex.isRetryable());
- assertEquals(0, ex.getRetryCount());
- }
+ transportFactory.transport.addResponseSequence(response408, response429);
+ GoogleAuthException ex = assertThrows(GoogleAuthException.class, credentials::refresh);
+ assertTrue(ex.getMessage().contains("com.google.api.client.http.HttpResponseException: 408"));
+ assertTrue(ex.isRetryable());
+ assertEquals(0, ex.getRetryCount());
IdTokenCredentials tokenCredential =
IdTokenCredentials.newBuilder().setIdTokenProvider(credentials).build();
@@ -808,14 +792,11 @@ void IdTokenCredentials_NoRetry_RetryableStatus_throws() throws IOException {
assertNull(tokenCredential.getIdToken());
// trigger the refresh like it would happen during a request build
- try {
- tokenCredential.getRequestMetadata(CALL_URI);
- fail("Should not be able to use credential without exception.");
- } catch (GoogleAuthException ex) {
- assertTrue(ex.getMessage().contains("com.google.api.client.http.HttpResponseException: 429"));
- assertTrue(ex.isRetryable());
- assertEquals(0, ex.getRetryCount());
- }
+ GoogleAuthException ex2 =
+ assertThrows(GoogleAuthException.class, () -> tokenCredential.getRequestMetadata(CALL_URI));
+ assertTrue(ex2.getMessage().contains("com.google.api.client.http.HttpResponseException: 429"));
+ assertTrue(ex2.isRetryable());
+ assertEquals(0, ex2.getRetryCount());
}
@Test
@@ -850,14 +831,10 @@ void refreshAccessToken_4xx_5xx_NonRetryableFails() throws IOException {
}
MockLowLevelHttpResponse mockResponse = new MockLowLevelHttpResponse().setStatusCode(status);
- try {
- transportFactory.transport.addResponseSequence(mockResponse);
- credentials.refresh();
- fail("Should not be able to use credential without exception.");
- } catch (GoogleAuthException ex) {
- assertFalse(ex.isRetryable());
- assertEquals(0, ex.getRetryCount());
- }
+ transportFactory.transport.addResponseSequence(mockResponse);
+ GoogleAuthException ex = assertThrows(GoogleAuthException.class, credentials::refresh);
+ assertFalse(ex.isRetryable());
+ assertEquals(0, ex.getRetryCount());
}
}
@@ -880,12 +857,8 @@ void IdTokenCredentials_NoUserEmailScope_throws() throws IOException {
+ " login'. The latter form would not work for Cloud Run, but would still generate an"
+ " id token.";
- try {
- tokenCredential.refresh();
- fail("Should not be able to use credential without exception.");
- } catch (IOException expected) {
- assertTrue(expected.getMessage().equals(expectedMessageContent));
- }
+ IOException exception = assertThrows(IOException.class, tokenCredential::refresh);
+ assertEquals(exception.getMessage(), expectedMessageContent);
}
@Test
@@ -940,15 +913,4 @@ static InputStream writeUserStream(
GenericJson json = writeUserJson(clientId, clientSecret, refreshToken, quotaProjectId, null);
return TestUtils.jsonToInputStream(json);
}
-
- private static void testFromStreamException(InputStream stream, String expectedMessageContent) {
- try {
- UserCredentials.fromStream(stream);
- fail(
- String.format(
- "Should throw exception with message containing '%s'", expectedMessageContent));
- } catch (IOException expected) {
- assertTrue(expected.getMessage().contains(expectedMessageContent));
- }
- }
}
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/functional/FTQuotaProjectId.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/functional/FTQuotaProjectId.java
index 034507e07bde..842781219edb 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/functional/FTQuotaProjectId.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/functional/FTQuotaProjectId.java
@@ -39,7 +39,7 @@
import java.io.IOException;
import org.junit.jupiter.api.Test;
-public final class FTQuotaProjectId {
+final class FTQuotaProjectId {
@Test
void validate_quota_from_environment_used() throws IOException {
diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/functional/FTServiceAccountCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/functional/FTServiceAccountCredentialsTest.java
index ca0ec4fc134f..82ba939611f5 100644
--- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/functional/FTServiceAccountCredentialsTest.java
+++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/functional/FTServiceAccountCredentialsTest.java
@@ -34,8 +34,8 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
@@ -50,7 +50,6 @@
import com.google.auth.oauth2.IdTokenCredentials;
import com.google.auth.oauth2.IdTokenProvider;
import com.google.auth.oauth2.OAuth2Utils;
-import java.io.FileNotFoundException;
import java.io.IOException;
import org.junit.jupiter.api.Test;
@@ -135,36 +134,35 @@ void ScopeSetNoAudienceOnePlatformTest() throws Exception {
}
@Test
- void WrongScopeComputeTest() throws Exception {
+ void WrongScopeComputeTest() {
executeRequestWrongScope(computeUrl);
}
@Test
- void WrongScopeStorageTest() throws Exception {
+ void WrongScopeStorageTest() {
executeRequestWrongScope(storageUrl);
}
@Test
- void WrongScopeBigQueryTest() throws Exception {
+ void WrongScopeBigQueryTest() {
executeRequestWrongScope(bigQueryUrl);
}
@Test
- void WrongScopeOnePlatformTest() throws Exception {
+ void WrongScopeOnePlatformTest() {
executeRequestWrongScope(cloudTasksUrl);
}
- private void executeRequestWrongScope(String serviceUri)
- throws FileNotFoundException, IOException {
+ private void executeRequestWrongScope(String serviceUri) {
String expectedMessage = "403 Forbidden";
- try {
- executeRequestWithCredentialsWithScope(
- serviceUri, "https://www.googleapis.com/auth/adexchange.buyer");
- fail("Should throw exception: " + expectedMessage);
- } catch (IOException expected) {
- assertTrue(expected.getMessage().contains(expectedMessage));
- }
+ IOException expected =
+ assertThrows(
+ IOException.class,
+ () ->
+ executeRequestWithCredentialsWithScope(
+ serviceUri, "https://www.googleapis.com/auth/adexchange.buyer"));
+ assertTrue(expected.getMessage().contains(expectedMessage));
}
private HttpResponse executeRequestWithCredentialsWithoutScope(String serviceUrl)
diff --git a/google-auth-library-java/oauth2_http/testresources/mtls/certificate_config.json b/google-auth-library-java/oauth2_http/testresources/mtls/certificate_config.json
new file mode 100644
index 000000000000..8a7592faf295
--- /dev/null
+++ b/google-auth-library-java/oauth2_http/testresources/mtls/certificate_config.json
@@ -0,0 +1,8 @@
+{
+ "cert_configs": {
+ "workload": {
+ "cert_path": "testresources/mtls/test_cert.pem",
+ "key_path": "testresources/mtls/test_key.pem"
+ }
+ }
+}
diff --git a/google-auth-library-java/oauth2_http/testresources/mtls/test_cert.pem b/google-auth-library-java/oauth2_http/testresources/mtls/test_cert.pem
new file mode 100644
index 000000000000..17fcf0227c80
--- /dev/null
+++ b/google-auth-library-java/oauth2_http/testresources/mtls/test_cert.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICGzCCAYSgAwIBAgIIWrt6xtmHPs4wDQYJKoZIhvcNAQEFBQAwMzExMC8GA1UE
+AxMoMTAwOTEyMDcyNjg3OC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbTAeFw0x
+MjEyMDExNjEwNDRaFw0yMjExMjkxNjEwNDRaMDMxMTAvBgNVBAMTKDEwMDkxMjA3
+MjY4NzguYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20wgZ8wDQYJKoZIhvcNAQEB
+BQADgY0AMIGJAoGBAL1SdY8jTUVU7O4/XrZLYTw0ON1lV6MQRGajFDFCqD2Fd9tQ
+GLW8Iftx9wfXe1zuaehJSgLcyCxazfyJoN3RiONBihBqWY6d3lQKqkgsRTNZkdFJ
+Wdzl/6CxhK9sojh2p0r3tydtv9iwq5fuuWIvtODtT98EgphhncQAqkKoF3zVAgMB
+AAGjODA2MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQM
+MAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4GBAD8XQEqzGePa9VrvtEGpf+R4
+fkxKbcYAzqYq202nKu0kfjhIYkYSBj6gi348YaxE64yu60TVl42l5HThmswUheW4
+uQIaq36JvwvsDP5Zoj5BgiNSnDAFQp+jJFBRUA5vooJKgKgMDf/r/DCOsbO6VJF1
+kWwa9n19NFiV0z3m6isj
+-----END CERTIFICATE-----
diff --git a/google-auth-library-java/oauth2_http/testresources/mtls/test_key.pem b/google-auth-library-java/oauth2_http/testresources/mtls/test_key.pem
new file mode 100644
index 000000000000..c6a91c3ce623
--- /dev/null
+++ b/google-auth-library-java/oauth2_http/testresources/mtls/test_key.pem
@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAL1SdY8jTUVU7O4/
+XrZLYTw0ON1lV6MQRGajFDFCqD2Fd9tQGLW8Iftx9wfXe1zuaehJSgLcyCxazfyJ
+oN3RiONBihBqWY6d3lQKqkgsRTNZkdFJWdzl/6CxhK9sojh2p0r3tydtv9iwq5fu
+uWIvtODtT98EgphhncQAqkKoF3zVAgMBAAECgYB51B9cXe4yiGTzJ4pOKpHGySAy
+sC1F/IjXt2eeD3PuKv4m/hL4l7kScpLx0+NJuQ4j8U2UK/kQOdrGANapB1ZbMZAK
+/q0xmIUzdNIDiGSoTXGN2mEfdsEpQ/Xiv0lyhYBBPC/K4sYIpHccnhSRQUZlWLLY
+lE5cFNKC9b7226mNvQJBAPt0hfCNIN0kUYOA9jdLtx7CE4ySGMPf5KPBuzPd8ty1
+fxaFm9PB7B76VZQYmHcWy8rT5XjoLJHrmGW1ZvP+iDsCQQDAvnKoarPOGb5iJfkq
+RrA4flf1TOlf+1+uqIOJ94959jkkJeb0gv/TshDnm6/bWn+1kJylQaKygCizwPwB
+Z84vAkA0Duur4YvsPJijoQ9YY1SGCagCcjyuUKwFOxaGpmyhRPIKt56LOJqpzyno
+fy8ReKa4VyYq4eZYT249oFCwMwIBAkAROPNF2UL3x5UbcAkznd1hLujtIlI4IV4L
+XUNjsJtBap7we/KHJq11XRPlniO4lf2TW7iji5neGVWJulTKS1xBAkAerktk4Hsw
+ErUaUG1s/d+Sgc8e/KMeBElV+NxGhcWEeZtfHMn/6VOlbzY82JyvC9OKC80A5CAE
+VUV6b25kqrcu
+-----END PRIVATE KEY-----