我正在尝试为我正在使用的聊天应用程序实现此Google People API。people API文档只有一个示例-https://github.com/googleworkspace/node-samples/blob/master/people/quickstart/index.js
我进行了一些更改以将其与我的项目集成。
// imports
const app = express();
app.use(cookieParser());
const SCOPES = ['https://www.googleapis.com/auth/contacts.readonly'];
const people = google.people('v1');
let credentials, oAuth2Client;
fs.readFile('./client_secret.json', async (err, content) => {
if (err) return console.error(err);
credentials = JSON.parse(content);
const { client_secret, client_id, redirect_uris } = credentials.web;
oAuth2Client = new google.auth.OAuth2(
client_id, client_secret, redirect_uris[1]);
});
app.get("/auth/google", (req, res) => {
console.log(req.cookies);
res.cookie("sample_cookie", "sample_value");
const authUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES,
});
console.log('Authorize this app by visiting this url:', authUrl);
res.redirect(authUrl);
});
app.get("/contacts", (req, resp) => {
if (req.cookies.access_token && req.cookies.refresh_token) {
const token = {
access_token: req.cookies.access_token,
refresh_token: req.cookies.refresh_token,
scope: req.cookies.scope,
token_type: "Bearer",
expiry_date: req.cookies.expiry_date,
}
oAuth2Client.setCredentials(token);
const service = google.people({ version: 'v1', oAuth2Client });
service.people.connections.list({
resourceName: 'people/me',
pageSize: 10,
personFields: 'names,emailAddresses,phoneNumbers',
}, (err, res) => {
if (err) return resp.send(err);
const connections = res.data.connections;
if (connections) {
connections.forEach((person) => {
if (person.names && person.names.length > 0) {
resp.write(person.names);
} else {
resp.write('No display name found for connection.');
}
});
} else {
resp.write('No connections found.');
}
resp.end();
});
} else {
res.send("Something's wrong yet.")
}
})
app.get(["/auth/google/callback", "authorized"], async (req, res) => {
const code = req.query.code;
oAuth2Client.getToken(code, (err, token) => {
if (err) return console.error('Error retrieving access token', err);
oAuth2Client.setCredentials(token);
res.cookie("access_token", token.access_token);
res.cookie("refresh_token", token.refresh_token);
res.cookie("scope", token.scope);
res.cookie("token_type", token.token_type);
res.cookie("expiry_date", token.expiry_date);
res.send("Done.")
})
})
app.listen(3000, () => {
console.log("running");
})
但我收到401:未经授权。我对前一个(google)示例所做的所有更改只是将详细信息保存为Cookie,而不是将详细信息保存到令牌中,并且添加了从浏览器访问它的路由。谷歌提供的示例按预期工作。在授权点之前,我所做的更改同样有效,但是当尝试访问联系人路由时,它将返回以下响应。
这是我正在接受的回复(仅包含我认为必要的详细信息):
{
"response": {
"config": {
"oAuth2Client": {
"credentials": {
"access_token": "my_access_token",
"refresh_token": "my_refresh_token",
"scope": "https://www.googleapis.com/auth/contacts.readonly",
"token_type": "Bearer",
"expiry_date": 1609256514576
},
"redirectUri": "http://localhost:3000/auth/google/callback",
},
"url": "https://people.googleapis.com/v1/people/me/connections?pageSize=10&personFields=names%2CemailAddresses%2CphoneNumbers",
"method": "GET",
"headers": {
"Accept-Encoding": "gzip",
"User-Agent": "google-api-nodejs-client/0.7.2 (gzip)",
"Accept": "application/json"
},
},
"data": {
"error": {
"code": 401,
"message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"errors": [{
"message": "Login Required.",
"domain": "global",
"reason": "required",
"location": "Authorization",
"locationType": "header"
}],
"status": "UNAUTHENTICATED"
}
},...
我试图调试代码。我什么都抓不到。但是我注意到的一件事是,在以上响应中,我没有设置Authorization标头。收到来自Google文档示例的成功API请求后,我收到了
{
"config": {
"url": "https://people.googleapis.com/v1/people/me/connections?pageSize=10&personFields=names%2CemailAddresses%2CphoneNumbers",
"method": "GET",
"headers": {
"Accept-Encoding": "gzip",
"User-Agent": "google-api-nodejs-client/0.7.2 (gzip)",
"Authorization": "Bearer access-code",
"Accept": "application/json"
},
},
"data": {
"connections": [{...
我不明白为什么我的代码没有设置Authorization标头,而且在此成功响应中也没有OAuthClient和凭据字段。如果我不是使用人的api,而是尝试在联系人路由中尝试以下操作,或者在邮递员中使用Bearer令牌提出GET请求,则可以正确获得响应。
let bearer = `Bearer ${req.cookies.access_token}`;
request({
url: 'https://people.googleapis.com/v1/people/me/connections?pageSize=10&personFields=names%2CemailAddresses%2CphoneNumbers',
headers: {
'Authorization': bearer
}}, (err, res) => {
if (err) {
console.error(err);
} else {
resp.send(res);
}
}
);
我正确收到了回复。但是我不想这样做。我无法弄清楚我的代码有什么问题,或者有人可以提供其他任何有效的示例……我也尝试使用passport.js,但遇到相同的401未经授权的错误。
// passport-setup.js
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (user, done) {
done(null, user);
});
passport.use(new GoogleStrategy({
clientID: "client-id",
clientSecret: "client-secret",
callbackURL: "http://localhost:3000/auth/google/callback",
passReqToCallback: true
},
function (req, accessToken, refreshToken, otherTokenDetails, profile, done) {
req.session.accessToken = accessToken;
req.session.refreshToken = refreshToken;
req.session.scope = otherTokenDetails.scope;
req.session.token_type = otherTokenDetails.token_type;
req.session.expiry_date = new Date().getTime() + otherTokenDetails.expires_in;
return done(null, profile);
}
));
index.js
// importing express, cors, bodyParser, passport, cookieSession, passport setup and googleapis
const app = express();
const people = google.people('v1');
// app.use(cors, bodyParser, cookieSession, passport init and session)
const isLoggedIn = (req, res, next) => {
if (req.user) {
next();
}
else {
res.sendStatus(401);
}
}
app.get("/success", isLoggedIn, (req, resp) => {
const oAuth2Client = new google.auth.OAuth2(id, secret and url...)
const token = {
access_token: req.session.accessToken,
refresh_token: req.session.refreshToken,
scope: req.session.scope,
token_type: req.session.token_type,
expiry_date: req.session.expiry_date,
}
oAuth2Client.setCredentials(token);
const service = google.people({ version: 'v1', oAuth2Client });
service.people.connections.list({
resourceName: 'people/me',
pageSize: 10,
personFields: 'names,emailAddresses,phoneNumbers',
}, (err, res) => {
if (err) return resp.send(err);
const connections = res.data.connections;
if (connections) {
console.log('Connections:');
connections.forEach((person) => {
if (person.names && person.names.length > 0) {
resp.write(person.names);
} else {
resp.write('No display name found for connection.');
}
});
} else {
resp.write("No connections.");
}
res.end();
});
})
app.get('/auth/google',
passport.authenticate('google', {
scope: ['profile', 'email', 'https://www.googleapis.com/auth/contacts'],
accessType: 'offline',
prompt: 'consent',
}));
app.get('/auth/google/callback',
passport.authenticate('google', { failureRedirect: '/login' }),
function (req, res) {
res.redirect('/success');
});
app.listen(3000, () => console.log("Server is up and running on port 3000."));
是的,我检查了几乎所有类似的StackOverflow答案和GitHub问题。似乎什么都没有解决。所以,请我要求金牌启动节点js的人们不要盲目地将其标记为重复。请。
传递给google.people的第二个参数的名称为auth
。在JavaScript中,您可以编写{auth: auth}
简单{auth}
。在google提供的示例中,变量的名称与字段名称相同,这就是为什么将其直接提供为auth
const service = google.people({ version: 'v1', auth });
但是您的变量名不同于字段名。因此,请更改名称或仅将这一行替换为
const service = google.people({ version: 'v1', auth: oAuth2Client });
它期望auth
作为第二个属性,但是它收到一个带有名称的属性oAuth2Client
,这就是它不起作用的原因。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句