Adding "admin" role for role based auth
Unanswered
TK2 posted this in #help-forum
TK2OP
Having trouble exposing the
Here's my
type dec
And these are my two
role value in my session for role based auth.Here's my
schema.prismamodel Session {
id String @id @default(cuid())
sessionToken String @unique
userId String
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
password String
username String @unique
isAdmin Boolean @default(false)
role String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
accounts Account[]
sessions Session[]
}type dec
import NextAuth from "next-auth"
declare module "next-auth" {
interface User {
username: string
id: string
}
interface Session {
user: User & {
username: string,
role: string
}
token: {
username: string,
}
}
}And these are my two
jwt and session callbacks callbacks: {
async jwt({ token, user, profile, account }) {
// console.log("token in jwt callback", token);
if(user) {
return {
...token,
username: user.username,
}
}
return token;
},
async session({ session, token, user }) {
// console.log("session callback", session, token);
if(session.user) {
return {
...session,
user: {
...session.user,
username: token.username,
role: session.user.role
}
}
}
return session;
}
}24 Replies
TK2OP
I'm trying to limit access to an admin dashboard but when I fetch the session and try to match the role as string
=== "admin" I can't find role in the object.const AdminPage = async () => {
const session = await getServerSession(options);
if(session?.user.role === "admin") {
return <h2> Admin Page - welcome back {session.user.username}</h2>
}
return (
<h2> You don't have admin permission to see this page </h2>
)
}For more context here's my
authorize function async authorize(credentials) {
console.log("credentials inside authorize function", credentials);
if (!credentials?.email || !credentials.password) {
return null;
}
const existingUser = await db.user.findUnique({
where: { email: credentials?.email }
})
if(!existingUser) {
return null;
}
const passwordMatch = await compare(credentials.password, existingUser.password);
if(!passwordMatch) {
return null;
}
// Check role somewhere?
const admin = existingUser.role === "admin"
console.log("isAdmin?", admin)
console.log("typeof", typeof admin);
return {
id: `${existingUser.id}`,
username: existingUser.username,
email: existingUser.email,
role: admin
}
}For this I had to query my db from user email and it gave me access to the role, I’m sure it’s nowhere near the most optimal solution but it works
User email that was in my session
@TK2
TK2OP
@redbabinks Where in your auth flow did you check the role? I feel like something can be added into the
authorize function above to achieve what I want but the logic for it is escaping meYou need to map the role inside session callback. Try logging with different possibilities to see how it appears. As far as I remember the flow was like:
User from providers > signIn callback > jwt callback > session callback
User from providers > signIn callback > jwt callback > session callback
@Riday 💙 You need to map the role inside session callback. Try logging with different possibilities to see how it appears. As far as I remember the flow was like:
User from providers > signIn callback > jwt callback > session callback
TK2OP
Ah I'm trying to mix jwt strategy / credential provider / with my db store which is an issue.
@TK2 Ah I'm trying to mix jwt strategy / credential provider / with my db store which is an issue.
I used to do that too, it's not an issue
From your credentials provider, you need to send the entire object
Then, in the jwt, you need to read all properties and make sure they are not lost in the multiple calls
And then you need to put them in the session callback
To access properties using
session.user.x, you will need to set them in the session callback by session.user.x = somethingTK2OP
@Riday 💙
callbacks: {
async jwt({ token, user, profile, account, session }) {
if(user) {
return {
...token,
username: user.username,
role: user.role
}
}
return token;
},
async session({ session, token, user }) {
return {
...session,
user: {
...session.user,
username: token.username,
role: session.user.role
}
}
}I found the solution actually I needed to update the type in next auth types file
TK2OP
@redbabinks care to share?
import "next-auth"
declare module "next-auth"{
interface Session{
user:{
name:string;
email:string;
image:string;
role:string;
}
}
}@/types/next-auth.d.tsyou can ofcourse put everything you want inside of your session
TK2OP
@redbabinks Sweet thanks, can you also share your
jwt and session callbacks?@TK2 <@660276013996965889> Sweet thanks, can you also share your `jwt` and `session` callbacks?
I didnt change my jwt callback
The session is just following this type
Oh, lmao. You could technically access it. You just didn't get the types
Forgot about that part