Javascript 谷歌认证令牌返回不';不包含刷新令牌
我用..写了一个关于GoogleAPI的例子。我遵循了指令集Javascript 谷歌认证令牌返回不';不包含刷新令牌,javascript,node.js,google-api,google-oauth,google-api-nodejs-client,Javascript,Node.js,Google Api,Google Oauth,Google Api Nodejs Client,我用..写了一个关于GoogleAPI的例子。我遵循了指令集access\u type:“offline”,但是返回的对象不包含refresh\u标记 我的代码: var http = require('http'); var express = require('express'); var Session = require('express-session'); var google = require('googleapis'); var plus = google.plus('v1')
access\u type:“offline”
,但是返回的对象不包含refresh\u标记
我的代码:
var http = require('http');
var express = require('express');
var Session = require('express-session');
var google = require('googleapis');
var plus = google.plus('v1');
var OAuth2 = google.auth.OAuth2;
const ClientId = "251872680446-rvkcvm5mjn1ps32iabf4i2611hcg086e.apps.googleusercontent.com";
const ClientSecret = "F1qG9fFS-QwcrEfZbT8VmUnx";
const RedirectionUrl = "http://localhost:8081/oauthCallback";
var app = express();
app.use(Session({
secret: 'raysources-secret-19890913007',
resave: true,
saveUninitialized: true
}));
function getOAuthClient () {
return new OAuth2(ClientId , ClientSecret, RedirectionUrl);
}
function getAuthUrl () {
var oauth2Client = getOAuthClient();
// generate a url that asks permissions for Google+ and Google Calendar scopes
var scopes = [
'https://www.googleapis.com/auth/plus.me'
];
var url = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: scopes // If you only need one scope you can pass it as string
});
return url;
}
app.use("/oauthCallback", function (req, res) {
var oauth2Client = getOAuthClient();
var session = req.session;
var code = req.query.code;
oauth2Client.getToken(code, function(err, tokens) {
console.log("tokens : ", tokens);
// Now tokens contains an access_token and an optional refresh_token. Save them.
if(!err) {
oauth2Client.setCredentials(tokens);
session["tokens"]=tokens;
res.send(`
<html>
<body>
<h3>Login successful!!</h3>
<a href="/details">Go to details page</a>
<body>
<html>
`);
}
else{
res.send(`
<html>
<body>
<h3>Login failed!!</h3>
</body>
</html>
`);
}
});
});
app.use("/details", function (req, res) {
var oauth2Client = getOAuthClient();
oauth2Client.setCredentials(req.session["tokens"]);
var p = new Promise(function (resolve, reject) {
plus.people.get({ userId: 'me', auth: oauth2Client }, function(err, response) {
console.log("response : " , response);
resolve(response || err);
});
}).then(function (data) {
res.send(`<html><body>
<img src=${data.image.url} />
<h3>Hello ${data.displayName}</h3>
</body>
</html>
`);
})
});
app.use("/", function (req, res) {
var url = getAuthUrl();
res.send(`
<html>
<body>
<h1>Authentication using google oAuth</h1>
<a href=${url}>Login</a>
</body>
</html>
`)
});
var port = 8081;
var server = http.createServer(app);
server.listen(port);
server.on('listening', function () {
console.log(`listening to ${port}`);
});
var http=require('http');
var express=需要(“express”);
var会话=需要(“快速会话”);
var google=require('googleapis');
var plus=google.plus('v1');
var OAuth2=google.auth.OAuth2;
const ClientId=“251872680446-rvkcvm5mjn1ps32iabf4i2611hcg086e.apps.googleusercontent.com”;
const ClientSecret=“F1qG9fFS-QwcrEfZbT8VmUnx”;
常量重定向URL=”http://localhost:8081/oauthCallback";
var-app=express();
应用程序使用(会话)({
秘密:'raysources-secret-19890913007',
雷萨夫:是的,
saveUninitialized:true
}));
函数getOAuthClient(){
返回新的OAuth2(ClientId、ClientSecret、RedirectionUrl);
}
函数getAuthUrl(){
var oauth2Client=getOAuthClient();
//生成请求Google+和Google日历范围权限的url
变量作用域=[
'https://www.googleapis.com/auth/plus.me'
];
var url=oauth2Client.generateAuthUrl({
访问类型:“脱机”,
scope:scopes//如果只需要一个作用域,则可以将其作为字符串传递
});
返回url;
}
应用程序使用(“/oauthCallback”,函数(req,res){
var oauth2Client=getOAuthClient();
var会话=请求会话;
var代码=req.query.code;
oauth2Client.getToken(代码、函数(错误、标记){
日志(“令牌:”,令牌);
//现在令牌包含一个访问令牌和一个可选的刷新令牌。保存它们。
如果(!err){
oauth2Client.setCredentials(令牌);
会话[“令牌”]=令牌;
res.send(`
登录成功!!
`);
}
否则{
res.send(`
登录失败!!
`);
}
});
});
应用程序使用(“/details”,函数(请求,res){
var oauth2Client=getOAuthClient();
oauth2Client.setCredentials(请求会话[“令牌]);
var p=新承诺(功能(解决、拒绝){
plus.people.get({userId:'me',auth:oauth2Client},函数(err,response){
日志(“响应:”,响应);
解决(回答| |错误);
});
}).then(功能(数据){
res.send(`
您好${data.displayName}
`);
})
});
应用程序使用(“/”,功能(请求,恢复){
var url=getAuthUrl();
res.send(`
使用googleoauth进行身份验证
`)
});
var端口=8081;
var server=http.createServer(app);
监听(端口);
server.on('listening',function(){
log(`listing to${port}`);
});
在某些情况下(主要是Web客户端),刷新令牌仅在用户第一次通过身份验证时发送
如果您要删除有问题的应用程序。然后重试并验证。选中后,现在应该有一个刷新令牌。用户在批准指定的范围后首次登录到应用程序时,刷新令牌只发送一次
编辑2018年8月:使用批准提示:“强制”
不再有效,您需要使用提示:“同意”
(检查@Alexander的答案)
如果希望在每次用户登录时获得刷新令牌(即使用户之前已经登录并批准了范围),则必须在Oauth2Client
配置中指定prompt:“同意”
:
var url = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: scopes,
prompt : 'consent'
});
请注意,这将要求用户在每次单击您的链接进行身份验证时接受指定的作用域:
您还可以在中手动禁用应用程序,这将撤销该应用程序,并且用户必须再次接受作用域,这将触发下次验证时发送的刷新\u令牌
:
仅供参考,如果您需要脱机使用access\u令牌
,您必须在服务器端存储refresh\u令牌
,当您从Google API接收到状态401时,使用存储的refresh\u令牌
刷新访问令牌。因此,如果您按照应该的方式存储refresh\u令牌
,实际上不需要使用提示符:“同意”
,每次用户连接到您的应用程序时都强制用户批准作用域。根据此规则,只有在第一次授权时才会返回refresh\u令牌
您可以手动删除以下权限:
您还可以通过在授权URL中传递&prompt=approve,强制用户再次查看屏幕,只需添加以下参数:
var url = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: scopes,
prompt: 'consent'
});
这对我来说很好:)你什么意思?我不明白。实际上我使用这段代码。你能帮我修一下吗?没有错。使用set access_type时遵循:generateAuthUrl中的“offline”返回的令牌将包含refresh_令牌,但我设置了,它不起作用。您可以检查第30行否,它不是我的代码。你能修好吗?