You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Issue: ERR_HTTP_HEADERS_SENT Error in Passport Google OAuth 2.0 Authentication
Expected behavior
Upon successful authentication using Google OAuth 2.0 with Passport, I expect the user to be redirected to a successful login route.
Actual behavior
I'm getting the Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client when trying to redirect after successful authentication using Google OAuth 2.0 with Passport. The error seems to originate from response.redirect within the handleAuthenticationWithGoogleSuccess function.
Steps to reproduce
Here are the main snippets from my code that relate to this issue:
import{injectable,inject}from"inversify";import{StrategyasGoogleStrategy}from"passport-google-oauth20";import{ICreateUserUseCase,ISearchUserUseCase,}from"@userManagement/modules/users/domain/interfaces/usecases.interfaces";import{UserManagementModuleIdentifiers}from"@userManagement/dependencies/identifiers";import{IUserCreatedFromValidSources}from"@userManagement/modules/users/domain/entities/user.entity";import{CURRENT_SERVER_HOST_URL,GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET,}from"@shared/infrastructure/config/env";
@injectable()exportclassPassportGoogleStrategy{privatestrategy: GoogleStrategy;constructor(
@inject(UserManagementModuleIdentifiers.CREATE_USER_USE_CASE)privatereadonlycreateUserUseCase: ICreateUserUseCase,
@inject(UserManagementModuleIdentifiers.SEARCH_USER_USE_CASE)privatereadonlysearchUserUseCase: ISearchUserUseCase){this.strategy=newGoogleStrategy({clientID: GOOGLE_CLIENT_ID,clientSecret: GOOGLE_CLIENT_SECRET,callbackURL: `${CURRENT_SERVER_HOST_URL}/auth/google/success`,},async(_,__,profile,done)=>{// Use arrow function heretry{letuser=awaitthis.searchUserUseCase.execute({email: profile.emails[0].value,});if(!user){user=awaitthis.createUserUseCase.execute({email: profile.emails[0].value,createdFrom: IUserCreatedFromValidSources.GOOGLE,});}returndone(null,user);}catch(err){returndone(err);}});}getStrategy(){returnthis.strategy;}}
Controller
import{controller,httpPost,BaseHttpController,httpGet,request,response,next,}from"inversify-express-utils";import{inject}from"inversify";import{UserManagementModuleIdentifiers}from"@userManagement/dependencies/identifiers";import{ISignUpHandler,ILoginHandler,}from"@authentication/domain/interfaces/handlers.interfaces";import{verifyApiKeyMiddleware}from"@authorization/presentation/middlewares/valid-api-key.middleware";import{IPassportService}from"@authentication/domain/interfaces/services.interfaces";import{NextFunction,Request,Response}from"express";import{EnabledAuthenticationStrategies}from"@authentication/domain/services/passport.service";import{IAuthenticationController}from"@authentication/domain/interfaces/controllers.interfaces";import{CURRENT_CLIENT_HOST_URL}from"@shared/infrastructure/config/env";exportfunctionsessionLogger(req: Request,res: Response,next: NextFunction){// Log session ID and user information (if available) for each requestconsole.log("Session ID:",(reqasany).sessionID);console.log("User:",req.user);next();// Call the next middleware in the chain}
@controller("/auth")exportclassAuthenticationControllerextendsBaseHttpControllerimplementsIAuthenticationController{constructor(
@inject(UserManagementModuleIdentifiers.SIGN_UP_HANDLER)privatesignUpHandler: ISignUpHandler,
@inject(UserManagementModuleIdentifiers.LOGIN_HANDLER)privateloginHandler: ILoginHandler,
@inject(UserManagementModuleIdentifiers.PASSPORT_SERVICE)privatepassportService: IPassportService){super();}
@httpPost("/signup",verifyApiKeyMiddleware)signUp(){returnthis.signUpHandler.handle(this.httpContext.request,this.httpContext.response);}
@httpPost("/login")login(){returnthis.loginHandler.handle(this.httpContext.request,this.httpContext.response);}
@httpGet("/google")authenticateWithGoogle(req: Request,res: Response,next: NextFunction){returnthis.passportService.authenticate(EnabledAuthenticationStrategies.GOOGLE,{scope: ["profile","email"]})(reqasany,res,next);}
@httpGet("/google/success")handleAuthenticationWithGoogleSuccess(
@request()req: Request,
@response()res: Response,
@next()next: NextFunction){this.passportService.authenticate(EnabledAuthenticationStrategies.GOOGLE,{failureRedirect: "/login",successReturnToOrRedirect: `${CURRENT_CLIENT_HOST_URL}/auth/google/success`,},(error,user,info)=>{// here use res directly, not via the callback argsres.redirect(`${CURRENT_CLIENT_HOST_URL}/auth/google/success`);})(reqasany,res,next);}
@httpGet("/me")getCurrentUser(req: Request,res: Response){// Log session information using the sessionLogger middlewaresessionLogger(req,res,()=>{if(req.isAuthenticated()){// User is authenticated, return the user's informationconstuser=req.user;res.json(user);}else{// User is not authenticated, return an appropriate responseres.status(401).json({error: "Not authenticated"});}});}
@httpPost("/logout")logout(req: Request){req.logout((err: any)=>{if(err){// Handle error if neededconsole.error("Error occurred during logout:",err);}});}}
server.ts
import"reflect-metadata";import*asSentryfrom"@sentry/node";import{connectCriticalInfrastructure,disconnectCriticalInfrastructure,}from"@shared/infrastructure/helpers/critical-infrastructure.helpers";import{setupGracefulShutdown}from"@shared/infrastructure/helpers/server.helpers";import{errorHandler}from"@shared/presentation/middlewares/error-handling.middleware";importcorsfrom"cors";importexpressfrom"express";importhelmetfrom"helmet";importmorganfrom"morgan";importsessionfrom"express-session";import{IPassportService}from"@authentication/domain/interfaces/services.interfaces";import{GlobalDependenciesIdentifiers}from"@shared/infrastructure/dependencies/identifiers";import{getRootContainer}from"@shared/infrastructure/dependencies/root-container";import{initializeLoggingInfrastructure}from"@shared/infrastructure/helpers/secondary-infrastructure.helpers";import{InversifyExpressServer}from"inversify-express-utils";import{mainRouter}from"shared/presentation/routes/main-router";import{JWT_SECRET}from"@shared/infrastructure/config/env";constPORT=process.env.PORT||3000;letserver=newInversifyExpressServer(getRootContainer());server.setConfig((app)=>{initializeLoggingInfrastructure(app);constpassport=getRootContainer().get<IPassportService>(GlobalDependenciesIdentifiers.USER_MANAGEMENT.PASSPORT_SERVICE);passport.initialize();// Initialize Passport// Middlewaresapp.use(session({secret: JWT_SECRET,resave: false,saveUninitialized: false,cookie: {secure: process.env.NODE_ENV==='production'},}));app.use(express.json());app.use(express.urlencoded({extended: true}));app.use(morgan("dev"));app.use(helmet());app.use(cors());app.use(passport.session());app.use("/",mainRouter);app.use(Sentry.Handlers.errorHandler());app.use(errorHandler);// Start serverconnectCriticalInfrastructure().catch(async(error)=>{console.error("AN ERROR OCCURED WHILE CONNECTING CRITICAL INFRASTRUCTURE DEPENDENCIES: ",error);awaitdisconnectCriticalInfrastructure();process.exit(1);}).then(()=>{constserver=app.listen(PORT,()=>{console.info(`Server is listening on port ${PORT}.`);});// Setting up graceful shutdownsetupGracefulShutdown(server,disconnectCriticalInfrastructure);});});server.build();
I'm unable to pinpoint the reason why this error occurs. I'm looking for any advice on how to troubleshoot or fix this issue. Thanks for any help or suggestions!
The text was updated successfully, but these errors were encountered:
The issue is likely occurring because you are calling res.redirect() directly within the Passport authenticate callback function. This will cause headers to be sent twice - once from the redirect and once from the original request handler.
A few ways to fix:
Don't call res.redirect() in the callback. Instead, just call done() and let the request handler send the response:
Issue: ERR_HTTP_HEADERS_SENT Error in Passport Google OAuth 2.0 Authentication
Expected behavior
Upon successful authentication using Google OAuth 2.0 with Passport, I expect the user to be redirected to a successful login route.
Actual behavior
I'm getting the
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
when trying to redirect after successful authentication using Google OAuth 2.0 with Passport. The error seems to originate fromresponse.redirect
within thehandleAuthenticationWithGoogleSuccess
function.Steps to reproduce
Here are the main snippets from my code that relate to this issue:
Passport Service
Google Strategy
Controller
server.ts
Environment
I'm unable to pinpoint the reason why this error occurs. I'm looking for any advice on how to troubleshoot or fix this issue. Thanks for any help or suggestions!
The text was updated successfully, but these errors were encountered: