Giter Club home page Giter Club logo

nestjs-session's Introduction

NestJS-Session

npm npm GitHub branch checks state Known Vulnerabilities Libraries.io Dependabot Supported platforms: Express

Idiomatic Session Module for NestJS. Built on top of express-session ๐Ÿ˜Ž

This module implements a session with storing data in one of external stores and passing ID of session to client via Cookie/Set-Cookie headers.

If you want to store data directly in Cookie, you can look at nestjs-cookie-session.

Example

Register module:

// app.module.ts
import { Module } from '@nestjs/common';
import { NestSessionOptions, SessionModule } from 'nestjs-session';
import { ViewsController } from './views.controller';

@Module({
  imports: [
    // sync params:

    SessionModule.forRoot({
      session: { secret: 'keyboard cat' },
    }),

    // or async:

    SessionModule.forRootAsync({
      imports: [ConfigModule],
      inject: [Config],
      //              TIP: to get autocomplete in return object
      //                  add `NestSessionOptions` here โ†“โ†“โ†“
      useFactory: async (config: Config): Promise<NestSessionOptions> => {
        return {
          session: { secret: config.secret },
        };
      },
    }),
  ],
  controllers: [ViewsController],
})
export class AppModule {}

In controllers use NestJS built-in Session decorator:

// views.controller.ts
import { Controller, Get, Session } from '@nestjs/common';

@Controller('views')
export class ViewsController {
  @Get()
  getViews(@Session() session: { views?: number }) {
    session.views = (session.views || 0) + 1;
    return session.views;
  }
}

BE AWARE THAT THIS EXAMPLE IS NOT FOR PRODUCTION! IT USES IN-MEMORY STORE, SO YOUR DATA WILL BE LOST ON RESTART. USE OTHER STORES


See redis-store example in examples folder.

To run examples:

git clone https://github.com/iamolegga/nestjs-session.git
cd nestjs-session
npm i
npm run build
cd examples/in-memory # or `cd examples/redis-store`
npm i
npm start

For Redis example, you should start Redis on localhost:6379. If you have Docker installed you can start Redis image by npm run redis from redis-store directory.

Install

npm i nestjs-session express-session @types/express-session

API

SessionModule

SessionModule class has two static methods, that returns DynamicModule, that you need to import:

  • SessionModule.forRoot for sync configuration without dependencies
  • SessionModule.forRootAsync for sync/async configuration with dependencies

SessionModule.forRoot

Accept NestSessionOptions. Returns NestJS DynamicModule for import.

SessionModule.forRootAsync

Accept NestSessionAsyncOptions. Returns NestJS DynamicModule for import.

NestSessionOptions

NestSessionOptions is the interface of all options. It has next properties:

  • session - required - express-session options.
  • forRoutes - optional - same as NestJS buil-in MiddlewareConfigProxy['forRoutes'] See examples in official docs. Specify routes, that should have access to session. If forRoutes and exclude will not be set, then sessions will be set to all routes.
  • exclude - optional - same as NestJS buil-in MiddlewareConfigProxy['exclude'] See examples in official docs. Specify routes, that should not have access to session. If forRoutes and exclude will not be set, then sessions will be set to all routes.
  • retries - optional - number - by default if your session store lost connection to database it will return session as undefined, and no errors will be thrown, and then you need to check session in controller. But you can set this property how many times it should retry to get session, and on fail InternalServerErrorException will be thrown. If you don't want retries, but just want to InternalServerErrorException to be throw, then set to 0. Set this option, if you dont't want manualy check session inside controllers.
  • retriesStrategy - optional - (attempt: number) => number - function that returns number of ms to wait between next attempt. Not calls on first attempt.

NestSessionAsyncOptions

NestSessionAsyncOptions is the interface of options to create session module, that depends on other modules. It has next properties:

  • imports - optional - modules, that session module depends on. See official docs.
  • inject - optional - providers from imports-property modules, that will be passed as arguments to useFactory method.
  • useFactory - required - method, that returns NestSessionOptions.

Migration

v2

express-session and @types/express-session are moved to peer dependencies, so you can update them independently.

Do you use this library?
Don't be shy to give it a star! โ˜…

Also if you are into NestJS you might be interested in one of my other NestJS libs.

nestjs-session's People

Contributors

