Session Variables are undefined after saving them "session-express" - node.js

I'm following a tutorial for Ben Awad and i'm trying to set a userId in an express session after the user logs in to save the cookies in the browser. But when i check the req.session.userId its always undefined.
this is my index.ts
`
const RedisStore = connectRedis(session);
const redis = new Redis({
port: 6379,
host: "127.0.0.1",
});
redis.on("connect", () => console.log("Redis redisClient Connected"));
redis.on("error", (err) => console.log("Redis Client Connection Error", err));
app.use(
session({
name: "SessionID",
store: new RedisStore({
client: redis,
disableTouch: true,
}),
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 365 * 10, //10 years
httpOnly: true,
sameSite: "lax",
domain: _prod_ ? ".codeponder.com" : undefined,
secure: _prod_, // cookie only works in https
},
secret: "adsadafasdasdasfasfdasda",
resave: false,
saveUninitialized: true,
})
);
const apolloServer = new ApolloServer({
schema: await buildSchema({
resolvers: [PostResolver, UserResolver],
validate: false,
}),
context: ({ req, res }): MyContext => ({ em: orm.em, res, req, redis }),
});
await apolloServer.start();
apolloServer.applyMiddleware({
app,
cors: {
credentials: true,
origin: ["http://localhost:3000", "https://studio.apollographql.com"],
},
});
app.listen(4000, () => {
console.log("server started on localhost:4000");
});
};
`
and when i try to save the userId in the login. Here when i log the req.session after assigning it to the user.id i can see it working
`
#Mutation(() => UserResponse)
async login(
#Arg("options") options: UsernamePasswordInput,
#Ctx() { em, req }: MyContext
): Promise<UserResponse> {
const user = await em.findOne(User, { username: options.username });
if (!user) {
return {
errors: [
{
field: "username",
message: "that username doesnt exist",
},
],
};
}
const valid = await argon2.verify(user.password, options.password);
if (!valid) {
return {
errors: [
{
field: "password",
message: "incorrect password",
},
],
};
}
req.session.userId = user.id;
console.log("req.>>", req.session);
req.session.save(() => {
console.log("saved");
});
return { user };
}
}
`
But when i check if the user is logged in or not from this function. req.session.userId is always undefined and not saved in the session
`
#Query(() => User, { nullable: true })
async me(#Ctx() { req, em }: MyContext) {
console.log("req", req.session);
if (!req.session.userId) {
return null;
}
const user = await em.findOne(User, { id: req.session.userId });
return user;
}
`
i tried upgrading/downgrading the packages. Checked my redis connection. Nothing seem to work

Related

nodejs cookie does not save on browser storage

I am building a nodejs application
I want to save cookies using nodejs
it send the cookie to the browser
but it does not save on the browser storage
export const signin = async (req, res, next) => {
try {
const user = await User.findOne({
$or: [{ phone: req.body.phone }, { username: req.body.username }],
});
if (!user) return res.status(401).json({ msg: "Wrong Credentials" });
const isCorrect = bcrypt.compareSync(req.body.password, user.password); // true
if (!isCorrect) return res.status(401).json({ msg: "Wrong Credentials" });
const token = jwt.sign({ id: user._id, role: user.role }, process.env.JWT);
const { password, ...others } = user._doc;
res
.cookie("access_token", token, {
httpOnly: false,
secure: false,
maxAge: 60 * 60 * 24 * 7,
})
.status(200)
.json(others);
} catch (error) {
next(error);
}
};
Frontend
const get = path => {
const new_url = `${BASE_URL}${path}`;
return axios.get(new_url || {}, {
withCredentials: true,
credentials: "include",
});
};

express-session does not set cookies

I'm following Fullstack React GraphQL TypeScript Tutorial by Ben Awad, but I encountered considerable difficulty during approximately (1:55:00) set up cookies.
I think I connect to Redis successfully, and set express-session, req type, but I'm unable to see my cookies in chrome->applications->cookies.
I try to follow this post, but it's not working-ish for me.
index.ts
const app = express();
app.set("trust proxy", true);
app.set("Access-Control-Allow-Origin", "https://studio.apollographql.com");
app.set("Access-Control-Allow-Credentials", true);
const RedisStore = connectRedis(session)
const redisClient = createClient({ legacyMode: true })
redisClient.connect().catch(console.error)
app.use(
session({
name: 'qid',
store: new RedisStore({
client: redisClient,
disableTouch: true,
}),
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 365 * 10, // 10 year
httpOnly: true,
secure: true, // cookies only works on https if it's true // set to __prod__ by ben awad
sameSite: "none" // csrf
},
saveUninitialized: false,
secret: "izodfg",
resave: false,
})
)
const apolloServer = new ApolloServer({
schema: await buildSchema({
resolvers: [HelloResolver, PostResolver, UserResolver],
validate: false,
}),
context: ({ req, res }): MyContext => ({ em: emFork, req, res })
})
const cors = { // add for apollo studio
credentials: true,
origin: 'https://studio.apollographql.com'
}
await apolloServer.start();
apolloServer.applyMiddleware({ app, cors });
type.ts
export type MyContext = {
em: EntityManager<IDatabaseDriver<Connection>>
req: Request & { session: { userId?: string } }
res: Response
};
./resolvers/user.ts
#Mutation(() => UserResponse)
async login(
#Arg('options') options: UsernamePasswordInput,
#Ctx() { em, req }: MyContext
): Promise<UserResponse> {
const user = await em.findOne(User, { username: options.username });
if (!user) {
return {
errors: [
{
field: "username",
message: "that username doesn't exists",
}
]
}
}
const vaild = await argon2.verify(user.password, options.password);
if (!vaild) {
return {
errors: [
{
field: "password",
message: "incorrect password",
}
]
}
}
req.session.userId = user.id.toString();
return {
user
}
}
Redis Inspect
stored cookie in Redis picture

TypeOrm query fails to fetch data from postgres sever in Nodejs Application after running fine for few hours

