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 ชื่อหน้าจอไม่ได้ถูกบันทึกไว้ที่นั่น ดังนั้นผมคิดว่านี่อาจเป็นคุณสมบัติภายในที่อาจมีการเปลี่ยนแปลงได้ตลอดเวลา
