#Access Astro.locals in ssr pages and protect these dynamic routes with middleware

3 messages · Page 1 of 1 (latest)

covert marsh
#

I have a project configured with output: "server", so everything is ssg and everything is working just fine. I have added a dynamic route as /preloads/[id].astro and that is ssr. It seems that there is no access to Astro.locals in that page and it seems I am not doing it right to protect that route. This is my middleware code:

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

const protectedRoutes = [
"/(|/)",
"/arreglos(|/)",
"/para-empezar(|/)",
"/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");
  }

  locals.id = data.user?.id!;
  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();

},
);

young lindenBOT
#

Hi @covert marsh. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Astro's middleware allows you to intercept requests and responses and inject behaviors dynamically. You can use middleware to protect your dynamic routes and set request-specific information across endpoints and pages by mutating a locals object. This object is available in all Astro components and API endpoints, including SSR pages.

In your middleware, you are correctly setting the locals.id value based on the authenticated user's ID. This value should be available in your SSR page via Astro.locals.

Here's an example of how you can access Astro.locals in your SSR page:

---
const { id } = Astro.locals;
---
<h1>User ID: {id}</h1>

If you're not able to access Astro.locals in your SSR page, it might be due to a bug or a misconfiguration. Make sure you're using a compatible version of Astro and that your project is correctly configured.

Also, note that the middleware runs at build time for all prerendered pages, but occurs when the route is requested for pages rendered on demand. So, if you're trying to access Astro.locals in a prerendered page, the middleware might not have run yet.

If you're still having issues, consider creating a minimal reproducible example and opening an issue on the Astro GitHub repository (https://github.com/withastro/astro/issues).

Sources:


Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: