How to properly setup next auth for a discord dashboard

Context: - I am setting up a dashboard for a discord bot and I'm using next auth to setup discord oauth - I use prisma as my database adaptor and next 13 app directory as my framework - I am v new to next and next auth so this might be common sense What I'm stuck on: - At the moment I've got it working but I feel like I've done it in a way that has pitfalls - It currently uses their email to check if the jwt is valid but what if a discord user changes their email, does this just break everything and make a new user and account - Should I use the uuid instead of email I changed the jwt account check to use id not email - should the id be discord's id instead of the generated one in the user table, each user has a row in the account table rn with their discord id instead - Finally (less important as I can probs eventually figure out), how do I make an api endpoint in next13 which takes the user who requested its token, gets their discord auth token and then requests all of their guilds I'd be truly grateful for any help as Its quite hard to wrap my head around still. The code:
import { PrismaAdapter } from "@next-auth/prisma-adapter"
import { NextAuthOptions } from "next-auth"
import DiscordProvider from "next-auth/providers/discord"

import { env } from "@/env.mjs"
import { db } from "@/lib/db"

const scopes = ["identify", "guilds", "email"].join(" ")

export const authOptions: NextAuthOptions = {
adapter: PrismaAdapter(db as any),
session: {
strategy: "jwt",
},
pages: {
signIn: "/login",
},
providers: [
DiscordProvider({
clientId: env.DISCORD_CLIENT_ID,
clientSecret: env.DISCORD_CLIENT_SECRET,
authorization: { params: { scope: scopes } },
}),
],
callbacks: {
async session({ token, session }) {
if (token) {
session.user.id = token.id
session.user.name = token.name
session.user.email = token.email
session.user.image = token.picture
}

return session
},
async jwt({ token, user }) {
const dbUser = await db.user.findFirst({
where: {
email: token.email,
},
})

if (!dbUser) {
if (user) {
token.id = user?.id
}
return token
}

return {
id: dbUser.id,
name: dbUser.name,
email: dbUser.email,
picture: dbUser.image,
}
},
},
}
import { PrismaAdapter } from "@next-auth/prisma-adapter"
import { NextAuthOptions } from "next-auth"
import DiscordProvider from "next-auth/providers/discord"

import { env } from "@/env.mjs"
import { db } from "@/lib/db"

const scopes = ["identify", "guilds", "email"].join(" ")

export const authOptions: NextAuthOptions = {
adapter: PrismaAdapter(db as any),
session: {
strategy: "jwt",
},
pages: {
signIn: "/login",
},
providers: [
DiscordProvider({
clientId: env.DISCORD_CLIENT_ID,
clientSecret: env.DISCORD_CLIENT_SECRET,
authorization: { params: { scope: scopes } },
}),
],
callbacks: {
async session({ token, session }) {
if (token) {
session.user.id = token.id
session.user.name = token.name
session.user.email = token.email
session.user.image = token.picture
}

return session
},
async jwt({ token, user }) {
const dbUser = await db.user.findFirst({
where: {
email: token.email,
},
})

if (!dbUser) {
if (user) {
token.id = user?.id
}
return token
}

return {
id: dbUser.id,
name: dbUser.name,
email: dbUser.email,
picture: dbUser.image,
}
},
},
}
2 Replies
EggsLeggs
EggsLeggsOP2y ago
I don't seem to have the secrets shown in this post but I'm not totally familiar with why u need them: https://discord.com/channels/966627436387266600/1048637700619636786/1048661079246516304 also they set their discord auth key to their session, is this the correct way of doing this. If it was me id have fetched their key from my database using the token they have for my site and then called the discord api from my server and returned the results
Jacob
Jacob2y ago
1. I would say using the users discord id in the database would be better than using the generated. 2. Not important but just for code cleanlyness something you can do here:
if (!dbUser) {
if (user) {
token.id = user?.id
}
return token
}
if (!dbUser) {
if (user) {
token.id = user?.id
}
return token
}
is change it to something like this:
if (!dbUser && user) {
token.id = user?.id
return token
}
if (!dbUser && user) {
token.id = user?.id
return token
}
Want results from more Discord servers?
Add your server