1818
1919import static com .google .common .base .Preconditions .checkNotNull ;
2020
21- import com .google .api .client .googleapis .auth .oauth2 .GoogleCredential ;
22- import com .google .api .client .googleapis .compute .ComputeCredential ;
23- import com .google .api .client .googleapis .extensions .appengine .auth .oauth2 .AppIdentityCredential ;
24- import com .google .api .client .googleapis .javanet .GoogleNetHttpTransport ;
25- import com .google .api .client .http .HttpRequestInitializer ;
26- import com .google .api .client .http .HttpTransport ;
27- import com .google .api .client .http .javanet .NetHttpTransport ;
28- import com .google .api .client .json .jackson .JacksonFactory ;
29- import com .google .auth .http .HttpCredentialsAdapter ;
21+ import com .google .auth .oauth2 .AccessToken ;
3022import com .google .auth .oauth2 .GoogleCredentials ;
23+ import com .google .auth .oauth2 .ServiceAccountCredentials ;
3124
3225import java .io .IOException ;
3326import java .io .InputStream ;
3427import java .io .Serializable ;
35- import java .security . GeneralSecurityException ;
28+ import java .lang . reflect . Method ;
3629import java .security .PrivateKey ;
30+ import java .util .Collection ;
3731import java .util .Objects ;
38- import java .util .Set ;
3932
4033/**
4134 * Credentials for accessing Google Cloud services.
@@ -45,8 +38,67 @@ public abstract class AuthCredentials implements Restorable<AuthCredentials> {
4538 private static class AppEngineAuthCredentials extends AuthCredentials {
4639
4740 private static final AuthCredentials INSTANCE = new AppEngineAuthCredentials ();
48- private static final AppEngineAuthCredentialsState STATE =
49- new AppEngineAuthCredentialsState ();
41+ private static final AppEngineAuthCredentialsState STATE = new AppEngineAuthCredentialsState ();
42+
43+ private static class AppEngineCredentials extends GoogleCredentials {
44+
45+ private final Object appIdentityService ;
46+ private final Method getAccessToken ;
47+ private final Method getAccessTokenResult ;
48+ private final Collection <String > scopes ;
49+
50+ AppEngineCredentials () {
51+ try {
52+ Class <?> factoryClass =
53+ Class .forName ("com.google.appengine.api.appidentity.AppIdentityServiceFactory" );
54+ Method method = factoryClass .getMethod ("getAppIdentityService" );
55+ this .appIdentityService = method .invoke (null );
56+ Class <?> serviceClass =
57+ Class .forName ("com.google.appengine.api.appidentity.AppIdentityService" );
58+ Class <?> tokenResultClass = Class .forName (
59+ "com.google.appengine.api.appidentity.AppIdentityService$GetAccessTokenResult" );
60+ this .getAccessTokenResult = serviceClass .getMethod ("getAccessToken" , Iterable .class );
61+ this .getAccessToken = tokenResultClass .getMethod ("getAccessToken" );
62+ this .scopes = null ;
63+ } catch (Exception e ) {
64+ throw new RuntimeException ("Could not create AppEngineCredentials." , e );
65+ }
66+ }
67+
68+ AppEngineCredentials (Collection <String > scopes , AppEngineCredentials unscoped ) {
69+ this .appIdentityService = unscoped .appIdentityService ;
70+ this .getAccessToken = unscoped .getAccessToken ;
71+ this .getAccessTokenResult = unscoped .getAccessTokenResult ;
72+ this .scopes = scopes ;
73+ }
74+
75+ /**
76+ * Refresh the access token by getting it from the App Identity service
77+ */
78+ @ Override
79+ public AccessToken refreshAccessToken () throws IOException {
80+ if (createScopedRequired ()) {
81+ throw new IOException ("AppEngineCredentials requires createScoped call before use." );
82+ }
83+ try {
84+ Object accessTokenResult = getAccessTokenResult .invoke (appIdentityService , scopes );
85+ String accessToken = (String ) getAccessToken .invoke (accessTokenResult );
86+ return new AccessToken (accessToken , null );
87+ } catch (Exception e ) {
88+ throw new IOException ("Could not get the access token." , e );
89+ }
90+ }
91+
92+ @ Override
93+ public boolean createScopedRequired () {
94+ return scopes == null || scopes .isEmpty ();
95+ }
96+
97+ @ Override
98+ public GoogleCredentials createScoped (Collection <String > scopes ) {
99+ return new AppEngineCredentials (scopes , this );
100+ }
101+ }
50102
51103 private static class AppEngineAuthCredentialsState
52104 implements RestorableState <AuthCredentials >, Serializable {
@@ -70,9 +122,8 @@ public boolean equals(Object obj) {
70122 }
71123
72124 @ Override
73- protected HttpRequestInitializer httpRequestInitializer (HttpTransport transport ,
74- Set <String > scopes ) {
75- return new AppIdentityCredential (scopes );
125+ public GoogleCredentials credentials () {
126+ return new AppEngineCredentials ();
76127 }
77128
78129 @ Override
@@ -86,8 +137,6 @@ public static class ServiceAccountAuthCredentials extends AuthCredentials {
86137 private final String account ;
87138 private final PrivateKey privateKey ;
88139
89- private static final AuthCredentials NO_CREDENTIALS = new ServiceAccountAuthCredentials ();
90-
91140 private static class ServiceAccountAuthCredentialsState
92141 implements RestorableState <AuthCredentials >, Serializable {
93142
@@ -103,9 +152,6 @@ private ServiceAccountAuthCredentialsState(String account, PrivateKey privateKey
103152
104153 @ Override
105154 public AuthCredentials restore () {
106- if (account == null && privateKey == null ) {
107- return NO_CREDENTIALS ;
108- }
109155 return new ServiceAccountAuthCredentials (account , privateKey );
110156 }
111157
@@ -130,23 +176,9 @@ public boolean equals(Object obj) {
130176 this .privateKey = checkNotNull (privateKey );
131177 }
132178
133- ServiceAccountAuthCredentials () {
134- account = null ;
135- privateKey = null ;
136- }
137-
138179 @ Override
139- protected HttpRequestInitializer httpRequestInitializer (
140- HttpTransport transport , Set <String > scopes ) {
141- GoogleCredential .Builder builder = new GoogleCredential .Builder ()
142- .setTransport (transport )
143- .setJsonFactory (new JacksonFactory ());
144- if (privateKey != null ) {
145- builder .setServiceAccountPrivateKey (privateKey );
146- builder .setServiceAccountId (account );
147- builder .setServiceAccountScopes (scopes );
148- }
149- return builder .build ();
180+ public ServiceAccountCredentials credentials () {
181+ return new ServiceAccountCredentials (null , account , privateKey , null , null );
150182 }
151183
152184 public String account () {
@@ -163,56 +195,7 @@ public RestorableState<AuthCredentials> capture() {
163195 }
164196 }
165197
166- private static class ComputeEngineAuthCredentials extends AuthCredentials {
167-
168- private ComputeCredential computeCredential ;
169-
170- private static final ComputeEngineAuthCredentialsState STATE =
171- new ComputeEngineAuthCredentialsState ();
172-
173- private static class ComputeEngineAuthCredentialsState
174- implements RestorableState <AuthCredentials >, Serializable {
175-
176- private static final long serialVersionUID = -6168594072854417404L ;
177-
178- @ Override
179- public AuthCredentials restore () {
180- try {
181- return new ComputeEngineAuthCredentials ();
182- } catch (IOException | GeneralSecurityException e ) {
183- throw new IllegalStateException (
184- "Could not restore " + ComputeEngineAuthCredentials .class .getSimpleName (), e );
185- }
186- }
187-
188- @ Override
189- public int hashCode () {
190- return getClass ().getName ().hashCode ();
191- }
192-
193- @ Override
194- public boolean equals (Object obj ) {
195- return obj instanceof ComputeEngineAuthCredentialsState ;
196- }
197- }
198-
199- ComputeEngineAuthCredentials () throws IOException , GeneralSecurityException {
200- computeCredential = getComputeCredential ();
201- }
202-
203- @ Override
204- protected HttpRequestInitializer httpRequestInitializer (HttpTransport transport ,
205- Set <String > scopes ) {
206- return computeCredential ;
207- }
208-
209- @ Override
210- public RestorableState <AuthCredentials > capture () {
211- return STATE ;
212- }
213- }
214-
215- private static class ApplicationDefaultAuthCredentials extends AuthCredentials {
198+ public static class ApplicationDefaultAuthCredentials extends AuthCredentials {
216199
217200 private GoogleCredentials googleCredentials ;
218201
@@ -250,9 +233,8 @@ public boolean equals(Object obj) {
250233 }
251234
252235 @ Override
253- protected HttpRequestInitializer httpRequestInitializer (HttpTransport transport ,
254- Set <String > scopes ) {
255- return new HttpCredentialsAdapter (googleCredentials );
236+ public GoogleCredentials credentials () {
237+ return googleCredentials ;
256238 }
257239
258240 @ Override
@@ -261,18 +243,12 @@ public RestorableState<AuthCredentials> capture() {
261243 }
262244 }
263245
264- protected abstract HttpRequestInitializer httpRequestInitializer (HttpTransport transport ,
265- Set <String > scopes );
246+ public abstract GoogleCredentials credentials ();
266247
267248 public static AuthCredentials createForAppEngine () {
268249 return AppEngineAuthCredentials .INSTANCE ;
269250 }
270251
271- public static AuthCredentials createForComputeEngine ()
272- throws IOException , GeneralSecurityException {
273- return new ComputeEngineAuthCredentials ();
274- }
275-
276252 /**
277253 * Returns the Application Default Credentials.
278254 *
@@ -319,21 +295,15 @@ public static ServiceAccountAuthCredentials createFor(String account, PrivateKey
319295 */
320296 public static ServiceAccountAuthCredentials createForJson (InputStream jsonCredentialStream )
321297 throws IOException {
322- GoogleCredential tempCredentials = GoogleCredential .fromStream (jsonCredentialStream );
323- return new ServiceAccountAuthCredentials (tempCredentials .getServiceAccountId (),
324- tempCredentials .getServiceAccountPrivateKey ());
325- }
326-
327- public static AuthCredentials noCredentials () {
328- return ServiceAccountAuthCredentials .NO_CREDENTIALS ;
329- }
330-
331- static ComputeCredential getComputeCredential () throws IOException , GeneralSecurityException {
332- NetHttpTransport transport = GoogleNetHttpTransport .newTrustedTransport ();
333- // Try to connect using Google Compute Engine service account credentials.
334- ComputeCredential credential = new ComputeCredential (transport , new JacksonFactory ());
335- // Force token refresh to detect if we are running on Google Compute Engine.
336- credential .refreshToken ();
337- return credential ;
298+ GoogleCredentials tempCredentials = GoogleCredentials .fromStream (jsonCredentialStream );
299+ if (tempCredentials instanceof ServiceAccountCredentials ) {
300+ ServiceAccountCredentials tempServiceAccountCredentials =
301+ (ServiceAccountCredentials ) tempCredentials ;
302+ return new ServiceAccountAuthCredentials (
303+ tempServiceAccountCredentials .getClientEmail (),
304+ tempServiceAccountCredentials .getPrivateKey ());
305+ }
306+ throw new IOException (
307+ "The given JSON Credentials Stream is not for a service account credential." );
338308 }
339309}
0 commit comments