My nodejs API runs fine for few hours then API does not return data to client. Once I debug I found that TypeOrm Unable to query data from remote postgres server even though postgres server is Connected. Query in Nodejs application die with no error.
I can query data from remote postgres DB from pgAdmin.
The app.ts code
const conn = await createConnection({
host: process.env.TYPEORM_HOST,
password: process.env.TYPEORM_PASSWORD,
type: 'postgres',
username: process.env.TYPEORM_USERNAME,
database: process.env.TYPEORM_DATABASE,
port: Number(TYPEORM_PORT),
logging: TYPEORM_LOGGING === 'true' ? true : false,
synchronize: TYPEORM_SYNCHRONIZE === 'true' ? true : false,
entities: [UserEntity],
});
console.log(conn.options.database);
////#### Middleware Section ####/////
const apolloServer = new ApolloServer({
schema: await CreateSchema(),
subscriptions: {
path: `${ENDPOINT_PATH}`,
},
uploads: false,
//tracing: true,
context: ({ req, res }: any) => ({
req,
res,
...dataLoaderInject,
}),
});
const app = Express();
const whitelist: any = process.env.ENDPOINT_CORS?.split(',').map((x) =>
x.trim()
);
var corsOptions = {
origin: function (origin: any, callback: any) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true);
} else {
callback(null, false);
}
},
credentials: true,
};
app.use(cors(corsOptions));
app.use(graphqlUploadExpress({ maxFileSize: 500000000, maxFiles: 50 }));
app.use(cookieParser());
apolloServer.applyMiddleware({ app, cors: false, path: ENDPOINT_PATH });
const httpServer = http.createServer(app);
apolloServer.installSubscriptionHandlers(httpServer);
httpServer.listen(ENDPOINT_PORT, () => {
//Register jobScheduler here
JobSchedulerService.sendReminder();
console.log(
`Server started at ${ENDPOINT}:${ENDPOINT_PORT}${ENDPOINT_PATH}`
);
});
POST request where TypeOrm fails to return results from remote postgres server.
app.post('/user', async (req, res) => {
let token = req.cookies.UserCookie;
if (!token) {
console.log('token is not valid ' + token);
return res.send({ ok: false, accessToken: '' });
}
let payload: any;
try {
payload = verify(token, process.env.REFRESH_TOKEN_SECRET!);
} catch (err) {
console.log(err);
return res.send({ ok: false, accessToken: '' });
}
const user = await
getRepository(UserEntity)
.createQueryBuilder()
.where('"ID"=:ID', { ID: payload.userID })
.getOne() // request die here , no error , does not respond anything
.catch( err => {
console.log(err, "User Query error")
})
if (!user) {
console.log('User not found');
return res.send({ ok: false, accessToken: '' });
}
Stack version
Postgres 12
Nodejs : v12.16.3
npm : 6.14.4
"pg": "^8.3.3"
"typeorm": "^0.2.26",
"express": "^4.17.1",
"node-cron": "^2.0.3",
Your response will be much appreciated Thank you.

AWS rds postgres session count keeps increasing and server becomes unresponsive

Platform Used:
NestJs 7.1.2
Postgres
After a certain duration my aws rds session count keeps increasing and the server becomes unresponsive. I need to restart the server again to make it working.
My database connection code in main.ts:
import * as session from 'express-session';
app.use(
session({
store: new (require('connect-pg-simple')(session))({
conString:
'pg://' +
process.env.TYPEORM_USERNAME +
':' +
process.env.TYPEORM_PASSWORD +
'#' +
process.env.TYPEORM_HOST +
'/' +
process.env.TYPEORM_DATABASE,
}),
secret: process.env.COOKIE_SECRET,
resave: false,
saveUninitialized: false,
cookie: { maxAge: 30 * 24 * 60 * 60 * 1000 }, // 30 days
}),
);
app.module.ts code:
TypeOrmModule.forRootAsync({
useFactory: (config: ConfigService) => config.get('database'),
inject: [ConfigService],
})
where my database config is as follows:
import * as path from 'path';
export default {
type: process.env.TYPEORM_CONNECTION,
host: process.env.TYPEORM_HOST,
port: +process.env.TYPEORM_PORT,
username: process.env.TYPEORM_USERNAME,
password: process.env.TYPEORM_PASSWORD,
database: process.env.TYPEORM_DATABASE,
synchronize: true,
dropSchema: false,
logging: false,
retryAttempts: 5,
keepConnectionAlive: true,
entities: [path.join(__dirname, '../') + '**/!(*.d).entity{.ts,.js}'],
migrations: ['migrations/**/*.ts'],
subscribers: ['subscriber/**/*.ts', 'dist/subscriber/**/.js'],
cli: {
entitiesDir: 'src',
migrationsDir: 'migrations',
subscribersDir: 'subscriber',
},
};
Kindly assist...have struggled a lot on this!!
Use the pgPromise connection param instead of the conString param. Also modify apolloServer+express-session configuration settings.
async function main() {
const connection = await createConnection(ormconfig as ConnectionOptions);
const schema = await buildSchema({ resolvers: [DysfunctionalThoughtResolver,UserResolver] });
const server = new ApolloServer({
schema,
context: async ({ req, res }) => ({ req, res }),
playground: {
settings: {
"request.credentials": "same-origin",
}
}
});
var app=express();
var pgSession = require('connect-pg-simple')(session);
app.use(session({
name: process.env.COOKIE_NAME,
saveUninitialized:false,
secret:process.env.COOKIE_SECRET?.split(','),
cookie: {
store: new pgSession({
pgPromise : connection
}),
httpOnly: true,
secure: process.env.NODE_ENV=="prod",
sameSite: true,
maxAge: 600000 // Time is in miliseconds
},
resave: false
}))
await app.listen({port:4000});
server.applyMiddleware({ app });
console.log("Server has started!");
}
main();
Dont forget to add the session table required in connect-pg-simple:
https://github.com/voxpelli/node-connect-pg-simple/blob/HEAD/table.sql
CREATE TABLE "session" (
"sid" varchar NOT NULL COLLATE "default",
"sess" json NOT NULL,
"expire" timestamp(6) NOT NULL
)
WITH (OIDS=FALSE);
ALTER TABLE "session" ADD CONSTRAINT "session_pkey" PRIMARY KEY ("sid") NOT DEFERRABLE INITIALLY IMMEDIATE;
CREATE INDEX "IDX_session_expire" ON "session" ("expire");
TypeORM translation(put in a session.ts file in your models/entities folder).
#Entity()
export class session {
#PrimaryColumn({
type: "varchar",
nullable: false,
//collation:"" //needed?
})
sid:string;
#Column({
type: "json",
nullable: false
})
sess:any;
#Index("IDX_session_expire")
#Column({
type: "timestamp",
precision: 6,
nullable: false
})
expire:Date;
}
Then access it in your resolvers
#Mutation(() => String)
async login(#Args() { email, password }: UserLoginArgs, #Ctx() ctx: any) {
let response = "";
let sess = ctx.req.session;
if (sess.userId) { response = "already logged in"; }
else {
let user = await User.findOne({ where: { email: email } });
if (user) {
let passwordsMatch = await bcrypt.compare(password, user?.password);
if (passwordsMatch) {
sess.userId = user.id;
sess.save();
response = "login successful";
} else {
response = "Password doesn't match"
}
} else {
response = "User not found";
}
}
return response;
}
#Mutation(() => String)
async logout(#Ctx() ctx: any) {
let sess = ctx.req.session;
if (!sess.userId) { return "already logged out"; }
else{
sess.destroy();
return "logged out";
}
}

