diff --git a/CVE-2021-22573.patch b/CVE-2021-22573.patch new file mode 100644 index 0000000000000000000000000000000000000000..bf858cff94ac99c382a64e3800aa9eea0090915c --- /dev/null +++ b/CVE-2021-22573.patch @@ -0,0 +1,953 @@ +Origin: https://github.com/googleapis/google-oauth-java-client/commit/22419d60579ef4c1a8a256a90e6ca7bc58f09aa1 +Reference patch: https://build.opensuse.org/projects/Java:packages:attic/packages/google-oauth-java-client/files/CVE-2021-22573.patch + +Index: google-oauth-java-client-1.22.0/google-oauth-client/src/main/java/com/google/api/client/auth/openidconnect/Environment.java +=================================================================== +--- /dev/null ++++ google-oauth-java-client-1.22.0/google-oauth-client/src/main/java/com/google/api/client/auth/openidconnect/Environment.java +@@ -0,0 +1,38 @@ ++/* ++ * Copyright 2022, 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.api.client.auth.openidconnect; ++ ++class Environment { ++ public String getVariable(String name) { ++ return System.getenv(name); ++ } ++} +Index: google-oauth-java-client-1.22.0/google-oauth-client/src/main/java/com/google/api/client/auth/openidconnect/HttpTransportFactory.java +=================================================================== +--- /dev/null ++++ google-oauth-java-client-1.22.0/google-oauth-client/src/main/java/com/google/api/client/auth/openidconnect/HttpTransportFactory.java +@@ -0,0 +1,50 @@ ++/* ++ * Copyright 2022, 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.api.client.auth.openidconnect; ++ ++import com.google.api.client.http.HttpTransport; ++ ++/** ++ * A base interface for all {@link HttpTransport} factories. ++ * ++ *

