MERN+TypeScript实现Google登录时遇Mongoose Schema配置错误
问题排查:TypeScript MERN项目中Passport Google登录的Schema配置错误
配置Passport实现Google登录时出现以下错误:
TypeError: Invalid schema configuration: `false` is not a valid type at path `select`
以下是相关代码及依赖版本,附问题修复方案:
User Schema代码
interface userInterface{ name : string, userHandle : string, profilePic? : string, following : Schema.Types.ObjectId[], followers : Schema.Types.ObjectId[], auth : { signInType :string, sessionInfo : { password : string }, googleInfo : { googleId : string, } } } const userSchema = new Schema<userInterface>({ name : { type : String, required : [true, 'Name is required.'], maxlength : [50 , 'Name must not exceed 50 charecters.'] }, userHandle : { type : String, required : [true , 'User handle is required.'], unique : [true, 'Please enter a unique user handle.'] }, profilePic : { type : String, }, following : { type: [Schema.Types.ObjectId], ref : 'User' }, followers : { type : [Schema.Types.ObjectId], ref : 'User' }, auth : { select: false, signInType : { type : String, enum : ["Google" , "Session"] }, sessionInfo : { password : { type : String, required : [function(this : any){ return this.auth.signInType === "Session"; } , "Please enter a password."], } }, googleInfo : { googleId : { type : String, required : [function(this : any){ return this.auth.signInType === "Google"; }, "Please enter a google id."] } }, }, }, {timestamps : true}) export default model<userInterface>('User' , userSchema);
Passport配置代码
import passport from "passport"; import passportGoogle from "passport-google-oauth2"; import User from "../model/UserSchema"; import {userHandleGenerater} from "../utils/utils"; const GoogleStrategy = passportGoogle.Strategy; passport.use( new GoogleStrategy( { clientID: process.env.GOOGLE_CLIENT_ID as string, clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, callbackURL: `${process.env.FRONTEND_URI as string}/home`, }, async (accessToken , refreshToken, profile , done) => { try{ let user = await User.findOne({"googleInfo.googleId" : profile.id}); if(!user){ let userHandle = ""; let found = true; while (found) { userHandle = userHandleGenerater(profile.name.givenName); let existingUser = await User.findOne({ userHandle }); if (existingUser) { found = true; } else { found = false; } } const newUser = { name : profile.displayName, userHandle : userHandle, auth : { signInType : "Google", googleInfo : { googleId : profile.id }, } } user = await User.create(newUser); } return done(null , user); }catch(e){ return done(e , null); } } ) ); passport.serializeUser((user : any , done) => { done(null , user._id); }); passport.deserializeUser(async (id , done) => { try { const user = await User.findById(id); return done(null , user); }catch(e){ return done(e, null); } });
项目依赖包版本
"dependencies": { "@types/express-session": "^1.18.1", "@types/node-cron": "^3.0.11", "@types/passport-google-oauth2": "^0.1.10", "backend": "file:", "cors": "^2.8.5", "express": "^4.21.2", "express-session": "^1.18.1", "mongoose": "^8.9.5", "node-cron": "^3.0.3", "passport": "^0.7.0", "passport-google-oauth2": "^0.2.0", "passport-google-oidc": "^0.1.0" }, "devDependencies": { "@types/cors": "^2.8.17", "@types/express": "^5.0.0", "@types/node": "^22.10.7", "@types/passport": "^1.0.17", "dotenv": "^16.4.7", "nodemon": "^3.1.9", "rimraf": "^6.0.1", "ts-node": "^10.9.2", "typescript": "^5.7.3" }
问题根源及修复方案
Schema配置错误
你在auth嵌套字段中直接将select: false写在对象内部,Mongoose会把select识别为普通字段,而false不是合法的字段类型,因此报错。正确的做法是将select作为auth字段的选项,与type同级定义。修复后的
auth字段定义:auth : { type: { signInType : { type : String, enum : ["Google" , "Session"] }, sessionInfo : { password : { type : String, required : [function(this : any){ return this.auth.signInType === "Session"; } , "Please enter a password."], } }, googleInfo : { googleId : { type : String, required : [function(this : any){ return this.auth.signInType === "Google"; }, "Please enter a google id."] } }, }, select: false, // 将select作为auth字段的选项 },Passport查询路径错误
原代码中查询Google用户的条件路径错误,应为auth.googleInfo.googleId而非googleInfo.googleId,同时因为auth字段默认不返回,需要显式指定查询该字段:let user = await User.findOne({"auth.googleInfo.googleId": profile.id}).select("+auth.googleInfo.googleId");
内容的提问来源于stack exchange,提问作者abhinav550
相关产品推荐
相关产品推荐

