Google 建议在首次注册用户时要求用户提供最少的权限,然后在用户需要时要求扩展这些权限。 因此,我一开始就使用基于令牌的身份验证,但如果用户想要在我的网站上执行某些功能,他们将需要授予应用程序特定的驱动器权限。 许多用户永远不会需要这个,所以我真的倾向于同意谷歌,只在需要时询问那些需要它的人。 所以,我继续执行这段代码来做到这一点:
app.use(session({
secret: vars.SESSIONSECRET,
resave: false,
saveUninitialized: false,
cookie: {
sameSite: true,
secure: true,
httpOnly: true,
maxAge: 86400000 // 1 day in milliseconds
},
store: new RedisStore({ client: redisClient }),
}));
const extendedGoogleStrategy = new GoogleStrategy(
{
clientID: vars.CLIENTID,
clientSecret: vars.CLIENTSECRET,
callbackURL: vars.EXTENDCALLBACKURL,
scope: ['openid', 'profile', 'email', 'https://www.googleapis.com/auth/drive.file'],
accessType: 'offline', // Request a refresh token
prompt: 'consent', // Show consent screen for refresh token
display: 'popup',
authorizationParams: function () {
return {
include_granted_scopes: true,
};
},
failureRedirect: '/oops',
passReqToCallback: true, // Pass the request object to the callback
},
(req, accessToken, refreshToken, profile, done) => {
// Now we have the access token, you can use it to make authorized API requests
// save that access token and refresh token to profile and send it back to the callback
// so they can be processed in the session and user db space
dp.debugPrint(["Google Strategy accessToken"], dp.DEBUG_LEVEL.MEDIUM);
profile.accessToken = accessToken;
profile.refreshToken = refreshToken;
profile.googleDriveEnabled = true;
return done(null, profile);
}
app.use(passport.initialize());
app.use(passport.session());
passport.use('googleExtended', authentication.extendedGoogleStrategy);
// Google OAuth2 authentication routes
router.get('/google/extend-scope',
(req, res, next) => {
// Redirect the user to initiate authentication with the new scope
passport.authenticate('googleExtended', {
scope: ['openid', 'profile', 'email', 'https://www.googleapis.com/auth/drive.file'],
accessType: 'offline', // Add this line
prompt: 'consent', // Add this line
display: 'popup',
authorizationParams: function () {
return {
include_granted_scopes: true,
};
},
failureRedirect: '/oops',
keepSessionInfo: true
})(req, res, next);
});
router.get('/google/extend-scope/callback',
passport.authenticate('googleExtended', {
failureRedirect: '/oops',
keepSessionInfo: true
}),
async (req, res) => {
//... store new accessToken in the session and store the renewToken in the user account db ...
});
代码似乎有效,直到我发现我的会话在某种程度上被覆盖了(一度设置 session: false 似乎解决了问题,但那是在我通过启动基于令牌的身份验证代码与 oath2 进行重构之前 - a长话短说为什么我改变了它但我做到了)。 也许其他东西发生了变化,或者它从来没有正常工作过,但我没有依赖关系,不会受到会话被覆盖的影响,直到后来。 不管怎样,我的会话被覆盖了。
keepSessionInfo: true
(护照 0.6.0 中引入的一项未记录的功能 - 这总是让我使用起来感到紧张)应该可以防止这种情况,但事实并非如此。 我已经在 git 存储库上发布了一张票证,但这让我开始思考。
A)有人遇到过此会话覆盖问题吗?如果是,解决方法是什么?
B)我是否以正确的方式处理这个问题? 如果是的话,我应该怎么做才能最好地保护刷新令牌(是的,谷歌对此有一些措辞,但我认为最好寻求一些建议)
C) 这个流程似乎不断询问权限,这正常吗? 我仍然处于开发模式,所以我明白它警告应用程序正在开发而不是生产,但是天啊,除此之外还有很多确认)
我希望扩展用户授予谷歌的权限以包括谷歌驱动器。 我期望获得 accessToken 和 renewToken,我期望能够将它们存储在用户会话/数据库中(分别)。 我获得了延期拨款,但会话被新会话覆盖,缺少会话中的其他数据,我对存储到非会话数据库进行检索不感兴趣。 (它是状态信息,不适合存储在会话存储之外)