【发布时间】:2023-01-24 02:13:06
【问题描述】:
我正在编写一个小型电子商务应用程序,使用 PostgreSQL 数据库通过 Google 进行第三方登录。这是我的谷歌策略配置:
const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy;
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: `${process.env.NODE_ENV === "production" ? [production URL] : "http://localhost:8000"}/api/auth/login/google/callback`,
passReqToCallback: true,
scope: ["email", "profile"]
}, db.third.login));
这是下面的 db.third.login,它与通过 Google 验证自己的新注册用户和现有用户完美配合。除了对用户进行身份验证外,它还会传递最终强制新注册用户在使用该应用程序之前在客户端中设置电话号码和密码的信息。
const login = async(req, accessToken, refreshToken, profile, done) => {
// Get request IP address
const ip = requestIP.getClientIp(req);
// Generate login attempt ID
const attemptId = idGen(15);
try { // Get federated credentials
let result = await pool.query("SELECT * FROM federated_credentials WHERE id = $1 AND provider = $2", [profile.id, profile.provider]);
// Create user account if credentials don't exist
if (result.rows.length === 0) {
// Send error if email already exists in database
result = await pool.query("SELECT email FROM users WHERE email = $1", [profile.emails[0].value]);
if (result.rows.length > 0) return done({ status: 409, message: "Error: A user with the provided email already exists." });
// Generate user ID and cart ID
const userId = idGen(7);
const cartId = idGen(7);
// Generate password hash
const salt = await bcrypt.genSalt(17);
const passwordHash = await bcrypt.hash(process.env.GENERIC_PASSWORD, salt);
// Add user to database
let text = `INSERT INTO users (id, first_name, last_name, phone, email, password, created_at) VALUES ($1, $2, $3, $4, $5, $6, to_timestamp(${Date.now()} / 1000)) RETURNING id`;
let values = [userId, profile.name.givenName, profile.name.familyName, "254700000000", profile.emails[0].value, passwordHash];
result = await pool.query(text, values);
// Add user cart to database
result = await pool.query("INSERT INTO carts (id, user_id) VALUES ($1, $2)", [cartId, userId]);
// Add federated credentials to database
result = await pool.query("INSERT INTO federated_credentials (id, provider, user_id) VALUES ($1, $2, $3)", [profile.id, profile.provider, userId]);
// Add user details to be confirmed to session
const federatedCredentials = { id: profile.id, provider: profile.provider, confirm: true };
return done(null, { id: userId, email: profile.emails[0].value, role: "customer", cartId: cartId, federatedCredentials });
}
// Save federated credentials details
const federatedCredentials = { id: result.rows[0].id, provider: result.rows[0].provider, confirm: !result.rows[0].confirmed };
// Get user details
result = await pool.query("SELECT users.id AS id, users.email AS email, users.password AS password, users.role AS role, carts.id AS cart_id FROM users JOIN carts ON carts.user_id = users.id WHERE email = $1", [profile.emails[0].value]);
// Log login attempt
await loginAttempt(attemptId, ip, profile.emails[0].value, "google", true);
// Add user to session
return done(null, { id: result.rows[0].id, email: result.rows[0].email, role: result.rows[0].role, cartId: result.rows[0].cart_id, federatedCredentials });
} catch (err) {
return done({ status: 500, message: "An unknown error occurred. Kindly try again." });
}
}
我现在想添加允许现有用户(以其他方式注册的用户)链接他们的 Google 帐户的功能,但我的问题是 req.user 显然无法在 passport.use() 中访问(控制台日志显示它是 undefined 甚至在我登录之后)。如何在passport.use() 中访问会话中当前用户的信息以实现此目的? (或者完全有另一种解决方案?)
【问题讨论】:
标签: node.js express passport.js