Replies: 13 comments 19 replies
-
Could you clarify what you mean by "session-based authentication"? Using a database for the session? In that case, it's currently not a NextAuth.js limitation, but simply that not many (if any) databases/ORMs support non-Node.js/Edge runtimes. |
Beta Was this translation helpful? Give feedback.
-
Yes, sorry, I mean using a database for the session. I'm not sure why that shouldn't be possible on an edge runtime, even if it migth require an extra fetch call (like we do client-side when we call |
Beta Was this translation helpful? Give feedback.
-
I am fairly new to TypeScript, and TypeScript is unhappy with:
Can someone explain how to fix this? |
Beta Was this translation helpful? Give feedback.
-
@GeeWee did you try to do a production build?
Correct? Cheers, |
Beta Was this translation helpful? Give feedback.
-
Edge runs a small subset of the V8 runtime, thus many things that are available in Node, aren't in the Edge and consequently in the middleware which was primarily thought to run at the Edge. As a temporary solution until a database adapter for the Edge shows up, you can defer the logic that requires the NodeJS engine to a NextJS API route because the Fetch API is available in the middleware, and at the API route we can finish our the authentication flow with all the tools available. Something to be aware of is that the middleware won't send the headers it got from the browser to the fetch request thus we have to copy those so we can get the I know this is not the most desirable solution cause it doesn't make too much sense to make HTTP requests within the server but it is the only workaround I can think of, and to be honest, works very well. So your import { NextRequest, NextResponse } from 'next/server'
export default async function middleware(req: NextRequest) {
const url = req.nextUrl.clone()
// fetch here requires an absolute URL to the auth API route
const {
data: { auth },
} = await fetch(`${url.origin}/api/authSSR`, {
headers: req.headers,
}).then((res) => res.json())
// we patch the callback to send the user back to where auth was required
url.search = new URLSearchParams(`callbackUrl=${url}`).toString()
url.pathname = `/api/auth/signin`
return !auth ? NextResponse.redirect(url) : NextResponse.next()
} And then you will have an API route (name it as you wish) to check if the user is logged in export default async function handle(
req: NextApiRequest,
res: NextApiResponse
) {
const session = await getSession({ req })
res.json({ data: { auth: !!session } })
} Hope it helps! |
Beta Was this translation helpful? Give feedback.
-
as per the documentation the middleware example only works with jwt sessions and I can agree that it would be nice to make it work with database sessions too. |
Beta Was this translation helpful? Give feedback.
-
For the use case where you want to protect certain routes, Next 13's Layouts have allowed us to skip using middleware while authenticating with a database. For example:
Protects /admin/* routes. |
Beta Was this translation helpful? Give feedback.
-
Is there any update on this? any fixes? |
Beta Was this translation helpful? Give feedback.
-
I was able to obtain a session from the import { NextRequest, NextResponse } from 'next/server'
export const config = {
runtime: 'edge',
}
export default async function handler(req: NextRequest) {
const resSession = await fetch(process.env.NEXTAUTH_URL + '/api/auth/session', {
headers: {
'Content-Type': 'application/json',
'Cookie' : req.headers.get('cookie') || '',
},
method: 'GET'
});
const session = await resSession.json();
if (!session) {
return new Response(JSON.stringify({text:'Not signed in.', status: 401}), { status: 401 });
}
console.log({session});
return new Response(JSON.stringify({session}), { status: 200});
} |
Beta Was this translation helpful? Give feedback.
-
I use Prisma adapter and then in my middleware.ts, I have the code (Next-Auth v4) const authMiddleware = withAuth(
// Note that this callback is only invoked if
// the `authorized` callback has returned `true`
// and not for pages listed in `pages`.
(req: NextRequest) => intlMiddleware(req),
{
callbacks: {
authorized: ({ req: { cookies } }) => {
const sessionToken = cookies.get("next-auth.session-token");
return sessionToken != null;
},
},
pages: {
signIn: customizedAuthRoutes.signIn,
},
},
); If user has logged in, My whole middleware is integrated with i18n, it's looks like this: import { withAuth } from "next-auth/middleware";
import createIntlMiddleware from "next-intl/middleware";
import { NextRequest } from "next/server";
const locales = ["en", "zh", "zh-TW"];
const customizedAuthRoutes = {
signIn: "/api/auth/signin",
// signOut: "/api/auth/signout",
// error: "/api/auth/error",
};
const publicPages = ["/", ...Object.values(customizedAuthRoutes)];
const intlMiddleware = createIntlMiddleware({
locales,
defaultLocale: "en",
});
const authMiddleware = withAuth(
// Note that this callback is only invoked if
// the `authorized` callback has returned `true`
// and not for pages listed in `pages`.
(req: NextRequest) => intlMiddleware(req),
{
callbacks: {
authorized: ({ req: { cookies } }) => {
const sessionToken = cookies.get("next-auth.session-token");
return sessionToken != null;
},
},
pages: {
signIn: customizedAuthRoutes.signIn,
},
},
);
export default function middleware(req: NextRequest) {
const publicPathnameRegex = RegExp(
`^(/(${locales.join("|")}))?(${publicPages.join("|")})?/?$`,
// TODO: use "i" flag?
"i",
);
const isPublicPage = publicPathnameRegex.test(req.nextUrl.pathname);
if (isPublicPage) {
return intlMiddleware(req);
} else {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (authMiddleware as any)(req);
}
}
export const config = {
// this matcher will not work for redirect 404 page to correct locale
matcher: ["/", "/(en|zh|zh-Hant)/:path*"],
// matcher: ["/((?!api|_next|.*\\..*).*)"],
}; |
Beta Was this translation helpful? Give feedback.
-
I recently ran into this issue you can simply do something like this import { getSession } from "next-auth/react";
// ..... rest of your code
const session = await getSession({
req: {
...req,
headers: {
...Object.fromEntries(req.headers),
},
},
});
// ... rest of your code |
Beta Was this translation helpful? Give feedback.
-
Thx men you save my life and I will tell you why, even wen I can get the token correctly if i make the request via postman etc with and old but valid token i can not get the updated information of the user, and because I am working on a plan based sistem where dates and resurces vary acordinly to the plan type it is critical for me to get the last updated info. |
Beta Was this translation helpful? Give feedback.
-
help please |
Beta Was this translation helpful? Give feedback.
-
Description 📓
Next-auth recently introduced middleware that validates JWT-tokens, which is a great step usability-wise.
Unfortunately those of us who are using alternate authentication methods such as session-based authentication don't have anything out of the box, and implementing a middleware like that yourself is trickier than you would expect, because you cannot simply pass the request in your middleware to
getSession
This seems to be because the next-auth accesses headers via
req.headers.cookie
, but the type of the headers inside middleware is not an object, but aHeaders
object which must be accessed throughreq.headers.get("cookie")
I have implemented a middleware that works for session-based authentication. It does this by converting the relevant part of the request headers to an object
However I think this means that an extra fetch call will be made to the
next-auth
backend. One in the middleware, and one later on if you want to access the session in API calls.Solution proposal 1: Middleware
It would be great if next-auth provided a middleware that did everything, like it does for the JWT-based flow
Solution proposal 2: Allow NextRequest in GetSession
Another great solution, which probably requires less work is to accept a
NextRequest
ingetSession
, which meant it could be used both client-side, server-side and in middleware.It does not seem like there are many code changes needed to make this work.
Related issues:
#3136
#4042
#3151
How to reproduce ☕️
N/A
Contributing 🙌🏽
Yes, I am willing to help implement this feature in a PR
Beta Was this translation helpful? Give feedback.
All reactions