17
17
package com .google .cloud .spanner .jdbc ;
18
18
19
19
import com .google .auth .Credentials ;
20
+ import com .google .auth .oauth2 .AccessToken ;
20
21
import com .google .auth .oauth2 .GoogleCredentials ;
21
22
import com .google .auth .oauth2 .ServiceAccountCredentials ;
22
23
import com .google .cloud .NoCredentials ;
@@ -140,6 +141,7 @@ public String[] getValidValues() {
140
141
static final boolean DEFAULT_READONLY = false ;
141
142
static final boolean DEFAULT_RETRY_ABORTS_INTERNALLY = true ;
142
143
private static final String DEFAULT_CREDENTIALS = null ;
144
+ private static final String DEFAULT_OAUTH_TOKEN = null ;
143
145
private static final String DEFAULT_NUM_CHANNELS = null ;
144
146
private static final String DEFAULT_USER_AGENT = null ;
145
147
@@ -156,6 +158,10 @@ public String[] getValidValues() {
156
158
public static final String RETRY_ABORTS_INTERNALLY_PROPERTY_NAME = "retryAbortsInternally" ;
157
159
/** Name of the 'credentials' connection property. */
158
160
public static final String CREDENTIALS_PROPERTY_NAME = "credentials" ;
161
+ /**
162
+ * OAuth token to use for authentication. Cannot be used in combination with a credentials file.
163
+ */
164
+ public static final String OAUTH_TOKEN_PROPERTY_NAME = "oauthToken" ;
159
165
/** Name of the 'numChannels' connection property. */
160
166
public static final String NUM_CHANNELS_PROPERTY_NAME = "numChannels" ;
161
167
/** Custom user agent string is only for other Google libraries. */
@@ -173,6 +179,7 @@ public String[] getValidValues() {
173
179
ConnectionProperty .createBooleanProperty (
174
180
RETRY_ABORTS_INTERNALLY_PROPERTY_NAME , "" , DEFAULT_RETRY_ABORTS_INTERNALLY ),
175
181
ConnectionProperty .createStringProperty (CREDENTIALS_PROPERTY_NAME , "" ),
182
+ ConnectionProperty .createStringProperty (OAUTH_TOKEN_PROPERTY_NAME , "" ),
176
183
ConnectionProperty .createStringProperty (NUM_CHANNELS_PROPERTY_NAME , "" ),
177
184
ConnectionProperty .createBooleanProperty (
178
185
USE_PLAIN_TEXT_PROPERTY_NAME , "" , DEFAULT_USE_PLAIN_TEXT ),
@@ -223,6 +230,7 @@ public static void closeSpanner() {
223
230
public static class Builder {
224
231
private String uri ;
225
232
private String credentialsUrl ;
233
+ private String oauthToken ;
226
234
private Credentials credentials ;
227
235
private List <StatementExecutionInterceptor > statementExecutionInterceptors =
228
236
Collections .emptyList ();
@@ -308,6 +316,22 @@ public Builder setCredentialsUrl(String credentialsUrl) {
308
316
return this ;
309
317
}
310
318
319
+ /**
320
+ * Sets the OAuth token to use with this connection. The token must be a valid token with access
321
+ * to the resources (project/instance/database) that the connection will be accessing. This
322
+ * authentication method cannot be used in combination with a credentials file. If both an OAuth
323
+ * token and a credentials file is specified, the {@link #build()} method will throw an
324
+ * exception.
325
+ *
326
+ * @param oauthToken A valid OAuth token for the Google Cloud project that is used by this
327
+ * connection.
328
+ * @return this builder
329
+ */
330
+ public Builder setOAuthToken (String oauthToken ) {
331
+ this .oauthToken = oauthToken ;
332
+ return this ;
333
+ }
334
+
311
335
@ VisibleForTesting
312
336
Builder setStatementExecutionInterceptors (List <StatementExecutionInterceptor > interceptors ) {
313
337
this .statementExecutionInterceptors = interceptors ;
@@ -339,6 +363,7 @@ public static Builder newBuilder() {
339
363
340
364
private final String uri ;
341
365
private final String credentialsUrl ;
366
+ private final String oauthToken ;
342
367
343
368
private final boolean usePlainText ;
344
369
private final String host ;
@@ -363,6 +388,13 @@ private ConnectionOptions(Builder builder) {
363
388
this .uri = builder .uri ;
364
389
this .credentialsUrl =
365
390
builder .credentialsUrl != null ? builder .credentialsUrl : parseCredentials (builder .uri );
391
+ this .oauthToken =
392
+ builder .oauthToken != null ? builder .oauthToken : parseOAuthToken (builder .uri );
393
+ // Check that not both credentials and an OAuth token have been specified.
394
+ Preconditions .checkArgument (
395
+ (builder .credentials == null && this .credentialsUrl == null ) || this .oauthToken == null ,
396
+ "Cannot specify both credentials and an OAuth token." );
397
+
366
398
this .usePlainText = parseUsePlainText (this .uri );
367
399
this .userAgent = parseUserAgent (this .uri );
368
400
@@ -376,8 +408,13 @@ private ConnectionOptions(Builder builder) {
376
408
// Using credentials on a plain text connection is not allowed, so if the user has not specified
377
409
// any credentials and is using a plain text connection, we should not try to get the
378
410
// credentials from the environment, but default to NoCredentials.
379
- if (builder .credentials == null && this .credentialsUrl == null && this .usePlainText ) {
411
+ if (builder .credentials == null
412
+ && this .credentialsUrl == null
413
+ && this .oauthToken == null
414
+ && this .usePlainText ) {
380
415
this .credentials = NoCredentials .getInstance ();
416
+ } else if (this .oauthToken != null ) {
417
+ this .credentials = new GoogleCredentials (new AccessToken (oauthToken , null ));
381
418
} else {
382
419
this .credentials =
383
420
builder .credentials == null
@@ -446,6 +483,12 @@ static String parseCredentials(String uri) {
446
483
return value != null ? value : DEFAULT_CREDENTIALS ;
447
484
}
448
485
486
+ @ VisibleForTesting
487
+ static String parseOAuthToken (String uri ) {
488
+ String value = parseUriProperty (uri , OAUTH_TOKEN_PROPERTY_NAME );
489
+ return value != null ? value : DEFAULT_OAUTH_TOKEN ;
490
+ }
491
+
449
492
@ VisibleForTesting
450
493
static String parseNumChannels (String uri ) {
451
494
String value = parseUriProperty (uri , NUM_CHANNELS_PROPERTY_NAME );
0 commit comments