1 /* 2 * Copyright 2015, Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 package com.google.auth.oauth2; 33 34 import static org.junit.Assert.*; 35 36 import com.google.api.client.json.GenericJson; 37 import com.google.api.client.util.Clock; 38 import com.google.auth.Credentials; 39 import com.google.auth.TestUtils; 40 import com.google.auth.http.HttpTransportFactory; 41 import com.google.auth.oauth2.ExternalAccountAuthorizedUserCredentialsTest.MockExternalAccountAuthorizedUserCredentialsTransportFactory; 42 import com.google.auth.oauth2.IdentityPoolCredentialsTest.MockExternalAccountCredentialsTransportFactory; 43 import com.google.auth.oauth2.ImpersonatedCredentialsTest.MockIAMCredentialsServiceTransportFactory; 44 import com.google.common.collect.ImmutableList; 45 import java.io.ByteArrayInputStream; 46 import java.io.IOException; 47 import java.io.InputStream; 48 import java.net.URI; 49 import java.util.Arrays; 50 import java.util.Collection; 51 import java.util.Collections; 52 import java.util.List; 53 import java.util.Map; 54 import java.util.concurrent.atomic.AtomicReference; 55 import org.junit.Test; 56 import org.junit.runner.RunWith; 57 import org.junit.runners.JUnit4; 58 59 /** Test case for {@link GoogleCredentials}. */ 60 @RunWith(JUnit4.class) 61 public class GoogleCredentialsTest extends BaseSerializationTest { 62 63 private static final String SA_CLIENT_EMAIL = 64 "36680232662-vrd7ji19qe3nelgchd0ah2csanun6bnr@developer.gserviceaccount.com"; 65 private static final String SA_CLIENT_ID = 66 "36680232662-vrd7ji19qe3nelgchd0ah2csanun6bnr.apps.googleusercontent.com"; 67 private static final String SA_PRIVATE_KEY_ID = "d84a4fefcf50791d4a90f2d7af17469d6282df9d"; 68 private static final String SA_PRIVATE_KEY_PKCS8 = 69 ServiceAccountCredentialsTest.PRIVATE_KEY_PKCS8; 70 private static final String GDCH_SA_FORMAT_VERSION = GdchCredentials.SUPPORTED_FORMAT_VERSION; 71 private static final String GDCH_SA_PROJECT_ID = "gdch-service-account-project-id"; 72 private static final String GDCH_SA_PRIVATE_KEY_ID = "d84a4fefcf50791d4a90f2d7af17469d6282df9d"; 73 private static final String GDCH_SA_PRIVATE_KEY_PKC8 = GdchCredentialsTest.PRIVATE_KEY_PKCS8; 74 private static final String GDCH_SA_SERVICE_IDENTITY_NAME = 75 "gdch-service-account-service-identity-name"; 76 private static final URI GDCH_SA_TOKEN_SERVER_URI = 77 URI.create("https://service-identity.domain/authenticate"); 78 private static final String GDCH_SA_CA_CERT_FILE_NAME = "cert.pem"; 79 private static final String GDCH_SA_CA_CERT_PATH = 80 GdchCredentialsTest.class.getClassLoader().getResource(GDCH_SA_CA_CERT_FILE_NAME).getPath(); 81 private static final URI GDCH_API_AUDIENCE = URI.create("https://gdch-api-audience"); 82 private static final String USER_CLIENT_SECRET = "jakuaL9YyieakhECKL2SwZcu"; 83 private static final String USER_CLIENT_ID = "ya29.1.AADtN_UtlxN3PuGAxrN2XQnZTVRvDyVWnYq4I6dws"; 84 private static final String REFRESH_TOKEN = "1/Tl6awhpFjkMkSJoj1xsli0H2eL5YsMgU_NKPY2TyGWY"; 85 private static final String ACCESS_TOKEN = "1/MkSJoj1xsli0AccessToken_NKPY2"; 86 private static final HttpTransportFactory DUMMY_TRANSPORT_FACTORY = 87 new MockTokenServerTransportFactory(); 88 private static final URI CALL_URI = URI.create("http://googleapis.com/testapi/v1/foo"); 89 private static final String QUOTA_PROJECT = "sample-quota-project-id"; 90 91 private static final Collection<String> SCOPES = 92 Collections.unmodifiableCollection(Arrays.asList("scope1", "scope2")); 93 private static final Collection<String> DEFAULT_SCOPES = 94 Collections.unmodifiableCollection(Arrays.asList("scope3")); 95 private static final String GOOGLE_DEFAULT_UNIVERSE = "googleapis.com"; 96 private static final String TPC_UNIVERSE = "foo.bar"; 97 98 @Test getApplicationDefault_nullTransport_throws()99 public void getApplicationDefault_nullTransport_throws() throws IOException { 100 try { 101 GoogleCredentials.getApplicationDefault(null); 102 fail(); 103 } catch (NullPointerException expected) { 104 // Expected 105 } 106 } 107 108 @Test fromStream_unknownType_throws()109 public void fromStream_unknownType_throws() throws IOException { 110 MockHttpTransportFactory transportFactory = new MockHttpTransportFactory(); 111 GenericJson json = new GenericJson(); 112 json.put("type", "unsupported_credential"); 113 InputStream stream = TestUtils.jsonToInputStream(json); 114 try { 115 GoogleCredentials.fromStream(stream, transportFactory); 116 fail("Should throw if type is unknown."); 117 } catch (IOException expected) { 118 String expectedError = 119 "Error reading credentials from stream, 'type' value " 120 + "'unsupported_credential' not recognized. Valid values are 'authorized_user', " 121 + "'service_account', 'gdch_service_account', 'external_account', " 122 + "'external_account_authorized_user', 'impersonated_service_account'."; 123 assertTrue(expected.getMessage().contains(expectedError)); 124 } 125 } 126 127 @Test fromStream_nullTransport_throws()128 public void fromStream_nullTransport_throws() throws IOException { 129 InputStream stream = new ByteArrayInputStream("foo".getBytes()); 130 try { 131 GoogleCredentials.fromStream(stream, null); 132 fail("Should throw if HttpTransportFactory is null"); 133 } catch (NullPointerException expected) { 134 // Expected 135 } 136 } 137 138 @Test fromStream_noType_throws()139 public void fromStream_noType_throws() throws IOException { 140 MockHttpTransportFactory transportFactory = new MockHttpTransportFactory(); 141 GenericJson json = 142 ServiceAccountCredentialsTest.writeServiceAccountJson( 143 "project_id", QUOTA_PROJECT, "universe"); 144 json.remove("type"); 145 InputStream stream = TestUtils.jsonToInputStream(json); 146 try { 147 GoogleCredentials.fromStream(stream, transportFactory); 148 fail("Should throw if type is unknown."); 149 } catch (IOException expected) { 150 String expectedError = "Error reading credentials from stream, 'type' field not specified."; 151 assertEquals(expectedError, expected.getMessage()); 152 } 153 } 154 155 @Test fromStream_nullStream_throws()156 public void fromStream_nullStream_throws() throws IOException { 157 MockHttpTransportFactory transportFactory = new MockHttpTransportFactory(); 158 try { 159 GoogleCredentials.fromStream(null, transportFactory); 160 fail("Should throw if InputStream is null"); 161 } catch (NullPointerException expected) { 162 // Expected 163 } 164 } 165 166 @Test fromStream_serviceAccount_noUniverse_providesToken()167 public void fromStream_serviceAccount_noUniverse_providesToken() throws IOException { 168 MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory(); 169 transportFactory.transport.addServiceAccount(SA_CLIENT_EMAIL, ACCESS_TOKEN); 170 InputStream serviceAccountStream = 171 ServiceAccountCredentialsTest.writeServiceAccountStream( 172 SA_CLIENT_ID, SA_CLIENT_EMAIL, SA_PRIVATE_KEY_PKCS8, SA_PRIVATE_KEY_ID); 173 174 GoogleCredentials credentials = 175 GoogleCredentials.fromStream(serviceAccountStream, transportFactory); 176 177 assertNotNull(credentials); 178 assertEquals(GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); 179 assertEquals(false, credentials.isExplicitUniverseDomain()); 180 credentials = credentials.createScoped(SCOPES); 181 Map<String, List<String>> metadata = credentials.getRequestMetadata(CALL_URI); 182 TestUtils.assertContainsBearerToken(metadata, ACCESS_TOKEN); 183 184 credentials = credentials.createScoped(SCOPES, DEFAULT_SCOPES); 185 metadata = credentials.getRequestMetadata(CALL_URI); 186 TestUtils.assertContainsBearerToken(metadata, ACCESS_TOKEN); 187 } 188 189 @Test fromStream_serviceAccount_Universe_noToken()190 public void fromStream_serviceAccount_Universe_noToken() throws IOException { 191 MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory(); 192 transportFactory.transport.addServiceAccount(SA_CLIENT_EMAIL, ACCESS_TOKEN); 193 InputStream serviceAccountStream = 194 ServiceAccountCredentialsTest.writeServiceAccountStream( 195 SA_CLIENT_ID, SA_CLIENT_EMAIL, SA_PRIVATE_KEY_PKCS8, SA_PRIVATE_KEY_ID, TPC_UNIVERSE); 196 197 GoogleCredentials credentials = 198 GoogleCredentials.fromStream(serviceAccountStream, transportFactory); 199 200 assertNotNull(credentials); 201 assertEquals(TPC_UNIVERSE, credentials.getUniverseDomain()); 202 assertEquals(true, credentials.isExplicitUniverseDomain()); 203 credentials = credentials.createScoped(SCOPES); 204 Map<String, List<String>> metadata = credentials.getRequestMetadata(CALL_URI); 205 assertNotNull(((ServiceAccountCredentials) credentials).getSelfSignedJwtCredentialsWithScope()); 206 } 207 208 @Test fromStream_serviceAccountNoClientId_throws()209 public void fromStream_serviceAccountNoClientId_throws() throws IOException { 210 InputStream serviceAccountStream = 211 ServiceAccountCredentialsTest.writeServiceAccountStream( 212 null, SA_CLIENT_EMAIL, SA_PRIVATE_KEY_PKCS8, SA_PRIVATE_KEY_ID); 213 214 testFromStreamException(serviceAccountStream, "client_id"); 215 } 216 217 @Test fromStream_serviceAccountNoClientEmail_throws()218 public void fromStream_serviceAccountNoClientEmail_throws() throws IOException { 219 InputStream serviceAccountStream = 220 ServiceAccountCredentialsTest.writeServiceAccountStream( 221 SA_CLIENT_ID, null, SA_PRIVATE_KEY_PKCS8, SA_PRIVATE_KEY_ID); 222 223 testFromStreamException(serviceAccountStream, "client_email"); 224 } 225 226 @Test fromStream_serviceAccountNoPrivateKey_throws()227 public void fromStream_serviceAccountNoPrivateKey_throws() throws IOException { 228 InputStream serviceAccountStream = 229 ServiceAccountCredentialsTest.writeServiceAccountStream( 230 SA_CLIENT_ID, SA_CLIENT_EMAIL, null, SA_PRIVATE_KEY_ID); 231 232 testFromStreamException(serviceAccountStream, "private_key"); 233 } 234 235 @Test fromStream_serviceAccountNoPrivateKeyId_throws()236 public void fromStream_serviceAccountNoPrivateKeyId_throws() throws IOException { 237 InputStream serviceAccountStream = 238 ServiceAccountCredentialsTest.writeServiceAccountStream( 239 SA_CLIENT_ID, SA_CLIENT_EMAIL, SA_PRIVATE_KEY_PKCS8, null); 240 241 testFromStreamException(serviceAccountStream, "private_key_id"); 242 } 243 244 @Test fromStream_gdchServiceAccount_correct()245 public void fromStream_gdchServiceAccount_correct() throws IOException { 246 MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory(); 247 InputStream gdchServiceAccountStream = 248 GdchCredentialsTest.writeGdchServiceAccountStream( 249 GDCH_SA_FORMAT_VERSION, 250 GDCH_SA_PROJECT_ID, 251 GDCH_SA_PRIVATE_KEY_ID, 252 GDCH_SA_PRIVATE_KEY_PKC8, 253 GDCH_SA_SERVICE_IDENTITY_NAME, 254 GDCH_SA_CA_CERT_PATH, 255 GDCH_SA_TOKEN_SERVER_URI); 256 GoogleCredentials credentials = 257 GoogleCredentials.fromStream(gdchServiceAccountStream, transportFactory); 258 259 assertNotNull(credentials); 260 assertTrue(credentials instanceof GdchCredentials); 261 assertEquals(GDCH_SA_PROJECT_ID, ((GdchCredentials) credentials).getProjectId()); 262 assertEquals( 263 GDCH_SA_SERVICE_IDENTITY_NAME, ((GdchCredentials) credentials).getServiceIdentityName()); 264 assertEquals(GDCH_SA_TOKEN_SERVER_URI, ((GdchCredentials) credentials).getTokenServerUri()); 265 assertEquals(GDCH_SA_CA_CERT_PATH, ((GdchCredentials) credentials).getCaCertPath()); 266 assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); 267 assertNull(((GdchCredentials) credentials).getApiAudience()); 268 269 credentials = ((GdchCredentials) credentials).createWithGdchAudience(GDCH_API_AUDIENCE); 270 assertNotNull(credentials); 271 assertTrue(credentials instanceof GdchCredentials); 272 assertEquals(GDCH_SA_PROJECT_ID, ((GdchCredentials) credentials).getProjectId()); 273 assertEquals( 274 GDCH_SA_SERVICE_IDENTITY_NAME, ((GdchCredentials) credentials).getServiceIdentityName()); 275 assertEquals(GDCH_SA_TOKEN_SERVER_URI, ((GdchCredentials) credentials).getTokenServerUri()); 276 assertEquals(GDCH_SA_CA_CERT_PATH, ((GdchCredentials) credentials).getCaCertPath()); 277 assertNotNull(((GdchCredentials) credentials).getApiAudience()); 278 } 279 280 @Test fromStream_gdchServiceAccountNoFormatVersion_throws()281 public void fromStream_gdchServiceAccountNoFormatVersion_throws() throws IOException { 282 InputStream gdchServiceAccountStream = 283 GdchCredentialsTest.writeGdchServiceAccountStream( 284 null, 285 GDCH_SA_PROJECT_ID, 286 GDCH_SA_PRIVATE_KEY_ID, 287 GDCH_SA_PRIVATE_KEY_PKC8, 288 GDCH_SA_SERVICE_IDENTITY_NAME, 289 GDCH_SA_CA_CERT_PATH, 290 GDCH_SA_TOKEN_SERVER_URI); 291 292 testFromStreamException(gdchServiceAccountStream, "format_version"); 293 } 294 295 @Test fromStream_gdchServiceAccountNoProjectId_throws()296 public void fromStream_gdchServiceAccountNoProjectId_throws() throws IOException { 297 InputStream gdchServiceAccountStream = 298 GdchCredentialsTest.writeGdchServiceAccountStream( 299 GDCH_SA_FORMAT_VERSION, 300 null, 301 GDCH_SA_PRIVATE_KEY_ID, 302 GDCH_SA_PRIVATE_KEY_PKC8, 303 GDCH_SA_SERVICE_IDENTITY_NAME, 304 GDCH_SA_CA_CERT_PATH, 305 GDCH_SA_TOKEN_SERVER_URI); 306 307 testFromStreamException(gdchServiceAccountStream, "project"); 308 } 309 310 @Test fromStream_gdchServiceAccountNoPrivateKeyId_throws()311 public void fromStream_gdchServiceAccountNoPrivateKeyId_throws() throws IOException { 312 InputStream gdchServiceAccountStream = 313 GdchCredentialsTest.writeGdchServiceAccountStream( 314 GDCH_SA_FORMAT_VERSION, 315 GDCH_SA_PROJECT_ID, 316 null, 317 GDCH_SA_PRIVATE_KEY_PKC8, 318 GDCH_SA_SERVICE_IDENTITY_NAME, 319 GDCH_SA_CA_CERT_PATH, 320 GDCH_SA_TOKEN_SERVER_URI); 321 322 testFromStreamException(gdchServiceAccountStream, "private_key_id"); 323 } 324 325 @Test fromStream_gdchServiceAccountNoPrivateKey_throws()326 public void fromStream_gdchServiceAccountNoPrivateKey_throws() throws IOException { 327 InputStream gdchServiceAccountStream = 328 GdchCredentialsTest.writeGdchServiceAccountStream( 329 GDCH_SA_FORMAT_VERSION, 330 GDCH_SA_PROJECT_ID, 331 GDCH_SA_PRIVATE_KEY_ID, 332 null, 333 GDCH_SA_SERVICE_IDENTITY_NAME, 334 GDCH_SA_CA_CERT_PATH, 335 GDCH_SA_TOKEN_SERVER_URI); 336 337 testFromStreamException(gdchServiceAccountStream, "private_key"); 338 } 339 340 @Test fromStream_gdchServiceAccountNoServiceIdentityName_throws()341 public void fromStream_gdchServiceAccountNoServiceIdentityName_throws() throws IOException { 342 InputStream gdchServiceAccountStream = 343 GdchCredentialsTest.writeGdchServiceAccountStream( 344 GDCH_SA_FORMAT_VERSION, 345 GDCH_SA_PROJECT_ID, 346 GDCH_SA_PRIVATE_KEY_ID, 347 GDCH_SA_PRIVATE_KEY_PKC8, 348 null, 349 GDCH_SA_CA_CERT_PATH, 350 GDCH_SA_TOKEN_SERVER_URI); 351 352 testFromStreamException(gdchServiceAccountStream, "name"); 353 } 354 355 @Test fromStream_gdchServiceAccountNoTokenServerUri_throws()356 public void fromStream_gdchServiceAccountNoTokenServerUri_throws() throws IOException { 357 InputStream gdchServiceAccountStream = 358 GdchCredentialsTest.writeGdchServiceAccountStream( 359 GDCH_SA_FORMAT_VERSION, 360 GDCH_SA_PROJECT_ID, 361 GDCH_SA_PRIVATE_KEY_ID, 362 GDCH_SA_PRIVATE_KEY_PKC8, 363 GDCH_SA_SERVICE_IDENTITY_NAME, 364 GDCH_SA_CA_CERT_PATH, 365 null); 366 367 testFromStreamException(gdchServiceAccountStream, "token_uri"); 368 } 369 370 @Test fromStream_gdchServiceAccountInvalidFormatVersion_throws()371 public void fromStream_gdchServiceAccountInvalidFormatVersion_throws() throws IOException { 372 InputStream gdchServiceAccountStream = 373 GdchCredentialsTest.writeGdchServiceAccountStream( 374 "100", 375 GDCH_SA_PROJECT_ID, 376 GDCH_SA_PRIVATE_KEY_ID, 377 GDCH_SA_PRIVATE_KEY_PKC8, 378 GDCH_SA_SERVICE_IDENTITY_NAME, 379 GDCH_SA_CA_CERT_PATH, 380 GDCH_SA_TOKEN_SERVER_URI); 381 382 testFromStreamException( 383 gdchServiceAccountStream, 384 String.format("Only format version %s is supported", GDCH_SA_FORMAT_VERSION)); 385 } 386 387 @Test fromStream_gdchServiceAccountInvalidCaCertPath_throws()388 public void fromStream_gdchServiceAccountInvalidCaCertPath_throws() throws IOException { 389 InputStream gdchServiceAccountStream = 390 GdchCredentialsTest.writeGdchServiceAccountStream( 391 GDCH_SA_FORMAT_VERSION, 392 GDCH_SA_PROJECT_ID, 393 GDCH_SA_PRIVATE_KEY_ID, 394 GDCH_SA_PRIVATE_KEY_PKC8, 395 GDCH_SA_SERVICE_IDENTITY_NAME, 396 "/path/to/missing/file", 397 GDCH_SA_TOKEN_SERVER_URI); 398 399 testFromStreamException( 400 gdchServiceAccountStream, 401 String.format("Error reading certificate file from CA cert path")); 402 } 403 404 @Test fromStream_userCredentials_providesToken()405 public void fromStream_userCredentials_providesToken() throws IOException { 406 MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory(); 407 transportFactory.transport.addClient(USER_CLIENT_ID, USER_CLIENT_SECRET); 408 transportFactory.transport.addRefreshToken(REFRESH_TOKEN, ACCESS_TOKEN); 409 InputStream userStream = 410 UserCredentialsTest.writeUserStream( 411 USER_CLIENT_ID, USER_CLIENT_SECRET, REFRESH_TOKEN, null); 412 413 GoogleCredentials credentials = GoogleCredentials.fromStream(userStream, transportFactory); 414 415 assertNotNull(credentials); 416 Map<String, List<String>> metadata = credentials.getRequestMetadata(CALL_URI); 417 TestUtils.assertContainsBearerToken(metadata, ACCESS_TOKEN); 418 } 419 420 @Test fromStream_userCredentials_defaultUniverse()421 public void fromStream_userCredentials_defaultUniverse() throws IOException { 422 MockTokenServerTransportFactory transportFactory = new MockTokenServerTransportFactory(); 423 InputStream userStream = 424 UserCredentialsTest.writeUserStream( 425 USER_CLIENT_ID, USER_CLIENT_SECRET, REFRESH_TOKEN, null); 426 427 GoogleCredentials credentials = GoogleCredentials.fromStream(userStream, transportFactory); 428 429 assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); 430 } 431 432 @Test fromStream_userCredentials_NoClientId_throws()433 public void fromStream_userCredentials_NoClientId_throws() throws IOException { 434 InputStream userStream = 435 UserCredentialsTest.writeUserStream(null, USER_CLIENT_SECRET, REFRESH_TOKEN, QUOTA_PROJECT); 436 437 testFromStreamException(userStream, "client_id"); 438 } 439 440 @Test fromStream_userCredentials_NoClientSecret_throws()441 public void fromStream_userCredentials_NoClientSecret_throws() throws IOException { 442 InputStream userStream = 443 UserCredentialsTest.writeUserStream(USER_CLIENT_ID, null, REFRESH_TOKEN, QUOTA_PROJECT); 444 445 testFromStreamException(userStream, "client_secret"); 446 } 447 448 @Test fromStream_userCredentials_NoRefreshToken_throws()449 public void fromStream_userCredentials_NoRefreshToken_throws() throws IOException { 450 InputStream userStream = 451 UserCredentialsTest.writeUserStream( 452 USER_CLIENT_ID, USER_CLIENT_SECRET, null, QUOTA_PROJECT); 453 454 testFromStreamException(userStream, "refresh_token"); 455 } 456 457 @Test fromStream_identityPoolCredentials_providesToken()458 public void fromStream_identityPoolCredentials_providesToken() throws IOException { 459 MockExternalAccountCredentialsTransportFactory transportFactory = 460 new MockExternalAccountCredentialsTransportFactory(); 461 InputStream identityPoolCredentialStream = 462 IdentityPoolCredentialsTest.writeIdentityPoolCredentialsStream( 463 transportFactory.transport.getStsUrl(), 464 transportFactory.transport.getMetadataUrl(), 465 /* serviceAccountImpersonationUrl= */ null, 466 /* serviceAccountImpersonationOptionsMap= */ null); 467 468 GoogleCredentials credentials = 469 GoogleCredentials.fromStream(identityPoolCredentialStream, transportFactory); 470 471 assertNotNull(credentials); 472 credentials = credentials.createScoped(SCOPES); 473 Map<String, List<String>> metadata = credentials.getRequestMetadata(CALL_URI); 474 TestUtils.assertContainsBearerToken(metadata, transportFactory.transport.getAccessToken()); 475 } 476 477 @Test fromStream_identityPoolCredentials_defaultUniverse()478 public void fromStream_identityPoolCredentials_defaultUniverse() throws IOException { 479 MockExternalAccountCredentialsTransportFactory transportFactory = 480 new MockExternalAccountCredentialsTransportFactory(); 481 InputStream identityPoolCredentialStream = 482 IdentityPoolCredentialsTest.writeIdentityPoolCredentialsStream( 483 transportFactory.transport.getStsUrl(), 484 transportFactory.transport.getMetadataUrl(), 485 /* serviceAccountImpersonationUrl= */ null, 486 /* serviceAccountImpersonationOptionsMap= */ null); 487 488 GoogleCredentials credentials = 489 GoogleCredentials.fromStream(identityPoolCredentialStream, transportFactory); 490 491 assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); 492 } 493 494 @Test fromStream_awsCredentials_providesToken()495 public void fromStream_awsCredentials_providesToken() throws IOException { 496 MockExternalAccountCredentialsTransportFactory transportFactory = 497 new MockExternalAccountCredentialsTransportFactory(); 498 499 InputStream awsCredentialStream = 500 AwsCredentialsTest.writeAwsCredentialsStream( 501 transportFactory.transport.getStsUrl(), 502 transportFactory.transport.getAwsRegionUrl(), 503 transportFactory.transport.getAwsCredentialsUrl()); 504 505 GoogleCredentials credentials = 506 GoogleCredentials.fromStream(awsCredentialStream, transportFactory); 507 508 assertNotNull(credentials); 509 credentials = credentials.createScoped(SCOPES); 510 Map<String, List<String>> metadata = credentials.getRequestMetadata(CALL_URI); 511 TestUtils.assertContainsBearerToken(metadata, transportFactory.transport.getAccessToken()); 512 } 513 514 @Test fromStream_awsCredentials_defaultUniverse()515 public void fromStream_awsCredentials_defaultUniverse() throws IOException { 516 MockExternalAccountCredentialsTransportFactory transportFactory = 517 new MockExternalAccountCredentialsTransportFactory(); 518 519 InputStream awsCredentialStream = 520 AwsCredentialsTest.writeAwsCredentialsStream( 521 transportFactory.transport.getStsUrl(), 522 transportFactory.transport.getAwsRegionUrl(), 523 transportFactory.transport.getAwsCredentialsUrl()); 524 525 GoogleCredentials credentials = 526 GoogleCredentials.fromStream(awsCredentialStream, transportFactory); 527 528 assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); 529 } 530 531 @Test fromStream_pluggableAuthCredentials_providesToken()532 public void fromStream_pluggableAuthCredentials_providesToken() throws IOException { 533 MockExternalAccountCredentialsTransportFactory transportFactory = 534 new MockExternalAccountCredentialsTransportFactory(); 535 536 InputStream stream = 537 PluggableAuthCredentialsTest.writeCredentialsStream(transportFactory.transport.getStsUrl()); 538 539 GoogleCredentials credentials = GoogleCredentials.fromStream(stream, transportFactory); 540 541 assertNotNull(credentials); 542 543 // Create copy with mock executable handler. 544 PluggableAuthCredentials copy = 545 PluggableAuthCredentials.newBuilder((PluggableAuthCredentials) credentials) 546 .setExecutableHandler(options -> "pluggableAuthToken") 547 .build(); 548 549 copy = copy.createScoped(SCOPES); 550 Map<String, List<String>> metadata = copy.getRequestMetadata(CALL_URI); 551 TestUtils.assertContainsBearerToken(metadata, transportFactory.transport.getAccessToken()); 552 } 553 554 @Test fromStream_pluggableAuthCredentials_defaultUniverse()555 public void fromStream_pluggableAuthCredentials_defaultUniverse() throws IOException { 556 MockExternalAccountCredentialsTransportFactory transportFactory = 557 new MockExternalAccountCredentialsTransportFactory(); 558 559 InputStream stream = 560 PluggableAuthCredentialsTest.writeCredentialsStream(transportFactory.transport.getStsUrl()); 561 562 GoogleCredentials credentials = GoogleCredentials.fromStream(stream, transportFactory); 563 564 assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); 565 } 566 567 @Test fromStream_externalAccountAuthorizedUserCredentials_providesToken()568 public void fromStream_externalAccountAuthorizedUserCredentials_providesToken() 569 throws IOException { 570 MockExternalAccountAuthorizedUserCredentialsTransportFactory transportFactory = 571 new MockExternalAccountAuthorizedUserCredentialsTransportFactory(); 572 InputStream stream = 573 TestUtils.jsonToInputStream( 574 ExternalAccountAuthorizedUserCredentialsTest.buildJsonCredentials()); 575 576 GoogleCredentials credentials = GoogleCredentials.fromStream(stream, transportFactory); 577 578 Map<String, List<String>> metadata = credentials.getRequestMetadata(CALL_URI); 579 TestUtils.assertContainsBearerToken(metadata, transportFactory.transport.getAccessToken()); 580 } 581 582 @Test fromStream_externalAccountAuthorizedUserCredentials_defaultUniverse()583 public void fromStream_externalAccountAuthorizedUserCredentials_defaultUniverse() 584 throws IOException { 585 MockExternalAccountAuthorizedUserCredentialsTransportFactory transportFactory = 586 new MockExternalAccountAuthorizedUserCredentialsTransportFactory(); 587 588 GenericJson json = ExternalAccountAuthorizedUserCredentialsTest.buildJsonCredentials(); 589 json.remove("universe_domain"); 590 InputStream stream = TestUtils.jsonToInputStream(json); 591 592 GoogleCredentials credentials = GoogleCredentials.fromStream(stream, transportFactory); 593 594 assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); 595 } 596 597 @Test fromStream_Impersonation_providesToken_WithQuotaProject()598 public void fromStream_Impersonation_providesToken_WithQuotaProject() throws IOException { 599 MockTokenServerTransportFactory transportFactoryForSource = 600 new MockTokenServerTransportFactory(); 601 transportFactoryForSource.transport.addServiceAccount( 602 ImpersonatedCredentialsTest.SA_CLIENT_EMAIL, ImpersonatedCredentialsTest.ACCESS_TOKEN); 603 604 MockIAMCredentialsServiceTransportFactory transportFactory = 605 new MockIAMCredentialsServiceTransportFactory(); 606 transportFactory.transport.setTargetPrincipal( 607 ImpersonatedCredentialsTest.IMPERSONATED_CLIENT_EMAIL); 608 transportFactory.transport.setAccessToken(ImpersonatedCredentialsTest.ACCESS_TOKEN); 609 transportFactory.transport.setExpireTime(ImpersonatedCredentialsTest.getDefaultExpireTime()); 610 transportFactory.transport.setAccessTokenEndpoint( 611 ImpersonatedCredentialsTest.IMPERSONATION_URL); 612 613 InputStream impersonationCredentialsStream = 614 ImpersonatedCredentialsTest.writeImpersonationCredentialsStream( 615 ImpersonatedCredentialsTest.IMPERSONATION_URL, 616 ImpersonatedCredentialsTest.DELEGATES, 617 ImpersonatedCredentialsTest.QUOTA_PROJECT_ID); 618 619 ImpersonatedCredentials credentials = 620 (ImpersonatedCredentials) 621 GoogleCredentials.fromStream(impersonationCredentialsStream, transportFactoryForSource); 622 credentials.setTransportFactory(transportFactory); 623 624 Map<String, List<String>> metadata = credentials.getRequestMetadata(CALL_URI); 625 TestUtils.assertContainsBearerToken(metadata, ImpersonatedCredentialsTest.ACCESS_TOKEN); 626 627 assertTrue(metadata.containsKey("x-goog-user-project")); 628 List<String> headerValues = metadata.get("x-goog-user-project"); 629 assertEquals(1, headerValues.size()); 630 assertEquals(ImpersonatedCredentialsTest.QUOTA_PROJECT_ID, headerValues.get(0)); 631 } 632 633 @Test fromStream_Impersonation_defaultUniverse()634 public void fromStream_Impersonation_defaultUniverse() throws IOException { 635 MockTokenServerTransportFactory transportFactoryForSource = 636 new MockTokenServerTransportFactory(); 637 transportFactoryForSource.transport.addServiceAccount( 638 ImpersonatedCredentialsTest.SA_CLIENT_EMAIL, ImpersonatedCredentialsTest.ACCESS_TOKEN); 639 640 MockIAMCredentialsServiceTransportFactory transportFactory = 641 new MockIAMCredentialsServiceTransportFactory(); 642 643 InputStream impersonationCredentialsStream = 644 ImpersonatedCredentialsTest.writeImpersonationCredentialsStream( 645 ImpersonatedCredentialsTest.IMPERSONATION_URL, 646 ImpersonatedCredentialsTest.DELEGATES, 647 ImpersonatedCredentialsTest.QUOTA_PROJECT_ID); 648 649 ImpersonatedCredentials credentials = 650 (ImpersonatedCredentials) 651 GoogleCredentials.fromStream(impersonationCredentialsStream, transportFactoryForSource); 652 credentials.setTransportFactory(transportFactory); 653 654 assertEquals(Credentials.GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); 655 } 656 657 @Test fromStream_Impersonation_providesToken_WithoutQuotaProject()658 public void fromStream_Impersonation_providesToken_WithoutQuotaProject() throws IOException { 659 MockTokenServerTransportFactory transportFactoryForSource = 660 new MockTokenServerTransportFactory(); 661 transportFactoryForSource.transport.addServiceAccount( 662 ImpersonatedCredentialsTest.SA_CLIENT_EMAIL, ImpersonatedCredentialsTest.ACCESS_TOKEN); 663 664 MockIAMCredentialsServiceTransportFactory transportFactory = 665 new MockIAMCredentialsServiceTransportFactory(); 666 transportFactory.transport.setTargetPrincipal( 667 ImpersonatedCredentialsTest.IMPERSONATED_CLIENT_EMAIL); 668 transportFactory.transport.setAccessToken(ImpersonatedCredentialsTest.ACCESS_TOKEN); 669 transportFactory.transport.setExpireTime(ImpersonatedCredentialsTest.getDefaultExpireTime()); 670 transportFactory.transport.setAccessTokenEndpoint( 671 ImpersonatedCredentialsTest.IMPERSONATION_URL); 672 673 InputStream impersonationCredentialsStream = 674 ImpersonatedCredentialsTest.writeImpersonationCredentialsStream( 675 ImpersonatedCredentialsTest.IMPERSONATION_URL, 676 ImpersonatedCredentialsTest.DELEGATES, 677 null); 678 679 ImpersonatedCredentials credentials = 680 (ImpersonatedCredentials) 681 GoogleCredentials.fromStream(impersonationCredentialsStream, transportFactoryForSource); 682 credentials.setTransportFactory(transportFactory); 683 684 Map<String, List<String>> metadata = credentials.getRequestMetadata(CALL_URI); 685 TestUtils.assertContainsBearerToken(metadata, ImpersonatedCredentialsTest.ACCESS_TOKEN); 686 687 assertFalse(metadata.containsKey("x-goog-user-project")); 688 } 689 690 @Test createScoped_overloadCallsImplementation()691 public void createScoped_overloadCallsImplementation() { 692 final AtomicReference<Collection<String>> called = new AtomicReference<>(); 693 final GoogleCredentials expectedScopedCredentials = new GoogleCredentials(); 694 695 GoogleCredentials credentials = 696 new GoogleCredentials() { 697 @Override 698 public GoogleCredentials createScoped(Collection<String> scopes) { 699 called.set(scopes); 700 return expectedScopedCredentials; 701 } 702 }; 703 704 GoogleCredentials scopedCredentials = credentials.createScoped("foo", "bar"); 705 706 assertEquals(expectedScopedCredentials, scopedCredentials); 707 assertEquals(ImmutableList.of("foo", "bar"), called.get()); 708 } 709 710 @Test create_withoutUniverse()711 public void create_withoutUniverse() throws IOException { 712 AccessToken token = AccessToken.newBuilder().setTokenValue(ACCESS_TOKEN).build(); 713 GoogleCredentials credentials = GoogleCredentials.create(token); 714 715 assertEquals(GOOGLE_DEFAULT_UNIVERSE, credentials.getUniverseDomain()); 716 assertEquals(false, credentials.isExplicitUniverseDomain()); 717 } 718 719 @Test create_withUniverse()720 public void create_withUniverse() throws IOException { 721 AccessToken token = AccessToken.newBuilder().setTokenValue(ACCESS_TOKEN).build(); 722 GoogleCredentials credentials = GoogleCredentials.create("some-universe", token); 723 724 assertEquals("some-universe", credentials.getUniverseDomain()); 725 assertEquals(true, credentials.isExplicitUniverseDomain()); 726 } 727 728 @Test buildWithQuotaProject()729 public void buildWithQuotaProject() { 730 final GoogleCredentials googleCredentials = 731 new GoogleCredentials.Builder().setQuotaProjectId("old_quota").build(); 732 GoogleCredentials withUpdatedQuota = googleCredentials.createWithQuotaProject("new_quota"); 733 734 assertEquals("old_quota", googleCredentials.getQuotaProjectId()); 735 assertEquals("new_quota", withUpdatedQuota.getQuotaProjectId()); 736 737 GoogleCredentials withEmptyQuota = googleCredentials.createWithQuotaProject(""); 738 assertEquals("", withEmptyQuota.getQuotaProjectId()); 739 740 GoogleCredentials sameCredentials = googleCredentials.createWithQuotaProject(null); 741 assertEquals(null, sameCredentials.getQuotaProjectId()); 742 } 743 744 @Test buildWithUniverseDomain()745 public void buildWithUniverseDomain() throws IOException { 746 final GoogleCredentials original = 747 new GoogleCredentials.Builder().setUniverseDomain("universe1").build(); 748 GoogleCredentials updated = original.toBuilder().setUniverseDomain("universe2").build(); 749 750 assertEquals("universe1", original.getUniverseDomain()); 751 assertEquals(true, original.isExplicitUniverseDomain()); 752 assertEquals("universe2", updated.getUniverseDomain()); 753 assertEquals(true, updated.isExplicitUniverseDomain()); 754 755 GoogleCredentials withEmpty = original.toBuilder().setUniverseDomain("").build(); 756 assertEquals(GOOGLE_DEFAULT_UNIVERSE, withEmpty.getUniverseDomain()); 757 assertEquals(false, withEmpty.isExplicitUniverseDomain()); 758 759 GoogleCredentials withNull = original.toBuilder().setUniverseDomain(null).build(); 760 assertEquals(GOOGLE_DEFAULT_UNIVERSE, withNull.getUniverseDomain()); 761 assertEquals(false, withNull.isExplicitUniverseDomain()); 762 } 763 764 @Test serialize()765 public void serialize() throws IOException, ClassNotFoundException { 766 final GoogleCredentials testCredentials = new GoogleCredentials.Builder().build(); 767 GoogleCredentials deserializedCredentials = serializeAndDeserialize(testCredentials); 768 assertEquals(testCredentials, deserializedCredentials); 769 assertEquals(testCredentials.hashCode(), deserializedCredentials.hashCode()); 770 assertEquals(testCredentials.toString(), deserializedCredentials.toString()); 771 assertSame(deserializedCredentials.clock, Clock.SYSTEM); 772 } 773 774 @Test toString_containsFields()775 public void toString_containsFields() throws IOException { 776 String expectedToString = 777 String.format( 778 "GoogleCredentials{quotaProjectId=%s, universeDomain=%s, isExplicitUniverseDomain=%s}", 779 "some-project", "googleapis.com", false, "[some scope]"); 780 GoogleCredentials credentials = 781 GoogleCredentials.newBuilder().setQuotaProjectId("some-project").build(); 782 assertEquals(expectedToString, credentials.toString()); 783 } 784 785 @Test hashCode_equals()786 public void hashCode_equals() throws IOException { 787 GoogleCredentials credentials = 788 GoogleCredentials.newBuilder().setUniverseDomain("some-domain").build(); 789 GoogleCredentials otherCredentials = 790 GoogleCredentials.newBuilder().setUniverseDomain("some-domain").build(); 791 assertEquals(credentials.hashCode(), otherCredentials.hashCode()); 792 } 793 794 @Test equals_true()795 public void equals_true() throws IOException { 796 GoogleCredentials credentials = 797 GoogleCredentials.newBuilder().setUniverseDomain("some-domain").build(); 798 GoogleCredentials otherCredentials = 799 GoogleCredentials.newBuilder().setUniverseDomain("some-domain").build(); 800 assertTrue(credentials.equals(otherCredentials)); 801 assertTrue(otherCredentials.equals(credentials)); 802 } 803 testFromStreamException(InputStream stream, String expectedMessageContent)804 private static void testFromStreamException(InputStream stream, String expectedMessageContent) { 805 try { 806 GoogleCredentials.fromStream(stream, DUMMY_TRANSPORT_FACTORY); 807 fail( 808 String.format( 809 "Should throw exception with message containing '%s'", expectedMessageContent)); 810 } catch (IOException expected) { 811 assertTrue(expected.getMessage().contains(expectedMessageContent)); 812 } 813 } 814 } 815