nextauthjs / next-auth

Authentication for the Web.
https://authjs.dev
ISC License
23.78k stars 3.27k forks source link

withAuth documentation insufficient #5498

Closed mkbctrl closed 1 year ago

mkbctrl commented 1 year ago

What is the improvement or update you wish to see?

Hey πŸ‘‹

I struggle a bit with understanding how to execute middleware wrapped withAuth for non protected pages.

What I am currently trying to achieve is to prevent user from visiting custom registration and login pages if the token exists.

Based on the information I read here https://next-auth.js.org/configuration/nextjs#advanced-usage I gather that the middleware is executed only if authorized returns true.

So following this information if I want logged in user to restrict from login/registration pages I should add:

// middleware.ts 

{
  … execute middleware logic
  { authorized: ({token, req}) => {
    return !!token
}, pages: {
  signIn: β€œ/auth/sign-in”
}}
}

const config = {
  matcher: [β€œ/some/:path*”, β€œ/auth/:path*”]
}

but that currently breaks my app entirely. The only solution is to remove the auth/path from the matcher.

But if I remove it how can I execute the middleware there?

Is there any context that might help us understand?

Added as many details above. Can provide video if that helps, lemme know

Does the docs page already exist? Please link to it.

No response

mkbctrl commented 1 year ago

Can I run withAuth inside the middleware? like here:

https://github.com/nextauthjs/next-auth/discussions/4832

that would help but it looks a bit odd, in every example I saw so far I didn’t see such a structure

balazsorban44 commented 1 year ago

There is probably multiple ways to go about it, I would do something like this:

import { withAuth } from "next-auth/middleware"

export default withAuth(
  function middleware(req) {
    // Execute middleware logic
    // `req.nextauth.token` is available. Note that it can be `null`,
    // for example when this is run on `/` and the user is not logged in
    // for any other route, this logic runs only when the user passed `authorized`
  },
  {
    callbacks: {
      authorized({ token, req }) {
        switch (req.nextUrl.pathname) {
          case "/middleware-protected":
            return !!token // Only require authentication
          case "/admin":
            return token?.role === "admin" // Require authorization
          case "/":
          default:
            return true // Bypass auth for these routes
        }
      },
    },
  }
)

// Match all the paths that need to run your Middleware.
export const config = {
  matcher: [
    "/",
    "/admin",
    "/middleware-protected"
  ]
}

Here, all the logic that decides if a route needs auth can be described in a simple callback, based on the path. If the auth check passes (evaluates to true), only then the logic inside your middleware will execute. Note, if you return a literal true value (like for /), that will explicitly bypass authentication for that given route.

I hope that this helps.

weidezhang commented 9 months ago

@balazsorban44 , i wonder for the nextauth.token passed into middleware, will it pass onto the getServerProps or server api handler ? since if the api/pages are guarded by middleware, it doesn't need to check against session using getServerSession right ?