My standard AppEngine application needs to perform changes in a Google Sheet documents (among others).
To achieve this, I need to obtain a credential for service account, and somehow configure that it should act in behalf of a user.
This method allows gives me default service account credentials:
private static GoogleCredential getDefaultServiceAccountCredential() throws IOException {
return GoogleCredential.getApplicationDefault()
.createScoped(MY_SCOPES);
}
but it does not work in behalf of a user.
Following code is similar, uses other (non-default) service account, but still no impersonation happens:
private static GoogleCredential getNonDefaultServiceAccountCredential() throws IOException {
return GoogleCredential.fromStream(IncomingMailHandlerServlet.class.getResourceAsStream("/tokens/anoher-e6351a8c5b91.json"))
.createScoped(MY_SCOPES);
}
For impersonation, Google Docs (and many SO advices) mentions how to do it with use of PKCS12 file; however, that file can only be read as PrivateKey
on installed application and not on AppEngine.
Is there any way to obtain impersonated credential for java application running in AppEngine?
Or, is there a trick to read from a File
on AppEngine?
Note that, for all service accounts that I tried, I configured them with role Owner and with DwD (Domain-wide delegation). Is there anything else to configure?
The GoogleCredential reference offers a sample to
also use the service account flow to impersonate a user in a domain that you own. This is very similar to the service account flow above, but you additionally call GoogleCredential.Builder.setServiceAccountUser(String)
public static GoogleCredential createCredentialForServiceAccountImpersonateUser(
HttpTransport transport,
JsonFactory jsonFactory,
String serviceAccountId,
Collection<String> serviceAccountScopes,
File p12File,
String serviceAccountUser) throws GeneralSecurityException, IOException {
return new GoogleCredential.Builder().setTransport(transport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(serviceAccountId)
.setServiceAccountScopes(serviceAccountScopes)
.setServiceAccountPrivateKeyFromP12File(p12File)
.setServiceAccountUser(serviceAccountUser)
.build();
}
There are multiple options on how to access a file from App Engine Standard. Below, you have two options explained:
p12File
(credentials file) is an App Engine Standard resource file. Check this answer to see how to access such files, code-wise. I strongly recommend this approach because
These files are only available to your code on a read-only basis and not for traffic serving.
File f = new File("path/below/my/project/directory/credentials.json");
and the appengine-web.xml
should define the resource files:
<resource-files>
<include path="path/below/my/project/directory/credentials.json"/>
</resource-files>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With