diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9f70bfaf0..6afcc5700 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -16,3 +16,52 @@ samples/**/*.java @googleapis/java-samples-reviewers # Generated snippets should not be owned by samples reviewers samples/snippets/generated/ @googleapis/yoshi-java + +# 3PI-related files and related base classes - joint ownership between googleapis-auth and aion-sdk +java/com/google/auth/oauth2/ActingParty.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/AwsCredentials.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/AwsDates.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/AwsRequestSignature.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/AwsRequestSigner.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/AwsSecurityCredentials.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/CredentialAccessBoundary.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/DefaultCredentialsProvider.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/DownscopedCredentials.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/EnvironmentProvider.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/ExecutableHandler.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/ExecutableResponse.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/ExternalAccountCredentials.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/GoogleCredentials.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/IdentityPoolCredentials.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/ImpersonatedCredentials.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/OAuth2Credentials.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/OAuth2CredentialsWithRefresh.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/OAuthException.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/PluggableAuthCredentials.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/PluggableAuthException.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/PluggableAuthHandler.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/StsRequestHandler.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/StsTokenExchangeRequest.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/StsTokenExchangeResponse.java @googleapis/googleapis-auth @googleapis/aion-sdk +java/com/google/auth/oauth2/SystemEnvironmentProvider.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/AwsCredentialsTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/AwsRequestSignerTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/CredentialAccessBoundaryTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/DefaultCredentialsProviderTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/DownscopedCredentialsTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/ExecutableResponseTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/ExternalAccountCredentialsTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/ITDownscopingTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/ITWorkloadIdentityFederationTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/IdentityPoolCredentialsTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/ImpersonatedCredentialsTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/MockExternalAccountCredentialsTransport.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/MockStsTransport.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/OAuth2CredentialsTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/OAuth2CredentialsWithRefreshTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/OAuthExceptionTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/PluggableAuthCredentialsTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/PluggableAuthExceptionTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/PluggableAuthHandlerTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/StsRequestHandlerTest.java @googleapis/googleapis-auth @googleapis/aion-sdk +javatests/com/google/auth/TestEnvironmentProvider.java @googleapis/googleapis-auth @googleapis/aion-sdk diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml index 3650d1268..65e82d9f2 100644 --- a/.github/sync-repo-settings.yaml +++ b/.github/sync-repo-settings.yaml @@ -81,3 +81,5 @@ permissionRules: permission: admin - team: googleapis-auth permission: push + - team: aion-sdk + permission: push diff --git a/.kokoro/presubmit/graalvm-native-17.cfg b/.kokoro/presubmit/graalvm-native-17.cfg index a3f7fb9d4..5e65d1ae1 100644 --- a/.kokoro/presubmit/graalvm-native-17.cfg +++ b/.kokoro/presubmit/graalvm-native-17.cfg @@ -30,4 +30,19 @@ env_vars: { env_vars: { key: "SECRET_MANAGER_KEYS" value: "java-it-service-account" -} \ No newline at end of file +} + +env_vars: { + key: "GCS_BUCKET" + value: "byoid-it-bucket" +} + +env_vars: { + key: "GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES" + value: "1" +} + +env_vars: { + key: "GOOGLE_CLOUD_QUOTA_PROJECT" + value: "gcloud-devel" +} diff --git a/.kokoro/presubmit/graalvm-native.cfg b/.kokoro/presubmit/graalvm-native.cfg index 4c7225ec9..73464797d 100644 --- a/.kokoro/presubmit/graalvm-native.cfg +++ b/.kokoro/presubmit/graalvm-native.cfg @@ -31,3 +31,19 @@ env_vars: { key: "SECRET_MANAGER_KEYS" value: "java-it-service-account" } + +env_vars: { + key: "GCS_BUCKET" + value: "byoid-it-bucket" +} + +env_vars: { + key: "GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES" + value: "1" +} + +env_vars: { + key: "GOOGLE_CLOUD_QUOTA_PROJECT" + value: "gcloud-devel" +} + diff --git a/CHANGELOG.md b/CHANGELOG.md index 61f02473c..5ef1e7d4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## [1.16.0](https://github.com/googleapis/google-auth-library-java/compare/v1.15.0...v1.16.0) (2023-02-15) + + +### Features + +* Add PKCE to 3LO exchange. ([#1146](https://github.com/googleapis/google-auth-library-java/issues/1146)) ([5bf606b](https://github.com/googleapis/google-auth-library-java/commit/5bf606bb8f6d863b44e87587eebf51eaeea4a0ae)) + + +### Bug Fixes + +* Create and reuse self signed jwt creds for better performance ([#1154](https://github.com/googleapis/google-auth-library-java/issues/1154)) ([eaaa8e8](https://github.com/googleapis/google-auth-library-java/commit/eaaa8e89cf69d1e0d581443121f315854d52c75f)) +* Java doc for DefaultPKCEProvider.java ([#1148](https://github.com/googleapis/google-auth-library-java/issues/1148)) ([154c127](https://github.com/googleapis/google-auth-library-java/commit/154c1279b3ec96cc34a3225e5e78800ccdda927c)) +* Removed url pattern validation for google urls in external account credential configurations ([#1150](https://github.com/googleapis/google-auth-library-java/issues/1150)) ([35495b1](https://github.com/googleapis/google-auth-library-java/commit/35495b1207ffe11712ee996d3e305449752fb87c)) + + +### Documentation + +* Clarified Maven artifact for HTTP-based clients ([#1136](https://github.com/googleapis/google-auth-library-java/issues/1136)) ([b49fc13](https://github.com/googleapis/google-auth-library-java/commit/b49fc13b10d0e326c7296e2aad7a50ea03e774f5)) + ## [1.15.0](https://github.com/googleapis/google-auth-library-java/compare/v1.14.0...v1.15.0) (2023-01-25) diff --git a/README.md b/README.md index c94afa4bb..dcf695426 100644 --- a/README.md +++ b/README.md @@ -728,6 +728,13 @@ ExternalAccountCredentials credentials = ExternalAccountCredentials.fromStream(new FileInputStream("/path/to/credentials.json")); ``` +##### Security Considerations +Note that this library does not perform any validation on the token_url, token_info_url, +or service_account_impersonation_url fields of the credential configuration. +It is not recommended to use a credential configuration that you did not +generate with the gcloud CLI unless you verify that the URL fields point to a +googleapis.com domain. + ### Downscoping with Credential Access Boundaries [Downscoping with Credential Access Boundaries](https://cloud.google.com/iam/docs/downscoping-short-lived-credentials) @@ -930,10 +937,12 @@ The above example requires `com.google.http-client:google-http-client-apache-v2` ## Using Credentials with `google-http-client` -Credentials provided by `google-auth-library` can be used with Google's -[HTTP-based clients][apiary-clients]. We provide a -[`HttpCredentialsAdapter`][http-credentials-adapter] which can be used as an -[`HttpRequestInitializer`][http-request-initializer]. +Credentials provided by [com.google.auth:google-auth-library-oauth2-http]( +https://search.maven.org/artifact/com.google.auth/google-auth-library-oauth2-http) +can be used with Google's [HTTP-based clients][apiary-clients]. +We provide a [`HttpCredentialsAdapter`][http-credentials-adapter] which can be used +as an [`HttpRequestInitializer`][http-request-initializer], the last argument for +their builders. ```java import com.google.api.client.http.HttpRequestInitializer; diff --git a/appengine/pom.xml b/appengine/pom.xml index 3e9f19bf3..ead41136a 100644 --- a/appengine/pom.xml +++ b/appengine/pom.xml @@ -5,7 +5,7 @@ com.google.auth google-auth-library-parent - 1.15.0 + 1.16.0 ../pom.xml diff --git a/bom/pom.xml b/bom/pom.xml index ee858d36e..2efc12a30 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.google.auth google-auth-library-bom - 1.15.0 + 1.16.0 pom Google Auth Library for Java BOM diff --git a/credentials/pom.xml b/credentials/pom.xml index 48a97db60..e4547d6a6 100644 --- a/credentials/pom.xml +++ b/credentials/pom.xml @@ -4,7 +4,7 @@ com.google.auth google-auth-library-parent - 1.15.0 + 1.16.0 ../pom.xml diff --git a/oauth2_http/java/com/google/auth/oauth2/DefaultPKCEProvider.java b/oauth2_http/java/com/google/auth/oauth2/DefaultPKCEProvider.java new file mode 100644 index 000000000..d4671dbe2 --- /dev/null +++ b/oauth2_http/java/com/google/auth/oauth2/DefaultPKCEProvider.java @@ -0,0 +1,109 @@ +/* + * Copyright 2023, 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.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Base64; + +/** + * Implements PKCE using only the Java standard library. See https://www.rfc-editor.org/rfc/rfc7636. + * + *

