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

TypeError: Cannot set property 'user' of undefined After passport upgradation from 0.4.1 to 0.6.0 in Nestjs 7. #966

Closed
bs-nikunj-sondagar opened this issue Jan 19, 2023 · 2 comments

Comments

@bs-nikunj-sondagar
Copy link

_**TypeError: Cannot set property 'user' of undefined**_
    at /var/www/project/my-project/node_modules/passport-windowsauth/node_modules/passport/lib/passport/http/request.js:45:35
    at pass (/var/www/project/my-project/node_modules/passport/lib/authenticator.js:274:43)
    at serialized (/var/www/project/my-project/node_modules/passport/lib/authenticator.js:283:7)
    at DatabasePassportSerializer.serializeUser (/var/www/project/my-project/server/libs/identity/src/domain/strategy/DatabasePassportSerializer.ts:38:5)
    at /var/www/project/my-project/node_modules/@nestjs/passport/dist/passport/passport.serializer.js:8:61
    at pass (/var/www/project/my-project/node_modules/passport/lib/authenticator.js:291:9)
    at Authenticator.serializeUser (/var/www/project/my-project/node_modules/passport/lib/authenticator.js:296:5)
    at IncomingMessage.req.login.req.logIn (/var/www/project/my-project/node_modules/passport-windowsauth/node_modules/passport/lib/passport/http/request.js:43:29)
    at /var/www/project/my-project/node_modules/@nestjs/passport/dist/auth.guard.js:63:64
    at new Promise (<anonymous>)

Error: Login sessions require session support. Did you forget to use `express-session` middleware?
    at SessionStrategy.authenticate (/var/www/project/my-project/node_modules/passport/lib/strategies/session.js:46:41)
    at attempt (/var/www/project/my-project/node_modules/passport/lib/middleware/authenticate.js:369:16)
    at authenticate (/var/www/project/my-project/node_modules/passport/lib/middleware/authenticate.js:370:7)
    at Layer.handle [as handle_request] (/var/www/project/my-project/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/var/www/project/my-project/node_modules/express/lib/router/index.js:317:13)
    at /var/www/project/my-project/node_modules/express/lib/router/index.js:284:7
    at Function.process_params (/var/www/project/my-project/node_modules/express/lib/router/index.js:335:12)
    at next (/var/www/project/my-project/node_modules/express/lib/router/index.js:275:10)
    at initialize (/var/www/project/my-project/node_modules/passport/lib/middleware/initialize.js:98:5)
    at Layer.handle [as handle_request] (/var/www/project/my-project/node_modules/express/lib/router/layer.js:95:5)

Files

DatabasePassportSerializer.ts

import { EventBus } from '@nestjs/cqrs'
import { Strategy } from 'passport'
import passport = require('passport')

/**
 * A Passport Strategy which delays the decision of the underlying strategy until application bootstrap is complete.
 *
 * We must wait to give time for all the options to be registered in {@link AuthenticationProviderRegistry}. It is assumed this is done as part of OnModuleInit.
 *
 * See {@link AuthStrategy} for more details.
 *
 * @export
 * @class DelegatingStrategy
 * @implements {Strategy}
 * @implements {OnApplicationBootstrap}
 */
@Injectable()
export class DelegatingStrategy implements Strategy, OnApplicationBootstrap {
  private readonly logger = new Logger(DelegatingStrategy.name)

  name = 'my-strategy-name'
  protected strategy: Strategy | null = null
  protected authenticationProvider: AuthenticationProvider | null = null

  constructor(
    protected readonly authenticationProviderRegistry: AuthenticationProviderRegistry,
    private readonly verifyCallback: VerifyFunction,
    protected readonly eventBus: EventBus
  ) {}

  async onApplicationBootstrap(): Promise<void> {
    // Create the strategy from the active provider
    this.authenticationProvider = this.authenticationProviderRegistry.getActive()

    this.logger.log(
      `Authentication is provided by ${this.authenticationProvider.type()}`
    )

    this.strategy = await this.authenticationProvider.createStrategy(
      this.verifyCallback
    )

    // Replace `this` with the this.strategy in passport
    passport.use(this.name, this.strategy)
  }

  authenticate(_this: unknown): void {
    // This is a fake method.
    // it is required to be a strategy but it is never called, because we replace this strategy in the
    // onApplicationBootstrap() method.
    const message = 'Authentication not setup properly'
    this.eventBus.publish(new OperationFailed(SYSTEM_SUBJECT, message))
    throw new InternalServerErrorException(message)
  }
}

// Login Guard
@Injectable()
export class LoginGuard extends AuthGuard(AUTH_STRATEGY) {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    const result = (await super.canActivate(context)) as boolean
    const request = context.switchToHttp().getRequest()
    await super.logIn(request)
    return result
  }
}

main.ts

  const sessionConfiguration: session.SessionOptions = {
    name: 'my-session',
    // We don't need to change the session each time
    resave: false,
    // Only create a session as required by authentication
    saveUninitialized: false,
    // Our secret
    secret: sessionSecret,
    // use our database backed store:
    store: sessionStore,
    cookie: {
      // Cookie is for the API
      path: '/api',
      // Our cookie can only last as long as session should
      maxAge: configStore.getDuration(SESSION_EXPIRY_TIME, '84000s'),
      // Ideally we use secure, but we assume that in dev you can won't be able to
      secure: configStore.getBoolean('SESSION_SECURE', false),
      // No JS access to cookies
      httpOnly: true,
      // Only our site can access these cookies
      sameSite: 'strict',
    },
  }
  app.use(session(sessionConfiguration))

  // Add passport
  app.use(passport.initialize())
  app.use(passport.session())
  • I have upgraded passport package from 0.4.1 to 0.6.0 and after that facing this error.
  • I have created local strategy for authentication and used login guard.
  • Also tried to upgrade @nestjs/passport from 7.1.5 to version latest version
  • Is it related to express-session ??
  • My session storage is database.

Environment

Operating System: Linux, ubuntu 22.04
Node version: 14.19.0
passport version: 0.6.0
NestJs version: 7.x (typescript: 4.0.2)
Related packages: "passport-local":1.0.0, "@nestjs/passport":7.x & "@nestjs/common": 7.x,

@jaredhanson @mde @coderberry @tschaub Please look into it.

Please let me know if anyone have some solution...
Thanks in advance. 😄

@markstos
Copy link

I got this error too, and further pinned it down to happening between the passport upgrade from 0.5.3 and 0.6.0.

Did you review the breaking changes in the Changelog to see if you are impacted by one of them (in which case, it's not a bug in passport).
https://github.com/jaredhanson/passport/blob/master/CHANGELOG.md

I'm currently tracking down the root-cause of this error myself, but I use "passport-oauth2-cognito": "0.1.0", which in turn uses passport-oauth2, which in turn uses passport-strategy. But I think it was only upgrading passport that caused my app to break.

@markstos
Copy link

I think this can be closed as a dupe of #939

@bs-nikunj-sondagar bs-nikunj-sondagar closed this as not planned Won't fix, can't repro, duplicate, stale Oct 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants