2121import com .google .auth .oauth2 .AccessToken ;
2222import com .google .auth .oauth2 .GoogleCredentials ;
2323import com .google .auth .oauth2 .ServiceAccountCredentials ;
24+ import com .google .common .collect .ImmutableSet ;
2425
2526import java .io .IOException ;
2627import java .io .InputStream ;
@@ -37,12 +38,14 @@ public abstract class AuthCredentials implements Restorable<AuthCredentials> {
3738
3839 private static class AppEngineAuthCredentials extends AuthCredentials {
3940
40- private static final AuthCredentials INSTANCE = new AppEngineAuthCredentials () ;
41- private static final AppEngineAuthCredentialsState STATE = new AppEngineAuthCredentialsState () ;
41+ private final Collection < String > scopes ;
42+ private final boolean scopesRequired ;
4243
4344 private static class AppEngineCredentials extends GoogleCredentials {
4445
4546 private final Object appIdentityService ;
47+ private final Method getAccessToken ;
48+ private final Method getAccessTokenResult ;
4649 private final Collection <String > scopes ;
4750 private final boolean scopesRequired ;
4851
@@ -52,17 +55,26 @@ private static class AppEngineCredentials extends GoogleCredentials {
5255 Class .forName ("com.google.appengine.api.appidentity.AppIdentityServiceFactory" );
5356 Method method = factoryClass .getMethod ("getAppIdentityService" );
5457 this .appIdentityService = method .invoke (null );
58+ Class <?> serviceClass =
59+ Class .forName ("com.google.appengine.api.appidentity.AppIdentityService" );
60+ Class <?> tokenResultClass = Class .forName (
61+ "com.google.appengine.api.appidentity.AppIdentityService$GetAccessTokenResult" );
62+ this .getAccessTokenResult = serviceClass .getMethod ("getAccessToken" , Iterable .class );
63+ this .getAccessToken = tokenResultClass .getMethod ("getAccessToken" );
5564 this .scopes = null ;
5665 this .scopesRequired = true ;
5766 } catch (Exception e ) {
5867 throw new RuntimeException ("Could not create AppEngineCredentials using reflection." );
5968 }
6069 }
6170
62- AppEngineCredentials (Collection <String > scopes , Object appIdentityService ) {
63- this .appIdentityService = appIdentityService ;
64- this .scopes = scopes ;
65- this .scopesRequired = (scopes == null || scopes .isEmpty ());
71+ AppEngineCredentials (Collection <String > scopes , Object appIdentityService ,
72+ Method getAccessToken , Method getAccessTokenResult ) {
73+ this .appIdentityService = appIdentityService ;
74+ this .getAccessToken = getAccessToken ;
75+ this .getAccessTokenResult = getAccessTokenResult ;
76+ this .scopes = scopes ;
77+ this .scopesRequired = (scopes == null || scopes .isEmpty ());
6678 }
6779
6880 /**
@@ -74,13 +86,7 @@ public AccessToken refreshAccessToken() throws IOException {
7486 throw new IOException ("AppEngineCredentials requires createScoped call before use." );
7587 }
7688 try {
77- Class <?> serviceClass =
78- Class .forName ("com.google.appengine.api.appidentity.AppIdentityService" );
79- Class <?> tokenResultClass = Class .forName (
80- "com.google.appengine.api.appidentity.AppIdentityService$GetAccessTokenResult" );
81- Method getAccessTokenResult = serviceClass .getMethod ("getAccessToken" , Iterable .class );
8289 Object accessTokenResult = getAccessTokenResult .invoke (appIdentityService , scopes );
83- Method getAccessToken = tokenResultClass .getMethod ("getAccessToken" );
8490 String accessToken = (String ) getAccessToken .invoke (accessTokenResult );
8591 return new AccessToken (accessToken , null );
8692 } catch (Exception e ) {
@@ -95,7 +101,8 @@ public boolean createScopedRequired() {
95101
96102 @ Override
97103 public GoogleCredentials createScoped (Collection <String > scopes ) {
98- return new AppEngineCredentials (scopes , appIdentityService );
104+ return new AppEngineCredentials (
105+ scopes , appIdentityService , getAccessToken , getAccessTokenResult );
99106 }
100107 }
101108
@@ -104,9 +111,17 @@ private static class AppEngineAuthCredentialsState
104111
105112 private static final long serialVersionUID = 3558563960848658928L ;
106113
114+ private final boolean scopesRequired ;
115+ private final Collection <String > scopes ;
116+
117+ private AppEngineAuthCredentialsState (Collection <String > scopes , boolean scopesRequired ) {
118+ this .scopes = scopes ;
119+ this .scopesRequired = scopesRequired ;
120+ }
121+
107122 @ Override
108123 public AuthCredentials restore () {
109- return INSTANCE ;
124+ return new AppEngineAuthCredentials ( scopes , scopesRequired ) ;
110125 }
111126
112127 @ Override
@@ -120,14 +135,19 @@ public boolean equals(Object obj) {
120135 }
121136 }
122137
138+ AppEngineAuthCredentials (Collection <String > scopes , boolean scopesRequired ) {
139+ this .scopes = scopes != null ? ImmutableSet .copyOf (checkNotNull (scopes )) : null ;
140+ this .scopesRequired = scopesRequired ;
141+ }
142+
123143 @ Override
124- protected GoogleCredentials credentials () {
144+ public GoogleCredentials credentials () {
125145 return new AppEngineCredentials ();
126146 }
127147
128148 @ Override
129149 public RestorableState <AuthCredentials > capture () {
130- return STATE ;
150+ return new AppEngineAuthCredentialsState ( scopes , scopesRequired ) ;
131151 }
132152 }
133153
@@ -176,7 +196,7 @@ public boolean equals(Object obj) {
176196 }
177197
178198 @ Override
179- protected GoogleCredentials credentials () {
199+ public GoogleCredentials credentials () {
180200 return new ServiceAccountCredentials (null , account , privateKey , null , null );
181201 }
182202
@@ -232,7 +252,7 @@ public boolean equals(Object obj) {
232252 }
233253
234254 @ Override
235- protected GoogleCredentials credentials () {
255+ public GoogleCredentials credentials () {
236256 return googleCredentials ;
237257 }
238258
@@ -251,10 +271,10 @@ public RestorableState<AuthCredentials> capture() {
251271 }
252272 }
253273
254- protected abstract GoogleCredentials credentials ();
274+ public abstract GoogleCredentials credentials ();
255275
256276 public static AuthCredentials createForAppEngine () {
257- return AppEngineAuthCredentials . INSTANCE ;
277+ return new AppEngineAuthCredentials ( null , true ) ;
258278 }
259279
260280 /**
@@ -297,11 +317,12 @@ public static ServiceAccountAuthCredentials createFor(String account, PrivateKey
297317 * Account Authentication</a>.
298318 * </p>
299319 *
300- * @param jsonCredentialStream stream for Service Account Credentials in JSON format
320+ * @param jsonCredentialStream stream for Service Account Credentials or User Credentials in JSON
321+ * format
301322 * @return the credentials instance.
302323 * @throws IOException if the credentials cannot be created from the stream.
303324 */
304- public static ServiceAccountAuthCredentials createForJson (InputStream jsonCredentialStream )
325+ public static AuthCredentials createForJson (InputStream jsonCredentialStream )
305326 throws IOException {
306327 GoogleCredentials tempCredentials = GoogleCredentials .fromStream (jsonCredentialStream );
307328 if (tempCredentials instanceof ServiceAccountCredentials ) {
@@ -310,9 +331,9 @@ public static ServiceAccountAuthCredentials createForJson(InputStream jsonCreden
310331 return new ServiceAccountAuthCredentials (
311332 tempServiceAccountCredentials .getClientEmail (),
312333 tempServiceAccountCredentials .getPrivateKey ());
313- } else {
314- throw new IOException (
315- "The given JSON Credentials Stream is not a service account credential." );
316334 }
335+ throw new IOException (
336+ "The given JSON credentials stream could not be parsed as service account credentials or"
337+ + " user credentials." );
317338 }
318339}
0 commit comments