1. Detail the issue
I am facing a challenge while developing a Full Stack Website using Next.js and Typescript. Specifically, I am having difficulty persisting the Github Username in the database when a user signs in via Github OAuth. Should I consider storing the user ID instead? My goal is to have URLs like "domain.com/[github username]". Currently, I am using the Github username as the primary key for storing user data in MongoDB. The user ID is added to the database during the sign-in callback in [...nextauth].ts.
Here is my [...nextauth].ts file:
/*
File: [..nextauth].ts
Description: This file will use NextAuth to handle requests, responses 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,
});
However, the main issue lies in not being able to retrieve the "login/username" within the sign-in callback function arguments.
async signIn({ user: User, account:Account, profile: profile, email:Email }) {
2. Attempts made so far
I have observed that the Github username is available in the JWT function. However, despite declaring the variable correctly, the 'User' object does not have that property elsewhere.
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. In-depth analysis of the code
Currently, I can only retrieve the user ID, which appears to be a numerical value used by Github. However, I specifically require the Github username for my project.
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;
}