Repository navigation
Commit dcb29b0
feat(oauth2): support certificate-bound OAuth2 tokens and mTLS rotation for Workload Identity Federation (#14781)
### Summary
Merges the `oauth2-bound-tokens` feature branch into `main`, adding
end-to-end support for certificate-bound OAuth 2.0 tokens and automatic
mTLS certificate rotation in Workload Identity Federation
(`IdentityPoolCredentials` and `ImpersonatedCredentials`).
#### Included Feature Branch PRs
- #13955 — `feat(oauth2): Extract actor tokens for cert-bound OAuth2 STS
exchange`
- #14212 — `feat(oauth2): implement IAM impersonation mTLS transport
pinning and 401 recovery`
- #14220 — `test(oauth2): add mTLS in-process socket tests and live GCP
WIF integration tests`
- #14430 — `feat(oauth2): support non-mTLS token URLs and unbound actor
tokens in IdentityPoolCredentials`
- #14554 — `test(auth): enable mTLS and actor_token WIF integration
tests by default`
#### Key Capabilities
- **Actor Token Support for Hybrid Certificate-Bound WIF
(`IdentityPoolActorTokenSupplier`,
`FileIdentityPoolSubjectTokenSupplier`)**:
- Supports extracting both a primary X.509 leaf certificate subject
token and a secondary file-sourced `actor_token` (text or JSON via
`actor_token_field_name` and `actor_token_type`) for STS token exchange.
- Caches file-sourced tokens using file metadata (`mtime`, size, file
key) and JWT `exp` claims with a 5-minute expiration margin to avoid
redundant disk reads.
- **Per-Cycle mTLS Transport Pinning & Certificate Rotation
(`IdentityPoolCredentials`, `ImpersonatedCredentials`,
`MtlsHttpTransportFactory`)**:
- Snapshots the `KeyStore` once per refresh cycle so leaf certificate
extraction, the STS token exchange, and downstream IAM Service Account
impersonation (`generateAccessToken` / `generateIdToken`) share the
exact same certificate and private key snapshot.
- Automatically recovers from `401 Unauthorized`, OAuth `invalid_grant`,
and transient TLS/KeyStore load failures during non-atomic split
cert/key writes by reloading the `KeyStore` once and retrying when a
certificate change is detected (`OAuth2Utils.hasCertificateChanged`).
- Supports standalone `ImpersonatedCredentials` configured with
`MtlsProvider` as well as delegated `ImpersonatedCredentials` chains.
- **Test Coverage**:
- Comprehensive unit tests across `IdentityPoolCredentialsTest`,
`ImpersonatedCredentialsTest`,
`FileIdentityPoolSubjectTokenSupplierTest`,
`MtlsHttpTransportFactoryTest`, `OAuth2UtilsTest`, and
`OAuthExceptionTest`.
- In-process mTLS socket tests (`MtlsPipelineLocalTest`) and live GCP
Workload Identity Federation integration tests
(`ITWorkloadIdentityFederationTest`).
### Manual & Live Verification
End-to-end live GCP and real-TLS socket fault-injection testing was
executed against `oauth2-bound-tokens` (`65d592bd783`):
- **Full verification report, logs, and test harness**:
https://paste.googleplex.com/6755399436525184
- **Scenarios verified (15 / 15 passed)**:
1. **Live Direct mTLS STS Exchange (`sts.mtls.googleapis.com`)**:
File-based JSON `subject_token` + `actor_token` with RFC 8705
`cnf.x5t#S256` certificate binding and atomic single-supplier file
reads.
2. **Serialization Round-Trip (`readObject`) + `createScoped()`**:
Deserialization of `IdentityPoolCredentials` with mTLS state
reconstruction across multiple live STS refresh cycles.
3. **Full 3-Hop Live mTLS Chain (`STS mTLS` -> `IAM Impersonation mTLS`
-> `GCS mTLS`)**: Cert-bound workload + actor token exchange at
`sts.mtls.googleapis.com`, service account impersonation at
`iamcredentials.mtls.googleapis.com`, and bucket access at
`storage.mtls.googleapis.com` (`HTTP 200`).
4. **Programmatic Builder (`Suppliers` + `MtlsHttpTransportFactory`)
Live 3-Hop mTLS**: End-to-end `STS mTLS` -> `IAM mTLS` -> `GCS mTLS`
(`HTTP 200`) and verification of `OAuth2Utils` mTLS helpers
(`hasMtlsKeyStore`, `isKeylessMtlsTransportFactory`,
`isDefaultOrMtlsTransportFactory`).
5. **Non-mTLS Unbound Actor Token over Public Endpoints**: Unbound
`subject_token` + `actor_token` exchange over public
`sts.googleapis.com` -> `iamcredentials.googleapis.com` ->
`storage.googleapis.com` (`HTTP 200`).
6. **X.509 Certificate Workload Identity Federation**: Leaf certificate
extraction and `trust_chain` handshake against `sts.mtls.googleapis.com`
via `CertificateIdentityPoolSubjectTokenSupplier`.
7. **`PluggableAuthCredentials` Impersonation Transport
Reconciliation**: Rebuilding `PluggableAuthCredentials` with a custom
`HttpTransportFactory` and verifying both STS and
`ImpersonatedCredentials` use the reconciled transport against live STS,
IAM, and GCS (`HTTP 200`).
8. **Review Feedback Edge Cases**:
`FileIdentityPoolSubjectTokenSupplier` TEXT format subject/actor token
handling and `OAuthException.createFromJsonErrorResponse` parsing across
live STS 400 errors, nested `google.rpc.Status` JSON, and empty-body
HTTP error fallbacks.
9. **Real-TLS Socket Fault Injection**: Mid-cycle cert rotation pinning
between STS and IAM, `401 Unauthorized` IAM recovery (both fresh and
cached STS token eviction), `400 invalid_grant` STS cert rotation
recovery, and 8-thread concurrent mTLS refresh.
---------
Co-authored-by: Jin Seop Kim <jinseop@google.com>
Co-authored-by: Blake Li <blakeli@google.com>
Co-authored-by: Sakthivel Subramanian <179120858+sakthivelmanii@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>1 parent 0bae268 commit dcb29b0
34 files changed
Lines changed: 9622 additions & 163 deletions
File tree
- google-auth-library-java
- oauth2_http
- javatests/com/google/auth
- mtls
- oauth2
- java/com/google/auth
- mtls
- oauth2
- testresources/mtls
- scripts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| 37 | + | |
37 | 38 | | |
38 | 39 | | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
39 | 43 | | |
40 | 44 | | |
| 45 | + | |
41 | 46 | | |
42 | 47 | | |
43 | 48 | | |
| |||
49 | 54 | | |
50 | 55 | | |
51 | 56 | | |
52 | | - | |
53 | | - | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
54 | 76 | | |
55 | 77 | | |
56 | 78 | | |
| |||
61 | 83 | | |
62 | 84 | | |
63 | 85 | | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
64 | 126 | | |
65 | 127 | | |
66 | 128 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
120 | 120 | | |
121 | 121 | | |
122 | 122 | | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
123 | 133 | | |
124 | 134 | | |
125 | 135 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
| 45 | + | |
| 46 | + | |
45 | 47 | | |
46 | 48 | | |
47 | 49 | | |
48 | 50 | | |
49 | 51 | | |
50 | 52 | | |
51 | 53 | | |
| 54 | + | |
52 | 55 | | |
53 | 56 | | |
54 | 57 | | |
| 58 | + | |
55 | 59 | | |
56 | 60 | | |
57 | 61 | | |
| |||
63 | 67 | | |
64 | 68 | | |
65 | 69 | | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
66 | 73 | | |
67 | 74 | | |
68 | 75 | | |
| |||
92 | 99 | | |
93 | 100 | | |
94 | 101 | | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
95 | 130 | | |
96 | 131 | | |
97 | 132 | | |
| |||
131 | 166 | | |
132 | 167 | | |
133 | 168 | | |
134 | | - | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
135 | 179 | | |
136 | 180 | | |
137 | 181 | | |
138 | 182 | | |
139 | 183 | | |
140 | | - | |
141 | | - | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
142 | 190 | | |
143 | 191 | | |
144 | 192 | | |
| |||
238 | 286 | | |
239 | 287 | | |
240 | 288 | | |
241 | | - | |
| 289 | + | |
242 | 290 | | |
243 | 291 | | |
244 | 292 | | |
| |||
0 commit comments