https://developers.google.com/identity/protocols/oauth2/native-app#step1-code-verifier. + */ +public class DefaultPKCEProvider implements PKCEProvider { + private String codeVerifier; + private CodeChallenge codeChallenge; + private static final int MAX_CODE_VERIFIER_LENGTH = 127; + + private String createCodeVerifier() { + SecureRandom sr = new SecureRandom(); + byte[] code = new byte[MAX_CODE_VERIFIER_LENGTH]; + sr.nextBytes(code); + return Base64.getUrlEncoder().encodeToString(code); + } + + private CodeChallenge createCodeChallenge(String codeVerifier) { + return new DefaultPKCEProvider.CodeChallenge(codeVerifier); + } + + public DefaultPKCEProvider() { + this.codeVerifier = createCodeVerifier(); + this.codeChallenge = createCodeChallenge(this.codeVerifier); + } + + @Override + public String getCodeVerifier() { + return codeVerifier; + } + + @Override + public String getCodeChallenge() { + return codeChallenge.getCodeChallenge(); + } + + @Override + public String getCodeChallengeMethod() { + return codeChallenge.getCodeChallengeMethod(); + } + + /** Class representing the Code Challenge derived from a Code Verifier string. */ + private class CodeChallenge { + private String codeChallenge; + private String codeChallengeMethod; + + CodeChallenge(String codeVerifier) { + try { + byte[] bytes = codeVerifier.getBytes(); + MessageDigest md = MessageDigest.getInstance("SHA-256"); + md.update(bytes); + + byte[] digest = md.digest(); + + this.codeChallenge = Base64.getUrlEncoder().encodeToString(digest); + this.codeChallengeMethod = "S256"; + } catch (NoSuchAlgorithmException e) { + this.codeChallenge = codeVerifier; + this.codeChallengeMethod = "plain"; + } + } + + public String getCodeChallenge() { + return codeChallenge; + } + + public String getCodeChallengeMethod() { + return codeChallengeMethod; + } + } +} diff --git a/oauth2_http/java/com/google/auth/oauth2/ExternalAccountCredentials.java b/oauth2_http/java/com/google/auth/oauth2/ExternalAccountCredentials.java index 0ec33935c..0140d0881 100644 --- a/oauth2_http/java/com/google/auth/oauth2/ExternalAccountCredentials.java +++ b/oauth2_http/java/com/google/auth/oauth2/ExternalAccountCredentials.java @@ -54,7 +54,6 @@ import java.util.Locale; import java.util.Map; import java.util.concurrent.Executor; -import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.annotation.Nullable; @@ -589,37 +588,20 @@ public boolean isWorkforcePoolConfiguration() { } static void validateTokenUrl(String tokenUrl) { - List patterns = new ArrayList<>(); - patterns.add(Pattern.compile("^[^\\.\\s\\/\\\\]+\\.sts\\.googleapis\\.com$")); - patterns.add(Pattern.compile("^sts\\.googleapis\\.com$")); - patterns.add(Pattern.compile("^sts\\.[^\\.\\s\\/\\\\]+\\.googleapis\\.com$")); - patterns.add(Pattern.compile("^[^\\.\\s\\/\\\\]+\\-sts\\.googleapis\\.com$")); - patterns.add(Pattern.compile("^sts\\-[^\\.\\s\\/\\\\]+\\.p\\.googleapis\\.com$")); - - if (!isValidUrl(patterns, tokenUrl)) { + if (!isValidUrl(tokenUrl)) { throw new IllegalArgumentException("The provided token URL is invalid."); } } static void validateServiceAccountImpersonationInfoUrl(String serviceAccountImpersonationUrl) { - List patterns = new ArrayList<>(); - patterns.add(Pattern.compile("^[^\\.\\s\\/\\\\]+\\.iamcredentials\\.googleapis\\.com$")); - patterns.add(Pattern.compile("^iamcredentials\\.googleapis\\.com$")); - patterns.add(Pattern.compile("^iamcredentials\\.[^\\.\\s\\/\\\\]+\\.googleapis\\.com$")); - patterns.add(Pattern.compile("^[^\\.\\s\\/\\\\]+\\-iamcredentials\\.googleapis\\.com$")); - patterns.add(Pattern.compile("^iamcredentials-[^\\.\\s\\/\\\\]+\\.p\\.googleapis\\.com$")); - - if (!isValidUrl(patterns, serviceAccountImpersonationUrl)) { + if (!isValidUrl(serviceAccountImpersonationUrl)) { throw new IllegalArgumentException( "The provided service account impersonation URL is invalid."); } } - /** - * Returns true if the provided URL's scheme is HTTPS and the host comforms to at least one of the - * provided patterns. - */ - private static boolean isValidUrl(List patterns, String url) { + /** Returns true if the provided URL's scheme is valid and is HTTPS. */ + private static boolean isValidUrl(String url) { URI uri; try { @@ -635,13 +617,7 @@ private static boolean isValidUrl(List patterns, String url) { return false; } - for (Pattern pattern : patterns) { - Matcher match = pattern.matcher(uri.getHost().toLowerCase(Locale.US)); - if (match.matches()) { - return true; - } - } - return false; + return true; } /** diff --git a/oauth2_http/java/com/google/auth/oauth2/PKCEProvider.java b/oauth2_http/java/com/google/auth/oauth2/PKCEProvider.java new file mode 100644 index 000000000..4800dd1cd --- /dev/null +++ b/oauth2_http/java/com/google/auth/oauth2/PKCEProvider.java @@ -0,0 +1,56 @@ +/* + * Copyright 2023, 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; + +public interface PKCEProvider { + /** + * Get the code_challenge parameter used in PKCE. + * + * @return The code_challenge String. + */ + String getCodeChallenge(); + + /** + * Get the code_challenge_method parameter used in PKCE. + * + *

