GraphQL 中的社交身份验证
Social authentication in GraphQL
我正在创建一个依赖于 Express 和 GraphQL 的后端,它将为客户端应用程序提供服务(android 并作出反应)。
我一直在关注这个article on how to nail social authentication in GraphQL using passport.js。
文章使用passport-google-token strategy and is based on Apollo-server but personally I prefer to use express-graphql.
将我的 android 应用程序设置为使用 google 身份验证并尝试向服务器发送突变后,我收到此错误
Google info: { InternalOAuthError: failed to fetch user profile
at E:\_Projects\myProject\myProject-backend\node_modules\passport-google-token\lib\passport-google-token\strategy.js:114:28
at passBackControl (E:\_Projects\myProject\myProject-backend\node_modules\oauth\lib\oauth2.js:132:9)
at IncomingMessage.<anonymous> (E:\_Projects\myProject\myProject-backend\node_modules\oauth\lib\oauth2.js:157:7)
at IncomingMessage.emit (events.js:194:15)
at endReadableNT (_stream_readable.js:1125:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
name: 'InternalOAuthError',
message: 'failed to fetch user profile',
oauthError:
{ statusCode: 401,
data:
'{\n "error": {\n "code": 401,\n "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.",\n "status": "UNAUTHENTICATED"\n }\n}\n' } }
我相信我传递的令牌可能没有达到预期的位置,但我不知道如何解决。
我已经在这里 https://oauth2.googleapis.com/tokeninfo?id_token=MyToken 测试了我的令牌,它们工作正常。
这是 app.js
中的 graphQL 配置
app.use('/graphql', graphqlHTTP((req, res) => ({
schema,
graphiql: true,
context: {req, res}
})));
这里是google auth mutation
googleAuth: {
type: authPayLoad,
args: {token: {type: new GraphQLNonNull(GraphQLString)}},
async resolve(_, {token}, {req, res}) {
req.body = {
...req.body,
access_token: token,
};
try {
const {data, info} = await authenticateGoogle(req, res);
console.log("Google data: ", data);
if (data) {
const user = await User.upsertGoogleUser(data);
if (user) {
return ({
name: user.name,
username: user.username,
token: user.generateJWT(),
});
}
}
if (info) {
console.log("Google info: ", info);
switch (info.code) {
case 'ETIMEDOUT':
return (new Error('Failed to reach Google: Try Again'));
default:
return (new Error('something went wrong'));
}
}
return (Error('server error'));
} catch (e) {
console.log("Error: ", e);
return e
}
},
},
这是我的授权控制器
const passport = require('passport');
const {Strategy: GoogleTokenStrategy} = require('passport-google-token');
// GOOGLE STRATEGY
const GoogleTokenStrategyCallback = (accessToken, refreshToken, profile, done) => done(null, {
accessToken,
refreshToken,
profile,
});
passport.use(new GoogleTokenStrategy({
clientID: 'MY_CLIET_ID',
clientSecret: 'SERVER-SECRET'
}, GoogleTokenStrategyCallback));
module.exports.authenticateGoogle = (req, res) => new Promise((resolve, reject) => {
passport.authenticate('google-token', {session: false}, (err, data, info) => {
if (err) reject(err);
resolve({data, info});
})(req, res);
});
我预计当客户端应用程序提交带有令牌作为 arg 的突变时,请求将被发送到 google 和 returns 用户数据。我该如何解决这个问题。
passport-google-token is archived and seems deprecated to me. Why don't you try passport-token-google。
可以类似的方式使用。
passport.use(new GoogleStrategy({
clientID: keys.google.oauthClientID,
clientSecret: keys.google.oauthClientSecret
},
function (accessToken, refreshToken, profile, done) {
return done(null, {
accessToken,
refreshToken,
profile,
});
}
));
module.exports.authenticate = (req, res) => new Promise((resolve, reject) => {
passport.authenticate('google-token', {session: false}, (err, data, info) => {
if (err) reject(err);
resolve({data, info});
})(req, res);
});
希望对您有所帮助。
我正在创建一个依赖于 Express 和 GraphQL 的后端,它将为客户端应用程序提供服务(android 并作出反应)。
我一直在关注这个article on how to nail social authentication in GraphQL using passport.js。
文章使用passport-google-token strategy and is based on Apollo-server but personally I prefer to use express-graphql.
将我的 android 应用程序设置为使用 google 身份验证并尝试向服务器发送突变后,我收到此错误
Google info: { InternalOAuthError: failed to fetch user profile
at E:\_Projects\myProject\myProject-backend\node_modules\passport-google-token\lib\passport-google-token\strategy.js:114:28
at passBackControl (E:\_Projects\myProject\myProject-backend\node_modules\oauth\lib\oauth2.js:132:9)
at IncomingMessage.<anonymous> (E:\_Projects\myProject\myProject-backend\node_modules\oauth\lib\oauth2.js:157:7)
at IncomingMessage.emit (events.js:194:15)
at endReadableNT (_stream_readable.js:1125:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
name: 'InternalOAuthError',
message: 'failed to fetch user profile',
oauthError:
{ statusCode: 401,
data:
'{\n "error": {\n "code": 401,\n "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.",\n "status": "UNAUTHENTICATED"\n }\n}\n' } }
我相信我传递的令牌可能没有达到预期的位置,但我不知道如何解决。
我已经在这里 https://oauth2.googleapis.com/tokeninfo?id_token=MyToken 测试了我的令牌,它们工作正常。
这是 app.js
中的 graphQL 配置app.use('/graphql', graphqlHTTP((req, res) => ({
schema,
graphiql: true,
context: {req, res}
})));
这里是google auth mutation
googleAuth: {
type: authPayLoad,
args: {token: {type: new GraphQLNonNull(GraphQLString)}},
async resolve(_, {token}, {req, res}) {
req.body = {
...req.body,
access_token: token,
};
try {
const {data, info} = await authenticateGoogle(req, res);
console.log("Google data: ", data);
if (data) {
const user = await User.upsertGoogleUser(data);
if (user) {
return ({
name: user.name,
username: user.username,
token: user.generateJWT(),
});
}
}
if (info) {
console.log("Google info: ", info);
switch (info.code) {
case 'ETIMEDOUT':
return (new Error('Failed to reach Google: Try Again'));
default:
return (new Error('something went wrong'));
}
}
return (Error('server error'));
} catch (e) {
console.log("Error: ", e);
return e
}
},
},
这是我的授权控制器
const passport = require('passport');
const {Strategy: GoogleTokenStrategy} = require('passport-google-token');
// GOOGLE STRATEGY
const GoogleTokenStrategyCallback = (accessToken, refreshToken, profile, done) => done(null, {
accessToken,
refreshToken,
profile,
});
passport.use(new GoogleTokenStrategy({
clientID: 'MY_CLIET_ID',
clientSecret: 'SERVER-SECRET'
}, GoogleTokenStrategyCallback));
module.exports.authenticateGoogle = (req, res) => new Promise((resolve, reject) => {
passport.authenticate('google-token', {session: false}, (err, data, info) => {
if (err) reject(err);
resolve({data, info});
})(req, res);
});
我预计当客户端应用程序提交带有令牌作为 arg 的突变时,请求将被发送到 google 和 returns 用户数据。我该如何解决这个问题。
passport-google-token is archived and seems deprecated to me. Why don't you try passport-token-google。 可以类似的方式使用。
passport.use(new GoogleStrategy({
clientID: keys.google.oauthClientID,
clientSecret: keys.google.oauthClientSecret
},
function (accessToken, refreshToken, profile, done) {
return done(null, {
accessToken,
refreshToken,
profile,
});
}
));
module.exports.authenticate = (req, res) => new Promise((resolve, reject) => {
passport.authenticate('google-token', {session: false}, (err, data, info) => {
if (err) reject(err);
resolve({data, info});
})(req, res);
});
希望对您有所帮助。