'NestJS | Passport: TypeError: Cannot read properties of undefined (reading 'logIn')
Situation:
- Developing api in nest & grapqhql
- Worked on one laptop, everything was working well
- Then cloned my repo on other laptops, installed dependencies, created a new local database.
- App is being built with no errors
- When following localhost:4000 in browser to open graphql playground I'm receiving 500 error end next message:
ERROR [ExceptionsHandler] Cannot read properties of undefined (reading 'logIn') TypeError: Cannot read properties of undefined (reading 'logIn') at authenticate (/home/gleb/Projects/artwine-api/node_modules/passport/lib/middleware/authenticate.js:96:21) at /home/gleb/Projects/artwine-api/node_modules/@nestjs/passport/dist/auth.guard.js:91:3 at new Promise (<anonymous>) at /home/gleb/Projects/artwine-api/node_modules/@nestjs/passport/dist/auth.guard.js:83:83 at JWTAccessAuthGuard.<anonymous> (/home/gleb/Projects/artwine-api/node_modules/@nestjs/passport/dist/auth.guard.js:49:36) at Generator.next (<anonymous>) at fulfilled (/home/gleb/Projects/artwine-api/node_modules/@nestjs/passport/dist/auth.guard.js:17:58) at processTicksAndRejections (node:internal/process/task_queues:96:5)
Code of a passport lib function where the error is caught:
return function authenticate(req, res, next) {
req.login =
req.logIn = req.logIn || IncomingMessageExt.logIn;
req.logout =
req.logOut = req.logOut || IncomingMessageExt.logOut;
req.isAuthenticated = req.isAuthenticated || IncomingMessageExt.isAuthenticated;
req.isUnauthenticated = req.isUnauthenticated || IncomingMessageExt.isUnauthenticated;
req._sessionManager = passport._sm;
..............
Link to the repo: https://github.com/Gleb-Gaiduk/artwine-api Any ideas on what could go wrong after cloning the working repository?
Solution 1:[1]
You need to transform the ExecutionContext from Graphql to one Nestjs/Passport can read: https://docs.nestjs.com/graphql/other-features#execution-context
import { ExecutionContext, Injectable } from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import { AuthGuard } from '@nestjs/passport';
@Injectable()
export class MySuperGuard extends AuthGuard('jwt') {
getRequest(context: ExecutionContext) {
const ctx = GqlExecutionContext.create(context);
return ctx.getContext().req;
}
}
Solution 2:[2]
You should look your Guard and strategy you are using and should handle errors from there for example:
@Injectable()
export class PassportLocalGuard extends AuthGuard('local') {
protected readonly logger = new Logger(PassportLocalGuard.name);
canActivate(context: ExecutionContext) {
const ctx = GqlExecutionContext.create(context);
const { req } = ctx.getContext();
return super.canActivate(new ExecutionContextHost([req]));
}
handleRequest(err: any, user: any) {
if (err) {
this.logger.error(`Auth Error! ${err.message}`);
throw err;
}
if (!user) {
this.logger.error('Auth Error! User not found');
throw new AuthenticationError('Auth Error! User not found');
}
return user;
}
}
Solution 3:[3]
try adding this into "subscriptions" section of GraphQL module initialization:
'subscriptions-transport-ws': {
onConnect: (headersRaw: Record<string, unknown>) => {
// Lowercase each header key
const headers = Object.keys(headersRaw).reduce((dest, key) => {
dest[key.toLowerCase()] = headersRaw[key];
return dest;
}, {});
return {
req: {
headers: headers,
},
};
},
},
I have no idea why it is not documented, but it worked for me.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Ervis H. |
| Solution 3 | Mike |
