Server-side OAuth for user impersonation via GMail

2019-08-12 09:26发布

问题:

I am trying to perform server-side OAuth so I can use a specific user account in my domain to send emails (hence using GMail API) via my application.

Mine is a purely server-side app and I cannot perform "user consent" via a UI.

I have created a project in Google App Engine and have obtained service account credentials (P12 key).

My code looks like this -

new GoogleCredential.Builder()
  .setTransport(httpTransport)
  .setJsonFactory(JSON_FACTORY)
  .setServiceAccountId(googleEmailerServiceAccountId)
  .setServiceAccountPrivateKeyFromP12File(new File(googleEmailerServiceAccountPrivateKeyLocation)).setServiceAccountScopes(Collections.singleton(GmailScopes.GMAIL_COMPOSE))
  .setServiceAccountUser("xxx@xxx.com")
  .build()

I have delegated domain wide access to the application (for GMAIL COMPOSE scope) via the admin console as per https://developers.google.com/identity/protocols/OAuth2ServiceAccount.

And I still get an Unauthorised 401 when I try to send emails from my app.

Since there is no explicit documentation for the Gmail API that says it allows domain wide delegation, I am guessing it is not allowed for Gmail.

Is there any way of achieving this programatically?

Any idea would be much appreciated. Thanks!

回答1:

As far as I know you cant use a service account with Gmail. Service accounts must be pre authorized.

Authorizing Your App with Gmail

All requests to the Gmail API must be authorized by an authenticated user. Gmail uses the OAuth 2.0 protocol for authenticating a Google account and authorizing access to user data. You can also use Google+ Sign-in to provide a "sign-in with Google" authentication method for your app.

  1. Share a Google drive folder with the Service account. Add the service account email as a user on a google drive folder it has access
  2. Share a Google calendar with the service account, just like any other user.

Service accounts don't work on all Google APIs. To my knowledge you cant give another user access to your Gmail so there will be now to pre authorize the service account.

Recommendation / work around / hack

Create a dummy app using the same client id, authenticate it get the refresh token then use the refresh token in your application.