3737import com .google .api .client .http .HttpResponse ;
3838import com .google .api .client .json .GenericJson ;
3939import com .google .api .client .json .JsonObjectParser ;
40- import com .google .auth .http .HttpTransportFactory ;
4140import com .google .auth .oauth2 .IdentityPoolCredentials .IdentityPoolCredentialSource .CredentialFormatType ;
4241import com .google .common .io .CharStreams ;
4342import java .io .BufferedReader ;
5453import java .util .Collection ;
5554import java .util .HashMap ;
5655import java .util .Map ;
56+ import java .util .regex .Pattern ;
5757import javax .annotation .Nullable ;
5858
5959/**
@@ -155,39 +155,37 @@ private boolean hasHeaders() {
155155
156156 private final IdentityPoolCredentialSource identityPoolCredentialSource ;
157157
158- /**
159- * Internal constructor. See {@link
160- * ExternalAccountCredentials#ExternalAccountCredentials(HttpTransportFactory, String, String,
161- * String, CredentialSource, String, String, String, String, String, Collection,
162- * EnvironmentProvider)}
163- */
164- IdentityPoolCredentials (
165- HttpTransportFactory transportFactory ,
166- String audience ,
167- String subjectTokenType ,
168- String tokenUrl ,
169- IdentityPoolCredentialSource credentialSource ,
170- @ Nullable String tokenInfoUrl ,
171- @ Nullable String serviceAccountImpersonationUrl ,
172- @ Nullable String quotaProjectId ,
173- @ Nullable String clientId ,
174- @ Nullable String clientSecret ,
175- @ Nullable Collection <String > scopes ,
176- @ Nullable EnvironmentProvider environmentProvider ) {
158+ // This is used for Workforce Pools. It is passed to STS during token exchange in the
159+ // `options` param and will be embedded in the token by STS.
160+ @ Nullable private String workforcePoolUserProject ;
161+
162+ /** Internal constructor. See {@link Builder}. */
163+ IdentityPoolCredentials (Builder builder ) {
177164 super (
178- transportFactory ,
179- audience ,
180- subjectTokenType ,
181- tokenUrl ,
182- credentialSource ,
183- tokenInfoUrl ,
184- serviceAccountImpersonationUrl ,
185- quotaProjectId ,
186- clientId ,
187- clientSecret ,
188- scopes ,
189- environmentProvider );
190- this .identityPoolCredentialSource = credentialSource ;
165+ builder .transportFactory ,
166+ builder .audience ,
167+ builder .subjectTokenType ,
168+ builder .tokenUrl ,
169+ builder .credentialSource ,
170+ builder .tokenInfoUrl ,
171+ builder .serviceAccountImpersonationUrl ,
172+ builder .quotaProjectId ,
173+ builder .clientId ,
174+ builder .clientSecret ,
175+ builder .scopes ,
176+ builder .environmentProvider );
177+ this .identityPoolCredentialSource = (IdentityPoolCredentialSource ) builder .credentialSource ;
178+ this .workforcePoolUserProject = builder .workforcePoolUserProject ;
179+
180+ if (workforcePoolUserProject != null && !isWorkforcePoolConfiguration ()) {
181+ throw new IllegalArgumentException (
182+ "The workforce_pool_user_project parameter should only be provided for a Workforce Pool configuration." );
183+ }
184+ }
185+
186+ @ Nullable
187+ public String getWorkforcePoolUserProject () {
188+ return workforcePoolUserProject ;
191189 }
192190
193191 @ Override
@@ -202,6 +200,15 @@ public AccessToken refreshAccessToken() throws IOException {
202200 stsTokenExchangeRequest .setScopes (new ArrayList <>(scopes ));
203201 }
204202
203+ // If this credential was initialized with a Workforce configuration then the
204+ // workforcePoolUserProject must passed to STS via the the internal options param.
205+ if (isWorkforcePoolConfiguration ()) {
206+ GenericJson options = new GenericJson ();
207+ options .setFactory (OAuth2Utils .JSON_FACTORY );
208+ options .put ("userProject" , workforcePoolUserProject );
209+ stsTokenExchangeRequest .setInternalOptions (options .toString ());
210+ }
211+
205212 return exchangeExternalCredentialForAccessToken (stsTokenExchangeRequest .build ());
206213 }
207214
@@ -269,22 +276,24 @@ private String getSubjectTokenFromMetadataServer() throws IOException {
269276 }
270277 }
271278
279+ /**
280+ * Returns whether or not the current configuration is for Workforce Pools (which enable 3p user
281+ * identities, rather than workloads).
282+ */
283+ public boolean isWorkforcePoolConfiguration () {
284+ Pattern workforceAudiencePattern =
285+ Pattern .compile (
286+ "^//iam.googleapis.com/projects/.+/locations/.+/workforcePools/.+/providers/.+$" );
287+ return workforcePoolUserProject != null
288+ && !workforcePoolUserProject .isEmpty ()
289+ && workforceAudiencePattern .matcher (getAudience ()).matches ();
290+ }
291+
272292 /** Clones the IdentityPoolCredentials with the specified scopes. */
273293 @ Override
274294 public IdentityPoolCredentials createScoped (Collection <String > newScopes ) {
275295 return new IdentityPoolCredentials (
276- transportFactory ,
277- getAudience (),
278- getSubjectTokenType (),
279- getTokenUrl (),
280- identityPoolCredentialSource ,
281- getTokenInfoUrl (),
282- getServiceAccountImpersonationUrl (),
283- getQuotaProjectId (),
284- getClientId (),
285- getClientSecret (),
286- newScopes ,
287- getEnvironmentProvider ());
296+ (IdentityPoolCredentials .Builder ) newBuilder (this ).setScopes (newScopes ));
288297 }
289298
290299 public static Builder newBuilder () {
@@ -297,27 +306,23 @@ public static Builder newBuilder(IdentityPoolCredentials identityPoolCredentials
297306
298307 public static class Builder extends ExternalAccountCredentials .Builder {
299308
309+ @ Nullable private String workforcePoolUserProject ;
310+
300311 Builder () {}
301312
302313 Builder (IdentityPoolCredentials credentials ) {
303314 super (credentials );
315+ setWorkforcePoolUserProject (credentials .getWorkforcePoolUserProject ());
316+ }
317+
318+ public Builder setWorkforcePoolUserProject (String workforcePoolUserProject ) {
319+ this .workforcePoolUserProject = workforcePoolUserProject ;
320+ return this ;
304321 }
305322
306323 @ Override
307324 public IdentityPoolCredentials build () {
308- return new IdentityPoolCredentials (
309- transportFactory ,
310- audience ,
311- subjectTokenType ,
312- tokenUrl ,
313- (IdentityPoolCredentialSource ) credentialSource ,
314- tokenInfoUrl ,
315- serviceAccountImpersonationUrl ,
316- quotaProjectId ,
317- clientId ,
318- clientSecret ,
319- scopes ,
320- environmentProvider );
325+ return new IdentityPoolCredentials (this );
321326 }
322327 }
323328}
0 commit comments