How can I properly implement Githhub Oauth2.0 authentication alongside JWT Authentication in Nest.js?

37 Views Asked by At

I have already implemented the jwt authentication. The problem occurs with Github Authentication using passport-github2 in Nest JS? I keep running into the error where I get req.user is equal to undefined in the callback url of the github auth. Below is my code for more context:

// github.strategy.ts
import { Injectable, Logger } from '@nestjs/common';
import { AppConfig } from '@/lib/config/config.provider';
import { PassportStrategy } from '@nestjs/passport';
import {
  Strategy,
  Profile,
  StrategyOptionsWithRequest,
} from 'passport-github2';
import { AuthenticationService } from '../authentication.service';
import { Request } from 'express';

type VerifyCallback = (error: any, user?: any, info?: any) => void;

const githubOptions: StrategyOptionsWithRequest = {
  clientID: AppConfig.authentication.GITHUB_CLIENT_ID,
  clientSecret: AppConfig.authentication.GITHUB_CLIENT_SECRET,
  callbackURL: AppConfig.authentication.GITHUB_CALLBACK_URL,
  passReqToCallback: true,
  scope: ['user:email'],
};

@Injectable()
export class GithubStrategy extends PassportStrategy(Strategy, 'github') {
  private readonly logger = new Logger(GithubStrategy.name);
  constructor(private readonly authService: AuthenticationService) {
    super(githubOptions);
  }

  async validate(
    req: Request,
    accessToken: string,
    _refreshToken: string,
    profile: Profile,
    done: VerifyCallback,
  ): Promise<any> {
    try {
      console.log('GitHub Profile:', profile);
      const user = await this.authService.validateGithubUser(profile);
      console.log('User object from AuthService:', user);
      if (!user) {
        console.log('No user found');
        return done(null, false);
      }
      console.log('User object passed to done callback:', user);
      return done(null, user);
    } catch (err) {
      this.logger.error('Failed to validate github authentication', {
        error: err,
      });
      throw new Error(err);
    }
  }
}
// github.guard.ts
import {
  ExecutionContext,
  Injectable,
  UnauthorizedException,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class GithubAuthGuard extends AuthGuard('github') {
  canActivate(context: ExecutionContext) {
    return super.canActivate(context);
  }

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  handleRequest(err, user, _info) {
    if (err || !user) {
      throw err || new UnauthorizedException();
    }
    return user;
  }
}
// authentication.module.ts
import { Global, Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { EventEmitterModule } from '@nestjs/event-emitter';
import { JwtModule } from '@nestjs/jwt';
import { AuthenticationController } from './authentication.controller';
import { AuthenticationService } from './authentication.service';
import { LocalStrategy } from './strategies/local.strategy';
import { AccessTokenJwtStrategy } from './strategies/access-token.strategy';
import { AppEventHandler } from '@/common/events/app.events';
import { GithubStrategy } from './strategies/github.strategy';

@Global()
@Module({
  imports: [
    PassportModule.register({
      defaultStrategy: ['jwt', 'github'],
      session: false,
    }),
    JwtModule.register({}),
    EventEmitterModule.forRoot(),
  ],
  controllers: [AuthenticationController],
  providers: [
    AuthenticationService,
    LocalStrategy,
    AccessTokenJwtStrategy,
    GithubStrategy,
    AppEventHandler,
  ],
  exports: [AuthenticationService],
})
export class AuthenticationModule {}

// auth.controller.ts
@UseGuards(GithubAuthGuard)
@Get('/auth/github')
public githubAuth() {}

@UseGuards(GithubAuthGuard)
@Get('/auth/github/callback')
public async githubAuthCallback(@Req() req: Request) {
  const user = req.user;
  console.log('User object in controller:', user);
  if (!user) {
    return { message: 'Authentication failed' };
  }
  return { message: 'Authentication successful', user: user };
}

In my github.strategy.ts, I logged to user object to see if it is been found or created by the validateGithubUser method. Yes, it is. So I am guessing the user is not been passed alongside the request. That is the problem.

I expect to get the req.user on the githubAuthCallback method not to be undefined at least for now

0

There are 0 best solutions below