Jay is a member of the NestJS core team, primarily helping out the community on Discord and Github and contributing to various parts of the framewo...
For further actions, you may consider blocking this person and/or reporting abuse
import { session as passportSession, initialize as passportInitialize } from 'passport';
This doesn't seem to work.
import * as passport from 'passport';
and then
passport.session(), passport.initialize()
seems to work. Maybe passport has no esm export?!This could be dependent on of your trying to use esm, or your tsconfig. By default, Typescript in a node project still uses the CommonJS syntax and the above methods are named exports. This runs fine for me and I'm fact there shouldn't be a difference between
import * as passport
...passport.session()
andimport { session }
...session()
, as the second one should just be destructing the firstThis is what it turns out with trying to use named exports.
That's definitely strange. All the code is available in the mentioned git repo along with the steps to run it. This is everything I used to run the project locally while driving into the code, so I'm confident that it works. There's probably a difference in a tsconfig file somewhere
nest cli will generate a different tsconfig as in the repo. If you follow from scratch.
Sure enough. That's super interesting. I couldn't modify the tsconfig to match the one in my sample repository either, though I know this was working there. Very strange issue indeed. It seemed to have to do with how the import was being generated
vs
I'll get the tutorial updated with your working fix.
@hinogi are you, by chance, on typescript
4.4.2
? I just noticed that difference in my test repo (usingnest new
) and my blog repo. The blog repo is on4.3.5
and works fine, but the same config on4.4.2
failedYes I am on 4.4.2
Looks like this was a breaking change of 4.4.0 which explains why it works with 4.3.5 but not 4.4.2. Thanks for pointing it out and helping me see what else has changed.
Just want to mention that this guide does not work with redis package version 4.
After troubleshooting I couldn't find a solution other than downgrading to ^3.1.2. Redis throws an error (below).
Some notes I discovered with redis v4+:
The type RedisClient is RedisClientType
host / port options for createClient have to be replaced by "url" option
Redis fails with:
return Promise.reject(new errors_1.ClientClosedError());
Error: The client is closed
Your error, The client is closed, is due to this breaking change.
You’ll need to make a change to the code above (in addition to the changes you already mentioned, like the url property) to call
connect()
on your new client, or you will get an error from connect-redis asking you to supply the client directly. I’m writing this from my phone at 1:30am, so if it doesn’t come out right, I’ll fix it in the morning. 😂Thank you for pointing this out!
hey @jmcdo29 ,
first of all, I wanted to thank you for this article. It's very well written and have done a wonderful done explaining to me how session storage, passport and nest play together.
I followed and can confirm the flow works when using cURL, and I have a question about using a proper front end. I am using
fetch
to authenticate my statically-served frontend (i.e. React), and am getting an HTTP 201 from the server when I enter the right credentials.How do I "save" the session and make sure the client can communicate with the server? I added credentials: 'include'` to my authenticated requests, and I keep getting HTTP 401, which leads me to thinking I'm missing something here still.
I was wondering if you had any idea what might that be.
Thanks,
Dan
If you're getting a 401, that sounds like passport is being used on other routes than just the login, and is causing the issue here. Wouldn't be able to really tell without seeing code though
already solved per discord, thanks!
Great article!
Is it necessary to protect this against CSRF?
I added the following to the Session options :
Should I add more protection like XSRF-TOKEN?
With the latest versions for redis and connect-redis. I am getting TS errors.
configure(consumer: MiddlewareConsumer) {
consumer.apply(
session({
store: new (RedisStore(session))({
client: this.redis,
}),
saveUninitialized: false,
resave: false,
cookie: {
httpOnly: true,
},
secret: this.configService.get('SESSION_SECRET'),
}),
);
}
TS Error:
Type 'RedisClientType' is not assignable to type 'Client'
Redis no longer exports RedisClient, which is what the article uses. For now I'm simply ignoring it with
client: this.redis as Client
withimport { Client } from 'connect-redis'
If someone knows how to type this correctly, I'd be glad to get some pointers towards resolving this issue..
hi nice blog thank you for the effort
I would like to point to that the code inside the app.module in the source need to be changed to
and you also need to remove the package @types/connect-redis and the legacy option in redis.module.ts in the Redius.createClient check the git hub link bellow
the source
stack over flow post
stackoverflow.com/questions/757875...
git hub page
github.com/tj/connect-redis/releas...
and thank for the blog post
have a nice day
How would I go about using Nest's
ConfigService
in theconfigure
method of theAppModule
? I need to set up the session options (e.g.secret
,sameSite
,maxAge
) depending on the environment, so hard-coding is a no-go. Should I use some other configuration method instead?You can inject the
ConfigService
just like we doRedis
and usethis.config.get('SESSION-SECRET')
or whatever else you would need tohey guys, i did setup session based authentication w/ redis store & i want to prevent the cookie object from being stored in redis
Thanks for sharing this, why do you think I'm having the following issue:
When using the LoggedInGuard in my app.controller an exception is thrown because passport is not initialized but if I use the LoggedInGuard in my auth.controller it's working. The one thing I have different I'm doing a MicroORMModule.forRoot call just before the session.
My issue was related to not adding a path in my controller decorator.
How can I correctly make logout from the session?
Try
req.logout():
req.session.destroy();
I believe that just
req.logout()
should do it , as passport should help in maintaining the session information under the hoodHi, What for you need redis? If you do request user from DB on every request in passport validate? You have your token as a cookie or localstorage item, you use it to get user from DB on every request? What is the reason to have session then.
Ig you fetch user once after login, then you could reuse this info from session. Otherwise what for?
Outstanding article!