admin管理员组

文章数量:1297106

I initially used NodeMailer for login method, but then i realized after completing the project that nodeMailer requires domain for sending emails, now i looked into documents Oauth Providers are following: Google and Nodemailer

As per docs i created it like this:

import { PrismaAdapter } from "@auth/prisma-adapter";
import NextAuth from "next-auth";
import Nodemailer from "next-auth/providers/nodemailer";
import prisma from "./db";



export const { handlers, signIn, signOut, auth } = NextAuth({
  adapter: PrismaAdapter(prisma),
  providers: [
    Nodemailer({
      server: {
        host: process.env.EMAIL_SERVER_HOST,
        port: process.env.EMAIL_SERVER_PORT,
        auth: {
          user: process.env.EMAIL_SERVER_USER,
          pass: process.env.EMAIL_SERVER_PASSWORD,
        },
      },
      from: process.env.EMAIL_FROM,
    }),
   
  ],
  
  pages: {
    verifyRequest: "/verify",
  },
});

Now it after reading docs i reassessed and changed it to:

// auth.ts
import { PrismaAdapter } from "@auth/prisma-adapter";
import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import prisma from "./db";

export const { handlers, signIn, signOut, auth } = NextAuth({
  adapter: PrismaAdapter(prisma),
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    }),
  ],
  callbacks: {
    async signIn({ user, account }) {
      // Ensure that user.email exists.
      if (!user.email) {
        // You can choose to return false (reject sign-in) or handle it otherwise.
        return false;
      }

      // Check if a user already exists with the same email.
      const existingUser = await prisma.user.findUnique({
        where: { email: user.email },
      });

      if (existingUser) {
        // You can implement account linking logic here if needed.
      }

      // Returning true proceeds with the sign-in.
      return true;
    },
  },
  pages: {
    verifyRequest: "/verify",
  },
});

and similarly changed the login to

"use client";

import { useState } from "react";
import { useRouter } from "next/navigation";
import { signInWithGoogle } from "../utils/firebase";
import {
  Card,
  CardContent,
  CardHeader,
  CardTitle,
  CardDescription,
} from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { DoorOpen } from "lucide-react"; // Ensure this import is on one line
import type { UserCredential } from "firebase/auth";

// Extend the UserCredential type to include additionalUserInfo
type ExtendedUserCredential = UserCredential & {
  additionalUserInfo?: {
    isNewUser: boolean;
    [key: string]: any;
  } | null;
};

export default function LoginPage() {
  const [error, setError] = useState("");
  const router = useRouter();

  const handleGoogleLogin = async () => {
    try {
      // Cast the returned credential to ExtendedUserCredential
      const userCredential = (await signInWithGoogle()) as ExtendedUserCredential;
      const isNewUser = userCredential.additionalUserInfo?.isNewUser;
      
      if (isNewUser) {
        router.push("/onboarding");
      } else {
        router.push("/dashboard");
      }
    } catch (err) {
      setError("Google sign-in failed");
    }
  };

  return (
    <div className="min-h-screen w-screen flex items-center justify-center">
      <div className="absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#f0f0f0_1px,transparent_1px),linear-gradient(to_bottom,#f0f0f0_1px,transparent_1px)] bg-[size:6rem_4rem]">
        <div className="absolute bottom-0 left-0 right-0 top-0 bg-[radial-gradient(circle_500px_at_50%_200px,#C9EBFF,transparent)]"></div>
      </div>
      <Card className="max-w-sm w-full mx-auto shadow-lg">
        <CardHeader>
          <CardTitle className="text-xl text-center">Welcome Back</CardTitle>
          <CardDescription className="text-center">
            Sign in to continue
          </CardDescription>
        </CardHeader>
        <CardContent>
          {error && <p className="text-red-500 text-center mb-4">{error}</p>}
          <Button
            onClick={handleGoogleLogin}
            className="w-full flex items-center justify-center gap-2 bg-red-500 text-white"
          >
            <DoorOpen size={20} /> Sign in with Google
          </Button>
        </CardContent>
      </Card>
    </div>
  );
}

I have an onboarding function where it posts firstname secondname and address and only then user redirects to dashboard else back to login.

The issue is i hit google api to login it gives a callback but sends back server error its taking some image i do not know why. The model is as followed:


model User {
  id            String          @id @default(cuid())
  firstName     String?
  secondName    String?
  address       String?
  email         String          @unique
  emailVerified DateTime?
  image         String?
  accounts      Account[]
  sessions      Session[]
  Authenticator Authenticator[]
  invoices      Invoice[]
  ownedBusiness Business? @relation("OwnedBusiness")
  Note          Note[]
  Todo          Todo[]
  Stock         Stock[]
  createdAt     DateTime @default(now())
  updatedAt     DateTime @updatedAt
}

everything works fine with nodemailer

本文标签: nextjsIssues migrating from nodeMailer to GoogleProvider using 0AuthStack Overflow