Reputation: 41
So I have a very simple Next.js application that I would like to add authentication to using next-iron-session and the withIronSession function. Inside of my api folder, I have a simple component that grabs the login form data, performs a complex authentication action, then sets the user using
req.session.set("user", { email });
import { withIronSession } from "next-iron-session";
const VALID_EMAIL = "user";
const VALID_PASSWORD = "password";
export default withIronSession(
async (req, res) => {
if (req.method === "POST") {
const { email, password } = req.body;
if (email === VALID_EMAIL && password === VALID_PASSWORD) {
req.session.set("user", { email });
await req.session.save();
console.log(req.session.get());
return res.status(201).send("");
}
return res.status(403).send("");
}
return res.status(404).send("");
},
{
cookieName: "MYSITECOOKIE",
password: '2gyZ3GDw3LHZQKDhPmPDL3sjREVRXPr8'
}
);
After the user is set in the session, I return a 201, and the client redirects to my protected page, where I try to grab that user in the getServerSideProps function using the withIronSession as a wrapper.
import { withIronSession } from "next-iron-session";
export const getServerSideProps = withIronSession(
async ({ req, res }) => {
const user = req.session.get("user");
console.log(user);
if (!user) {
res.statusCode = 403;
res.end();
return { props: {} };
}
return {
props: { }
};
},
{
cookieName: 'MYSITECOOKIE',
password: "2gyZ3GDw3LHZQKDhPmPDL3sjREVRXPr8"
}
);
However, even though the user is found in the API function after it is set, ({"user", { email }}), that same session object returns {} in the getServerSideProps function in my protected component, which in my case always results in a 403. Is there a way to access the user that is set in the login component in the getServerSideProps function?
Note* I was trying to follow this article, maybe it provides more information.
https://dev.to/chrsgrrtt/easy-user-authentication-with-next-js-18oe
Upvotes: 2
Views: 23725
Reputation: 8693
I faced the same problem & found a simple solution:
import { GetServerSidePropsContext } from 'next'
import { withSessionSsr } from '@/utils/index'
export const withAuth = (gssp: any) => {
return async (context: GetServerSidePropsContext) => {
const { req } = context
const user = req.session.user
if (!user) {
return {
redirect: {
destination: '/',
statusCode: 302,
},
}
}
return await gssp(context)
}
}
export const withAuthSsr = (handler: any) => withSessionSsr(withAuth(handler))
And then I use it like:
export const getServerSideProps = withAuthSsr((context: GetServerSidePropsContext) => {
return {
props: {},
}
})
My withSessionSsr
function looks like:
import { GetServerSidePropsContext, GetServerSidePropsResult, NextApiHandler } from 'next'
import { withIronSessionApiRoute, withIronSessionSsr } from 'iron-session/next'
import { IronSessionOptions } from 'iron-session'
const IRON_OPTIONS: IronSessionOptions = {
cookieName: process.env.IRON_COOKIE_NAME,
password: process.env.IRON_PASSWORD,
ttl: 60 * 2,
}
function withSessionRoute(handler: NextApiHandler) {
return withIronSessionApiRoute(handler, IRON_OPTIONS)
}
// Theses types are compatible with InferGetStaticPropsType https://nextjs.org/docs/basic-features/data-fetching#typescript-use-getstaticprops
function withSessionSsr<P extends { [key: string]: unknown } = { [key: string]: unknown }>(
handler: (
context: GetServerSidePropsContext
) => GetServerSidePropsResult<P> | Promise<GetServerSidePropsResult<P>>
) {
return withIronSessionSsr(handler, IRON_OPTIONS)
}
export { withSessionRoute, withSessionSsr }
Upvotes: 2
Reputation: 89
I believe that this happens only on an http
origin. Are you testing on localhost or any other non secure origin? If yes, then you need to specify secure: false
in the cookieOptions.
From the documentation of next-iron-session
, it is set to true
by default, and this means that only secure origins (typically, origins with https
) will be allowed.
Consider updating cookieOptions with secure: false
for development environment and secure: true
for production.
Like this:
withIronSession(
async ({ req, res }) => {...},
{
cookieName: 'MYSITECOOKIE',
cookieOptions: {
secure: process.env.NODE_ENV === 'production' ? true : false
},
password: '2gyZ3GDw3LHZQKDhPmPDL3sjREVRXPr8'
}
);
Upvotes: 3
Reputation: 11
next-iron-session works with node version > 12. It worked for me.
import React from "react";
import { withIronSession } from "next-iron-session";
const PrivatePage = ({ user }) => (
<div>
<h1>Hello {user.email}</h1>
<p>Secret things live here...</p>
</div>
);
export const getServerSideProps = withIronSession(
async ({ req, res }) => {
const user = req.session.get("user");
if (!user) {
res.statusCode = 404;
res.end();
return { props: {} };
}
return {
props: { user }
};
},
{
cookieName: "MYSITECOOKIE",
cookieOptions: {
secure: process.env.NODE_ENV === "production" ? true : false
},
password: process.env.APPLICATION_SECRET
}
);
export default PrivatePage;
Upvotes: 1