Closed vettloffah closed 3 years ago
I figured out how to solve the issue.
I would like to sbumit a pull request for this issue to add a sample to the gmail sample library. It would look something like this (can work on refactoring to match code style in other samples if you give me the go-ahead on submitting a PR):
const path = require('path');
const {google} = require('googleapis');
async getMessageList(userId, qty) {
const JWT = google.auth.JWT;
const authClient = new JWT({
keyFile: path.resolve(__dirname, 'google-key.json'),
scopes: ['https://www.googleapis.com/auth/gmail.readonly'],
subject: 'admin@example.com' // google admin email address to impersonate
});
await authClient.authorize(); // once authorized, can do whatever you want
const gmail = google.gmail({
auth: authClient,
version: 'v1'
});
const response = await gmail.users.messages.list({
includeSpamTrash: false,
maxResults: qty,
q: "",
userId: userId
});
// the data object includes a "messages" array of message data
return response.data;
}
@vettloffah What was the actual fix here? I am running into the same issue and have not been able to come up with a solution.
@cpereyra5199 i posted the solution in my last comment. You have to delegate the service to a specific user using JWT authentication
@vettloffah I would like to know "if you have used a service account for authorization?"
I have actually tried something similar with GoogleAuth. I didn't understand what went wrong here. I have even tried the approach which @vettloffah has mentioned by replacing the GoogleAuth code. Can someone point me to what's wrong here?
import { google } from "googleapis";
import dotenv from "dotenv";
import path from "path";
dotenv.config();
(async () => {
const SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"];
const fileName = process.env.GOOGLE_APPLICATION_CREDENTIALS!;
console.log({ fileName });
const keyFile = path.resolve("./",fileName);
console.log("calling gauth client");
const gAuth = new google.auth.GoogleAuth({
keyFile,
scopes: SCOPES,
});
google.options({ auth: gAuth });
const token = await gAuth.getAccessToken();
console.log({ token });
// token is getting generated here.
const gmail = await google.gmail({ auth: gAuth, version: "v1" });
const userId = process.env.SERVICE_ACCOUNT! || "me";
const messages = await gmail.users.messages.list({ userId, token });
console.log(messages);
})();
`
I have found another issue with a similar error here I am using a personal gmail account for this. And, I have created a service account for the same. @JustinBeckwith Can you let me know if this is possible or not?
The Gmail API isn't intended to be used with service accounts (other than domain-wide delegation use cases.) You need to be acting as a real user -- either using oauth credentials obtained with user consent, or in the case of a Gsuite domain, using a service account delegating/impersonating a real user.
I'll file a bug to make the error message clearer, but it's likely that the failed precondition is that the service account isn't a valid gmail user.
Greetings, we're closing this. Looks like the issue got resolved. Please let us know if the issue needs to be reopened.
The Gmail API isn't intended to be used with service accounts (other than domain-wide delegation use cases.) You need to be acting as a real user -- either using oauth credentials obtained with user consent, or in the case of a Gsuite domain, using a service account delegating/impersonating a real user.
I'll file a bug to make the error message clearer, but it's likely that the failed precondition is that the service account isn't a valid gmail user.
This is ridiculous.
So it has to be able to impersonate any user or none at all? Isn't that a pretty significant security risk?
Impersonation is neither required nor encouraged. Use regular OAuth 2.
Most of the conversation has been about wanting to use the gmail API with a service account where the service account is running as it's own identity. That isn't supported as gmail is inherently a product for human users. Service accounts with delegation is an option for some enterprise use cases, and the scope of delegation is users within that org.
There are handful of operations that actually require delegation, and that's mostly for security reasons. Settings that create forwarding rules are particularly sensitive as those forwarding rules persist even after a user has revoked access to an app. Anything guarded by https://www.googleapis.com/auth/gmail.settings.sharing is in that camp.
But the rest of the API no service accounts and no delegation required.
I'm trying to connect with the google API's for the first time, and when I attempt to make a request to the gmail API I'm getting a
Precondition check failed
error. I am using a service account authorization, not Oauth2 user consent. Things I've tried:This is adapted from a sample, but the sample did not use service account auth so I wasn't able to use the sample directly.
returning
Error: Precondition check failed.