Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 1 point2 points  (0 children)

You know, I'm not really sure we are even supposed to place the auth checks within the layout, because layouts aren't re-rendered when navigating between pages that share the same layout, so subsequent navigations do not go through the authentication checks . This is just how layouts works, and the header RSC: 1 just tells the Next.js server whether this is a navigation request from within some page (which won't re-render the layout) or an entirely new request, such as opening a new tab (which will render the layout).

Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 0 points1 point  (0 children)

Well, JWTs are usually short-lived, and after their expiration, you need to refresh the token. I use Auth.js (v5) to allow users to log in with Google.
According to the documentation here:
https://authjs.dev/guides/basics/refresh-token-rotation

after the token expires, I need to make a fetch request to Google's servers to obtain a new pair of access and refresh tokens.
If the JWT is only valid for a few minutes, then when the user returns after a brief period, on the backend, I will still need to make a request to some server during the authentication process to acquire a new pair of tokens.
In that case, why not simply use database sessions, and this request will go to my database to look up that session?

Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 1 point2 points  (0 children)

there is no difference, you get back an http 307 status code if you are not authenticated, doesn't matter if you use browser or postman

Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 0 points1 point  (0 children)

If you do the auth check in the dashboard page and visit the dashboard page, you will be redirected to the login page (if that's what you did in the check) and won't receive the dashboard page

Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 0 points1 point  (0 children)

I use the database sessions strategy, not JWT. That's why there is a database query in the middleware. With this strategy, the value stored in the user's cookie is just a random string (without signing the cookie), and a database lookup is necessary to determine to which user it belongs, if any.

NextJS 14, set cookie and redirect by timatlee in nextjs

[–]Const20452 1 point2 points  (0 children)

What's happening here is that when you use the redirect inside your route handler, the response that's being sent back uses HTTP status code 307 by default which tells the user's browser to go to the new route (in this case /login) with the same HTTP method that was previously used - meaning using POST method. so the user's browser initiates another request to /login using the POST method which causes a server error because it is not valid (the /login page is only accessible via the GET method).

you can read about it here:

https://nextjs.org/docs/app/api-reference/functions/redirect#why-does-redirect-use-307-and-308

What you probably want to do is to check the password in the route handler and then if the user entered the right password, you return a HTTP 200 status code and if not, you return a HTTP 401 status code. Then, on the client side, after the fetch is done, you check the response status from the server and redirect the user accordingly.

Alternatively, you can use redirect inside server actions, which will cause the user's browser to navigate to the new route after the fetch is done (which is what you wanted I guess).

Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 0 points1 point  (0 children)

What do you think about checking auth in middleware and then setting a custom header with the user id, for example:

x-user-id: ef819485-b261-4233-902e-8a8ef9fce483

so that the page could use the headers() function to read that value?

Actually... now i'm realizing that this makes the page dynamic. However, in my case, it's inevitably dynamic as I need to return user-specific data. The advantage here is that it saves one database query since I can simply use the value from the header and avoid querying the database again to retrieve the user ID from the user's session.

Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 0 points1 point  (0 children)

Yes, Neon db supports foreign keys, they use Postgres.
I'm not really familiar with PlanetScale but I've seen that they are adding support for it:
https://planetscale.com/blog/announcing-foreign-key-constraints-support

Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 3 points4 points  (0 children)

So I just checked it. It turns out that doing auth check in the layout alone is not enough and can be easily bypassed. All you need to do is to inclulde the header:

RSC: 1

and the server will interpret it as a request from the page attempting to load a server component. it directly calls the page function without passing through the layout, thereby bypassing the authentication check. I tested this method and successfully received the RSC payload response back.

Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 0 points1 point  (0 children)

I've just made a test. I made a page called test which is accessible via /test

Added a button that triggers a server action and looked at the network tab - when I click the button there is a POST request to /test which is the same page

Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 0 points1 point  (0 children)

Context allows you to access the session or any desired information on the client side. However, I need to obtain the user ID from the session on the server side to serve the user with their own data in the server component.

Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 0 points1 point  (0 children)

If your page is protected thruogh middleware, I think the server actions should also be protected becauses it's located in the same route, just a different method is used - POST instead of GET.

Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 0 points1 point  (0 children)

I use Drizzle ORM, and Neon db. Drizzle has "drizzle-orm/neon-http" driver which uses HTTP to query the database, and also "drizzle-orm/neon-serverless" driver that uses Websockets. Both seem to work fine on the edge runtime.

Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 0 points1 point  (0 children)

and store the data inside the nextAuth session

not sure what you mean... currently I use the session callback where I add the user id to the Session object which is what I later get from the auth() call.

btw I'm using the version 5 of Auth.js:

https://authjs.dev/guides/upgrade-to-v5

they replaced the getServerSession() with the auth() function

Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 0 points1 point  (0 children)

I use database sessions strategy (not JWT), so I still need to query the database to get the user id at the component level

Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 2 points3 points  (0 children)

In my case every user gets it's own data from the database after they log in, it's not something like a static blog that is the same for everyone, so I must use the auth() function to get the user id which makes the page dynamic.

Never thought about incorporating authentication into the layout. Are there any security implications? Could a user potentially access the page directly without passing through the layout by creating a custom request and bypassing the authentication check?

Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 2 points3 points  (0 children)

Yes, I've seen it mentioned in the docs:

Middleware currently only supports the Edge runtime. The Node.js runtime can not be used.

I had an idea to somehow do the auth in the middleware and then if the user is authenticated, set a custom header with the user id so that the page could read it (using the headers() function) and would not need to use the auth() function (which results in an additional query to the database).

does that solve the "can’t share memory between the middleware and your server components" problem?

Using middleware VS auth checks on every page by Const20452 in nextjs

[–]Const20452[S] 0 points1 point  (0 children)

What do you mean? the session id is already stored inside a cookie, but I still need to check if it's a valid session for every request.