Problem using google provider for login in backend using Next + Nest js projec

i am using backend with Nest.js and Frontend with Next.js. the Next js supposed to be frontend only with a few backend capability such as the Next-Auth.

so in the front side every thing works great, i can sign in with google and i get the details from the user. as the current session. but from the backend i am exposing the following api:
http://localhost:3001/auth/google-redirect as you can see in the following file:
src/auth/auth.controller.ts:

import { Controller, Get, Req, SetMetadata, UseGuards } from '@nestjs/common';
import { AuthService } from './auth.service';
import { Request } from 'express';
import { HttpUser } from 'src/decorators/http-user.decorator';
import { HttpGoogleOAuthGuard } from '../guards/http-google-oauth.guard';
import { GoogleLoginUserDto } from './dto/google-login.dto';

@SetMetadata('google-login', true)
@UseGuards(HttpGoogleOAuthGuard)
@Controller('auth')
export class AuthController {
  constructor(private readonly authService: AuthService) { }
  @Get()
  async googleAuth(@Req() _req: Request) { }

  @Get('google-redirect')
  googleAuthRedirect(@HttpUser() user: GoogleLoginUserDto) {
    return this.authService.googleLogin(user);
  }
}

in the google console:
inside the credential: OAuth 2.0 Client IDs
enter image description here

the first uri callback works at the frontend:
http://localhost:3000/api/auth/callback/google

but the second uri at the callback:
http://localhost:3001/auth/google-redirect

won’t work, i tried to put log to the console when i get request but nothing happens, if i try to go to this uri i get an anwser:

{"message":"No user from google","error":"Unauthorized","statusCode":401}

as you can see in the src/auth/auth.service.ts:

import { Injectable, UnauthorizedException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import { PrismaService } from 'src/prisma/prisma.service';
import { GoogleLoginUserDto } from './dto/google-login.dto';

@Injectable()
export class AuthService {
    constructor(
        private jwtService: JwtService,
        private configService: ConfigService,
        private prisma: PrismaService,
    ) { }
    async googleLogin(user: GoogleLoginUserDto) {
        if (!user) {
            throw new UnauthorizedException('No user from google');
        }
        const {
            firstName,
            lastName,
            email,
            email_verified,
            expires_in,
            picture,
            providerAccountId,
            accessToken,
            refreshToken,
            id_token,
        } = user;
        const userData = await this.prisma.user.findFirst({
            where: { email },
            include: { accounts: true },
        });
        if (!userData) {

            const newUserData = await this.prisma.user.create({
                data: {
                    name: `${firstName} ${lastName}`,
                    email: email,
                    emailVerified: email_verified ? (new Date()).toISOString() : null,
                    image: picture,
                },
            });

            // creating new account
            const newAccount = await this.prisma.account.create({
                data: {
                    type: 'oauth',
                    provider: 'google',
                    providerAccountId: providerAccountId,
                    accessToken: accessToken,
                    refreshToken: refreshToken,
                    id_token: id_token,
                    expires_at: expires_in,
                    user: {
                        connect: {
                            id: newUserData.id,
                        },
                    },
                },
            });

            const access_token = await this.signJwt(
                newUserData.id,
                id_token,
                accessToken,
                expires_in,
            );
            return { access_token };
        }
        const access_token = await this.signJwt(
            userData.id,
            id_token,
            accessToken,
            expires_in,
        );
        return { access_token };
    }
    signJwt(
        userId: string,
        id_token: string,
        access_token: string,
        expires_at: number,
        expiresIn = '1d',
    ): Promise<string> {
        const payload = {
            sub: userId,
            id_token,
            access_token,
            expires_at,
        };
        return this.jwtService.signAsync(payload, {
            expiresIn,
            secret: this.configService.get('APP_JWT_SECRET'),
        });
    }
}

any one have any ideas why it wont work?

tried to change uris, and search the web for an anwser but no clue

Leave a Comment