Trouble Integrating Google OAuth Authentication API Nest using PassportJS with React Frontend

14 Views Asked by At

I'm encountering difficulties integrating my React frontend with a backend API that handles Google OAuth authentication.

I cannot retrieve data from my nestJS api with passport using the Google strategy

Below are the relevant code snippets:

const fetchAuthUser = async () => {
    const response = await axios.get(window.location.href);
    if (!response.data) throw new Error('Error');
    if (response.data) setData(response.data);
};


const authWithGoogle = async () => {
   window.open(
    'http://localhost:3000/auth/callback',
    '_blank',
    'width=500,height=600'
);
   if (window.opener) {
    if (!await fetchAuthUser()) {
    window.close();
   }
 }
};

Here is my API

@Get('googleaccount')
  @UseGuards(GoogleOAuthGuard)
  async googleAuth() {}

  @Get('callback')
  @UseGuards(GoogleOAuthGuard)
  async googleAuthRedirect(@Req() req: any, @Res() res: any | Response) {
    try {
      const result = await this.authService.googleAccount(req);
      res.json({ ...result.data, token: result.token });
    } catch (error) {
      console.error('Erreur lors de la redirection Google OAuth:', error);
      res.status(500).send('Erreur lors de la redirection Google OAuth');
    }
  }
import { ExecutionContext, Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class GoogleOAuthGuard extends AuthGuard('google') {
  constructor(private configService: ConfigService) {
    super({
      accessType: 'offline',
    });
  }
}
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy, VerifyCallback } from 'passport-google-oauth20';

@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, '') {
  constructor() {
    super({
      clientID: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
      callbackURL: 'http://localhost:3000/auth/callback',
      scope: ['email', 'profile'],
    });
  }
  async validate(
    accessToken: string,
    refreshToken: string,
    profile: any,
    done: VerifyCallback,
  ): Promise<any> {
    const { name, emails, photos } = profile;
    const user = {
      email: emails[0].value,
      firstName: name.givenName,
      lastName: name.familyName,
      picture: photos[0].value,
      accessToken,
      refreshToken,
    };
    
    done(null, user);
  }
}
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { Request as RequestType } from 'express';
import { ConfigService } from '@nestjs/config';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { PrismaService } from 'src/prisma/prisma.service';

type Payload = {
  sub: number;
  email: string;
};

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    configService: ConfigService,
    private readonly prismaService: PrismaService,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromExtractors([
        JwtStrategy.extractJWT,
        ExtractJwt.fromAuthHeaderAsBearerToken(),
      ]),
      secretOrKey: configService.get('JWT_SECRET'),
      ignoreExpiration: false,
    });
  }

  private static extractJWT(req: RequestType): string | null {
    if (
      req.cookies &&
      'token' in req.cookies &&
      req.cookies.user_token.length > 0
    ) {
      return req.cookies.token;
    }
    return null;
  }

  async validate(payload: Payload) {
    const user = await this.prismaService.user.findUnique({where: {email: payload.email}});
    if (!user) throw new UnauthorizedException('Unauthorized !');
    Reflect.deleteProperty(user, "password");
    return user
  }
}

Despite this, I cannot retrieve the data from the API and redirect afterwards. Any insights, suggestions, or corrections to my approach would be greatly appreciated. Thank you!

0

There are 0 best solutions below