ค้นหาเว็บไซต์

typescript - วิธีการดึงชื่อผู้ใช้งาน GitHub ในการเรียกกลับการเข้าสู่ระบบ Github OAuth บน Next.js เพื่อนำไปเพิ่มในฐานข้อมูล?


1. สรุปปัญหา

ตอนนี้ฉันกำลังสร้างเว็บไซต์แบบ Full Stack โดยใช้ Next.js และ Typescript และฉันติดปัญหาในการเก็บชื่อผู้ใช้ Github เพื่อบันทึกลงในฐานข้อมูลเมื่อผู้ใช้เข้าสู่ระบบผ่าน Github OAuth

ฉันควรเก็บบางอย่างอื่นเช่น ID ไว้ด้วยหรือไม่? อย่างไรก็ตาม ฉันต้องการให้เว็บไซต์ของฉันสามารถเป็น "domain.com/[ชื่อผู้ใช้ GitHub]" ได้

ฉันกำลังพยายามใช้ชื่อผู้ใช้ Github เป็นคีย์หลักในการจัดเก็บข้อมูลผู้ใช้ในฐานข้อมูล (mongodb)

ฉันเพิ่มรหัสผู้ใช้ในปัจจุบันไปยังฐานข้อมูลในระหว่างการกลับเรียกเข้าสู่ระบบใน [...nextauth].ts

นี่คือ [...nextauth].ts ของฉัน

/*
File: [..nextauth].ts
Description: This file will uses nextAuth to handle the requests, res of any OAuth...
*/
import NextAuth from "next-auth/next";
import GitHubProvider from "next-auth/providers/github"
import type {CredentialsProvider} from "next-auth/providers";
import axios from "axios"
import clientPromise from "../../../lib/mongodb";
import {useSession} from "next-auth/react";

export default NextAuth({
    providers: [
        GitHubProvider({
            clientId: process.env.GITHUB_CLIENT_ID,
            clientSecret : process.env.GITHUB_CLIENT_SECRET,
            
        }),
    ],
    callbacks: {
        async jwt({ token, user, account, profile, isNewUser }) {
        // Persist the OAuth access_token to the token right after signin
        if(profile){
            token.login = profile.login
            // @ts-ignore
            user.login = profile.login
            console.log(user)
            // code up here is the user name in the jwt but user.login isn't being persisted in session nor signin
            token.id = profile.id
        }
        if (account) {
            token.accessToken = account.access_token
        }
        return token
        },
        async session({ session, token, user}) {
            // Send properties to the client, like an access_token from a provider.
            session.accessToken = token.accessToken
            session.login = token.login;
            session.id = token.id;
            // @ts-ignore
            console.log(user.name)
            return session
        },
        async signIn({ user: User, account:Account, profile: profile, email:Email }) {
            // define client
            const client = await clientPromise;

            // define database
            const db = client.db("userData");

            // define users
            const users = db.collection("users");

            console.log(User.login)


            try{
                // get user data
                const insertDocument = {"_id":User.id, "User":User}
                // @ts-ignore
                const dataUsers = await db.collection("users").insertOne(insertDocument);
                if(dataUsers){
                    console.log("Added " + String(User.id) + " to database!")
                    return true;
                }

                // if we are here user simply could not be added at all...

                return false;
            } catch (error) {
                console.log("User could not be added to database due to an error or either existing")
                return true;

            }
            return true;
        },
    },
    debug:true,
});

อย่างไรก็ตาม ปัญหาจริงคือฉันดูเหมือนจะหาคำว่า 'เข้าสู่ระบบ/ชื่อผู้ใช้' ในภายในการเรียกกลับการลงชื่อเข้าใช้ด้วยอาร์กิวเมนต์ที่กำหนดของฟังก์ชันไม่ได้

       async signIn({ user: User, account:Account, profile: profile, email:Email }) {

2. อธิบายสิ่งที่ฉันได้ลองทำ

ฉันพบว่าชื่อผู้ใช้ Github อยู่ที่นี่ในฟังก์ชัน JWT อย่างไรก็ตามฉันประกาศตัวแปรตามนั้น และ User ไม่มีคุณสมบัตินั้นที่ใดที่อื่น

async jwt({ token, user, account, profile, isNewUser }) {
        // Persist the OAuth access_token to the token right after signin
        if(profile){
            token.login = profile.login
            // @ts-ignore
            user.login = profile.login // code here is the user name in the jwt but user.login isn't being saved in the other functions for Arg User
            persisted in session nor signin
            token.id = profile.id
        }
        if (account) {
            token.accessToken = account.access_token
        }
        return token
        },

3. การเจาะลึกโค้ด

ในจุดนี้ ผมสามารถได้แค่รหัสผู้ใช้ซึ่งเป็นตัวเลขที่อาจจะถูก Github ใช้เก็บข้อมูลของพวกเขาด้วย แต่ผม ต้องการชื่อผู้ใช้ Github

try{
                // get user data
                const insertDocument = {"_id":User.id, "User":User}
                // @ts-ignore
                const dataUsers = await db.collection("users").insertOne(insertDocument);
                if(dataUsers){
                    console.log("Added " + String(User.id) + " to database!")
                    return true;
                }

                // if we are here user simply could not be added at all...

                return false;
            } catch (error) {
                console.log("User could not be added to database due to an error or either existing")
                return true;

            }

คำตอบ #1

ฉันได้มองหาสิ่งเดียวกันนี้และสามารถทำได้โดยการแทนที่ callback profile เริ่มต้นของผู้ให้บริการ GitHub OAuth เพื่อส่งคืนคุณสมบัติโปรไฟล์เพิ่มเติม

ฉันใช้วิธีแก้ปัญหานี้ซึ่งก็ส่งค่าชื่อผู้ใช้งานกลับมาด้วย:

    GitHubProvider({
      clientId: env.GITHUB_CLIENT_ID,
      clientSecret: env.GITHUB_CLIENT_SECRET,
      profile(profile: GithubProfile) {
        return {
          id: profile.id.toString(),
          name: profile.name,
          userName: profile.login,
          email: profile.email,
          image: profile.avatar_url,
        };
      },
    }),

คำตอบ #2

คำตอบปี 2024 สำหรับ Firebase กับ React Web API แบบโมดูลาร์

คุณสามารถพิมพ์วัตถุผู้ใช้ปัจจุบันที่คุณได้รับจาก auth.onAuthStateChanged ได้ดังนี้:

import { getAuth } from "firebase/auth";


  // place into component that initiates login with signInWithRedirect or signInWithPopup

  React.useEffect(() => {
    // Listen to auth state changes
    auth.onAuthStateChanged((user) => {
      if (user) {
        console.log("onAuthStateChanged", "User is signed in:", user);
      } else {
        console.log("onAuthStateChanged", "User is signed out");
      }
    });
  }, []);

ผู้ใช้ currentUser ภายใน firebase auth จะมีชื่อผู้ใช้ github ที่จำเป็น + รหัสผู้ใช้ github ภายใน:

const auth = getAuth();
console.log(auth.currentUser.reloadUserInfo.screenName);
console.log(auth.currentUser.reloadUserInfo.providerUserInfo[0].rawId);
console.log(auth.currentUser.reloadUserInfo.providerUserInfo[0].screenName);

ถ้าคุณดูที่รีเฟอเรนซ์ของ Firebase ชื่อหน้าจอไม่ได้ถูกบันทึกไว้ที่นั่น ดังนั้นผมคิดว่านี่อาจเป็นคุณสมบัติภายในที่อาจมีการเปลี่ยนแปลงได้ตลอดเวลา

บทความที่เกี่ยวข้อง