Implementation must provide a public no-arg constructor. Loading of a factory implementation ++ * is done via {@link java.util.ServiceLoader}. ++ */ ++public interface HttpTransportFactory { ++ ++ /** ++ * Creates a {@code HttpTransport} instance. ++ * ++ * @return The HttpTransport instance. ++ */ ++ HttpTransport create(); ++} +Index: google-oauth-java-client-1.22.0/google-oauth-client/src/main/java/com/google/api/client/auth/openidconnect/IdTokenVerifier.java +=================================================================== +--- google-oauth-java-client-1.22.0.orig/google-oauth-client/src/main/java/com/google/api/client/auth/openidconnect/IdTokenVerifier.java ++++ google-oauth-java-client-1.22.0/google-oauth-client/src/main/java/com/google/api/client/auth/openidconnect/IdTokenVerifier.java +@@ -14,12 +14,53 @@ + + package com.google.api.client.auth.openidconnect; + ++import com.google.api.client.http.GenericUrl; ++import com.google.api.client.http.HttpRequest; ++import com.google.api.client.http.HttpResponse; ++import com.google.api.client.http.HttpTransport; ++import com.google.api.client.http.javanet.NetHttpTransport; ++import com.google.api.client.json.GenericJson; ++import com.google.api.client.json.gson.GsonFactory; ++import com.google.api.client.json.webtoken.JsonWebSignature.Header; ++import com.google.api.client.util.Base64; + import com.google.api.client.util.Beta; + import com.google.api.client.util.Clock; ++import com.google.api.client.util.Key; + import com.google.api.client.util.Preconditions; +- ++import com.google.common.annotations.VisibleForTesting; ++import com.google.common.cache.CacheBuilder; ++import com.google.common.cache.CacheLoader; ++import com.google.common.cache.LoadingCache; ++import com.google.common.collect.ImmutableMap; ++import com.google.common.collect.ImmutableSet; ++import com.google.common.util.concurrent.UncheckedExecutionException; ++import java.io.ByteArrayInputStream; ++import java.io.IOException; ++import java.io.UnsupportedEncodingException; ++import java.math.BigInteger; ++import java.security.AlgorithmParameters; ++import java.security.GeneralSecurityException; ++import java.security.KeyFactory; ++import java.security.NoSuchAlgorithmException; ++import java.security.PublicKey; ++import java.security.cert.CertificateException; ++import java.security.cert.CertificateFactory; ++import java.security.spec.ECGenParameterSpec; ++import java.security.spec.ECParameterSpec; ++import java.security.spec.ECPoint; ++import java.security.spec.ECPublicKeySpec; ++import java.security.spec.InvalidKeySpecException; ++import java.security.spec.InvalidParameterSpecException; ++import java.security.spec.RSAPublicKeySpec; + import java.util.Collection; + import java.util.Collections; ++import java.util.List; ++import java.util.Map; ++import java.util.Set; ++import java.util.concurrent.ExecutionException; ++import java.util.concurrent.TimeUnit; ++import java.util.logging.Level; ++import java.util.logging.Logger; + + /** + * {@link Beta}
+@@ -44,7 +85,7 @@ import java.util.Collections; + *

+ * Note that {@link #verify(IdToken)} only implements a subset of the verification steps, mostly + * just the MUST steps. Please read ID Token + * Validation for the full list of verification steps. + *

+ * +@@ -52,13 +93,26 @@ import java.util.Collections; + */ + @Beta + public class IdTokenVerifier { ++ private static final Logger LOGGER = Logger.getLogger(IdTokenVerifier.class.getName()); ++ private static final String IAP_CERT_URL = "https://www.gstatic.com/iap/verify/public_key-jwk"; ++ private static final String FEDERATED_SIGNON_CERT_URL = ++ "https://www.googleapis.com/oauth2/v3/certs"; ++ private static final Set SUPPORTED_ALGORITHMS = ImmutableSet.of("RS256", "ES256"); ++ private static final String NOT_SUPPORTED_ALGORITHM = ++ "Unexpected signing algorithm %s: expected either RS256 or ES256"; + ++ static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); ++ static final String SKIP_SIGNATURE_ENV_VAR = "OAUTH_CLIENT_SKIP_SIGNATURE"; + /** Default value for seconds of time skew to accept when verifying time (5 minutes). */ + public static final long DEFAULT_TIME_SKEW_SECONDS = 300; + + /** Clock to use for expiration checks. */ + private final Clock clock; + ++ private final String certificatesLocation; ++ private final Environment environment; ++ private final LoadingCache> publicKeyCache; ++ + /** Seconds of time skew to accept when verifying time. */ + private final long acceptableTimeSkewSeconds; + +@@ -82,11 +136,21 @@ public class IdTokenVerifier { + * @param builder builder + */ + protected IdTokenVerifier(Builder builder) { ++ this.certificatesLocation = builder.certificatesLocation; + clock = builder.clock; + acceptableTimeSkewSeconds = builder.acceptableTimeSkewSeconds; + issuers = builder.issuers == null ? null : Collections.unmodifiableCollection(builder.issuers); + audience = + builder.audience == null ? null : Collections.unmodifiableCollection(builder.audience); ++ HttpTransportFactory transport = ++ builder.httpTransportFactory == null ++ ? new DefaultHttpTransportFactory() ++ : builder.httpTransportFactory; ++ this.publicKeyCache = ++ CacheBuilder.newBuilder() ++ .expireAfterWrite(1, TimeUnit.HOURS) ++ .build(new PublicKeyLoader(transport)); ++ this.environment = builder.environment == null ? new Environment() : builder.environment; + } + + /** Returns the clock. */ +@@ -133,13 +197,20 @@ public class IdTokenVerifier { + * It verifies: + * + * + * + *

+@@ -150,9 +221,74 @@ public class IdTokenVerifier { + * @return {@code true} if verified successfully or {@code false} if failed + */ + public boolean verify(IdToken idToken) { +- return (issuers == null || idToken.verifyIssuer(issuers)) +- && (audience == null || idToken.verifyAudience(audience)) +- && idToken.verifyTime(clock.currentTimeMillis(), acceptableTimeSkewSeconds); ++ boolean tokenFieldsValid = ++ (issuers == null || idToken.verifyIssuer(issuers)) ++ && (audience == null || idToken.verifyAudience(audience)) ++ && idToken.verifyTime(clock.currentTimeMillis(), acceptableTimeSkewSeconds); ++ ++ if (!tokenFieldsValid) { ++ return false; ++ } ++ ++ try { ++ return verifySignature(idToken); ++ } catch (VerificationException ex) { ++ LOGGER.log( ++ Level.SEVERE, ++ "id token signature verification failed. " ++ + "Please see docs for IdTokenVerifier for default settings and configuration options", ++ ex); ++ return false; ++ } ++ } ++ ++ @VisibleForTesting ++ boolean verifySignature(IdToken idToken) throws VerificationException { ++ if (Boolean.parseBoolean(environment.getVariable(SKIP_SIGNATURE_ENV_VAR))) { ++ return true; ++ } ++ ++ // Short-circuit signature types ++ if (!SUPPORTED_ALGORITHMS.contains(idToken.getHeader().getAlgorithm())) { ++ throw new VerificationException( ++ String.format(NOT_SUPPORTED_ALGORITHM, idToken.getHeader().getAlgorithm())); ++ } ++ ++ PublicKey publicKeyToUse = null; ++ try { ++ String certificateLocation = getCertificateLocation(idToken.getHeader()); ++ publicKeyToUse = publicKeyCache.get(certificateLocation).get(idToken.getHeader().getKeyId()); ++ } catch (ExecutionException | UncheckedExecutionException e) { ++ throw new VerificationException( ++ "Error fetching PublicKey from certificate location " + certificatesLocation, e); ++ } ++ ++ if (publicKeyToUse == null) { ++ throw new VerificationException( ++ "Could not find PublicKey for provided keyId: " + idToken.getHeader().getKeyId()); ++ } ++ ++ try { ++ if (idToken.verifySignature(publicKeyToUse)) { ++ return true; ++ } ++ throw new VerificationException("Invalid signature"); ++ } catch (GeneralSecurityException e) { ++ throw new VerificationException("Error validating token", e); ++ } ++ } ++ ++ private String getCertificateLocation(Header header) throws VerificationException { ++ if (certificatesLocation != null) return certificatesLocation; ++ ++ switch (header.getAlgorithm()) { ++ case "RS256": ++ return FEDERATED_SIGNON_CERT_URL; ++ case "ES256": ++ return IAP_CERT_URL; ++ } ++ ++ throw new VerificationException(String.format(NOT_SUPPORTED_ALGORITHM, header.getAlgorithm())); + } + + /** +@@ -171,6 +307,11 @@ public class IdTokenVerifier { + /** Clock. */ + Clock clock = Clock.SYSTEM; + ++ String certificatesLocation; ++ ++ /** wrapper for environment variables */ ++ Environment environment; ++ + /** Seconds of time skew to accept when verifying time. */ + long acceptableTimeSkewSeconds = DEFAULT_TIME_SKEW_SECONDS; + +@@ -180,6 +321,8 @@ public class IdTokenVerifier { + /** List of trusted audience client IDs or {@code null} to suppress the audience check. */ + Collection audience; + ++ HttpTransportFactory httpTransportFactory; ++ + /** Builds a new instance of {@link IdTokenVerifier}. */ + public IdTokenVerifier build() { + return new IdTokenVerifier(this); +@@ -231,6 +374,18 @@ public class IdTokenVerifier { + } + + /** ++ * Override the location URL that contains published public keys. Defaults to well-known Google ++ * locations. ++ * ++ * @param certificatesLocation URL to published public keys ++ * @return the builder ++ */ ++ public Builder setCertificatesLocation(String certificatesLocation) { ++ this.certificatesLocation = certificatesLocation; ++ return this; ++ } ++ ++ /** + * Returns the equivalent expected issuers or {@code null} if issuer check suppressed. + * + * @since 1.21.0 +@@ -303,5 +458,172 @@ public class IdTokenVerifier { + return this; + } + ++ /** Returns an instance of the {@link Environment} */ ++ final Environment getEnvironment() { ++ return environment; ++ } ++ ++ /** Sets the environment. Used mostly for testing */ ++ Builder setEnvironment(Environment environment) { ++ this.environment = environment; ++ return this; ++ } ++ ++ /** ++ * Sets the HttpTransportFactory used for requesting public keys from the certificate URL. Used ++ * mostly for testing. ++ * ++ * @param httpTransportFactory the HttpTransportFactory used to build certificate URL requests ++ * @return the builder ++ */ ++ public Builder setHttpTransportFactory(HttpTransportFactory httpTransportFactory) { ++ this.httpTransportFactory = httpTransportFactory; ++ return this; ++ } ++ } ++ ++ /** Custom CacheLoader for mapping certificate urls to the contained public keys. */ ++ static class PublicKeyLoader extends CacheLoader> { ++ private final HttpTransportFactory httpTransportFactory; ++ ++ /** ++ * Data class used for deserializing a JSON Web Key Set (JWKS) from an external HTTP request. ++ */ ++ public static class JsonWebKeySet extends GenericJson { ++ @Key public List keys; ++ } ++ ++ /** Data class used for deserializing a single JSON Web Key. */ ++ public static class JsonWebKey { ++ @Key public String alg; ++ ++ @Key public String crv; ++ ++ @Key public String kid; ++ ++ @Key public String kty; ++ ++ @Key public String use; ++ ++ @Key public String x; ++ ++ @Key public String y; ++ ++ @Key public String e; ++ ++ @Key public String n; ++ } ++ ++ PublicKeyLoader(HttpTransportFactory httpTransportFactory) { ++ super(); ++ this.httpTransportFactory = httpTransportFactory; ++ } ++ ++ @Override ++ public Map load(String certificateUrl) throws Exception { ++ HttpTransport httpTransport = httpTransportFactory.create(); ++ JsonWebKeySet jwks; ++ try { ++ HttpRequest request = ++ httpTransport ++ .createRequestFactory() ++ .buildGetRequest(new GenericUrl(certificateUrl)) ++ .setParser(GsonFactory.getDefaultInstance().createJsonObjectParser()); ++ HttpResponse response = request.execute(); ++ jwks = response.parseAs(JsonWebKeySet.class); ++ } catch (IOException io) { ++ LOGGER.log( ++ Level.WARNING, ++ "Failed to get a certificate from certificate location " + certificateUrl, ++ io); ++ return ImmutableMap.of(); ++ } ++ ++ ImmutableMap.Builder keyCacheBuilder = new ImmutableMap.Builder<>(); ++ if (jwks.keys == null) { ++ // Fall back to x509 formatted specification ++ for (String keyId : jwks.keySet()) { ++ String publicKeyPem = (String) jwks.get(keyId); ++ keyCacheBuilder.put(keyId, buildPublicKey(publicKeyPem)); ++ } ++ } else { ++ for (JsonWebKey key : jwks.keys) { ++ try { ++ keyCacheBuilder.put(key.kid, buildPublicKey(key)); ++ } catch (NoSuchAlgorithmException ++ | InvalidKeySpecException ++ | InvalidParameterSpecException ignored) { ++ LOGGER.log(Level.WARNING, "Failed to put a key into the cache", ignored); ++ } ++ } ++ } ++ ++ return keyCacheBuilder.build(); ++ } ++ ++ private PublicKey buildPublicKey(JsonWebKey key) ++ throws NoSuchAlgorithmException, InvalidParameterSpecException, InvalidKeySpecException { ++ if ("ES256".equals(key.alg)) { ++ return buildEs256PublicKey(key); ++ } else if ("RS256".equals((key.alg))) { ++ return buildRs256PublicKey(key); ++ } else { ++ return null; ++ } ++ } ++ ++ private PublicKey buildPublicKey(String publicPem) ++ throws CertificateException, UnsupportedEncodingException { ++ return CertificateFactory.getInstance("X.509") ++ .generateCertificate(new ByteArrayInputStream(publicPem.getBytes("UTF-8"))) ++ .getPublicKey(); ++ } ++ ++ private PublicKey buildRs256PublicKey(JsonWebKey key) ++ throws NoSuchAlgorithmException, InvalidKeySpecException { ++ com.google.common.base.Preconditions.checkArgument("RSA".equals(key.kty)); ++ com.google.common.base.Preconditions.checkNotNull(key.e); ++ com.google.common.base.Preconditions.checkNotNull(key.n); ++ ++ BigInteger modulus = new BigInteger(1, Base64.decodeBase64(key.n)); ++ BigInteger exponent = new BigInteger(1, Base64.decodeBase64(key.e)); ++ ++ RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent); ++ KeyFactory factory = KeyFactory.getInstance("RSA"); ++ return factory.generatePublic(spec); ++ } ++ ++ private PublicKey buildEs256PublicKey(JsonWebKey key) ++ throws NoSuchAlgorithmException, InvalidParameterSpecException, InvalidKeySpecException { ++ com.google.common.base.Preconditions.checkArgument("EC".equals(key.kty)); ++ com.google.common.base.Preconditions.checkArgument("P-256".equals(key.crv)); ++ ++ BigInteger x = new BigInteger(1, Base64.decodeBase64(key.x)); ++ BigInteger y = new BigInteger(1, Base64.decodeBase64(key.y)); ++ ECPoint pubPoint = new ECPoint(x, y); ++ AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC"); ++ parameters.init(new ECGenParameterSpec("secp256r1")); ++ ECParameterSpec ecParameters = parameters.getParameterSpec(ECParameterSpec.class); ++ ECPublicKeySpec pubSpec = new ECPublicKeySpec(pubPoint, ecParameters); ++ KeyFactory kf = KeyFactory.getInstance("EC"); ++ return kf.generatePublic(pubSpec); ++ } ++ } ++ ++ /** Custom exception for wrapping all verification errors. */ ++ static class VerificationException extends Exception { ++ public VerificationException(String message) { ++ super(message); ++ } ++ ++ public VerificationException(String message, Throwable cause) { ++ super(message, cause); ++ } ++ } ++ ++ static class DefaultHttpTransportFactory implements HttpTransportFactory { ++ public HttpTransport create() { ++ return HTTP_TRANSPORT; ++ } + } + } +Index: google-oauth-java-client-1.22.0/google-oauth-client/src/test/java/com/google/api/client/auth/openidconnect/IdTokenVerifierTest.java +=================================================================== +--- google-oauth-java-client-1.22.0.orig/google-oauth-client/src/test/java/com/google/api/client/auth/openidconnect/IdTokenVerifierTest.java ++++ google-oauth-java-client-1.22.0/google-oauth-client/src/test/java/com/google/api/client/auth/openidconnect/IdTokenVerifierTest.java +@@ -15,15 +15,30 @@ + package com.google.api.client.auth.openidconnect; + + import com.google.api.client.auth.openidconnect.IdToken.Payload; ++import com.google.api.client.auth.openidconnect.IdTokenVerifier.VerificationException; ++import com.google.api.client.http.HttpTransport; ++import com.google.api.client.http.LowLevelHttpRequest; ++import com.google.api.client.http.LowLevelHttpResponse; ++import com.google.api.client.http.javanet.NetHttpTransport; ++import com.google.api.client.json.JsonFactory; ++import com.google.api.client.json.gson.GsonFactory; + import com.google.api.client.json.webtoken.JsonWebSignature.Header; ++import com.google.api.client.testing.http.MockHttpTransport; ++import com.google.api.client.testing.http.MockLowLevelHttpRequest; ++import com.google.api.client.testing.http.MockLowLevelHttpResponse; + import com.google.api.client.util.Clock; + import com.google.api.client.util.Lists; +- +-import junit.framework.TestCase; +- ++import com.google.common.io.CharStreams; ++import java.io.IOException; ++import java.io.InputStream; ++import java.io.InputStreamReader; ++import java.io.Reader; + import java.util.Arrays; + import java.util.Collections; ++import java.util.HashMap; + import java.util.List; ++import java.util.Map; ++import junit.framework.TestCase; + + /** + * Tests {@link IdTokenVerifier}. +@@ -41,6 +56,25 @@ public class IdTokenVerifierTest extends + private static final String ISSUER2 = ISSUER + "2"; + private static final String ISSUER3 = ISSUER + "3"; + ++ private static final String ES256_TOKEN = ++ "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Im1wZjBEQSJ9.eyJhdWQiOiIvcHJvamVjdHMvNjUyNTYyNzc2Nzk4L2FwcHMvY2xvdWQtc2FtcGxlcy10ZXN0cy1waHAtaWFwIiwiZW1haWwiOiJjaGluZ29yQGdvb2dsZS5jb20iLCJleHAiOjE1ODQwNDc2MTcsImdvb2dsZSI6eyJhY2Nlc3NfbGV2ZWxzIjpbImFjY2Vzc1BvbGljaWVzLzUxODU1MTI4MDkyNC9hY2Nlc3NMZXZlbHMvcmVjZW50U2VjdXJlQ29ubmVjdERhdGEiLCJhY2Nlc3NQb2xpY2llcy81MTg1NTEyODA5MjQvYWNjZXNzTGV2ZWxzL3Rlc3ROb09wIiwiYWNjZXNzUG9saWNpZXMvNTE4NTUxMjgwOTI0L2FjY2Vzc0xldmVscy9ldmFwb3JhdGlvblFhRGF0YUZ1bGx5VHJ1c3RlZCJdfSwiaGQiOiJnb29nbGUuY29tIiwiaWF0IjoxNTg0MDQ3MDE3LCJpc3MiOiJodHRwczovL2Nsb3VkLmdvb2dsZS5jb20vaWFwIiwic3ViIjoiYWNjb3VudHMuZ29vZ2xlLmNvbToxMTIxODE3MTI3NzEyMDE5NzI4OTEifQ.yKNtdFY5EKkRboYNexBdfugzLhC3VuGyFcuFYA8kgpxMqfyxa41zkML68hYKrWu2kOBTUW95UnbGpsIi_u1fiA"; ++ ++ private static final String FEDERATED_SIGNON_RS256_TOKEN = ++ "eyJhbGciOiJSUzI1NiIsImtpZCI6ImY5ZDk3YjRjYWU5MGJjZDc2YWViMjAwMjZmNmI3NzBjYWMyMjE3ODMiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJodHRwczovL2V4YW1wbGUuY29tL3BhdGgiLCJhenAiOiJpbnRlZ3JhdGlvbi10ZXN0c0BjaGluZ29yLXRlc3QuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJlbWFpbCI6ImludGVncmF0aW9uLXRlc3RzQGNoaW5nb3ItdGVzdC5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJleHAiOjE1ODc2Mjk4ODgsImlhdCI6MTU4NzYyNjI4OCwiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTA0MDI5MjkyODUzMDk5OTc4MjkzIn0.Pj4KsJh7riU7ZIbPMcHcHWhasWEcbVjGP4yx_5E0iOpeDalTdri97E-o0dSSkuVX2FeBIgGUg_TNNgJ3YY97T737jT5DUYwdv6M51dDlLmmNqlu_P6toGCSRC8-Beu5gGmqS2Y82TmpHH9Vhoh5PsK7_rVHk8U6VrrVVKKTWm_IzTFhqX1oYKPdvfyaNLsXPbCt_NFE0C3DNmFkgVhRJu7LtzQQN-ghaqd3Ga3i6KH222OEI_PU4BUTvEiNOqRGoMlT_YOsyFN3XwqQ6jQGWhhkArL1z3CG2BVQjHTKpgVsRyy_H6WTZiju2Q-XWobgH-UPSZbyymV8-cFT9XKEtZQ"; ++ private static final String LEGACY_FEDERATED_SIGNON_CERT_URL = ++ "https://www.googleapis.com/oauth2/v1/certs"; ++ ++ private static final String SERVICE_ACCOUNT_RS256_TOKEN = ++ "eyJhbGciOiJSUzI1NiIsImtpZCI6IjJlZjc3YjM4YTFiMDM3MDQ4NzA0MzkxNmFjYmYyN2Q3NGVkZDA4YjEiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJodHRwczovL2V4YW1wbGUuY29tL2F1ZGllbmNlIiwiZXhwIjoxNTg3NjMwNTQzLCJpYXQiOjE1ODc2MjY5NDMsImlzcyI6InNvbWUgaXNzdWVyIiwic3ViIjoic29tZSBzdWJqZWN0In0.gGOQW0qQgs4jGUmCsgRV83RqsJLaEy89-ZOG6p1u0Y26FyY06b6Odgd7xXLsSTiiSnch62dl0Lfi9D0x2ByxvsGOCbovmBl2ZZ0zHr1wpc4N0XS9lMUq5RJQbonDibxXG4nC2zroDfvD0h7i-L8KMXeJb9pYwW7LkmrM_YwYfJnWnZ4bpcsDjojmPeUBlACg7tjjOgBFbyQZvUtaERJwSRlaWibvNjof7eCVfZChE0PwBpZc_cGqSqKXv544L4ttqdCnmONjqrTATXwC4gYxruevkjHfYI5ojcQmXoWDJJ0-_jzfyPE4MFFdCFgzLgnfIOwe5ve0MtquKuv2O0pgvg"; ++ private static final String SERVICE_ACCOUNT_CERT_URL = ++ "https://www.googleapis.com/robot/v1/metadata/x509/integration-tests%40chingor-test.iam.gserviceaccount.com"; ++ ++ private static final List ALL_TOKENS = ++ Arrays.asList(ES256_TOKEN, FEDERATED_SIGNON_RS256_TOKEN, SERVICE_ACCOUNT_RS256_TOKEN); ++ ++ static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance(); ++ static final MockClock FIXED_CLOCK = new MockClock(1584047020000L); ++ + private static IdToken newIdToken(String issuer, String audience) { + Payload payload = new Payload(); + payload.setIssuer(issuer); +@@ -56,8 +90,8 @@ public class IdTokenVerifierTest extends + assertEquals(Clock.SYSTEM, builder.getClock()); + assertEquals(ISSUER, builder.getIssuer()); + assertEquals(Collections.singleton(ISSUER), builder.getIssuers()); +- assertTrue(TRUSTED_CLIENT_IDS.equals(builder.getAudience())); +- Clock clock = new MyClock(); ++ assertEquals(TRUSTED_CLIENT_IDS, builder.getAudience()); ++ Clock clock = new MockClock(); + builder.setClock(clock); + assertEquals(clock, builder.getClock()); + IdTokenVerifier verifier = builder.build(); +@@ -67,22 +101,22 @@ public class IdTokenVerifierTest extends + assertEquals(TRUSTED_CLIENT_IDS, Lists.newArrayList(verifier.getAudience())); + } + +- static class MyClock implements Clock { +- +- long timeMillis; +- +- public long currentTimeMillis() { +- return timeMillis; +- } +- } +- + public void testVerify() throws Exception { +- MyClock clock = new MyClock(); +- IdTokenVerifier verifier = new IdTokenVerifier.Builder() +- .setIssuers(Arrays.asList(ISSUER, ISSUER3)) +- .setAudience(Arrays.asList(CLIENT_ID)).setClock(clock).build(); ++ MockClock clock = new MockClock(); ++ MockEnvironment testEnvironment = new MockEnvironment(); ++ testEnvironment.setVariable(IdTokenVerifier.SKIP_SIGNATURE_ENV_VAR, "true"); ++ IdTokenVerifier verifier = ++ new IdTokenVerifier.Builder() ++ .setIssuers(Arrays.asList(ISSUER, ISSUER3)) ++ .setAudience(Arrays.asList(CLIENT_ID)) ++ .setClock(clock) ++ .setEnvironment(testEnvironment) ++ .build(); ++ + // verifier flexible doesn't check issuer and audience +- IdTokenVerifier verifierFlexible = new IdTokenVerifier.Builder().setClock(clock).build(); ++ IdTokenVerifier verifierFlexible = ++ new IdTokenVerifier.Builder().setClock(clock).setEnvironment(testEnvironment).build(); ++ + // issuer + clock.timeMillis = 1500000L; + IdToken idToken = newIdToken(ISSUER, CLIENT_ID); +@@ -136,4 +170,165 @@ public class IdTokenVerifierTest extends + assertNull(verifier.getIssuers()); + assertNull(verifier.getIssuer()); + } ++ ++ public void testVerifyEs256TokenPublicKeyMismatch() throws Exception { ++ // Mock HTTP requests ++ HttpTransportFactory httpTransportFactory = ++ new HttpTransportFactory() { ++ @Override ++ public HttpTransport create() { ++ return new MockHttpTransport() { ++ @Override ++ public LowLevelHttpRequest buildRequest(String method, String url) ++ throws IOException { ++ return new MockLowLevelHttpRequest() { ++ @Override ++ public LowLevelHttpResponse execute() throws IOException { ++ MockLowLevelHttpResponse response = new MockLowLevelHttpResponse(); ++ response.setStatusCode(200); ++ response.setContentType("application/json"); ++ response.setContent(""); ++ return response; ++ } ++ }; ++ } ++ }; ++ } ++ }; ++ IdTokenVerifier tokenVerifier = ++ new IdTokenVerifier.Builder() ++ .setClock(FIXED_CLOCK) ++ .setHttpTransportFactory(httpTransportFactory) ++ .build(); ++ ++ try { ++ tokenVerifier.verifySignature(IdToken.parse(JSON_FACTORY, ES256_TOKEN)); ++ fail("Should have failed verification"); ++ } catch (VerificationException ex) { ++ assertTrue(ex.getMessage().contains("Error fetching PublicKey")); ++ } ++ } ++ ++ public void testVerifyEs256Token() throws VerificationException, IOException { ++ HttpTransportFactory httpTransportFactory = ++ mockTransport( ++ "https://www.gstatic.com/iap/verify/public_key-jwk", ++ readResourceAsString("iap_keys.json")); ++ IdTokenVerifier tokenVerifier = ++ new IdTokenVerifier.Builder() ++ .setClock(FIXED_CLOCK) ++ .setHttpTransportFactory(httpTransportFactory) ++ .build(); ++ assertTrue(tokenVerifier.verify(IdToken.parse(JSON_FACTORY, ES256_TOKEN))); ++ } ++ ++ public void testVerifyRs256Token() throws VerificationException, IOException { ++ HttpTransportFactory httpTransportFactory = ++ mockTransport( ++ "https://www.googleapis.com/oauth2/v3/certs", ++ readResourceAsString("federated_keys.json")); ++ MockClock clock = new MockClock(1587625988000L); ++ IdTokenVerifier tokenVerifier = ++ new IdTokenVerifier.Builder() ++ .setClock(clock) ++ .setHttpTransportFactory(httpTransportFactory) ++ .build(); ++ assertTrue(tokenVerifier.verify(IdToken.parse(JSON_FACTORY, FEDERATED_SIGNON_RS256_TOKEN))); ++ } ++ ++ public void testVerifyRs256TokenWithLegacyCertificateUrlFormat() ++ throws VerificationException, IOException { ++ HttpTransportFactory httpTransportFactory = ++ mockTransport( ++ LEGACY_FEDERATED_SIGNON_CERT_URL, readResourceAsString("legacy_federated_keys.json")); ++ MockClock clock = new MockClock(1587626288000L); ++ IdTokenVerifier tokenVerifier = ++ new IdTokenVerifier.Builder() ++ .setCertificatesLocation(LEGACY_FEDERATED_SIGNON_CERT_URL) ++ .setClock(clock) ++ .setHttpTransportFactory(httpTransportFactory) ++ .build(); ++ assertTrue(tokenVerifier.verify(IdToken.parse(JSON_FACTORY, FEDERATED_SIGNON_RS256_TOKEN))); ++ } ++ ++ public void testVerifyServiceAccountRs256Token() throws VerificationException, IOException { ++ MockClock clock = new MockClock(1587626643000L); ++ IdTokenVerifier tokenVerifier = ++ new IdTokenVerifier.Builder() ++ .setClock(clock) ++ .setCertificatesLocation(SERVICE_ACCOUNT_CERT_URL) ++ .setHttpTransportFactory(new DefaultHttpTransportFactory()) ++ .build(); ++ assertTrue(tokenVerifier.verify(IdToken.parse(JSON_FACTORY, SERVICE_ACCOUNT_RS256_TOKEN))); ++ } ++ ++ static String readResourceAsString(String resourceName) throws IOException { ++ InputStream inputStream = ++ IdTokenVerifierTest.class.getClassLoader().getResourceAsStream(resourceName); ++ try (final Reader reader = new InputStreamReader(inputStream)) { ++ return CharStreams.toString(reader); ++ } ++ } ++ ++ static HttpTransportFactory mockTransport(String url, String certificates) { ++ final String certificatesContent = certificates; ++ final String certificatesUrl = url; ++ return new HttpTransportFactory() { ++ @Override ++ public HttpTransport create() { ++ return new MockHttpTransport() { ++ @Override ++ public LowLevelHttpRequest buildRequest(String method, String url) throws IOException { ++ assertEquals(certificatesUrl, url); ++ return new MockLowLevelHttpRequest() { ++ @Override ++ public LowLevelHttpResponse execute() throws IOException { ++ MockLowLevelHttpResponse response = new MockLowLevelHttpResponse(); ++ response.setStatusCode(200); ++ response.setContentType("application/json"); ++ response.setContent(certificatesContent); ++ return response; ++ } ++ }; ++ } ++ }; ++ } ++ }; ++ } ++ ++ /** A mock implementation of {@link Clock} to set clock for testing */ ++ static class MockClock implements Clock { ++ public MockClock() {} ++ ++ public MockClock(long timeMillis) { ++ this.timeMillis = timeMillis; ++ } ++ ++ long timeMillis; ++ ++ public long currentTimeMillis() { ++ return timeMillis; ++ } ++ } ++ ++ /** A default http transport factory for testing */ ++ static class DefaultHttpTransportFactory implements HttpTransportFactory { ++ public HttpTransport create() { ++ return new NetHttpTransport(); ++ } ++ } ++ ++ /** A mock implementation of {@link Environment} to set environment variables for testing */ ++ class MockEnvironment extends Environment { ++ private final Map variables = new HashMap<>(); ++ ++ @Override ++ public String getVariable(String name) { ++ return variables.get(name); ++ } ++ ++ public void setVariable(String name, String value) { ++ variables.put(name, value); ++ } ++ } + } +Index: google-oauth-java-client-1.22.0/google-oauth-client/src/test/resources/aws_security_credentials.json +=================================================================== +--- /dev/null ++++ google-oauth-java-client-1.22.0/google-oauth-client/src/test/resources/aws_security_credentials.json +@@ -0,0 +1,9 @@ ++{ ++ "Code" : "Success", ++ "LastUpdated" : "2020-08-11T19:33:07Z", ++ "Type" : "AWS-HMAC", ++ "AccessKeyId" : "ASIARD4OQDT6A77FR3CL", ++ "SecretAccessKey" : "Y8AfSaucF37G4PpvfguKZ3/l7Id4uocLXxX0+VTx", ++ "Token" : "IQoJb3JpZ2luX2VjEIz//////////wEaCXVzLWVhc3QtMiJGMEQCIH7MHX/Oy/OB8OlLQa9GrqU1B914+iMikqWQW7vPCKlgAiA/Lsv8Jcafn14owfxXn95FURZNKaaphj0ykpmS+Ki+CSq0AwhlEAAaDDA3NzA3MTM5MTk5NiIMx9sAeP1ovlMTMKLjKpEDwuJQg41/QUKx0laTZYjPlQvjwSqS3OB9P1KAXPWSLkliVMMqaHqelvMF/WO/glv3KwuTfQsavRNs3v5pcSEm4SPO3l7mCs7KrQUHwGP0neZhIKxEXy+Ls//1C/Bqt53NL+LSbaGv6RPHaX82laz2qElphg95aVLdYgIFY6JWV5fzyjgnhz0DQmy62/Vi8pNcM2/VnxeCQ8CC8dRDSt52ry2v+nc77vstuI9xV5k8mPtnaPoJDRANh0bjwY5Sdwkbp+mGRUJBAQRlNgHUJusefXQgVKBCiyJY4w3Csd8Bgj9IyDV+Azuy1jQqfFZWgP68LSz5bURyIjlWDQunO82stZ0BgplKKAa/KJHBPCp8Qi6i99uy7qh76FQAqgVTsnDuU6fGpHDcsDSGoCls2HgZjZFPeOj8mmRhFk1Xqvkbjuz8V1cJk54d3gIJvQt8gD2D6yJQZecnuGWd5K2e2HohvCc8Fc9kBl1300nUJPV+k4tr/A5R/0QfEKOZL1/k5lf1g9CREnrM8LVkGxCgdYMxLQow1uTL+QU67AHRRSp5PhhGX4Rek+01vdYSnJCMaPhSEgcLqDlQkhk6MPsyT91QMXcWmyO+cAZwUPwnRamFepuP4K8k2KVXs/LIJHLELwAZ0ekyaS7CptgOqS7uaSTFG3U+vzFZLEnGvWQ7y9IPNQZ+Dffgh4p3vF4J68y9049sI6Sr5d5wbKkcbm8hdCDHZcv4lnqohquPirLiFQ3q7B17V9krMPu3mz1cg4Ekgcrn/E09NTsxAqD8NcZ7C7ECom9r+X3zkDOxaajW6hu3Az8hGlyylDaMiFfRbBJpTIlxp7jfa7CxikNgNtEKLH9iCzvuSg2vhA==", ++ "Expiration" : "2020-08-11T07:35:49Z" ++} +\ No newline at end of file +Index: google-oauth-java-client-1.22.0/google-oauth-client/src/test/resources/client_secret.json +=================================================================== +--- /dev/null ++++ google-oauth-java-client-1.22.0/google-oauth-client/src/test/resources/client_secret.json +@@ -0,0 +1,16 @@ ++{ ++ "web": { ++ "client_id":"ya29.1.AADtN_UtlxN3PuGAxrN2XQnZTVRvDyVWnYq4I6dws", ++ "auth_uri":"https://accounts.google.com/o/oauth2/auth", ++ "token_uri":"https://accounts.google.com/o/oauth2/token", ++ "auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs", ++ "client_secret":"jakuaL9YyieakhECKL2SwZcu", ++ "redirect_uris":[ ++ "http://example.appspot.com/oauth2callback", ++ "http://localhost:8080/oauth2callback" ++ ], ++ "javascript_origins":[ ++ "https://www.example.com" ++ ] ++ } ++} +Index: google-oauth-java-client-1.22.0/google-oauth-client/src/test/resources/federated_keys.json +=================================================================== +--- /dev/null ++++ google-oauth-java-client-1.22.0/google-oauth-client/src/test/resources/federated_keys.json +@@ -0,0 +1,20 @@ ++{ ++ "keys": [ ++ { ++ "kid": "f9d97b4cae90bcd76aeb20026f6b770cac221783", ++ "e": "AQAB", ++ "kty": "RSA", ++ "alg": "RS256", ++ "n": "ya_7gVJrvqFp5xfYPOco8gBLY38kQDlTlT6ueHtUtbTkRVE1X5tFmPqChnX7wWd2fK7MS4-nclYaGLL7IvJtN9tjrD0h_3_HvnrRZTaVyS-yfWqCQDRq_0VW1LBEygwYRqbO2T0lOocTY-5qUosDvJfe-o-lQYMH7qtDAyiq9XprVzKYTfS545BTECXi0he9ikJl5Q_RAP1BZoaip8F0xX5Y_60G90VyXFWuy16nm5ASW8fwqzdn1lL_ogiO1LirgBFFEXz_t4PwmjWzfQwkoKv4Ab_l9u2FdAoKtFH2CwKaGB8hatIK3bOAJJgRebeU3w6Ah3gxRfi8HWPHbAGjtw", ++ "use": "sig" ++ }, ++ { ++ "kid": "28b741e8de984a47159f19e6d7783e9d4fa810db", ++ "e": "AQAB", ++ "kty": "RSA", ++ "alg": "RS256", ++ "n": "zc4ELn-9nLzCZb4PdXGVhtUtzwmQI8HZH8tOIEg9omx6CW-PZ5xtVQ5O5EBG2AA5_K-aOWvVEWyfeHe8WwZltM1cXu6QNdXbpVVYeZ0th9hm7ZflNz7h1PMM9lNXLJjokax5gxGskc8CsjhkwurEot1TD2zbGIQsOYoebQTvJ2AYxIjk77BU20nLplurge8jrK-V1G3zJlp0xIKqxjsfIFYm1Mp-HQhJzdMbjNEScs0dDT4rPxdA-wOVGix0wrPdIE1gM4GxZ7AlSZ7IcjuYMZIe6d6oAeKG0FG0avbtipAQglxTHM3UOge6PmThr_mmiI82oLqGutul-XYgy1S2NQ", ++ "use": "sig" ++ } ++ ] ++} +\ No newline at end of file +Index: google-oauth-java-client-1.22.0/google-oauth-client/src/test/resources/iap_keys.json +=================================================================== +--- /dev/null ++++ google-oauth-java-client-1.22.0/google-oauth-client/src/test/resources/iap_keys.json +@@ -0,0 +1,49 @@ ++{ ++ "keys" : [ ++ { ++ "alg" : "ES256", ++ "crv" : "P-256", ++ "kid" : "2nMJtw", ++ "kty" : "EC", ++ "use" : "sig", ++ "x" : "9e1x7YRZg53A5zIJ0p2ZQ9yTrgPLGIf4ntOk-4O2R28", ++ "y" : "q8iDm7nsnpz1xPdrWBtTZSowzciS3O7bMYtFFJ8saYo" ++ }, ++ { ++ "alg" : "ES256", ++ "crv" : "P-256", ++ "kid" : "LYyP2g", ++ "kty" : "EC", ++ "use" : "sig", ++ "x" : "SlXFFkJ3JxMsXyXNrqzE3ozl_0913PmNbccLLWfeQFU", ++ "y" : "GLSahrZfBErmMUcHP0MGaeVnJdBwquhrhQ8eP05NfCI" ++ }, ++ { ++ "alg" : "ES256", ++ "crv" : "P-256", ++ "kid" : "mpf0DA", ++ "kty" : "EC", ++ "use" : "sig", ++ "x" : "fHEdeT3a6KaC1kbwov73ZwB_SiUHEyKQwUUtMCEn0aI", ++ "y" : "QWOjwPhInNuPlqjxLQyhveXpWqOFcQPhZ3t-koMNbZI" ++ }, ++ { ++ "alg" : "ES256", ++ "crv" : "P-256", ++ "kid" : "b9vTLA", ++ "kty" : "EC", ++ "use" : "sig", ++ "x" : "qCByTAvci-jRAD7uQSEhTdOs8iA714IbcY2L--YzynI", ++ "y" : "WQY0uCoQyPSozWKGQ0anmFeOH5JNXiZa9i6SNqOcm7w" ++ }, ++ { ++ "alg" : "ES256", ++ "crv" : "P-256", ++ "kid" : "0oeLcQ", ++ "kty" : "EC", ++ "use" : "sig", ++ "x" : "MdhRXGEoGJLtBjQEIjnYLPkeci9rXnca2TffkI0Kac0", ++ "y" : "9BoREHfX7g5OK8ELpA_4RcOnFCGSjfR4SGZpBo7juEY" ++ } ++ ] ++} +\ No newline at end of file +Index: google-oauth-java-client-1.22.0/google-oauth-client/src/test/resources/legacy_federated_keys.json +=================================================================== +--- /dev/null ++++ google-oauth-java-client-1.22.0/google-oauth-client/src/test/resources/legacy_federated_keys.json +@@ -0,0 +1,4 @@ ++{ ++ "f9d97b4cae90bcd76aeb20026f6b770cac221783": "-----BEGIN CERTIFICATE-----\nMIIDJjCCAg6gAwIBAgIILRTfnfU3e2gwDQYJKoZIhvcNAQEFBQAwNjE0MDIGA1UE\nAxMrZmVkZXJhdGVkLXNpZ25vbi5zeXN0ZW0uZ3NlcnZpY2VhY2NvdW50LmNvbTAe\nFw0yMDA0MTQwNDI5MzBaFw0yMDA0MzAxNjQ0MzBaMDYxNDAyBgNVBAMTK2ZlZGVy\nYXRlZC1zaWdub24uc3lzdGVtLmdzZXJ2aWNlYWNjb3VudC5jb20wggEiMA0GCSqG\nSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJr/uBUmu+oWnnF9g85yjyAEtjfyRAOVOV\nPq54e1S1tORFUTVfm0WY+oKGdfvBZ3Z8rsxLj6dyVhoYsvsi8m0322OsPSH/f8e+\netFlNpXJL7J9aoJANGr/RVbUsETKDBhGps7ZPSU6hxNj7mpSiwO8l976j6VBgwfu\nq0MDKKr1emtXMphN9LnjkFMQJeLSF72KQmXlD9EA/UFmhqKnwXTFflj/rQb3RXJc\nVa7LXqebkBJbx/CrN2fWUv+iCI7UuKuAEUURfP+3g/CaNbN9DCSgq/gBv+X27YV0\nCgq0UfYLApoYHyFq0grds4AkmBF5t5TfDoCHeDFF+LwdY8dsAaO3AgMBAAGjODA2\nMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsG\nAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4IBAQA1Wrx3XsIAAYOaycAkV2mZW1j+Vqxx\nSAeUyuhLoaJ7jntd7LqTuTr+qRnR/fH/CjTbPzngvCyVE6hjClh159YRpf4TJ4aL\nMJ97qDxc/f/pM/7yklIaHHOwqYU10plIyw+m0dnQutPqy1o/aDUytDznNmM6L3v+\ncot2bxyd2PtjGfa1hPNNnEnrZfS2Gc0qqR64RUWbsdLVVQB8MKcaNUqjk9o/1O4p\nNNk2D2VcofdaLPpwSmtzV8wEd4vfzI17qFSPi6gbTfydvxkejk0kdSyWUPw+1YC4\nv2o2rzwXub9hcP2zXyZvTGKPMAkZ8VKuzWuvfuSsTtgcPJ20GpIkin/j\n-----END CERTIFICATE-----\n", ++ "28b741e8de984a47159f19e6d7783e9d4fa810db": "-----BEGIN CERTIFICATE-----\nMIIDJjCCAg6gAwIBAgIIcog+uwMaMb8wDQYJKoZIhvcNAQEFBQAwNjE0MDIGA1UE\nAxMrZmVkZXJhdGVkLXNpZ25vbi5zeXN0ZW0uZ3NlcnZpY2VhY2NvdW50LmNvbTAe\nFw0yMDA0MjIwNDI5MzBaFw0yMDA1MDgxNjQ0MzBaMDYxNDAyBgNVBAMTK2ZlZGVy\nYXRlZC1zaWdub24uc3lzdGVtLmdzZXJ2aWNlYWNjb3VudC5jb20wggEiMA0GCSqG\nSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNzgQuf72cvMJlvg91cZWG1S3PCZAjwdkf\ny04gSD2ibHoJb49nnG1VDk7kQEbYADn8r5o5a9URbJ94d7xbBmW0zVxe7pA11dul\nVVh5nS2H2Gbtl+U3PuHU8wz2U1csmOiRrHmDEayRzwKyOGTC6sSi3VMPbNsYhCw5\nih5tBO8nYBjEiOTvsFTbScumW6uB7yOsr5XUbfMmWnTEgqrGOx8gVibUyn4dCEnN\n0xuM0RJyzR0NPis/F0D7A5UaLHTCs90gTWAzgbFnsCVJnshyO5gxkh7p3qgB4obQ\nUbRq9u2KkBCCXFMczdQ6B7o+ZOGv+aaIjzaguoa626X5diDLVLY1AgMBAAGjODA2\nMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsG\nAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4IBAQBEfCN7qgI2GJJAC99PDbafqC1EMBlv\nBT/7UiQdTuDV04+cQH9IpzROW7IZc/ILcqpF6KXUmj6j0sWO+hxKFY66TJKPcypK\n/ZMI58epwwVgGZyYU0BbAIZ9uvOgDfuveMildlMDMg1cJNp7WjBrEJ2DcGfC56wJ\nuKvqB1upxnfh+Ceg3ApU50k6Ld6+dbDDR0Vzt/wGZlZZ5Uj6AwDFe+5p9zEpWg61\nHeny/tSBfgZ19vP2h3ye9ZTK1OFRMNufj8iSzmlkbSqWuy82XVSBRKy5QslqXsYe\nU3gM3EVvXHA/Of3sROFpvznCXNr+Kn03wTv0ny6rnSgHQUzj7p9fydXY\n-----END CERTIFICATE-----\n" ++} +\ No newline at end of file +Index: google-oauth-java-client-1.22.0/google-oauth-client/src/test/resources/service_account_keys.json +=================================================================== +--- /dev/null ++++ google-oauth-java-client-1.22.0/google-oauth-client/src/test/resources/service_account_keys.json +@@ -0,0 +1,4 @@ ++{ ++ "a8611b6a9c0a0a8b940d0f915c326fd1605c8ac6": "-----BEGIN CERTIFICATE-----\nMIIDPDCCAiSgAwIBAgIIFJsPvyc/ZSUwDQYJKoZIhvcNAQEFBQAwQTE/MD0GA1UE\nAxM2aW50ZWdyYXRpb24tdGVzdHMuY2hpbmdvci10ZXN0LmlhbS5nc2VydmljZWFj\nY291bnQuY29tMB4XDTIwMDQwMjIyMjIxN1oXDTIyMDUwMTEzNTYxNVowQTE/MD0G\nA1UEAxM2aW50ZWdyYXRpb24tdGVzdHMuY2hpbmdvci10ZXN0LmlhbS5nc2Vydmlj\nZWFjY291bnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6Yys\nP5LIa1rRxQY93FXIJDzq6Tai4VuetffJbltRtYbdwC5Vyl99O2zoVdRlg+iYXK5B\nb6kidjmWOf0kNimQ5FwYvu+xsm6w8vjL/XShkHEKiURszyCua8wvLeGVCiGBg/XU\nDOgYMjzRIH5fTuj3PTZk4sMj02ZCpCQEMQ6ogpLXjaLp3ZXtFhkuHyCxVYbTRr+k\nGU86JAg4XwD6AdC349v+8FEQD7YtJezUAAKEgXh9e5UeL5CpOo3Vsdv/yEVo00jh\nYuWzLM6Oxt55WAhiD29vKrm7VQPSr1XwwqpdyFL2BlmqyTlb3amwvc9qv2kojGvM\nSUqgS83dc0jFqtMvEQIDAQABozgwNjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQE\nAwIHgDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQUFAAOCAQEA\nm3XUMKOtXdpw0oRjykLHdYzTHHFjQTMmhWD172rsxSzwpkFoErAC7bnmEvpcRU7D\nr4M+pE5VuDJ64J3lEpAh7W0zMXezPtGyWr39hVxL3vp3nh4CbCzzkUCfFvBOFFhm\nOI9qnjtMtaozoGi5zLs5jEaFmgR3wfij9KQjNGZJxAg0ZkwcSNb76qOCG1/vG5au\n4UuoIaq8WqSxMqBF/g+NrAE2PZhjNGnUwFPTre3SyR0otYDzJfmpL/tp5VDie8hM\nL5UZU/CmZk46+T9VbvnZ5mkPAjGiPumiptO5iliBOHPtPdn8VrP+aSQM1btHA094\n1HwfbFp7pZHBUn9COAP/1Q==\n-----END CERTIFICATE-----\n", ++ "2ef77b38a1b0370487043916acbf27d74edd08b1": "-----BEGIN CERTIFICATE-----\nMIIC+jCCAeKgAwIBAgIIIwRR4+AftjswDQYJKoZIhvcNAQEFBQAwIDEeMBwGA1UE\nAxMVMTA0MDI5MjkyODUzMDk5OTc4MjkzMB4XDTIwMDMwNDA1NTIyMloXDTMwMDMw\nMjA1NTIyMlowIDEeMBwGA1UEAxMVMTA0MDI5MjkyODUzMDk5OTc4MjkzMIIBIjAN\nBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm4jAbNdDEDkG/36wP07lFKMTAnWy\nhtV/Vp4QFSIE456moU/HEmBwJX2wocPgvoxPat7FxUv7mwdgHq7+sczis4DrDIIY\n8XfZ+D98+X+rOfkS1WLXpO76REZE4JCUfkB3NKVMP0kfoCFPf2pafz1NJRrZczUw\nbSi/q1+KYHmbk8YS+Q7Iq7gW9dvQtWrsRH8dQIrToJfGH+rbSQyKUFN7skFOflw4\n/OSuT0wvD6z57JcRFtAD3zgeUuCPNRIbkPQC3vCLwWGLKSYWLJ3eM9PPW9bk+czf\nSxJOie7zRMToh4BchLO6ZQgshoEaBHbwdOTu8455skqlRJMU9SKwA6eqVQIDAQAB\nozgwNjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDAWBgNVHSUBAf8EDDAK\nBggrBgEFBQcDAjANBgkqhkiG9w0BAQUFAAOCAQEAXvt8M2GFK+5UHG0GclIqse8j\n+EgqXvDTkbeTxFP+onbA/RwKM+fzdYpDwrH1dQ6jJervmceewUTTMegfFzhF33GC\nxvjQfhs+yVOXQiBHosd93CgR19dMUYs/r1wuUpwqBGdW2S81ns3yreY72BHrikrl\nHNLD3aSJ6hq5CZ01EFpjTW10ndBdPhJRSWD2g8VI1lpd716HEmrXfPHX73KVkk5/\nWfvrMA1UK/Ag+TWQerKG3iQFUAPIUiyepdaG4uFWTBY9nzLPiC1cx3bVPVZ+5yul\nJN15hmAMd3qPgSbbeQ6JC72zXCfW3buBE2n9cGtRbZF1URJZ3NbvwRS5BD425g==\n-----END CERTIFICATE-----\n" ++} +\ No newline at end of file + diff --git a/google-oauth-java-client.spec b/google-oauth-java-client.spec index 2e0530fa369ca6bd83b0c3f00e51b1bf8e165753..2f20f7b121cbc83287f05429014226cee832b572 100644 --- a/google-oauth-java-client.spec +++ b/google-oauth-java-client.spec @@ -1,16 +1,20 @@ Name: google-oauth-java-client Version: 1.22.0 -Release: 5 +Release: 6 Summary: Google OAuth Client Library for Java License: ASL 2.0 URL: https://github.com/google/google-oauth-java-client Source0: https://github.com/google/google-oauth-java-client/archive/%{version}/%{name}-%{version}.tar.gz +Patch0: CVE-2021-22573.patch BuildArch: noarch BuildRequires: mvn(com.google.code.findbugs:jsr305) mvn(com.google.http-client:google-http-client) BuildRequires: mvn(com.google.http-client:google-http-client-jdo) BuildRequires: maven-local mvn(javax.jdo:jdo2-api) mvn(javax.servlet:javax.servlet-api) BuildRequires: mvn(org.sonatype.oss:oss-parent:pom:) +BuildRequires: mvn(com.google.http-client:google-http-client-gson) +BuildRequires: java-11-openjdk-devel mvn(com.google.guava:guava) +Requires: java-11-openjdk Provides: google-oauth-java-client-java6 = %{version}-%{release} Obsoletes: google-oauth-java-client-java6 < %{version}-%{release} @@ -48,6 +52,7 @@ The google-oauth-java-client package contains related documents. %pom_disable_module google-oauth-client-appengine %pom_disable_module google-oauth-client-jetty %pom_disable_module samples/dailymotion-cmdline-sample +%pom_xpath_remove "pom:dependency[pom:artifactId ='guava-jdk5']/pom:scope" google-oauth-client %pom_change_dep -r :guava-jdk5 :guava %pom_change_dep -r :servlet-api :javax.servlet-api:3.1.0 %pom_remove_plugin -r :animal-sniffer-maven-plugin @@ -57,12 +62,14 @@ The google-oauth-java-client package contains related documents. %pom_remove_plugin -r :maven-deploy-plugin %pom_remove_plugin -r :maven-source-plugin %pom_remove_plugin -r :maven-release-plugin +%pom_add_dep com.google.http-client:google-http-client-gson google-oauth-client %pom_xpath_remove -r "pom:plugin[pom:artifactId ='maven-jar-plugin']/pom:executions" %pom_remove_plugin org.datanucleus:maven-datanucleus-plugin google-oauth-client-servlet %build -%mvn_build -s --skip-tests +export JAVA_HOME=%{_jvmdir}/java-11-openjdk +%mvn_build -s -f -- -Dmaven.compiler.release=8 %install %mvn_install @@ -74,6 +81,9 @@ The google-oauth-java-client package contains related documents. %doc LICENSE %changelog +* Mon Oct 13 2025 yaoxin <1024769339@qq.com> - 1.22.0-6 +- Fix CVE-2021-22573 + * Wed Jan 27 2021 huanghaitao - 1.22.0-5 - Skip tests to drop datanuclues components