Skip to content

Commit 68e3de9

Browse files
author
Ajay Kannan
committed
Make AppEngineAuthCredentials Restorable
1 parent b5c1cae commit 68e3de9

File tree

2 files changed

+57
-52
lines changed

2 files changed

+57
-52
lines changed

gcloud-java-core/src/main/java/com/google/gcloud/AuthCredentials.java

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.google.auth.oauth2.AccessToken;
2222
import com.google.auth.oauth2.GoogleCredentials;
2323
import com.google.auth.oauth2.ServiceAccountCredentials;
24+
import com.google.common.collect.ImmutableSet;
2425

2526
import java.io.IOException;
2627
import java.io.InputStream;
@@ -37,32 +38,42 @@ 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;
4242

4343
private static class AppEngineCredentials extends GoogleCredentials {
4444

4545
private final Object appIdentityService;
46+
private final Method getAccessToken;
47+
private final Method getAccessTokenResult;
4648
private final Collection<String> scopes;
4749
private final boolean scopesRequired;
4850

49-
AppEngineCredentials() {
51+
AppEngineCredentials(Collection<String> scopes) {
5052
try {
5153
Class<?> factoryClass =
5254
Class.forName("com.google.appengine.api.appidentity.AppIdentityServiceFactory");
5355
Method method = factoryClass.getMethod("getAppIdentityService");
5456
this.appIdentityService = method.invoke(null);
55-
this.scopes = null;
56-
this.scopesRequired = true;
57+
Class<?> serviceClass =
58+
Class.forName("com.google.appengine.api.appidentity.AppIdentityService");
59+
Class<?> tokenResultClass = Class.forName(
60+
"com.google.appengine.api.appidentity.AppIdentityService$GetAccessTokenResult");
61+
this.getAccessTokenResult = serviceClass.getMethod("getAccessToken", Iterable.class);
62+
this.getAccessToken = tokenResultClass.getMethod("getAccessToken");
63+
this.scopes = scopes;
64+
this.scopesRequired = (scopes == null || scopes.isEmpty());
5765
} catch (Exception e) {
5866
throw new RuntimeException("Could not create AppEngineCredentials using reflection.");
5967
}
6068
}
6169

62-
AppEngineCredentials(Collection<String> scopes, Object appIdentityService) {
63-
this.appIdentityService = appIdentityService;
64-
this.scopes = scopes;
65-
this.scopesRequired = (scopes == null || scopes.isEmpty());
70+
AppEngineCredentials(Collection<String> scopes, Object appIdentityService,
71+
Method getAccessToken, Method getAccessTokenResult) {
72+
this.appIdentityService = appIdentityService;
73+
this.getAccessToken = getAccessToken;
74+
this.getAccessTokenResult = getAccessTokenResult;
75+
this.scopes = scopes;
76+
this.scopesRequired = (scopes == null || scopes.isEmpty());
6677
}
6778

6879
/**
@@ -74,13 +85,7 @@ public AccessToken refreshAccessToken() throws IOException {
7485
throw new IOException("AppEngineCredentials requires createScoped call before use.");
7586
}
7687
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);
8288
Object accessTokenResult = getAccessTokenResult.invoke(appIdentityService, scopes);
83-
Method getAccessToken = tokenResultClass.getMethod("getAccessToken");
8489
String accessToken = (String) getAccessToken.invoke(accessTokenResult);
8590
return new AccessToken(accessToken, null);
8691
} catch (Exception e) {
@@ -95,7 +100,8 @@ public boolean createScopedRequired() {
95100

96101
@Override
97102
public GoogleCredentials createScoped(Collection<String> scopes) {
98-
return new AppEngineCredentials(scopes, appIdentityService);
103+
return new AppEngineCredentials(
104+
scopes, appIdentityService, getAccessToken, getAccessTokenResult);
99105
}
100106
}
101107

@@ -104,9 +110,15 @@ private static class AppEngineAuthCredentialsState
104110

105111
private static final long serialVersionUID = 3558563960848658928L;
106112

113+
private final Collection<String> scopes;
114+
115+
private AppEngineAuthCredentialsState(Collection<String> scopes) {
116+
this.scopes = scopes;
117+
}
118+
107119
@Override
108120
public AuthCredentials restore() {
109-
return INSTANCE;
121+
return new AppEngineAuthCredentials(scopes);
110122
}
111123

112124
@Override
@@ -120,14 +132,18 @@ public boolean equals(Object obj) {
120132
}
121133
}
122134

135+
AppEngineAuthCredentials(Collection<String> scopes) {
136+
this.scopes = scopes != null ? ImmutableSet.copyOf(scopes) : null;
137+
}
138+
123139
@Override
124-
protected GoogleCredentials credentials() {
125-
return new AppEngineCredentials();
140+
public GoogleCredentials credentials() {
141+
return new AppEngineCredentials(null);
126142
}
127143

128144
@Override
129145
public RestorableState<AuthCredentials> capture() {
130-
return STATE;
146+
return new AppEngineAuthCredentialsState(scopes);
131147
}
132148
}
133149

@@ -176,7 +192,7 @@ public boolean equals(Object obj) {
176192
}
177193

178194
@Override
179-
protected GoogleCredentials credentials() {
195+
public GoogleCredentials credentials() {
180196
return new ServiceAccountCredentials(null, account, privateKey, null, null);
181197
}
182198

@@ -232,29 +248,20 @@ public boolean equals(Object obj) {
232248
}
233249

234250
@Override
235-
protected GoogleCredentials credentials() {
251+
public GoogleCredentials credentials() {
236252
return googleCredentials;
237253
}
238254

239-
public ServiceAccountAuthCredentials toServiceAccountCredentials() {
240-
if (googleCredentials instanceof ServiceAccountCredentials) {
241-
ServiceAccountCredentials credentials = (ServiceAccountCredentials) googleCredentials;
242-
return new ServiceAccountAuthCredentials(credentials.getClientEmail(),
243-
credentials.getPrivateKey());
244-
}
245-
return null;
246-
}
247-
248255
@Override
249256
public RestorableState<AuthCredentials> capture() {
250257
return STATE;
251258
}
252259
}
253260

254-
protected abstract GoogleCredentials credentials();
261+
public abstract GoogleCredentials credentials();
255262

256263
public static AuthCredentials createForAppEngine() {
257-
return AppEngineAuthCredentials.INSTANCE;
264+
return new AppEngineAuthCredentials(null);
258265
}
259266

260267
/**
@@ -297,11 +304,12 @@ public static ServiceAccountAuthCredentials createFor(String account, PrivateKey
297304
* Account Authentication</a>.
298305
* </p>
299306
*
300-
* @param jsonCredentialStream stream for Service Account Credentials in JSON format
307+
* @param jsonCredentialStream stream for Service Account Credentials or User Credentials in JSON
308+
* format
301309
* @return the credentials instance.
302310
* @throws IOException if the credentials cannot be created from the stream.
303311
*/
304-
public static ServiceAccountAuthCredentials createForJson(InputStream jsonCredentialStream)
312+
public static AuthCredentials createForJson(InputStream jsonCredentialStream)
305313
throws IOException {
306314
GoogleCredentials tempCredentials = GoogleCredentials.fromStream(jsonCredentialStream);
307315
if (tempCredentials instanceof ServiceAccountCredentials) {
@@ -310,9 +318,9 @@ public static ServiceAccountAuthCredentials createForJson(InputStream jsonCreden
310318
return new ServiceAccountAuthCredentials(
311319
tempServiceAccountCredentials.getClientEmail(),
312320
tempServiceAccountCredentials.getPrivateKey());
313-
} else {
314-
throw new IOException(
315-
"The given JSON Credentials Stream is not a service account credential.");
316321
}
322+
throw new IOException(
323+
"The given JSON credentials stream could not be parsed as service account credentials or"
324+
+ " user credentials.");
317325
}
318326
}

gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,26 @@
3131
import static java.nio.charset.StandardCharsets.UTF_8;
3232

3333
import com.google.api.services.storage.model.StorageObject;
34+
import com.google.auth.oauth2.GoogleCredentials;
35+
import com.google.auth.oauth2.ServiceAccountCredentials;
3436
import com.google.common.base.Function;
3537
import com.google.common.base.Functions;
3638
import com.google.common.collect.ImmutableList;
3739
import com.google.common.collect.ImmutableMap;
3840
import com.google.common.collect.Iterables;
3941
import com.google.common.collect.Lists;
4042
import com.google.common.collect.Maps;
41-
import com.google.common.collect.Sets;
4243
import com.google.common.hash.Hashing;
4344
import com.google.common.io.BaseEncoding;
4445
import com.google.common.primitives.Ints;
4546
import com.google.gcloud.AuthCredentials;
46-
import com.google.gcloud.AuthCredentials.ApplicationDefaultAuthCredentials;
4747
import com.google.gcloud.AuthCredentials.ServiceAccountAuthCredentials;
48-
import com.google.gcloud.PageImpl;
4948
import com.google.gcloud.BaseService;
5049
import com.google.gcloud.ExceptionHandler;
5150
import com.google.gcloud.ExceptionHandler.Interceptor;
52-
import com.google.gcloud.RetryHelper.RetryHelperException;
5351
import com.google.gcloud.Page;
52+
import com.google.gcloud.PageImpl;
53+
import com.google.gcloud.RetryHelper.RetryHelperException;
5454
import com.google.gcloud.spi.StorageRpc;
5555
import com.google.gcloud.spi.StorageRpc.RewriteResponse;
5656
import com.google.gcloud.spi.StorageRpc.Tuple;
@@ -71,7 +71,6 @@
7171
import java.util.EnumMap;
7272
import java.util.List;
7373
import java.util.Map;
74-
import java.util.Set;
7574
import java.util.concurrent.Callable;
7675
import java.util.concurrent.TimeUnit;
7776

@@ -566,15 +565,13 @@ public URL signUrl(BlobInfo blobInfo, long duration, TimeUnit unit, SignUrlOptio
566565
ServiceAccountAuthCredentials cred =
567566
(ServiceAccountAuthCredentials) optionMap.get(SignUrlOption.Option.SERVICE_ACCOUNT_CRED);
568567
if (cred == null) {
569-
AuthCredentials serviceCred = this.options().authCredentials();
570-
if (serviceCred instanceof ServiceAccountAuthCredentials) {
571-
cred = (ServiceAccountAuthCredentials) serviceCred;
572-
} else {
573-
if (serviceCred instanceof ApplicationDefaultAuthCredentials) {
574-
cred = ((ApplicationDefaultAuthCredentials) serviceCred).toServiceAccountCredentials();
575-
}
576-
}
577-
checkArgument(cred != null, "Signing key was not provided and could not be derived");
568+
AuthCredentials authCredentials = this.options().authCredentials();
569+
GoogleCredentials serviceCred =
570+
authCredentials != null ? authCredentials.credentials() : null;
571+
checkArgument(
572+
serviceCred instanceof ServiceAccountCredentials,
573+
"Signing key was not provided and could not be derived");
574+
cred = (ServiceAccountAuthCredentials) authCredentials;
578575
}
579576
// construct signature - see https://cloud.google.com/storage/docs/access-control#Signed-URLs
580577
StringBuilder stBuilder = new StringBuilder();

0 commit comments

Comments
 (0)