actions-user avatar dependabot-preview[bot] avatar dependabot[bot] avatar github-actions[bot] avatar iamolegga avatar mergify[bot] avatar ovr avatar quantumsheep avatar snyk-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

nestjs-session's Issues

[BUG] Middleware not called while using nestjs-session with @nestjs/graphql

What is the current behavior?

I don't succeed to make this package work with @nestjs/graphql.
When I call a REST route, it's working well, and the session(req, res, next) middleware (from express-session) is well called.
But when I call the GraphQL entrypoint, the middleware is not called at all.

I've digged deep in nestjs source-code, but I don't know really where to look.

Even with a forRoutes: [{ path: '/*', method: RequestMethod.ALL }], this change nothing.

What is the expected behavior?

In practice, the consequences are that no cookie is defined in the GraphQL response, and so, the sessions don't work.

Please mention other relevant information such as Node.js version and Operating System.

[BUG] Depracation warnings

After integrating this into my Nest project we ran into these warnings. Could you resolve them please?

Fri, 18 Dec 2020 04:00:02 GMT express-session deprecated undefined resave option; provide resave option at node_modules/nestjs-session/dist/index.js:8:22

Fri, 18 Dec 2020 04:00:02 GMT express-session deprecated undefined saveUninitialized option; provide saveUninitialized option at node_modules/nestjs-session/dist/index.js:8:22

[BUG] misconfigured csrf

What is the current behavior?

If using this module alongside with csurf then got an error misconfigured csrf

Please provide the steps to reproduce.

  1. create new nest project.
  2. add SessionModule.forRoot({ session: { secret: 'secret' } }) to app.module.ts.
  3. add app.use(csurf()) to main.ts.
  4. create a controller to handle request.
  5. got the error misconfigured csrf.

What is the expected behavior?

Do not get this error.

Please mention other relevant information such as Node.js version and Operating System.

- Nest version: 7.2.0
- Node version: v12.16.3
- Platform: Windows

[BUG] Not working with @nestjs/graphql

What is the current behavior?

Using @Session in a resolver dosen't work, and session is null.

Please provide the steps to reproduce.

Install Nest with graphql, and install this. Then, in your resolver have a @Session parameter and see what it is. It will be null.

What is the expected behavior?
It isn't null.

Please mention other relevant information such as Node.js version and Operating System.
Node 11.15.0, session configuration:

SessionModule.forRoot({
  session: {
    secret: 'temp',
    store: new RedisStore({ client: RedisConnection }),
    resave: false,
    saveUninitialized: true
  }
});

In my resolver:

  @Mutation(() => User)
  async register(
    @Session() session: SessionType
  ) {
    .....

    session.user = user.id; // TypeError: Cannot set property 'user' of null
  }

[QUESTION] How to get session in custom middleware?

I have my own middlewares and need to get session from there, from req.session, but it is undefined.

But it is available in nest controllers via @Session() session or @Req() req.session...

How to get session in middleware?

[QUESTION] How to setup this nestjs-session with session-file-store?

Question

I was previously initializing my session stuff in main.ts, like this

import { NestFactory} from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import * as cookieParser from 'cookie-parser';
import * as session from 'express-session';
import * as sessionFileStore from 'session-file-store';
import { AppModule } from './app.module';

async function bootstrap(): Promise<void> {
  const app = await NestFactory.create<NestExpressApplication>(AppModule});

  const sessionTimeToLiveInSeconds = 60 * 60 * 12; //43200 seconds = 12 days
  const cookieMaxAgeInMilliseconds = 1000 * 60 * 60 * 24 * 7; //604800000 ms = 1 week

  //Set up sessions - https://docs.nestjs.com/techniques/session
  const FileStore = sessionFileStore(session);
  const appFileStore = new FileStore({
    path: './sessions/',
    ttl: sessionTimeToLiveInSeconds,
  });

  app.use(
    session({
      secret: process.env.secret,
      resave: true,
      store: appFileStore,
      saveUninitialized: true, //This needs to be true for session files to be saved locally at all! We might need this to be false when on a "real" server though
      cookie: {
        secure: process.env.environment !== 'dev', //secure for non-dev environments because they use HTTPS
        httpOnly: false,
        sameSite: false,
        maxAge: cookieMaxAgeInMilliseconds,
      },
    }),
  );

  app.use(cookieParser(process.env.secret)); //Allow session cookies

  //other stuff here
});

and then I remembered this project so I've moved everything over to my app.module.ts