Currently possible values are: S256,plain + * + * @return The code_challenge_method String. + */ + String getCodeChallengeMethod(); + /** + * Get the code_verifier parameter used in PKCE. + * + * @return The code_verifier String. + */ + String getCodeVerifier(); +} diff --git a/oauth2_http/java/com/google/auth/oauth2/ServiceAccountCredentials.java b/oauth2_http/java/com/google/auth/oauth2/ServiceAccountCredentials.java index 479041ead..c6c95a71c 100644 --- a/oauth2_http/java/com/google/auth/oauth2/ServiceAccountCredentials.java +++ b/oauth2_http/java/com/google/auth/oauth2/ServiceAccountCredentials.java @@ -110,6 +110,8 @@ public class ServiceAccountCredentials extends GoogleCredentials private transient HttpTransportFactory transportFactory; + private transient JwtCredentials selfSignedJwtCredentialsWithScope = null; + /** * Internal constructor * @@ -704,6 +706,11 @@ public boolean getUseJwtAccessWithScope() { return useJwtAccessWithScope; } + @VisibleForTesting + JwtCredentials getSelfSignedJwtCredentialsWithScope() { + return selfSignedJwtCredentialsWithScope; + } + @Override public String getAccount() { return getClientEmail(); @@ -935,8 +942,11 @@ public Map> getRequestMetadata(URI uri) throws IOException // Otherwise, use self signed JWT with uri as the audience. JwtCredentials jwtCredentials; if (!createScopedRequired() && useJwtAccessWithScope) { - // Create JWT credentials with the scopes. - jwtCredentials = createSelfSignedJwtCredentials(null); + // Create selfSignedJwtCredentialsWithScope when needed and reuse it for better performance. + if (selfSignedJwtCredentialsWithScope == null) { + selfSignedJwtCredentialsWithScope = createSelfSignedJwtCredentials(null); + } + jwtCredentials = selfSignedJwtCredentialsWithScope; } else { // Create JWT credentials with the uri as audience. jwtCredentials = createSelfSignedJwtCredentials(uri); diff --git a/oauth2_http/java/com/google/auth/oauth2/UserAuthorizer.java b/oauth2_http/java/com/google/auth/oauth2/UserAuthorizer.java index c152b8b44..29a8284d5 100644 --- a/oauth2_http/java/com/google/auth/oauth2/UserAuthorizer.java +++ b/oauth2_http/java/com/google/auth/oauth2/UserAuthorizer.java @@ -67,6 +67,7 @@ public class UserAuthorizer { private final HttpTransportFactory transportFactory; private final URI tokenServerUri; private final URI userAuthUri; + private final PKCEProvider pkce; /** * Constructor with all parameters. @@ -79,6 +80,7 @@ public class UserAuthorizer { * tokens. * @param tokenServerUri URI of the end point that provides tokens * @param userAuthUri URI of the Web UI for user consent + * @param pkce PKCE implementation */ private UserAuthorizer( ClientId clientId, @@ -87,7 +89,8 @@ private UserAuthorizer( URI callbackUri, HttpTransportFactory transportFactory, URI tokenServerUri, - URI userAuthUri) { + URI userAuthUri, + PKCEProvider pkce) { this.clientId = Preconditions.checkNotNull(clientId); this.scopes = ImmutableList.copyOf(Preconditions.checkNotNull(scopes)); this.callbackUri = (callbackUri == null) ? DEFAULT_CALLBACK_URI : callbackUri; @@ -96,6 +99,7 @@ private UserAuthorizer( this.tokenServerUri = (tokenServerUri == null) ? OAuth2Utils.TOKEN_SERVER_URI : tokenServerUri; this.userAuthUri = (userAuthUri == null) ? OAuth2Utils.USER_AUTH_URI : userAuthUri; this.tokenStore = (tokenStore == null) ? new MemoryTokensStorage() : tokenStore; + this.pkce = pkce; } /** @@ -181,6 +185,10 @@ public URL getAuthorizationUrl(String userId, String state, URI baseUri) { url.put("login_hint", userId); } url.put("include_granted_scopes", true); + if (pkce != null) { + url.put("code_challenge", pkce.getCodeChallenge()); + url.put("code_challenge_method", pkce.getCodeChallengeMethod()); + } return url.toURL(); } @@ -248,6 +256,11 @@ public UserCredentials getCredentialsFromCode(String code, URI baseUri) throws I tokenData.put("client_secret", clientId.getClientSecret()); tokenData.put("redirect_uri", resolvedCallbackUri); tokenData.put("grant_type", "authorization_code"); + + if (pkce != null) { + tokenData.put("code_verifier", pkce.getCodeVerifier()); + } + UrlEncodedContent tokenContent = new UrlEncodedContent(tokenData); HttpRequestFactory requestFactory = transportFactory.create().createRequestFactory(); HttpRequest tokenRequest = @@ -430,6 +443,7 @@ public static class Builder { private URI userAuthUri; private Collection scopes; private HttpTransportFactory transportFactory; + private PKCEProvider pkce; protected Builder() {} @@ -441,6 +455,7 @@ protected Builder(UserAuthorizer authorizer) { this.tokenStore = authorizer.tokenStore; this.callbackUri = authorizer.callbackUri; this.userAuthUri = authorizer.userAuthUri; + this.pkce = new DefaultPKCEProvider(); } public Builder setClientId(ClientId clientId) { @@ -478,6 +493,20 @@ public Builder setHttpTransportFactory(HttpTransportFactory transportFactory) { return this; } + public Builder setPKCEProvider(PKCEProvider pkce) { + if (pkce != null) { + if (pkce.getCodeChallenge() == null + || pkce.getCodeVerifier() == null + || pkce.getCodeChallengeMethod() == null) { + + throw new IllegalArgumentException( + "PKCE provider contained null implementations. PKCE object must implement all PKCEProvider methods."); + } + } + this.pkce = pkce; + return this; + } + public ClientId getClientId() { return clientId; } @@ -506,9 +535,20 @@ public HttpTransportFactory getHttpTransportFactory() { return transportFactory; } + public PKCEProvider getPKCEProvider() { + return pkce; + } + public UserAuthorizer build() { return new UserAuthorizer( - clientId, scopes, tokenStore, callbackUri, transportFactory, tokenServerUri, userAuthUri); + clientId, + scopes, + tokenStore, + callbackUri, + transportFactory, + tokenServerUri, + userAuthUri, + pkce); } } } diff --git a/oauth2_http/javatests/com/google/auth/oauth2/DefaultPKCEProviderTest.java b/oauth2_http/javatests/com/google/auth/oauth2/DefaultPKCEProviderTest.java new file mode 100644 index 000000000..e56739aad --- /dev/null +++ b/oauth2_http/javatests/com/google/auth/oauth2/DefaultPKCEProviderTest.java @@ -0,0 +1,61 @@ +/* + * Copyright 2023, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.google.auth.oauth2; + +import static org.junit.Assert.assertEquals; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public final class DefaultPKCEProviderTest { + @Test + public void testPkceExpected() throws NoSuchAlgorithmException { + PKCEProvider pkce = new DefaultPKCEProvider(); + + byte[] bytes = pkce.getCodeVerifier().getBytes(); + MessageDigest md = MessageDigest.getInstance("SHA-256"); + md.update(bytes); + + byte[] digest = md.digest(); + + String expectedCodeChallenge = Base64.getUrlEncoder().encodeToString(digest); + String expectedCodeChallengeMethod = "S256"; + + assertEquals(pkce.getCodeChallenge(), expectedCodeChallenge); + assertEquals(pkce.getCodeChallengeMethod(), expectedCodeChallengeMethod); + } +} diff --git a/oauth2_http/javatests/com/google/auth/oauth2/ExternalAccountCredentialsTest.java b/oauth2_http/javatests/com/google/auth/oauth2/ExternalAccountCredentialsTest.java index d8f5b30e4..2350af89d 100644 --- a/oauth2_http/javatests/com/google/auth/oauth2/ExternalAccountCredentialsTest.java +++ b/oauth2_http/javatests/com/google/auth/oauth2/ExternalAccountCredentialsTest.java @@ -980,34 +980,14 @@ public void validateTokenUrl_validUrls() { public void validateTokenUrl_invalidUrls() { List invalidUrls = Arrays.asList( - "https://iamcredentials.googleapis.com", "sts.googleapis.com", "https://", "http://sts.googleapis.com", - "https://st.s.googleapis.com", "https://us-eas\\t-1.sts.googleapis.com", "https:/us-east-1.sts.googleapis.com", - "https://US-WE/ST-1-sts.googleapis.com", - "https://sts-us-east-1.googleapis.com", - "https://sts-US-WEST-1.googleapis.com", "testhttps://us-east-1.sts.googleapis.com", - "https://us-east-1.sts.googleapis.comevil.com", - "https://us-east-1.us-east-1.sts.googleapis.com", - "https://us-ea.s.t.sts.googleapis.com", - "https://sts.googleapis.comevil.com", "hhttps://us-east-1.sts.googleapis.com", - "https://us- -1.sts.googleapis.com", - "https://-sts.googleapis.com", - "https://us-east-1.sts.googleapis.com.evil.com", - "https://sts.pgoogleapis.com", - "https://p.googleapis.com", - "https://sts.p.com", - "http://sts.p.googleapis.com", - "https://xyz-sts.p.googleapis.com", - "https://sts-xyz.123.p.googleapis.com", - "https://sts-xyz.p1.googleapis.com", - "https://sts-xyz.p.foo.com", - "https://sts-xyz.p.foo.googleapis.com"); + "https://us- -1.sts.googleapis.com"); for (String url : invalidUrls) { try { @@ -1046,34 +1026,14 @@ public void validateServiceAccountImpersonationUrls_validUrls() { public void validateServiceAccountImpersonationUrls_invalidUrls() { List invalidUrls = Arrays.asList( - "https://sts.googleapis.com", "iamcredentials.googleapis.com", "https://", "http://iamcredentials.googleapis.com", - "https://iamcre.dentials.googleapis.com", + "https:/iamcredentials.googleapis.com", "https://us-eas\t-1.iamcredentials.googleapis.com", - "https:/us-east-1.iamcredentials.googleapis.com", - "https://US-WE/ST-1-iamcredentials.googleapis.com", - "https://iamcredentials-us-east-1.googleapis.com", - "https://iamcredentials-US-WEST-1.googleapis.com", "testhttps://us-east-1.iamcredentials.googleapis.com", - "https://us-east-1.iamcredentials.googleapis.comevil.com", - "https://us-east-1.us-east-1.iamcredentials.googleapis.com", - "https://us-ea.s.t.iamcredentials.googleapis.com", - "https://iamcredentials.googleapis.comevil.com", "hhttps://us-east-1.iamcredentials.googleapis.com", - "https://us- -1.iamcredentials.googleapis.com", - "https://-iamcredentials.googleapis.com", - "https://us-east-1.iamcredentials.googleapis.com.evil.com", - "https://iamcredentials.pgoogleapis.com", - "https://p.googleapis.com", - "https://iamcredentials.p.com", - "http://iamcredentials.p.googleapis.com", - "https://xyz-iamcredentials.p.googleapis.com", - "https://iamcredentials-xyz.123.p.googleapis.com", - "https://iamcredentials-xyz.p1.googleapis.com", - "https://iamcredentials-xyz.p.foo.com", - "https://iamcredentials-xyz.p.foo.googleapis.com"); + "https://us- -1.iamcredentials.googleapis.com"); for (String url : invalidUrls) { try { diff --git a/oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountCredentialsTest.java b/oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountCredentialsTest.java index 14eb16b92..f3b3f0983 100644 --- a/oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountCredentialsTest.java +++ b/oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountCredentialsTest.java @@ -1465,6 +1465,7 @@ public void getRequestMetadata_selfSignedJWT_withScopes() throws IOException { .build(); Map> metadata = credentials.getRequestMetadata(CALL_URI); + assertNotNull(((ServiceAccountCredentials) credentials).getSelfSignedJwtCredentialsWithScope()); verifyJwtAccess(metadata, "dummy.scope"); } @@ -1518,6 +1519,7 @@ public void getRequestMetadata_selfSignedJWT_withAudience() throws IOException { .build(); Map> metadata = credentials.getRequestMetadata(CALL_URI); + assertNull(((ServiceAccountCredentials) credentials).getSelfSignedJwtCredentialsWithScope()); verifyJwtAccess(metadata, null); } diff --git a/oauth2_http/javatests/com/google/auth/oauth2/UserAuthorizerTest.java b/oauth2_http/javatests/com/google/auth/oauth2/UserAuthorizerTest.java index 822fcbe12..7f444330f 100644 --- a/oauth2_http/javatests/com/google/auth/oauth2/UserAuthorizerTest.java +++ b/oauth2_http/javatests/com/google/auth/oauth2/UserAuthorizerTest.java @@ -72,6 +72,7 @@ public class UserAuthorizerTest { private static final URI CALLBACK_URI = URI.create("/testcallback"); private static final String CODE = "thisistheend"; private static final URI BASE_URI = URI.create("http://example.com/foo"); + private static final PKCEProvider pkce = new DefaultPKCEProvider(); @Test public void constructorMinimum() { @@ -148,6 +149,7 @@ public void getAuthorizationUrl() throws IOException { .setScopes(DUMMY_SCOPES) .setCallbackUri(CALLBACK_URI) .setUserAuthUri(AUTH_URI) + .setPKCEProvider(pkce) .build(); URL authorizationUrl = authorizer.getAuthorizationUrl(USER_ID, CUSTOM_STATE, BASE_URI); @@ -164,6 +166,8 @@ public void getAuthorizationUrl() throws IOException { assertEquals(CLIENT_ID_VALUE, parameters.get("client_id")); assertEquals(DUMMY_SCOPE, parameters.get("scope")); assertEquals("code", parameters.get("response_type")); + assertEquals(pkce.getCodeChallenge(), parameters.get("code_challenge")); + assertEquals(pkce.getCodeChallengeMethod(), parameters.get("code_challenge_method")); } @Test @@ -471,4 +475,91 @@ public void revokeAuthorization_revokesAndClears() throws IOException { UserCredentials credentials2 = authorizer.getCredentials(USER_ID); assertNull(credentials2); } + + @Test(expected = IllegalArgumentException.class) + public void nullCodeVerifierPKCEProvider() { + PKCEProvider pkce = + new PKCEProvider() { + @Override + public String getCodeVerifier() { + return null; + } + + @Override + public String getCodeChallengeMethod() { + return "dummy string"; + } + + @Override + public String getCodeChallenge() { + return "dummy string"; + } + }; + + UserAuthorizer authorizer = + UserAuthorizer.newBuilder() + .setClientId(CLIENT_ID) + .setScopes(DUMMY_SCOPES) + .setTokenStore(new MemoryTokensStorage()) + .setPKCEProvider(pkce) + .build(); + } + + @Test(expected = IllegalArgumentException.class) + public void nullCodeChallengePKCEProvider() { + PKCEProvider pkce = + new PKCEProvider() { + @Override + public String getCodeVerifier() { + return "dummy string"; + } + + @Override + public String getCodeChallengeMethod() { + return "dummy string"; + } + + @Override + public String getCodeChallenge() { + return null; + } + }; + + UserAuthorizer authorizer = + UserAuthorizer.newBuilder() + .setClientId(CLIENT_ID) + .setScopes(DUMMY_SCOPES) + .setTokenStore(new MemoryTokensStorage()) + .setPKCEProvider(pkce) + .build(); + } + + @Test(expected = IllegalArgumentException.class) + public void nullCodeChallengeMethodPKCEProvider() { + PKCEProvider pkce = + new PKCEProvider() { + @Override + public String getCodeVerifier() { + return "dummy string"; + } + + @Override + public String getCodeChallengeMethod() { + return null; + } + + @Override + public String getCodeChallenge() { + return "dummy string"; + } + }; + + UserAuthorizer authorizer = + UserAuthorizer.newBuilder() + .setClientId(CLIENT_ID) + .setScopes(DUMMY_SCOPES) + .setTokenStore(new MemoryTokensStorage()) + .setPKCEProvider(pkce) + .build(); + } } diff --git a/oauth2_http/pom.xml b/oauth2_http/pom.xml index be57457b1..576309e7d 100644 --- a/oauth2_http/pom.xml +++ b/oauth2_http/pom.xml @@ -1,11 +1,13 @@ - + 4.0.0 com.google.auth google-auth-library-parent - 1.15.0 + 1.16.0 ../pom.xml @@ -19,8 +21,73 @@ + + + + native + + + org.junit.vintage + junit-vintage-engine + 5.9.1 + test + + + org.graalvm.buildtools + junit-platform-native + 0.9.19 + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + 2.22.2 + + + + + **/IT*.java + **/functional/*.java + + + + + org.graalvm.buildtools + native-maven-plugin + 0.9.19 + true + + + test-native + + test + + test + + + + + --no-fallback + --no-server + + + + + + + + java + + + resources + + javatests @@ -44,7 +111,8 @@ org.apache.maven.plugins maven-dependency-plugin - com.google.auto.value:auto-value + com.google.auto.value:auto-value + @@ -151,7 +219,7 @@ org.mockito mockito-core - 4.9.0 + 4.11.0 test diff --git a/oauth2_http/resources/META-INF/native-image/com.google.auth/google-auth-library-oauth2-http/reflect-config.json b/oauth2_http/resources/META-INF/native-image/com.google.auth/google-auth-library-oauth2-http/reflect-config.json new file mode 100644 index 000000000..f2732db41 --- /dev/null +++ b/oauth2_http/resources/META-INF/native-image/com.google.auth/google-auth-library-oauth2-http/reflect-config.json @@ -0,0 +1,780 @@ +[ + { + "name": "[B" + }, + { + "name": "[Ljava.lang.String;" + }, + { + "name": "[Lsun.security.pkcs.SignerInfo;" + }, + { + "name": "com.google.api.client.http.GenericUrl", + "allDeclaredFields": true + }, + { + "name": "com.google.api.client.http.HttpHeaders", + "allDeclaredFields": true, + "queryAllDeclaredMethods": true, + "methods": [ + { + "name": "setAccept", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setAcceptEncoding", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setAge", + "parameterTypes": [ + "java.lang.Long" + ] + }, + { + "name": "setAuthenticate", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setAuthorization", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setAuthorization", + "parameterTypes": [ + "java.util.List" + ] + }, + { + "name": "setCacheControl", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setContentEncoding", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setContentLength", + "parameterTypes": [ + "java.lang.Long" + ] + }, + { + "name": "setContentMD5", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setContentRange", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setContentType", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setCookie", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setDate", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setETag", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setExpires", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setIfMatch", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setIfModifiedSince", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setIfNoneMatch", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setIfRange", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setIfUnmodifiedSince", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setLastModified", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setLocation", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setMimeVersion", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setRange", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setRetryAfter", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setUserAgent", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "name": "com.google.api.client.json.GenericJson", + "allDeclaredFields": true, + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.google.api.client.json.webtoken.JsonWebSignature$Header", + "allDeclaredFields": true, + "queryAllDeclaredMethods": true, + "methods": [ + { + "name": "", + "parameterTypes": [] + }, + { + "name": "setAlgorithm", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setKeyId", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "name": "com.google.api.client.json.webtoken.JsonWebToken$Header", + "allDeclaredFields": true, + "queryAllDeclaredMethods": true, + "methods": [ + { + "name": "setType", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "name": "com.google.api.client.json.webtoken.JsonWebToken$Payload", + "allDeclaredFields": true, + "queryAllDeclaredMethods": true, + "methods": [ + { + "name": "", + "parameterTypes": [] + }, + { + "name": "setAudience", + "parameterTypes": [ + "java.lang.Object" + ] + }, + { + "name": "setExpirationTimeSeconds", + "parameterTypes": [ + "java.lang.Long" + ] + }, + { + "name": "setIssuedAtTimeSeconds", + "parameterTypes": [ + "java.lang.Long" + ] + }, + { + "name": "setIssuer", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setSubject", + "parameterTypes": [ + "java.lang.String" + ] + } + ] + }, + { + "name": "com.google.api.client.util.ArrayMap", + "allDeclaredFields": true + }, + { + "name": "com.google.api.client.util.GenericData", + "allDeclaredFields": true, + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.google.common.util.concurrent.AbstractFuture", + "fields": [ + { + "name": "listeners" + }, + { + "name": "value" + }, + { + "name": "waiters" + } + ] + }, + { + "name": "com.google.common.util.concurrent.AbstractFuture$Waiter", + "fields": [ + { + "name": "next" + }, + { + "name": "thread" + } + ] + }, + { + "name": "com.sun.crypto.provider.AESCipher$General", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.sun.crypto.provider.DHParameters", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.sun.crypto.provider.HmacCore$HmacSHA256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.sun.crypto.provider.HmacCore$HmacSHA384", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.sun.crypto.provider.TlsKeyMaterialGenerator", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.sun.crypto.provider.TlsMasterSecretGenerator", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.sun.crypto.provider.TlsPrfGenerator$V12", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "java.lang.Object", + "allDeclaredFields": true, + "queryAllDeclaredMethods": true + }, + { + "name": "java.lang.String" + }, + { + "name": "java.security.AlgorithmParametersSpi" + }, + { + "name": "java.security.KeyStoreSpi" + }, + { + "name": "java.security.MessageDigestSpi" + }, + { + "name": "java.security.SecureRandomParameters" + }, + { + "name": "java.security.interfaces.ECPrivateKey" + }, + { + "name": "java.security.interfaces.ECPublicKey" + }, + { + "name": "java.security.interfaces.RSAPrivateKey" + }, + { + "name": "java.security.interfaces.RSAPublicKey" + }, + { + "name": "java.util.AbstractMap", + "allDeclaredFields": true + }, + { + "name": "java.util.Date" + }, + { + "name": "javax.security.auth.x500.X500Principal", + "fields": [ + { + "name": "thisX500Name" + } + ], + "methods": [ + { + "name": "", + "parameterTypes": [ + "sun.security.x509.X500Name" + ] + } + ] + }, + { + "name": "sun.misc.Unsafe", + "allDeclaredFields": true + }, + { + "name": "sun.security.pkcs12.PKCS12KeyStore", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.provider.DSA$SHA224withDSA", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.provider.DSA$SHA256withDSA", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.provider.JavaKeyStore$DualFormatJKS", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.provider.JavaKeyStore$JKS", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.provider.NativePRNG", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.provider.SHA", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.provider.SHA2$SHA224", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.provider.SHA2$SHA256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.provider.SHA5$SHA384", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.provider.SHA5$SHA512", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.provider.X509Factory", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.provider.certpath.PKIXCertPathValidator", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.rsa.PSSParameters", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.rsa.RSAKeyFactory$Legacy", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.rsa.RSAPSSSignature", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.rsa.RSASignature$SHA224withRSA", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.rsa.RSASignature$SHA256withRSA", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.ssl.KeyManagerFactoryImpl$SunX509", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.ssl.SSLContextImpl$DefaultSSLContext", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "sun.security.util.ObjectIdentifier" + }, + { + "name": "sun.security.x509.AuthorityInfoAccessExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "name": "sun.security.x509.AuthorityKeyIdentifierExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "name": "sun.security.x509.BasicConstraintsExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "name": "sun.security.x509.CRLDistributionPointsExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "name": "sun.security.x509.CertificateExtensions" + }, + { + "name": "sun.security.x509.CertificatePoliciesExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "name": "sun.security.x509.ExtendedKeyUsageExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "name": "sun.security.x509.IssuerAlternativeNameExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "name": "sun.security.x509.KeyUsageExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "name": "sun.security.x509.NetscapeCertTypeExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "name": "sun.security.x509.PrivateKeyUsageExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "name": "sun.security.x509.SubjectAlternativeNameExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + }, + { + "name": "sun.security.x509.SubjectKeyIdentifierExtension", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.Boolean", + "java.lang.Object" + ] + } + ] + } +] diff --git a/oauth2_http/resources/META-INF/native-image/native-image.properties b/oauth2_http/resources/META-INF/native-image/native-image.properties new file mode 100644 index 000000000..c7a7fe4db --- /dev/null +++ b/oauth2_http/resources/META-INF/native-image/native-image.properties @@ -0,0 +1 @@ +Args=--enable-url-protocols=https,http diff --git a/owlbot.py b/owlbot.py index c245dee99..610e82700 100644 --- a/owlbot.py +++ b/owlbot.py @@ -32,7 +32,10 @@ "samples/**", ".github/workflows/approve-readme.yaml", ".github/workflows/samples.yaml", + ".github/CODEOWNERS", ".kokoro/nightly/integration.cfg", ".kokoro/presubmit/integration.cfg", + ".kokoro/presubmit/graalvm-native.cfg", + ".kokoro/presubmit/graalvm-native-17.cfg" ] ) diff --git a/pom.xml b/pom.xml index 6cbd21677..43f05d384 100644 --- a/pom.xml +++ b/pom.xml @@ -1,13 +1,16 @@ - + 4.0.0 com.google.auth google-auth-library-parent - 1.15.0 + 1.16.0 pom Google Auth Library for Java Client libraries providing authentication and - authorization to enable calling Google APIs. + authorization to enable calling Google APIs. + https://github.com/googleapis/google-auth-library-java @@ -53,7 +56,8 @@ scm:git:https://github.com/googleapis/google-auth-library-java.git - scm:git:https://github.com/googleapis/google-auth-library-java.git + scm:git:https://github.com/googleapis/google-auth-library-java.git + https://github.com/googleapis/google-auth-library-java @@ -202,7 +206,7 @@ org.apache.maven.plugins maven-dependency-plugin - 3.3.0 + 3.5.0 com.coveo @@ -478,7 +482,7 @@ ${project.artifactId} - 7 + 7 @@ -490,12 +494,12 @@ com.microsoft.doclet.DocFxDoclet false - + ${env.KOKORO_GFILE_DIR}/${docletName}.jar - -outputpath ${outputpath} - -projectname ${projectname} - -excludeclasses ${excludeclasses}: + -outputpath ${outputpath} + -projectname ${projectname} + -excludeclasses ${excludeclasses}: -excludepackages ${excludePackages}: none @@ -507,7 +511,7 @@ false - + diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index 09f07fcda..db1da8a40 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.1.5 + 26.8.0 pom import @@ -50,7 +50,7 @@ com.google.cloud google-iam-admin - 3.1.0 + 3.5.0 diff --git a/versions.txt b/versions.txt index b32643763..d1e798829 100644 --- a/versions.txt +++ b/versions.txt @@ -1,9 +1,9 @@ # Format: # module:released-version:current-version -google-auth-library:1.15.0:1.15.0 -google-auth-library-bom:1.15.0:1.15.0 -google-auth-library-parent:1.15.0:1.15.0 -google-auth-library-appengine:1.15.0:1.15.0 -google-auth-library-credentials:1.15.0:1.15.0 -google-auth-library-oauth2-http:1.15.0:1.15.0 +google-auth-library:1.16.0:1.16.0 +google-auth-library-bom:1.16.0:1.16.0 +google-auth-library-parent:1.16.0:1.16.0 +google-auth-library-appengine:1.16.0:1.16.0 +google-auth-library-credentials:1.16.0:1.16.0 +google-auth-library-oauth2-http:1.16.0:1.16.0