@Override public String getAccount() { return getClientEmail(); }
@Override public byte[] sign(byte[] toSign) { try { Signature signer = Signature.getInstance(OAuth2Utils.SIGNATURE_ALGORITHM); signer.initSign(getPrivateKey()); signer.update(toSign); return signer.sign(); } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException ex) { throw new ServiceAccountSigner.SigningException("Failed to sign the provided bytes", ex); } }
/** * Factory using PKCS#8 for the private key. * * @param clientId Client ID of the service account from the console. May be null. * @param clientEmail Client email address of the service account from the console. * @param privateKeyPkcs8 RSA private key object for the service account in PKCS#8 format. * @param privateKeyId Private key identifier for the service account. May be null. * @return New ServiceAccountJwtAcceessCredentials created from a private key. * @throws IOException if the credential cannot be created from the private key. */ public static ServiceAccountJwtAccessCredentials fromPkcs8(String clientId, String clientEmail, String privateKeyPkcs8, String privateKeyId) throws IOException { return fromPkcs8(clientId, clientEmail, privateKeyPkcs8, privateKeyId, null); }
@Test public void constructor_allParameters_constructs() throws IOException { PrivateKey privateKey = ServiceAccountCredentials.privateKeyFromPkcs8(SA_PRIVATE_KEY_PKCS8); ServiceAccountJwtAccessCredentials credentials = ServiceAccountJwtAccessCredentials.newBuilder() .setClientId(SA_CLIENT_ID) .setClientEmail(SA_CLIENT_EMAIL) .setPrivateKey(privateKey) .setPrivateKeyId(SA_PRIVATE_KEY_ID) .build(); assertEquals(SA_CLIENT_ID, credentials.getClientId()); assertEquals(SA_CLIENT_EMAIL, credentials.getClientEmail()); assertEquals(privateKey, credentials.getPrivateKey()); assertEquals(SA_PRIVATE_KEY_ID, credentials.getPrivateKeyId()); }
@Test public void getRequestMetadata_blocking_cached() throws IOException { TestClock testClock = new TestClock(); PrivateKey privateKey = ServiceAccountCredentials.privateKeyFromPkcs8(SA_PRIVATE_KEY_PKCS8); ServiceAccountJwtAccessCredentials credentials = ServiceAccountJwtAccessCredentials.newBuilder() .setClientId(SA_CLIENT_ID) .setClientEmail(SA_CLIENT_EMAIL) .setPrivateKey(privateKey) .setPrivateKeyId(SA_PRIVATE_KEY_ID) .build(); credentials.clock = testClock; Map<String, List<String>> metadata1 = credentials.getRequestMetadata(CALL_URI); // Fast forward time a little long lifeSpanMs = TimeUnit.SECONDS.toMillis(10); testClock.setCurrentTime(lifeSpanMs); Map<String, List<String>> metadata2 = credentials.getRequestMetadata(CALL_URI); assertEquals(metadata1, metadata2); }
/** * Initializes OAuth2 credential from a private keyfile, as described in * <a href="https://developers.google.com/api-client-library/java/google-api-java-client/oauth2#service_accounts" * >Service accounts</a>. * * @param serviceAccountEmail Email address of the service account associated with the keyfile. * @param privateKeyFile Full local path to private keyfile. * @return a {@link com.google.auth.Credentials} object. * @throws java.io.IOException if any. * @throws java.security.GeneralSecurityException if any. */ public static Credentials getCredentialFromPrivateKeyServiceAccount( String serviceAccountEmail, String privateKeyFile) throws IOException, GeneralSecurityException { PrivateKey privateKey = SecurityUtils.loadPrivateKeyFromKeyStore(SecurityUtils.getPkcs12KeyStore(), new FileInputStream(privateKeyFile), "notasecret", "privatekey", "notasecret"); return ServiceAccountJwtAccessCredentials.newBuilder() .setClientEmail(serviceAccountEmail) .setPrivateKey(privateKey) .build(); }
@Test public void sign_sameAs() throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException { PrivateKey privateKey = ServiceAccountCredentials.privateKeyFromPkcs8(SA_PRIVATE_KEY_PKCS8); byte[] toSign = {0xD, 0xE, 0xA, 0xD}; ServiceAccountJwtAccessCredentials credentials = ServiceAccountJwtAccessCredentials.newBuilder() .setClientId(SA_CLIENT_ID) .setClientEmail(SA_CLIENT_EMAIL) .setPrivateKey(privateKey) .setPrivateKeyId(SA_PRIVATE_KEY_ID) .build(); byte[] signedBytes = credentials.sign(toSign); Signature signature = Signature.getInstance(OAuth2Utils.SIGNATURE_ALGORITHM); signature.initSign(credentials.getPrivateKey()); signature.update(toSign); assertArrayEquals(signature.sign(), signedBytes); }
@Test public void equals_false_clientId() throws IOException { PrivateKey privateKey = ServiceAccountCredentials.privateKeyFromPkcs8(SA_PRIVATE_KEY_PKCS8); ServiceAccountJwtAccessCredentials credentials = ServiceAccountJwtAccessCredentials.newBuilder() .setClientId(SA_CLIENT_ID) .setClientEmail(SA_CLIENT_EMAIL) .setPrivateKey(privateKey) .setPrivateKeyId(SA_PRIVATE_KEY_ID) .setDefaultAudience(CALL_URI) .build(); ServiceAccountJwtAccessCredentials otherCredentials = ServiceAccountJwtAccessCredentials.newBuilder() .setClientId("otherClientId") .setClientEmail(SA_CLIENT_EMAIL) .setPrivateKey(privateKey) .setPrivateKeyId(SA_PRIVATE_KEY_ID) .setDefaultAudience(CALL_URI) .build(); assertFalse(credentials.equals(otherCredentials)); assertFalse(otherCredentials.equals(credentials)); }
@Test public void serialize() throws IOException, ClassNotFoundException { PrivateKey privateKey = ServiceAccountCredentials.privateKeyFromPkcs8(SA_PRIVATE_KEY_PKCS8); ServiceAccountJwtAccessCredentials credentials = ServiceAccountJwtAccessCredentials.newBuilder() .setClientId(SA_CLIENT_ID) .setClientEmail(SA_CLIENT_EMAIL) .setPrivateKey(privateKey) .setPrivateKeyId(SA_PRIVATE_KEY_ID) .setDefaultAudience(CALL_URI) .build(); ServiceAccountJwtAccessCredentials deserializedCredentials = serializeAndDeserialize(credentials); verifyJwtAccess(deserializedCredentials.getRequestMetadata(), SA_CLIENT_EMAIL, CALL_URI, SA_PRIVATE_KEY_ID); assertEquals(credentials, deserializedCredentials); assertEquals(credentials.hashCode(), deserializedCredentials.hashCode()); assertEquals(credentials.toString(), deserializedCredentials.toString()); assertSame(deserializedCredentials.clock, Clock.SYSTEM); }
@Test public void getAccount_sameAs() throws IOException { PrivateKey privateKey = ServiceAccountCredentials.privateKeyFromPkcs8(SA_PRIVATE_KEY_PKCS8); ServiceAccountJwtAccessCredentials credentials = ServiceAccountJwtAccessCredentials.newBuilder() .setClientId(SA_CLIENT_ID) .setClientEmail(SA_CLIENT_EMAIL) .setPrivateKey(privateKey) .setPrivateKeyId(SA_PRIVATE_KEY_ID) .build(); assertEquals(SA_CLIENT_EMAIL, credentials.getAccount()); }
@Test public void hashCode_equals() throws IOException { PrivateKey privateKey = ServiceAccountCredentials.privateKeyFromPkcs8(SA_PRIVATE_KEY_PKCS8); ServiceAccountJwtAccessCredentials credentials = ServiceAccountJwtAccessCredentials.newBuilder() .setClientId(SA_CLIENT_ID) .setClientEmail(SA_CLIENT_EMAIL) .setPrivateKey(privateKey) .setPrivateKeyId(SA_PRIVATE_KEY_ID) .setDefaultAudience(CALL_URI) .build(); ServiceAccountJwtAccessCredentials otherCredentials = ServiceAccountJwtAccessCredentials.newBuilder() .setClientId(SA_CLIENT_ID) .setClientEmail(SA_CLIENT_EMAIL) .setPrivateKey(privateKey) .setPrivateKeyId(SA_PRIVATE_KEY_ID) .setDefaultAudience(CALL_URI) .build(); assertEquals(credentials.hashCode(), otherCredentials.hashCode()); }
@Test public void toString_containsFields() throws IOException { PrivateKey privateKey = ServiceAccountCredentials.privateKeyFromPkcs8(SA_PRIVATE_KEY_PKCS8); ServiceAccountJwtAccessCredentials credentials = ServiceAccountJwtAccessCredentials.newBuilder() .setClientId(SA_CLIENT_ID) .setClientEmail(SA_CLIENT_EMAIL) .setPrivateKey(privateKey) .setPrivateKeyId(SA_PRIVATE_KEY_ID) .setDefaultAudience(CALL_URI) .build(); String expectedToString = String.format( "ServiceAccountJwtAccessCredentials{clientId=%s, clientEmail=%s, privateKeyId=%s, " + "defaultAudience=%s}", SA_CLIENT_ID, SA_CLIENT_EMAIL, SA_PRIVATE_KEY_ID, CALL_URI); assertEquals(expectedToString, credentials.toString()); }
/** * Returns credentials defined by a Service Account key file in JSON format from the Google * Developers Console. * * @param credentialsStream the stream with the credential definition. * @return the credential defined by the credentialsStream. * @throws IOException if the credential cannot be created from the stream. **/ public static ServiceAccountJwtAccessCredentials fromStream(InputStream credentialsStream) throws IOException { return fromStream(credentialsStream, null); }
@Test public void serviceAccountReplacedWithJwtTokens() throws Exception { ServiceAccountCredentials serviceAccountCredentials = ServiceAccountCredentials.newBuilder() .setClientId("fake-client-id") .setClientEmail("fake@example.com") .setPrivateKeyId("fake-private-key") .setPrivateKey(Mockito.mock(PrivateKey.class)) .build(); PowerMockito.mockStatic(GoogleCredentials.class); Mockito.when(GoogleCredentials.getApplicationDefault()).thenReturn(serviceAccountCredentials); GoogleCredentialsProvider provider = GoogleCredentialsProvider.newBuilder() .setScopesToApply(ImmutableList.of("scope1", "scope2")) .setJwtEnabledScopes(ImmutableList.of("scope1")) .build(); Credentials credentials = provider.getCredentials(); assertThat(credentials).isInstanceOf(ServiceAccountJwtAccessCredentials.class); ServiceAccountJwtAccessCredentials jwtCreds = (ServiceAccountJwtAccessCredentials) credentials; assertThat(jwtCreds.getClientId()).isEqualTo(serviceAccountCredentials.getClientId()); assertThat(jwtCreds.getClientEmail()).isEqualTo(serviceAccountCredentials.getClientEmail()); assertThat(jwtCreds.getPrivateKeyId()).isEqualTo(serviceAccountCredentials.getPrivateKeyId()); assertThat(jwtCreds.getPrivateKey()).isEqualTo(serviceAccountCredentials.getPrivateKey()); }
@Test public void getRequestMetadata_blocking_cache_expired() throws IOException { TestClock testClock = new TestClock(); PrivateKey privateKey = ServiceAccountCredentials.privateKeyFromPkcs8(SA_PRIVATE_KEY_PKCS8); ServiceAccountJwtAccessCredentials credentials = ServiceAccountJwtAccessCredentials.newBuilder() .setClientId(SA_CLIENT_ID) .setClientEmail(SA_CLIENT_EMAIL) .setPrivateKey(privateKey) .setPrivateKeyId(SA_PRIVATE_KEY_ID) .build(); credentials.clock = testClock; Map<String, List<String>> metadata1 = credentials.getRequestMetadata(CALL_URI); // Fast forward time past the expiration long lifeSpanMs = TimeUnit.SECONDS.toMillis(ServiceAccountJwtAccessCredentials.LIFE_SPAN_SECS); testClock.setCurrentTime(lifeSpanMs); Map<String, List<String>> metadata2 = credentials.getRequestMetadata(CALL_URI); assertNotEquals(metadata1, metadata2); }
private static Credentials getJwtToken(ServiceAccountCredentials serviceAccount) { return ServiceAccountJwtAccessCredentials.newBuilder() .setClientEmail(serviceAccount.getClientEmail()) .setClientId(serviceAccount.getClientId()) .setPrivateKey(serviceAccount.getPrivateKey()) .setPrivateKeyId(serviceAccount.getPrivateKeyId()) .build(); } }
@Test public void equals_false_callUri() throws IOException { PrivateKey privateKey = ServiceAccountCredentials.privateKeyFromPkcs8(SA_PRIVATE_KEY_PKCS8); final URI otherCallUri = URI.create("https://foo.com/bar"); ServiceAccountJwtAccessCredentials credentials = ServiceAccountJwtAccessCredentials.newBuilder() .setClientId(SA_CLIENT_ID) .setClientEmail(SA_CLIENT_EMAIL) .setPrivateKey(privateKey) .setPrivateKeyId(SA_PRIVATE_KEY_ID) .setDefaultAudience(CALL_URI) .build(); ServiceAccountJwtAccessCredentials otherCredentials = ServiceAccountJwtAccessCredentials.newBuilder() .setClientId(SA_CLIENT_ID) .setClientEmail(SA_CLIENT_EMAIL) .setPrivateKey(privateKey) .setPrivateKeyId(SA_PRIVATE_KEY_ID) .setDefaultAudience(otherCallUri) .build(); assertFalse(credentials.equals(otherCredentials)); assertFalse(otherCredentials.equals(credentials)); }
/** * Returns credentials defined by a Service Account key file in JSON format from the Google * Developers Console. * * @param credentialsStream the stream with the credential definition. * @return the credential defined by the credentialsStream. * @throws IOException if the credential cannot be created from the stream. **/ public static ServiceAccountJwtAccessCredentials fromStream(InputStream credentialsStream) throws IOException { return fromStream(credentialsStream, null); }
@Test public void getRequestMetadata_blocking_hasJwtAccess() throws IOException { PrivateKey privateKey = ServiceAccountCredentials.privateKeyFromPkcs8(SA_PRIVATE_KEY_PKCS8); ServiceAccountJwtAccessCredentials credentials = ServiceAccountJwtAccessCredentials.newBuilder() .setClientId(SA_CLIENT_ID) .setClientEmail(SA_CLIENT_EMAIL) .setPrivateKey(privateKey) .setPrivateKeyId(SA_PRIVATE_KEY_ID) .build(); Map<String, List<String>> metadata = credentials.getRequestMetadata(CALL_URI); verifyJwtAccess(metadata, SA_CLIENT_EMAIL, CALL_URI, SA_PRIVATE_KEY_ID); }
@Test public void constructor_noPrivateKeyId_constructs() throws IOException { PrivateKey privateKey = ServiceAccountCredentials.privateKeyFromPkcs8(SA_PRIVATE_KEY_PKCS8); ServiceAccountJwtAccessCredentials.newBuilder() .setClientId(SA_CLIENT_ID) .setClientEmail(SA_CLIENT_EMAIL) .setPrivateKey(privateKey) .build(); }