получаю ошибку, что заголовок уже отправлен с использованием инфраструктуры Passport и Nest - PullRequest
0 голосов
/ 05 октября 2018

У меня есть приложение NestJS, в котором есть некоторая логика аутентификации.Вход в систему реализован для Google Oauth с использованием Passport и, кажется, работает, за исключением того, что на сервере я выдам эту ошибку:

(node:19195) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

Я немного погуглил и, похоже, одной из распространенных причин может бытьотправьте ответ несколько раз клиенту.Тем не менее, я не могу обнаружить это в своем коде, поэтому я подозрительно, если это причинаВот соответствующие фрагменты.

Использование @ nestjs / passport для сериализации и десериализации пользователя.

@Injectable()
export class GoogleSerializer extends PassportSerializer {
    constructor(private readonly usersService: UsersService) {
        super();
    }

    public serializeUser(user: User, done: Function) {
        console.log('serialize', user);
        if (user) {
            done(null, user.id);
        } else {
            done(null);
        }
    }

    public async deserializeUser(id: number, done: Function) {
        console.log('deserialize', id);
        this.usersService.findById(id).then(user => {
            done(null, user);
        }).catch(error => {
            done(error, null);
        });
    }
}

Вот стратегия Google для Passport JS:

@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy) {
  constructor(private readonly usersService: UsersService) {
    super({
      clientID:
        'client',
      clientSecret: 'I'm-secret',
      callbackURL: '/auth/google/callback',
      scope: ['email', 'profile'],
    });
  }

  async validate(accessToken, refreshToken, profile, done) {
    const user = <create the user object from google profile> 

    this.usersService.findOne(user.email).then(userEntity => {
      if (!userEntity) {
        this.usersService.createOne(user);
      }
    });
    return this.usersService
      .findOne(user.email)
      .then(user => {
        done(null, user);
        return user;
      })
      .catch(error => {
        done(error);
        return null;
      });
  }
}

Вот маршруты для AuthController:

@Controller('auth')
export class AuthController {
  @Get('/google/callback')
  async googleCallback(@Req() req, @Res() res, @Next() next) {
    passport.authenticate('google', {
      successReturnToOrRedirect: '/users/test',
      failureRedirect: '/auth/login'
    })(req, res, next);
  }

  @Get('/login')
  async login(@Req() req) {
    return '<a href="/auth/google/login">Login</a>';
  }

  @Get('/google/login')
  async googleLogin(@Req() req, @Res() res, @Next() next) {
    passport.authenticate('google', { scope: ['profile', 'email'] })(req, res, next);
  }
}

У меня есть промежуточное ПО для путей, по которым пользователь должен войти в систему:

    @Injectable()
    export class LoginRequired implements NestMiddleware {
        resolve(...args: any[]): MiddlewareFunction {
            console.log('calling loginrequired');
            return (req, res, next) => {
                if (!req.isAuthenticated || !req.isAuthenticated()) {
                    if (req.session) {
                        req.session.returnTo = req.originalUrl || req.url;
                    }
                    return res.redirect('/auth/login');
                }
                next();
            }
        }
    }

и вот этап установки:

app.use(session({
secret: 'secret',
resave: false,
saveUninitialized: true,
cookie: { secure: false }}));
app.use(passport.initialize());
app.use(passport.session());

Например, я пытаюсь зайти / пользователь, который защищен этим промежуточным ПО и который должен отправить пользователя на страницу входа, которая предлагает пользователю войти в систему и приводит пользователя на страницу / пользователя.Все работает, но я получаю

Невозможно установить заголовки после их отправки клиенту

Есть идеи, как это происходит?

Я используюПаспорт и Джест.

...