diff --git a/CHANGELOG.md b/CHANGELOG.md index 25e44203b..12e9025c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [1.10.0](https://github.com/googleapis/google-auth-library-java/compare/v1.9.0...v1.10.0) (2022-08-05) + + +### Features + +* workforce identity federation for pluggable auth ([#959](https://github.com/googleapis/google-auth-library-java/issues/959)) ([7f2c535](https://github.com/googleapis/google-auth-library-java/commit/7f2c535ab7c842a672d6761f4cd80df88e1a37ed)) + + +### Bug Fixes + +* updates executable response spec for executable-sourced credentials ([#955](https://github.com/googleapis/google-auth-library-java/issues/955)) ([48ff83d](https://github.com/googleapis/google-auth-library-java/commit/48ff83dc68e29dcae07fdea963cbbe5525f86a89)) + + +### Documentation + +* **samples:** added auth samples and tests ([#927](https://github.com/googleapis/google-auth-library-java/issues/927)) ([32c717f](https://github.com/googleapis/google-auth-library-java/commit/32c717fdf1a721f3e7ca3d75f03fcc229923689c)) + ## [1.9.0](https://github.com/googleapis/google-auth-library-java/compare/v1.8.1...v1.9.0) (2022-08-02) diff --git a/appengine/pom.xml b/appengine/pom.xml index 6fff828c5..ecadff5a3 100644 --- a/appengine/pom.xml +++ b/appengine/pom.xml @@ -5,7 +5,7 @@ com.google.auth google-auth-library-parent - 1.9.1-SNAPSHOT + 1.10.1-SNAPSHOT ../pom.xml diff --git a/bom/pom.xml b/bom/pom.xml index 77d8f99f4..6c00beddb 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.google.auth google-auth-library-bom - 1.9.1-SNAPSHOT + 1.10.1-SNAPSHOT pom Google Auth Library for Java BOM diff --git a/credentials/pom.xml b/credentials/pom.xml index c1d4f46ff..6048dc662 100644 --- a/credentials/pom.xml +++ b/credentials/pom.xml @@ -4,7 +4,7 @@ com.google.auth google-auth-library-parent - 1.9.1-SNAPSHOT + 1.10.1-SNAPSHOT ../pom.xml diff --git a/oauth2_http/java/com/google/auth/oauth2/ServiceAccountCredentials.java b/oauth2_http/java/com/google/auth/oauth2/ServiceAccountCredentials.java index 9b9c99c54..123d72dc0 100644 --- a/oauth2_http/java/com/google/auth/oauth2/ServiceAccountCredentials.java +++ b/oauth2_http/java/com/google/auth/oauth2/ServiceAccountCredentials.java @@ -181,6 +181,7 @@ static ServiceAccountCredentials fromJson( } catch (URISyntaxException e) { throw new IOException("Token server URI specified in 'token_uri' could not be parsed."); } + if (clientId == null || clientEmail == null || privateKeyPkcs8 == null diff --git a/oauth2_http/java/com/google/auth/oauth2/TokenVerifier.java b/oauth2_http/java/com/google/auth/oauth2/TokenVerifier.java index aed9949b5..12c6af92e 100644 --- a/oauth2_http/java/com/google/auth/oauth2/TokenVerifier.java +++ b/oauth2_http/java/com/google/auth/oauth2/TokenVerifier.java @@ -314,17 +314,13 @@ public static class JsonWebKey { public Map load(String certificateUrl) throws Exception { HttpTransport httpTransport = httpTransportFactory.create(); JsonWebKeySet jwks; - try { - HttpRequest request = - httpTransport - .createRequestFactory() - .buildGetRequest(new GenericUrl(certificateUrl)) - .setParser(OAuth2Utils.JSON_FACTORY.createJsonObjectParser()); - HttpResponse response = request.execute(); - jwks = response.parseAs(JsonWebKeySet.class); - } catch (IOException io) { - return ImmutableMap.of(); - } + HttpRequest request = + httpTransport + .createRequestFactory() + .buildGetRequest(new GenericUrl(certificateUrl)) + .setParser(OAuth2Utils.JSON_FACTORY.createJsonObjectParser()); + HttpResponse response = request.execute(); + jwks = response.parseAs(JsonWebKeySet.class); ImmutableMap.Builder keyCacheBuilder = new ImmutableMap.Builder<>(); if (jwks.keys == null) { @@ -345,7 +341,14 @@ public Map load(String certificateUrl) throws Exception { } } - return keyCacheBuilder.build(); + ImmutableMap keyCache = keyCacheBuilder.build(); + + if (keyCache.isEmpty()) { + throw new VerificationException( + "No valid public key returned by the keystore: " + certificateUrl); + } + + return keyCache; } private PublicKey buildPublicKey(JsonWebKey key) diff --git a/oauth2_http/javatests/com/google/auth/oauth2/MockTokenServerTransport.java b/oauth2_http/javatests/com/google/auth/oauth2/MockTokenServerTransport.java index 7eea7d462..29c8e6337 100644 --- a/oauth2_http/javatests/com/google/auth/oauth2/MockTokenServerTransport.java +++ b/oauth2_http/javatests/com/google/auth/oauth2/MockTokenServerTransport.java @@ -133,6 +133,24 @@ 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()) { + return new MockLowLevelHttpRequest(url) { + @Override + public LowLevelHttpResponse execute() throws IOException { + try { + return responseSequence.poll().get(); + } catch (ExecutionException e) { + Throwable cause = e.getCause(); + throw (IOException) cause; + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Unexpectedly interrupted"); + } + } + }; + } + if (urlWithoutQuery.equals(tokenServerUri.toString())) { return new MockLowLevelHttpRequest(url) { @Override diff --git a/oauth2_http/javatests/com/google/auth/oauth2/TokenVerifierTest.java b/oauth2_http/javatests/com/google/auth/oauth2/TokenVerifierTest.java index 6c6373267..041fbabe4 100644 --- a/oauth2_http/javatests/com/google/auth/oauth2/TokenVerifierTest.java +++ b/oauth2_http/javatests/com/google/auth/oauth2/TokenVerifierTest.java @@ -43,6 +43,8 @@ import com.google.api.client.testing.http.MockLowLevelHttpResponse; import com.google.api.client.util.Clock; import com.google.auth.http.HttpTransportFactory; +import com.google.auth.oauth2.GoogleCredentialsTest.MockTokenServerTransportFactory; +import com.google.auth.oauth2.TokenVerifier.VerificationException; import com.google.common.io.CharStreams; import java.io.IOException; import java.io.InputStream; @@ -145,7 +147,8 @@ public LowLevelHttpResponse execute() throws IOException { TokenVerifier.VerificationException exception = assertThrows( TokenVerifier.VerificationException.class, () -> tokenVerifier.verify(ES256_TOKEN)); - assertTrue(exception.getMessage().contains("Could not find PublicKey")); + assertTrue( + exception.getMessage().contains("Error fetching PublicKey from certificate location")); } @Test @@ -186,6 +189,54 @@ public LowLevelHttpResponse execute() throws IOException { assertTrue(exception.getMessage().contains("Error fetching PublicKey")); } + @Test + void verifyPublicKeyStoreIntermittentError() throws IOException, VerificationException { + // mock responses + MockLowLevelHttpResponse response404 = + new MockLowLevelHttpResponse() + .setStatusCode(404) + .setContentType("application/json") + .setContent(""); + + MockLowLevelHttpResponse responseEmpty = + new MockLowLevelHttpResponse() + .setStatusCode(200) + .setContentType("application/json") + .setContent("{\"keys\":[]}"); + + MockLowLevelHttpResponse responseGood = + new MockLowLevelHttpResponse() + .setStatusCode(200) + .setContentType("application/json") + .setContent(readResourceAsString("iap_keys.json")); + + // Mock HTTP requests + MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory(); + + transportFactory.transport.addResponseSequence(response404, responseEmpty, responseGood); + + TokenVerifier tokenVerifier = + TokenVerifier.newBuilder() + .setClock(FIXED_CLOCK) + .setHttpTransportFactory(transportFactory) + .build(); + TokenVerifier.VerificationException exception = + assertThrows( + TokenVerifier.VerificationException.class, + () -> tokenVerifier.verify(ES256_TOKEN), + "Should have failed verification"); + assertTrue(exception.getMessage().contains("Error fetching PublicKey")); + + exception = + assertThrows( + TokenVerifier.VerificationException.class, + () -> tokenVerifier.verify(ES256_TOKEN), + "Should have failed verification"); + assertTrue(exception.getCause().getMessage().contains("No valid public key")); + + assertNotNull(tokenVerifier.verify(ES256_TOKEN)); + } + @Test void verifyEs256Token() throws TokenVerifier.VerificationException, IOException { HttpTransportFactory httpTransportFactory = diff --git a/oauth2_http/pom.xml b/oauth2_http/pom.xml index 8aadf3e73..d9bd261b5 100644 --- a/oauth2_http/pom.xml +++ b/oauth2_http/pom.xml @@ -5,7 +5,7 @@ com.google.auth google-auth-library-parent - 1.9.1-SNAPSHOT + 1.10.1-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 10171892d..46e761589 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.google.auth google-auth-library-parent - 1.9.1-SNAPSHOT + 1.10.1-SNAPSHOT pom Google Auth Library for Java Client libraries providing authentication and diff --git a/versions.txt b/versions.txt index d8f0ea5fd..36266972f 100644 --- a/versions.txt +++ b/versions.txt @@ -1,9 +1,9 @@ # Format: # module:released-version:current-version -google-auth-library:1.9.0:1.9.1-SNAPSHOT -google-auth-library-bom:1.9.0:1.9.1-SNAPSHOT -google-auth-library-parent:1.9.0:1.9.1-SNAPSHOT -google-auth-library-appengine:1.9.0:1.9.1-SNAPSHOT -google-auth-library-credentials:1.9.0:1.9.1-SNAPSHOT -google-auth-library-oauth2-http:1.9.0:1.9.1-SNAPSHOT +google-auth-library:1.10.0:1.10.1-SNAPSHOT +google-auth-library-bom:1.10.0:1.10.1-SNAPSHOT +google-auth-library-parent:1.10.0:1.10.1-SNAPSHOT +google-auth-library-appengine:1.10.0:1.10.1-SNAPSHOT +google-auth-library-credentials:1.10.0:1.10.1-SNAPSHOT +google-auth-library-oauth2-http:1.10.0:1.10.1-SNAPSHOT