Protect dynamic route (SSR) with middleware in astro project configured as SSG by default

75 Views Asked by At

I have an astro project connected with Supabase and I am using middleware to protect routes and redirect the user if there is no cookie. Everything works just fine in server generated pages, but I just added a dynamic route that is static and it seems that there is something I am not doing fine. This is the code that I have in the middleware:

import { defineMiddleware } from "astro:middleware";
import { supabase } from "../lib/supabase";
import micromatch from "micromatch";

const protectedRoutes = [
  "/(|/)",
  "/follow(|/)",
  "/preloads/*(|/)",
];
const redirectRoutes = ["/signin(|/)", "/register(|/)"];

export const onRequest = defineMiddleware(
  async ({ locals, url, cookies, redirect }, next) => {
    if (micromatch.isMatch(url.pathname, protectedRoutes)) {
      const accessToken = cookies.get("sb-access-token");
      const refreshToken = cookies.get("sb-refresh-token");

      if (!accessToken || !refreshToken) {
        return redirect("/signin");
      }

      const { data, error } = await supabase.auth.setSession({
        refresh_token: refreshToken.value,
        access_token: accessToken.value,
      });

      if (error) {
        cookies.delete("sb-access-token", {
          path: "/",
        });
        cookies.delete("sb-refresh-token", {
          path: "/",
        });
        return redirect("/signin");
      }

      const { data: user, error: userError } = await supabase
        .from("profiles")
        .select("avatar_url, user_role, first_visit")
        .eq("id", data?.user?.id);

      if (userError) {
        return redirect("/signin");
      }

      if (user?.[0]?.first_visit === 1 ) {
        return redirect("/primera-visita");
      }

      locals.id = data.user?.id!;
      locals.email = data.user?.email!;
      locals.avatar_url = user?.[0]?.avatar_url!;
      cookies.set("sb-access-token", data?.session?.access_token!, {
        sameSite: "strict",
        path: "/",
        secure: true,
      });
      cookies.set("sb-refresh-token", data?.session?.refresh_token!, {
        sameSite: "strict",
        path: "/",
        secure: true,
      });
    }

    if (micromatch.isMatch(url.pathname, redirectRoutes)) {
      const accessToken = cookies.get("sb-access-token");
      const refreshToken = cookies.get("sb-refresh-token");

      if (accessToken && refreshToken) {
        return redirect("/");
      }
    }
    return next();
  },
);

With that code, I have access to any route after /preloads/* even if I am not signed in. However, if I change that line for "/preloads/" instead of "/preloads/(|/)" the route is secured, but the problem is that I have no access at all to that route even though I am signed in. I get a warning in console that says:

Astro.request.headers is not available in "static" output mode. To enable header access: set output: "server" or output: "hybrid" in your config file.

I have configured my project with 'output: "server"' and that dynamic route has "export const prerender = true;"

Is it that I have no access to middleware in a static page?

0

There are 0 best solutions below