Papa Dragon
Papa Dragon

Reputation: 41

Using next-iron-session's "withIronSession" with Next.JS to perform simple authentication

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

Answers (3)

deadcoder0904
deadcoder0904

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

Ileriayo Adebiyi
Ileriayo Adebiyi

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

Sanjana
Sanjana

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

Related Questions