auth0 / nextjs-auth0

Next.js SDK for signing in with Auth0
MIT License
2.08k stars 391 forks source link

Custom SessionStore not working in middleware #1232

Closed andrienpecson closed 1 year ago

andrienpecson commented 1 year ago

Checklist

Description

I am currently implementing a custom SessionStore to bypass the large cookie issue. In the auth0.ts, I am using ioredis as the Redis library. The problem is that I am encountering an issue when NextJs is generating the pages.

Reproduction

auth0.ts

import { Auth0Server, initAuth0 } from '@auth0/nextjs-auth0';
import config from './auth0Config';

let _auth0: Auth0Server;

export default function auth0() {
  if (!_auth0) {
    _auth0 = initAuth0(config);
  }
  return _auth0;
}

auth0Config

import Redis from "ioredis";
import { SessionStorePayload, SessionStore, Auth0Server, initAuth0 } from '@auth0/nextjs-auth0';

const redis = new Redis(process.env.REDIS_URL!);

class Store implements SessionStore {
  private redis: Redis;

  constructor() {
    this.redis = redis;
  }

  async get(id: string) {
    const payload = await this.redis.get(id);
    return (payload) ? JSON.parse(payload) : null
  }
  async set(id: string, val: SessionStorePayload) {
    // Set the expiry of the store entry to match the expiry of the session.
    const expiryMs = val.header.exp * 1000;
    await redis.set(id, JSON.stringify(val), 'PX', expiryMs);
  }
  async delete(id: string) {
    await this.redis.del(id);
  }
}

const config = {
  session: {
    store: new Store(),
  },
};

export default config;

middleware.ts

import { NextRequest, NextResponse } from 'next/server';
import { initAuth0 } from '@auth0/nextjs-auth0/edge';
import auth0Config from "@/src/lib/auth0Config";

const auth0 = initAuth0(auth0Config);

export async function middleware(req: NextRequest) {
  const res = NextResponse.next();
  const user = await auth0.getSession(req, res);
  const urlObj = new URL(req.url);

  let returnResponse: NextResponse | Response = res;

  if ((urlObj.pathname.includes("api/auth") || urlObj.pathname.includes("api/login")) || user) {
    if (urlObj.pathname == "/") {
      returnResponse = NextResponse.redirect(new URL("/dashboard", req.nextUrl));
    }
  } else {
    returnResponse = NextResponse.redirect(new URL("/api/auth/login", req.nextUrl));
  }

  return returnResponse;
}

export const config = {
  matcher: [
    '/',
    '/api/:path*',
    '/dashboard/:path*',
    '/team/:path*',
    '/shop/:path*',
  ]
};

Issue Screenshot 2023-06-08 at 18 13 21

Additional context

No response

nextjs-auth0 version

2.4.0

Next.js version

13

Node.js version

16.16.0

Widcket commented 1 year ago

Hi @andrienpecson, thanks for raising this.

This error seems to be a matter of compatibility of the Redis library you're using with the Edge runtime. Not sure this is a SDK issue.

adamjmcgrath commented 1 year ago

Yep - ioredis requires the Node.js runtime (see also https://github.com/luin/ioredis/issues/769#issuecomment-1480869051)

andrienpecson commented 1 year ago

@Widcket @adamjmcgrath Thank You for the reply, but is there any recommended library I can use for this matter?

adamjmcgrath commented 1 year ago

@andrienpecson - I used @upstash/redis when I was testing it in https://github.com/adamjmcgrath/nextjs-auth0-redis-session

Any storage client that works on Vercel's Edge runtime will work.

johnbellone commented 1 year ago

I am seeing this error running locally on my laptop.