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!