👻

【NextJs + ElysiaJs】NexJs&ElysiaJs【#6 Protected Route】

に公開

【#6 Protected Route】
YouTube: https://youtu.be/8s9NyEJ9crY
https://youtu.be/8s9NyEJ9crY

今回は各ルートに対して、BetterAuthによる
プロテクトを実装していきます。

npm i @elysiajs/cors@1.4.1

https://www.better-auth.com/docs/integrations/elysia

.env
DATABASE_URL="postgresql://neondb_owner:xxxxxxxxxxxxxxxxxx........"

BETTER_AUTH_SECRET="BUYGjrsiBFA6PyTAAoBYkCKvOuMNBYG6"
BETTER_AUTH_URL="http://localhost:3000" # Base URL of your app

NEXT_PUBLIC_APP_URL="http://localhost:3000"
app/api/[[...slugs]]/route.ts
import { Elysia } from "elysia";
import { cors } from "@elysiajs/cors";

import { helloRouter } from "@/server/routes/hello";

export const app = new Elysia({ prefix: "/api" })
  .use(
    cors({
      origin:
        process.env.NODE_ENV === "production"
          ? process.env.NEXT_PUBLIC_APP_URL
          : true,
      methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
      credentials: true,
      allowedHeaders: ["Content-Type", "Authorization", "Cookie"],
      exposeHeaders: ["Set-Cookie"],
    })
  )
  .use(helloRouter);

export const GET = app.fetch;
export const POST = app.fetch;
export const PUT = app.fetch;
export const PATCH = app.fetch;
export const DELETE = app.fetch;
export const OPTIONS = app.fetch;
server/protected-route.ts
import { Elysia } from "elysia";
import { auth } from "@/lib/auth";

export const protectedRoute = (app: Elysia) =>
  app.derive(async ({ request, status }) => {
    const session = await auth.api.getSession({
      headers: request.headers,
    });

    if (!session) return status(401);

    return { session };
  });

export const betterAuth = new Elysia({ name: "better-auth" })
  .mount(auth.handler)
  .macro({
    auth: {
      async resolve({ status, request: { headers } }) {
        const session = await auth.api.getSession({
          headers,
        });

        if (!session) return status(401);

        return {
          session,
        };
      },
    },
  });

server/routes/hello.ts
import { Elysia, status, t } from "elysia";
import { betterAuth, protectedRoute } from "../protected-route";

export const helloRouter = new Elysia({ prefix: "/hello" })
  .use(betterAuth)
  .get("/", () => {
    const hello = "Hello Elysia";

    if (!hello) {
      throw new Response("Internal Error", { status: 500 });
      // return status(500)
    }

    return {
      hello,
    };
  })
  .post("/", ({ body }) => body, {
    body: t.Object({
      name: t.String(),
    }),
    auth: true,
  });

Discussion