Role-based access control in middleware using Auth.js v5 #9609
Replies: 11 comments 4 replies
-
I got same error |
Beta Was this translation helpful? Give feedback.
-
same here |
Beta Was this translation helpful? Give feedback.
-
The same. // app/admin/layout.tsx
export default async function AdminLayout({ children }) {
const session = await auth()
if (session?.user.role !== "ADMIN") redirect("/")
return (
<div>
{children}
</div>
)
} But I would like to know the correct solution through an middleware |
Beta Was this translation helpful? Give feedback.
-
A little while later... // package.json
"dependencies": {
"next": "^14.1.0",
"next-auth": "^5.0.0-beta.3",
"npm": "^10.2.5",
"react": "^18",
"react-dom": "^18"
}, // src/types/next-auth.d.ts
declare module "next-auth" {
interface Session extends DefaultSession {
user: {
uid: string
email: string
roles: string[]
status: string
}
} // src/app/api/auth/auth.ts
export const {
handlers: { GET, POST },
auth,
signIn,
signOut,
} = NextAuth({
...authConfig,
providers: [
CredentialsProvider({
async authorize(credentials: ILogin) {
try {
const user = await fetchLogin(credentials)
return user
} catch (e) {
return null
}
},
}),
],
}) I receive public data about the roles (array), status, etc. from a accessToken that is sent when logging in. // src/app/api/auth/auth.config.ts
import { NextAuthConfig } from "next-auth"
export const authConfig = {
pages: { signIn: "/login" },
providers: [],
callbacks: {
async jwt({ token, user, trigger, session, account, profile }) {
if (user) {
const payload = JSON.parse(
Buffer.from(user?.accessToken.split(".")[1], "base64").toString()
)
token.uid = payload.uid
token.email = payload.email
token.roles = payload.roles
token.status = payload.status
return token
}
return token
},
async session({ session, token, user, trigger, newSession }) {
session.user.uid = token?.uid
session.user.status = token?.status
session.user.roles = token?.roles
return session
},
},
} satisfies NextAuthConfig // src/middleware.ts
import NextAuth from "next-auth"
import { NextResponse } from "next/server"
import { authConfig } from "./app/api/auth/auth.config"
const { auth } = NextAuth(authConfig)
export default auth((req) => {
const { nextUrl, auth } = req
const user = auth?.user
console.log("\n user in middleware:>> ", user)
// Print User in console
// email: 'mysupermail@gmail.com',
// uid: '6408f7838db2ba8030d72e18',
// status: 'ACTIVE',
// roles: [ 'ADMIN', 'USER' ]
const isAdminPage = nextUrl?.pathname.startsWith("/admin")
// Redirect if not ADMIN
if (isAdminPage && !user?.roles.includes("ADMIN")) {
return Response.redirect(new URL("/", nextUrl))
}
// Other protected pages ...
return null
})
export const config = {
matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
} |
Beta Was this translation helpful? Give feedback.
-
same problem here 😔 |
Beta Was this translation helpful? Give feedback.
-
Has anyone got a solution? I have tried by adding user role properties inside next-auth.d.td , but still same issue . |
Beta Was this translation helpful? Give feedback.
-
I also have same problem |
Beta Was this translation helpful? Give feedback.
-
#9836 this has all the answers :D |
Beta Was this translation helpful? Give feedback.
-
same problem, any solution? |
Beta Was this translation helpful? Give feedback.
-
My solution for this has been the use of the In my case I had to populate the session token via const secret = process.env.AUTH_SECRET as string;
const token = await getToken({
req,
secret,
salt: 'authjs.session-token',
}); |
Beta Was this translation helpful? Give feedback.
-
Same. I've successfully added it to the token and the session but only name, email, and image will populate in the middleware. |
Beta Was this translation helpful? Give feedback.
-
Hello, I am trying to use the middleware to have role-based access control, the users role should determine if the user can access the pages or not. There are two roles, one role can only access the pages for that type of user.
In the NextAuth i have used the callback function "async jwt({token})" to edit the token so that the users role is added.
`
async jwt({ token, user }) {
if (!token.sub) return token;
`
But in the middleware when i use the NextAuthRequest "req" i can find the user at req.auth?.user but the role is not added here? I can not seem to get the role to the middleware to properly limit access.
`const { auth } = NextAuth(authConfig);
export default auth((req) => {
console.log(req.auth?.user);
}`
The only thing shown in the user is "name", "email" and "image". Not the added role. I searched on the documentation and it said that you could use the middleware and JWT token to preform role based control but it uses NextAuth v4.
Beta Was this translation helpful? Give feedback.
All reactions