Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: validateSession return null in Express Mongoose #1668

Open
issam-seghir opened this issue Aug 17, 2024 · 7 comments
Open

[Bug]: validateSession return null in Express Mongoose #1668

issam-seghir opened this issue Aug 17, 2024 · 7 comments
Labels
bug Something ain't right...

Comments

@issam-seghir
Copy link

Package

lucia

Describe the bug

when using the sessionValidationMiddleware , the await lucia.validateSession(sessionId) always return null

  • sessionValidationMiddleware :
import { lucia } from "@/config/luciaConfig";
import { NextFunction, Request, Response } from "express";


export const sessionValidationMiddleware = async (req: Request, res: Response, next: NextFunction) => {
    const sessionId = lucia.readSessionCookie(req.headers.cookie ?? "");
    console.log(sessionId); // 4tfc6cclchl7.....

    if (!sessionId) {
        res.locals.user = null;
        res.locals.session = null;
        return next();
    }

    try {

        const data = await lucia.validateSession(sessionId );
        console.log(data);µ
        /*
        {
           "data": {
                   "user": null,
                   "session": null
               }
          }
        */

        if (session && session.fresh) {
            res.append("Set-Cookie", lucia.createSessionCookie(session.id).serialize());
        }

         if (!session) {
            res.append("Set-Cookie", lucia.createBlankSessionCookie().serialize());
         }

         res.locals.session = session;
         res.locals.user = user;
    } catch (error) {
        console.error("Session validation error:", error);
        res.locals.user = null;
        res.locals.session = null;
    }

    return next();
};
  • Lucia Config :
import { isProd } from "@/config/const";
import type { Session, User } from "lucia";
import { Lucia } from "lucia";

import { IUser } from "@/model/User";
import { MongodbAdapter } from "@lucia-auth/adapter-mongodb";
import mongoose from "mongoose";

export const adapter = new MongodbAdapter(
    mongoose.connection.collection("sessions"),
    mongoose.connection.collection("users")
);

export const lucia = new Lucia(adapter, {
    sessionCookie: {
        attributes: {
            secure: isProd,
        },
    },
    getUserAttributes: (attributes) => {
        return {
            id: attributes.id,
            fullName: attributes.fullName,
            role: attributes.role,
            email: attributes.email,
        };
    },
});

declare module "lucia" {
    interface Register {
        Lucia: typeof lucia;
        DatabaseUserAttributes: Omit<IUser, "_id">;
    }
}
@issam-seghir issam-seghir added the bug Something ain't right... label Aug 17, 2024
@zacharybenson
Copy link

Related issue: #1681

@CodeImm
Copy link

CodeImm commented Sep 1, 2024

Note whether you are using _id or id: existingUser._id and existingUser.id are different things. When creating a user in the database, don't generate the _id yourself. (Just my opinion) Everything is working for me.

@issam-seghir
Copy link
Author

Note whether you are using _id or id: existingUser._id and existingUser.id are different things. When creating a user in the database, don't generate the _id yourself. (Just my opinion) Everything is working for me.

i'm not generating the id myself; mongoose has a shortcut so I can use either id or _id , and using only User._id doesn't fix the problem for me

@CodeImm
Copy link

CodeImm commented Sep 2, 2024

@issam-seghir Can you show me how you create a session? So that I can understand better.

@issam-seghir
Copy link
Author

issam-seghir commented Sep 2, 2024

@issam-seghir Can you show me how you create a session? So that I can understand better.

export const loginHandler = asyncWrapper(async (req: Request, res: Response, next: NextFunction) => {
    const {
        body: { email, password },
    } = await zParse(loginSchema, req, res);

    const user = await User.findOne({ email }).exec();
    if (!user) {
        return res.status(400).json({ error: "User not Found" });
    }
    const isPasswordValid = await user.isPasswordMatch(password);

    if (!isPasswordValid) {
        return res.status(400).json({ error: "Incorrect password" });
    }

    const session = await lucia.createSession(user.id, {});
    res.setHeader("Set-Cookie", lucia.createSessionCookie(session.id).serialize());
    res.status(200).json({
        success: `Login : ${user.fullName}!`,
        data: {
            user: user,
            session: session,
        },
    });
  • routes :
const router = Router();

router.use("/auth", authRouter);

router.use(verifyRequestOriginMiddleware);
router.use(sessionValidationMiddleware);

//* Protected routes
router.use("/users", usersRouter);
router.use("/messages", messagesRouter);
...
export default router;
  • schema :

  • Session.ts

import mongoose, { Document } from "mongoose";

export interface ISession extends Document {
    user_id: string;
    expires_at: Date;
}

export const SessionSchema = new mongoose.Schema<ISession>({
    user_id: {
        type: String,
        required: true,
    },
    expires_at: {
        type: Date,
        required: true,
    },
});

const Session = mongoose.model<ISession>("Session", SessionSchema);

export default Session;
  • User.ts
const userSchema: Schema<IUser, IUserModel, IUserMethods, object> = new mongoose.Schema(
    {
        fullName: {
            type: String,
            required: true,
            trim: true,
        },
        email: {
            type: String,
            // unique: true,
            trim: true,
            lowercase: true,
            private: true,
        },
        password: {
            type: String,
            trim: true,
            minlength: 8,
            private: true,
        },
        role: {
            type: String,
            enum: ["user", "admin"],
            default: "user",
        },
           .....
        },
    },
    {
        timestamps: true,
        toJSON: { virtuals: true },
        toObject: { virtuals: true },
    }
);

//* Apply plugins
userSchema.plugin(toJSON);
userSchema.plugin(paginate);

@CodeImm
Copy link

CodeImm commented Sep 3, 2024

In the loginHandler function, the line const session = await lucia.createSession(user.id, {});
try to log the user object and check if it actually has an id field?

@issam-seghir
Copy link
Author

the response is :

{
  "success": "Login : admin!",
  "data": {
    "user": {
      "attachment": {
        ....
      },
      "fullName": "admin",
      "role": "admin",
      "id": "66d6e9ac2010a31b4d541580"
    },
    "session": {
      "id": "fga7xlsupkdwpaz2rnlkqf6dvycsrhm7zfgev4qw",
      "userId": "66d6e9ac2010a31b4d541580",
      "fresh": true,
      "expiresAt": "2024-10-09T11:16:17.696Z"
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something ain't right...
Projects
None yet
Development

No branches or pull requests

3 participants