How to get sessions which were added after socket.io is conneted in socket.request

I want to get user property in session after login, but when i set session after login, socket.request.session doesn't change, there is no user property in it. But i can get it in router.post.
I tried to edit sessions in router.post()/router.get(), socket.request.session was still not change.
index.js
const io = require('socket.io').listen('8082', { origins: '*' })
const schedule = require('node-schedule')
io.set('transports', [
'websocket',
'flashsocket',
'htmlfile',
'xhr-polling',
'jsonp-polling',
'polling'
])
io.set('origins', '*:*')
const app = new express()
const sessionStore = new session.MemoryStore({ reapInterval: 3600 * 1000 })
const sessionMiddleware = session({
secret: 'Stefanie Sun',
store: sessionStore,
resave: false,
saveUninitialized: true,
cookie: {
maxAge: 8 * 3600 * 1000,
secure: false
},
rolling: true
})
io.use((socket, next) => {
sessionMiddleware(socket.request, socket.request.res, next);
})
app.use(sessionMiddleware)
routes(app)
io.on('connection', (socket) => {
const comment_schedule = schedule.scheduleJob('*/10 * * * * *', async () => { /** 10s查询一次是否有新的内容 **/
const COOKIE_STR = socket.request.session
console.log(COOKIE_STR)
})
})
router.js
...
router.post('/pagelist', (req, res, next) => {
req.session.user = { username: 'test1', gender: 'x', bio: 'this is a test' }
console.log(req.session)
res.status(200).json({ code: 'OK' })
}
app.user('/api/page', router)
when i visited /api/page/pagelist after signin, i wish i can get the same session in socket.request and req.session in router.post,
but socket.request.session is
Session {
cookie:
{ path: '/',
_expires: 2019-04-07T22:57:13.379Z,
originalMaxAge: 28800000,
httpOnly: true,
secure: false } }
but in router.post req.session is
Session {
cookie:
{ path: '/',
_expires: 2019-04-07T22:57:48.146Z,
originalMaxAge: 28799999,
httpOnly: true,
secure: false },
user:
{
username: 'test1',
gender: 'x',
bio: 'this is a test'
}}
i hope in socket.request.session i can also get
user property.
My fontend project is with Vue.js. And i set socket.on('event') in home.vue. I connect socket.io before the page logins, and after login i set user property in session, i can't get this property in socket.request.session.
login code in frontend
// api.js
export const loginApi = ({ username, password } = { username: '', password: '' }) => {
const data = {
username,
password
};
return axios.request({
url: '/api/signin',
data: qs.stringify(data),
method: 'post'
})
}
// login.vue
submit() {
loginApi({ username: this.username, password: this.password})
.then((result: any) => {
this.$toast.success('login success');
this.Cookies.set('user', this.username, { expires: 7 });
getUserInfo(this.username).then((res: any) => {
const { data } = res;
localStorage.setItem('user', JSON.stringify(data));
const url = this.redirect && this.redirect || '/pages';
this.$router.push(url);
})
})
}

Resources