-
Notifications
You must be signed in to change notification settings - Fork 1.2k
feat(oauth2): Extract actor tokens for cert-bound OAuth2 STS exchange #13955
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
macastelaz
merged 28 commits into
googleapis:oauth2-bound-tokens
from
macastelaz:cert-bound-oauth-part2
Sep 17, 2026
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
a4813a2
feat(oauth2): Extract actor tokens for cert-bound OAuth2 STS exchange
macastelaz c739b37
fix(oauth2): share parsed JSON cache between subject and actor tokens
macastelaz 1a32e6f
feat(oauth2): fail loudly if actor token requested against non-file s…
macastelaz c42bd53
feat(oauth2): relax actor token mTLS URL validation to .mtls. for PSC…
macastelaz 803dd53
test(oauth2): add tests for strict actor token exceptions
macastelaz cbcce28
chore(oauth2): update copyright year to 2026 for new files
macastelaz 745d26b
Address architectural review feedback from paste 5381957298028544
macastelaz 48c29d2
Fix trailing whitespace and formatting in IdentityPoolCredentialsTest
macastelaz 178d71d
test: use real MtlsHttpTransportFactory instead of mock to fix Java 8…
macastelaz c22c521
Fix line width formatting in ExternalAccountCredentialsTest
macastelaz 1aa5036
fix(oauth2): Address review findings from paste 5644036370202624
macastelaz 474f0d7
fix(oauth2): preserve shared FileIdentityPoolTokenSupplier cache in B…
macastelaz 62b8bd5
test(oauth2): expand unit test coverage across IdentityPoolCredential…
macastelaz 3288350
Address PR #13955 review comments
macastelaz 8dbaa6f
Review session improvements
macastelaz 48ee795
chore: fix google-java-format compliance
macastelaz 728d654
Address review comments for cert-bound OAuth Part 2
macastelaz 483cfe0
test(oauth2): rename refreshAccessToken_useSameCertForStsAndIam to re…
macastelaz d9b26e4
fix(oauth2): address review comments on PR #13955
macastelaz 2b8a0e7
fix(oauth2): rely on transport mTLS validation rather than URL string…
macastelaz e6a4797
fix(oauth2): validate plain public endpoints when actor tokens are co…
macastelaz 3f95ff5
fix(oauth2): implement Serializable in MtlsHttpTransportFactory
macastelaz f3dd3bf
fix(oauth2): address PR #13955 review feedback on mTLS and token supp…
macastelaz f853f76
fix(oauth2): clarify MtlsHttpTransportFactory serialization Javadoc a…
macastelaz 8ab1856
Merge remote-tracking branch 'origin/main' into cert-bound-oauth-part2
macastelaz bd0dd45
fix(oauth2): address review feedback on MtlsHttpTransportFactory Java…
macastelaz 33bad8a
fix(oauth2): honor custom HttpTransportFactory in refreshAccessToken,…
macastelaz 1052410
fix(oauth2): refresh MtlsHttpTransportFactory snapshot on createScope…
macastelaz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,10 +34,15 @@ | |
| import com.google.api.client.http.javanet.NetHttpTransport; | ||
| import com.google.api.core.InternalApi; | ||
| import com.google.auth.http.HttpTransportFactory; | ||
| import java.io.Serializable; | ||
| import java.security.GeneralSecurityException; | ||
| import java.security.KeyStore; | ||
| import java.security.KeyStoreException; | ||
| import java.security.cert.Certificate; | ||
| import java.util.Enumeration; | ||
| import java.util.Objects; | ||
| import org.jspecify.annotations.NullMarked; | ||
| import org.jspecify.annotations.Nullable; | ||
|
|
||
| /** | ||
| * An HttpTransportFactory that creates {@link NetHttpTransport} instances configured for mTLS | ||
|
|
@@ -49,8 +54,25 @@ | |
| */ | ||
| @NullMarked | ||
| @InternalApi | ||
| public class MtlsHttpTransportFactory implements HttpTransportFactory { | ||
| private final KeyStore mtlsKeyStore; | ||
| public class MtlsHttpTransportFactory implements HttpTransportFactory, Serializable { | ||
| private static final long serialVersionUID = 1L; | ||
| private final transient @Nullable KeyStore mtlsKeyStore; | ||
| private final transient boolean hasKeyStore; | ||
|
|
||
| /** | ||
| * Default no-arg constructor creating an instance without a KeyStore ({@code hasKeyStore() == | ||
| * false}). This constructor is invoked reflectively by {@code | ||
| * ExternalAccountCredentials.readObject()} during deserialization (since {@code transportFactory} | ||
| * is transient on {@code ExternalAccountCredentials}), after which {@code | ||
| * IdentityPoolCredentials.readObject()} reconstructs {@code X509Provider} from the serialized | ||
| * certificate configuration and replaces the transport factory with {@link | ||
| * #MtlsHttpTransportFactory(KeyStore)}. Not intended for direct use; callers configuring mTLS | ||
| * should use {@link #MtlsHttpTransportFactory(KeyStore)}. | ||
| */ | ||
| public MtlsHttpTransportFactory() { | ||
| this.mtlsKeyStore = null; | ||
| this.hasKeyStore = false; | ||
| } | ||
|
|
||
| /** | ||
| * Constructs a factory for mTLS transports. | ||
|
|
@@ -61,6 +83,41 @@ | |
| */ | ||
| public MtlsHttpTransportFactory(KeyStore mtlsKeyStore) { | ||
| this.mtlsKeyStore = Objects.requireNonNull(mtlsKeyStore, "mtlsKeyStore cannot be null"); | ||
| this.hasKeyStore = checkHasKeyStore(this.mtlsKeyStore); | ||
| } | ||
|
|
||
| /** | ||
| * Returns whether this factory was constructed with a non-null {@link KeyStore} containing client | ||
| * certificates for mTLS. A factory created via the no-arg constructor (e.g. during | ||
| * deserialization), with an empty KeyStore, or with a KeyStore containing only trusted CA | ||
| * certificates (without a private key entry and certificate chain) will return {@code false}. | ||
| */ | ||
| public boolean hasKeyStore() { | ||
|
Check warning on line 95 in google-auth-library-java/oauth2_http/java/com/google/auth/mtls/MtlsHttpTransportFactory.java
|
||
| return this.hasKeyStore; | ||
| } | ||
|
|
||
| private static boolean checkHasKeyStore(@Nullable KeyStore keyStore) { | ||
| if (keyStore == null) { | ||
| return false; | ||
| } | ||
| try { | ||
| Enumeration<String> aliases = keyStore.aliases(); | ||
| if (aliases == null) { | ||
| return false; | ||
| } | ||
| while (aliases.hasMoreElements()) { | ||
| String alias = aliases.nextElement(); | ||
| if (keyStore.isKeyEntry(alias)) { | ||
| Certificate[] chain = keyStore.getCertificateChain(alias); | ||
| if (chain != null && chain.length > 0) { | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| return false; | ||
| } catch (KeyStoreException e) { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.