Thursday, 14 September 2023

Next-Auth Redis Adapter support for user session persistence?

I was going through the next-auth documentation but didn't find any mention of connecting to custom configured Redis without the use of Upstash for a persistent session store.

My use case is straightforward. I am using Nginx as a load balancer between multiple nodes for my nextJS application and I would like to persist the session if in case the user logs in and refreshes the page as Nginx switches between nodes.

For e.g My Nginx config

server {
    listen 80;
    server_name _;
    location / {
      proxy_pass http://backend;
    }
}
upstream backend {
        ip_hash;
        server <nextjs_app_ip_1>:8000;
        server <nextjs_app_ip_2>:8000;
}

As you can see from the example Nginx config, there are multiple upstream server pointers here that require user session persistence.

I am using the credentials provider of next-auth as I have a Django-based auth system already available.

I did see the implementation of the next-auth adapter with Upstash. However, I have my own custom server running with Redis.

I tried connecting to Redis using ioredis which works fine as it is connected. However, I am not sure how can I use Redis here with next-auth to persist session and validate at the same time?

For e.g In express, you have a session store which you can pass your Redis Client with and it should automatically take care of persistence. Is there anything I can do to replicate the same behavior in my case?

For e.g In Express

App.use(session({
    store: new RedisStore({ client: redisClient }),
    secret: 'secret$%^134',
    resave: false,
    saveUninitialized: false,
    cookie: {
        secure: false, // if true only transmit cookie over https
        httpOnly: false, // if true prevent client side JS from reading the cookie 
        maxAge: 1000 * 60 * 10 // session max age in miliseconds
    }
}))

My Code:

import CredentialsProvider from "next-auth/providers/credentials";
import {UpstashRedisAdapter} from "@next-auth/upstash-redis-adapter";
import Redis from 'ioredis';

const redis = new Redis(process.env.REDIS_URL); //points to my custom redis docker container

export const authOptions = {
    providers: [CredentialsProvider({
            name: 'auth',
            credentials: {
                email: {
                    label: 'email',
                    type: 'text',
                    placeholder: 'jsmith@example.com'
                },
                password: {
                    label: 'Password',
                    type: 'password'
                }
            },
            async authorize(credentials, req) {
                const payload = {
                    email: credentials.email,
                    password: credentials.password
                };

                const res = await fetch(`my-auth-system-url`, {
                    method: 'POST',
                    body: JSON.stringify(payload),
                    headers: {
                        'Content-Type': 'application/json'
                    }
                });

                const user = await res.json();
                console.log("user", user);
                if (!res.ok) {
                    throw new Error(user.exception);
                }
                // If no error and we have user data, return it
                if (res.ok && user) {
                    return user;
                }

                // Return null if user data could not be retrieved
                return null;
            }
        })],
    adapter: UpstashRedisAdapter(redis),
    pages: {
        signIn: '/login'
    },
    jwt: {
        secret: process.env.SECRET,
        encryption: true
    },
    callbacks: {
        jwt: async({token, user}) => {
            user && (token.user = user)
            return token
        },
        session: async({session, token}) => {
            session.user = token.user
            return session
        },
        async redirect({baseUrl}) {
            return `${baseUrl}/`
        }
    },
    session: {
        strategy: "jwt",
        maxAge: 3000
    },
    secret: process.env.SECRET,
    debug: true
}

export default NextAuth(authOptions)

Thank you so much for the help.



from Next-Auth Redis Adapter support for user session persistence?

No comments:

Post a Comment