Google api 使用JWT授权GMail API
我正在尝试从Node.js应用程序通过gmail API发送电子邮件。我已经完成了这项工作,遵循文档并使用node-mailer包。然而,我注意到,当我们更改组织密码时,连接不再良好,这是有意义的。因此,我尝试使用JWT进行授权 JWT已正确生成并发布到https://oauth2.googleapis.com/token. 然后,该请求返回一个访问令牌 在编写和发送电子邮件时,我试图简单地修改以前使用的代码,该代码使用的是客户机密码、客户机id和重定向URI:Google api 使用JWT授权GMail API,google-api,jwt,google-oauth,gmail-api,Google Api,Jwt,Google Oauth,Gmail Api,我正在尝试从Node.js应用程序通过gmail API发送电子邮件。我已经完成了这项工作,遵循文档并使用node-mailer包。然而,我注意到,当我们更改组织密码时,连接不再良好,这是有意义的。因此,我尝试使用JWT进行授权 JWT已正确生成并发布到https://oauth2.googleapis.com/token. 然后,该请求返回一个访问令牌 在编写和发送电子邮件时,我试图简单地修改以前使用的代码,该代码使用的是客户机密码、客户机id和重定向URI: const gmail = go
const gmail = google.gmail({ version: 'v1', auth: access_token });
gmail.users.messages.send(
{
userId: 'email',
resource: {
raw: encodedMessage
}
},
(err, result) => {
if (err) {
return console.log('NODEMAILER - The API returned: ' + err);
}
console.log(
'NODEMAILER Sending email reply from server: ' + result.data
);
}
);
API不断返回错误:需要登录
有人知道如何解决这个问题吗
编辑
我已修改了代码和密码以添加客户id和客户机密:
const oAuth2Client = new google.auth.OAuth2(
credentials.gmail.client_id,
credentials.gmail.client_secret,
credentials.gmail.redirect_uris[0]
);
oAuth2Client.credentials = {
access_token: access_token
};
const gmail = google.gmail({ version: 'v1', auth: oAuth2Client });
gmail.users.messages.send(
{
userId: 'email',
resource: {
raw: encodedMessage
}
},
(err, result) => {
if (err) {
return console.log('NODEMAILER - The API returned: ' + err);
}
console.log(
'NODEMAILER Sending email reply from server: ' + result.data
);
}
);
但现在错误更不精确了:错误:错误请求以下是对我有效的最终授权代码:
var credentials = require('../../credentials');
const privKey = credentials.gmail.priv_key.private_key;
var jwtParams = {
iss: credentials.gmail.priv_key.client_email,
scope: 'https://www.googleapis.com/auth/gmail.send',
aud: 'https://oauth2.googleapis.com/token',
exp: Math.floor(new Date().getTime() / 1000 + 120),
iat: Math.floor(new Date().getTime() / 1000),
sub: [INSERT EMAIL THAT WILL BE SENDING (not the service email, the one that has granted delegated access to the service account)]
};
var gmail_token = jwt.sign(jwtParams, privKey, {
algorithm: 'RS256'
});
var params = {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: gmail_token
};
var params_string = querystring.stringify(params);
axios({
method: 'post',
url: 'https://oauth2.googleapis.com/token',
data: params_string,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(response => {
let mail = new mailComposer({
to: [ARRAY OF RECIPIENTS],
text: [MESSAGE CONTENT],
subject: subject,
textEncoding: 'base64'
});
mail.compile().build((err, msg) => {
if (err) {
return console.log('Error compiling mail: ' + err);
}
const encodedMessage = Buffer.from(msg)
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
sendMail(encodedMessage, response.data.access_token, credentials);
});
});
因此,上面的代码段使用私钥创建JSON Web令牌JWT,其中:iss是要使用的服务帐户,scope是要访问的gmail API的端点这必须经过预授权,aud是google API oAuth2端点,exp是过期时间,iat是创建的时间,sub是服务帐户代理的电子邮件
然后对令牌进行签名,并向Google oAuth2端点发出POST请求。成功后,我使用NodeMailer的mailComposer组件构建电子邮件,其中包含一组收件人、一条消息、一个主题和一个编码。然后对该消息进行编码
下面是我的sendMail功能:
const oAuth2Client = new google.auth.OAuth2(
credentials.gmail.client_id,
credentials.gmail.client_secret,
credentials.gmail.redirect_uris[0]
);
oAuth2Client.credentials = {
access_token: access_token
};
const gmail = google.gmail({ version: 'v1', auth: oAuth2Client });
gmail.users.messages.send(
{
userId: 'me',
resource: {
raw: encodedMessage
}
},
(err, result) => {
if (err) {
return console.log('NODEMAILER - The API returned: ' + err);
}
console.log(
'NODEMAILER Sending email reply from server: ' + result.data
);
}
);
在这个函数中,我使用存储在外部文件中的服务帐户的凭据创建一个新的googleapis OAuth2对象,以增加安全性。然后,我用JWT传入auth脚本中生成的access_令牌。然后发送消息
请注意sendMail函数中的用户名:“me”,这对我来说至关重要。您能否分享更多有关您实际请求的信息?这是在获取访问令牌之前还是之后失败?你用的是什么范围?我可以建议你看看Hi@Raserhin吗?只有当邮件试图发送gmail.users.messages.send时,这才是失败的。正确生成access_令牌,唯一使用的作用域是www.googleapis/auth/gmail.send。我相信这可能与需要使用服务帐户有关?我需要此集成始终自动工作,无需用户授权。您如何验证您的服务帐户?据我所知,如果服务帐户不使用域范围的授权,他们就不能使用Gmail,想象一下所有可能产生的垃圾邮件。您正在使用域范围的委派吗?如果您不熟悉该主题,可以阅读或阅读。你真的试图从你的域中模拟一个用户吗?我发现了这个问题。出于某种原因,将userId设置为要模拟的电子邮件是不起作用的,但是将其设置为“我”就像一个字符一样起作用。不过,我很困惑,您是使用您帐户的凭据还是服务帐户的凭据?另外,请记住将您的解决方案作为答案发布,以便其他人可以从中受益。谢谢,@Phil!我花了几天的时间来寻找如何用GTW交换ID令牌,但官方文档中似乎不存在。