import { Module } from '@nestjs/common';
import * as session from 'express-session';
import { NestSessionOptions, SessionModule } from 'nestjs-session';
import * as sessionFileStore from 'session-file-store';

@Module({
  imports: [
    //Set up sessions
    SessionModule.forRootAsync({
      useFactory: (): NestSessionOptions => {
        const sessionTimeToLiveInSeconds = 60 * 60 * 12; //43200 seconds = 12 days
        const cookieMaxAgeInMilliseconds = 1000 * 60 * 60 * 24 * 7; //604800000 ms = 1 week

        //Set up sessions - https://docs.nestjs.com/techniques/session
        const FileStore = sessionFileStore(session);
        const appFileStore = new FileStore({
          path: './sessions/',
          ttl: sessionTimeToLiveInSeconds,
        });
        return {
          session: {
            secret: process.env.secret,
            resave: true,
            store: appFileStore,
            saveUninitialized: true, //This needs to be true for session files to be saved locally at all! We might need this to be false when on a "real" server though
            cookie: {
              secure: process.env.environment !== 'dev', //secure for non-dev environments because they use HTTPS
              httpOnly: false,
              sameSite: false,
              maxAge: cookieMaxAgeInMilliseconds,
            },
          },
        };
      },
    }),
	
    //other modules go here

  ],
  controllers: [AppController],
})
export class AppModule {}

but when I try and do something that would access sessions I get:

ERROR [ExceptionsHandler] Login sessions require session support. Did you forget to use `express-session` middleware?

I guess I'm just confused. This worked when I set it up in main.ts, but this project is supposed to allow me to set up session in a module without having to manually set up an express interceptor. But this error message seems to be saying that I MUST set it up in main.ts.

I feel like either I am missing something obvious here or that the docs are missing some key information needed about how to set this up.

Please mention other relevant information such as Node.js version and Operating System.

[QUESTION] Getting "ENOENT: no such file or directory" error with session-file-store

[x] I've read the docs

[x] I've read the docs of express-session

[x] I couldn't find the same question

Question
I am re-writing a plain Express app into a more structured NestJS app and I am having trouble dealing with sessions. Here is my setup.

main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap(): Promise<void> {
  const app = await NestFactory.create(AppModule);

  const port = process.env.PORT;
  await app.listen(port);
}

bootstrap().catch((err: unknown) => {
  console.error(err);
});

app.module.ts

import { Module } from '@nestjs/common';
import * as session from 'express-session';
import { SessionModule } from 'nestjs-session';
import * as sessionFileStore from 'session-file-store';

import { AppController } from './app.controller';
import { AppLoggerModule } from './app-logger/app-logger.module';
import { AuthModule } from './auth/auth.module';

const sessionTimeToLiveInSeconds = 60 * 60 * 12; //43200 seconds = 12 days
const cookieMaxAgeInMilliseconds = 1000 * 60 * 60 * 24 * 7; //604800000 ms = 1 week
const FileStore = sessionFileStore(session);

@Module({
  imports: [
    SessionModule.forRoot({
      session: {
        secret: process.env.secret,
        resave: true,
        store: new FileStore({ path: './sessions', ttl: sessionTimeToLiveInSeconds }),
        saveUninitialized: false,
        cookie: {
          secure: false,
          httpOnly: false,
          sameSite: false,
          maxAge: cookieMaxAgeInMilliseconds,
        },
      },
    }),
    AuthModule,
    AppLoggerModule,
  ],
  controllers: [AppController],
  providers: [],
})
export class AppModule {}

And when I start the NestJS server it's all good, but I make a simple GET request for something that just returns a "Hello World" string which works but I get the following error in my console 5 times

[session-file-store] will retry, error on last attempt: Error: ENOENT: no such file or directory, open 'C:\Users\<my-repo>\sessions\jm22rlgjMBLrxR0H3SUayhAlPEXI6oZY.json'

And of course no session JSON files are created either. Please help, I'm a little new at this but I feel like I'm doing everything correctly here and my system just can't write files to that folder for some reason. The sessions folder does exist, and it has the correct read/write permission on it.

Please mention other relevant information such as Node.js version and Operating System.

NestJS Version : 10.3.8
OS Version     : Windows 10.0.19045
NodeJS Version : v20.10.0
NPM Version    : 10.2.3

express-session: 1.18.0
nestjs-session : 3.0.1   

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.