Vercel circular redirects when using Firebase authentication

Viewed 22

I do have a super weird error coming up only when deploying the code to Vercel. It doesn't happen locally which makes it quite annoying to begin with.

I do have a staging and a production instance for my code. I want to protect the staging with a password which is not difficult since I implemented the authentication via Firebase. The only tricky part is that I don't use Firebase to keep track of the user but my server (basically setting a cookie). I should mention that I am using Sveltekit to put it all together.

In sveltekit you can use hooks, which can be seen as middlewares, to redirect a user to the sign-in page if the env variable for the environment is set to dev. Another hook redirects a logged-in user, so if you are already logged in and try to go to auth/sign-in or auth/sign-up you'll get redirected to the home page.

Now the weird happens: I go on the deployed version of the site, and I get immediately redirected to the sign-in page, which is correct. I try to navigate to all the pages of the website, the redirect still works fine. I log in and upon success, I should be redirected to the homepage, which I do BUT the home page redirects me to the sign-in page as if I wasn't logged in and again the sign-in page redirects me to the home page as if I was, thus creating a loop.

I honestly don't know why this happens since it perfectly works locally, so my thoughts go to Vercel. I would exclude Firebase since I remembered to put the custom domain as an allowed domain in the settings.

To give a bitmore context, I structured the hooks responsible for the redirect in this way:

export const authSessionHandler: Handle = async ({ event, resolve }) => {
    const cookie = event.locals.cookie;

    const idToken = await getIdTokenFromSessionCookie(getCookieValue(cookie, 'session'));
    const user = idToken
        ? {
                uid: idToken?.sub,
                email: idToken?.email
          }
        : null;
    event.locals.idToken = idToken;
    event.locals.user = user;

    return resolve(event);
};

export const redirectLoggedInUserHandler: Handle = async ({ event, resolve }) => {
    const { user } = event.locals;

    const next = event.url.searchParams.get('next') || '/';

    if (
        user &&
        (event.url.pathname.startsWith('/auth/sign-in') ||
            event.url.pathname.startsWith('/auth/sign-up'))
    ) {
        return new Response('Redirect', {
            status: http_302.status,
            headers: {
                location: `${next}`
            }
        });
    }

    return resolve(event);
};

export const redirectToSignInForDevEnvironmentHandler: Handle = async ({ event, resolve }) => {
    const { user } = event.locals;

    const allowedEndpoints = ['/auth/sign-in', '/auth/session'];

    if (!user && env === 'dev' && !allowedEndpoints.includes(event.url.pathname)) {
        return new Response('Redirect', {
            status: http_302.status,
            headers: {
                location: '/auth/sign-in'
            }
        });
    }

    return resolve(event);
};

The handlers are in that order, so the first one populates the user and the rest can check the rest.

In the code I am getting the user from event.locals which kind of decides the entire logic (as it should) and to me it's quite interesting and telling the fact that the sign-in page redirects me to home which mean the user is defined, but the home page redirects back as if the user was not defined. This made me think it is not a problem with the code but probably the provider(s) Vercel or Firebase.

It would be very helpful to know your thoughts about it.

0 Answers
Related