如何在NextJS后端向Google signIn传递参数?

emeijp43  于 2023-06-22  发布在  Go
关注(0)|答案(1)|浏览(134)

我试图在nextJs 13应用程序中创建一个基于角色的谷歌登录,该应用程序使用next-auth,以便调用2个不同的表来创建基于他们的角色的用户。
我使用mongodb/mongoose作为数据库。用户型号为:

import mongoose, { Schema, model, models } from "mongoose";

const userSchema = new Schema({
  email: {
    type: String,
    required: [true, "Email is required"],
    unique: [true, "Email already exists"],
    index: true,
  },
  username: {
    type: String,
    required: [true, "Username is required"],
    match: [/^[a-zA-Z0-9]+$/, "Username is invalid"],
    index: true,
  },
  image: {
    type: String,
  },
  userType: {
    type: String,
    enum: ["typeA", "typeB"],
    required: [true, "User type is required"],
  },
});

const typeASchema = new Schema({
  typeA: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "User",
  },
  other1: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: "other_table1",
  }],
});

const typeBSchema = new Schema({
  typeB: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "User",
  },
  other2: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: "other_table2",
  }],
});

const User = models.User || model("User", userSchema);
const TypeA= models.TypeA || User.discriminator("TypeA", typeASchema);
const TypeB= models.TypeB || User.discriminator("TypeB", typeBSchema);

export { User, TypeA, TypeB};

然后在我的/app/API/auth/[... nextauth]/route.js中,我定义:

import NextAuth from 'next-auth';
import GoogleProvider from 'next-auth/providers/google';
import { connectToDB } from '@/utils/database';
import {User, TypeA, TypeB} from '@/models/user';

function getRandomAvatarURL() {
  
}

const handler = NextAuth({
    providers: [
        GoogleProvider({
            clientId: process.env.GOOGLE_ID,
            clientSecret: process.env.GOOGLE_CLIENT_SECRET,
        })
    ],
    
    callbacks: {
        async session({ session }) {
                const sessionUser = await User.findOne({
                email: session.user.email
            })    
            session.user.id = sessionUser._id.toString();   
            session.user.image = sessionUser.image; 
            return session;
    
        },
          
        async signIn({ profile, userType}) {

            try {
                await connectToDB();

                // check if a user already exists
                const userExists = await User.findOne({
                    email: profile.email
                });
                
                // if not, create user and add to db
                if(!userExists) {
                    
                    const name = profile.name.split(" ");
                    const firstName = name[0] || ".";
                    const lastName = name.slice(1).join(" ") || ".";
                    const username = `${firstName}${lastName}`.replace(/\s/g, "");
                    
                    if (userType === "typeA"){
                        await TypeA.create({
                            email: profile.email,
                            username: username,
                            image: getRandomAvatarURL(),
                            userType: "typeA",
                        })
                    } else if (userType === "typeB"){
                        await TypeB.create({
                            email: profile.email,
                            username: username,
                            image: getRandomAvatarURL(),
                            userType: "typeB",
                        })
                    }
                }   
                
                return true;
    
            } catch (error) {
                console.log(error)
                if (error.code === 11000){
                    console.log("Unique constraint violation error! Username already Exists!")
                }
                return false;
            }
        }
    },

})

export { handler as GET, handler as POST };

在我的Nav组件中,我调用如下函数:

//imports
const Nav = () => {

// other code ...

const handleSignin = async(providerId, userType) => {
    console.log('provider.id:', providerId); // returns correctly
    console.log('userType:', userType); //returns correctly
    await signIn(providerId, { callbackUrl: "/dashboard"}, {credentials:{userType: userType}});
  }

//...

return(
    //....
    {providers &&
                Object.values(providers).map((provider) => (              
                  <button
                    type="button"
                    key={provider.name}
                    onClick={() => handleSignin(provider.id, "refree")}
                  >
                    <Image src="/assets/icons/signin.svg" width={20} height={20} className="rounded-none" alt="signin" />
                  </button>
                ))}
);
};
export default Nav;

我尝试了所有可能的前端和后端组合,其中一些是:

Frontend:

const handleSignin = async(providerId, userType) => {
    await signIn(providerId, { callbackUrl: "/dashboard"}, {credentials:{userType: userType}});
  }

const handleSignin = async(providerId, userType) => {
    await signIn(providerId, { callbackUrl: "/dashboard"}, {credentials:userType});

const handleSignin = async(providerId, userType) => {
    await signIn(providerId, { callbackUrl: "/dashboard"}, {userType: userType});
  }
const handleSignin = async(providerId, userType) => {
    await signIn(providerId, {userType: userType, callbackUrl: "/dashboard"});
  }

Backend:
async signIn({ profile, userType}) {
            try {
                await connectToDB();
                console.log(userType)

async signIn({ profile, credentials}) {
            try {
                await connectToDB();
                console.log(credentials)

它总是返回undefined。我似乎无法捕获从前端传递到后端的参数。任何帮助或指针都非常感谢。当我不传递userType参数,而只是尝试在登录时创建任何一种类型的用户时,该流就可以工作。

kyxcudwk

kyxcudwk1#

nextauth中signIn的第三个参数authorizationParams被传递给提供者(google),而不是signIn回调。您可以创建一个自定义提供程序,并从signIn回调的user中获取userType,如下所示:

providers: [
    {
      id: "googleUserA",
      name: "GoogleUserA",
      type: "oauth",
      wellKnown: "https://accounts.google.com/.well-known/openid-configuration",
      authorization: { params: { scope: "openid email profile" } },
      idToken: true,
      checks: ["pkce", "state"],
      profile(profile) {
        return {
          id: profile.sub,
          name: profile.name,
          email: profile.email,
          image: profile.picture,
          userType: "userA",
        };
      },
      clientId: process.env.GOOGLE_ID,
      clientSecret: process.env.GOOGLE_SECRET,
    },
    {
      id: "googleUserB",
      name: "GoogleUserB",
      type: "oauth",
      wellKnown: "https://accounts.google.com/.well-known/openid-configuration",
      authorization: { params: { scope: "openid email profile" } },
      idToken: true,
      checks: ["pkce", "state"],
      profile(profile) {
        return {
          id: profile.sub,
          name: profile.name,
          email: profile.email,
          image: profile.picture,
          userType: "userB",
        };
      },
      clientId: process.env.GOOGLE_ID,
      clientSecret: process.env.GOOGLE_SECRET,
    },
  ],
  callbacks: {
    signIn: async ({ user, profile }) => {
      console.log(user.userType); // userA or userB
      ...

前端会像……

signIn("googleUserA", { callbackUrl: "/dashboard" });

相关问题