petoma
petoma

Reputation: 117

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

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?

Upvotes: 0

Views: 987

Answers (1)

stacker
stacker

Reputation: 71

I encountered this issue similar to yours, in a slightly different context.

I wanted my middleware to take the user straight into the dashboard when signed in. The flow is: user visits home page, clicks on signin, and if signed in the middleware should redirect the user to the dashboard, otherwise the signin page is to be displayed.

This only works if export const prerender = false; is added to the signin page, when using output: "server" configuration. Actually, in server (SSR) mode, you can simply remove that line once you convince yourself what is happening and how it works.

If I set it to export const prerender = true; then the redirect won't work since the middleware won't come into the play.

In summary you have surmised correctly! I am assuming you already figured this out or have moved on. If you have a better explanation, please post for others to learn from.

Upvotes: 0

Related Questions