Skip to content

(Headers doesn't pass) Jstack Better Auth Incompatibility in Different Server and Client #68

@avera-hills-admin

Description

@avera-hills-admin
import { NextRequest, NextResponse } from "next/server";
import { client } from "./lib/client";
import { headers } from "next/headers";

export const middleware = async (req: NextRequest) => {
	const { userSession } = await (
		await client.user.getUserSession.$get(undefined, {
			headers: Object.fromEntries(await headers())
		})
	).json();
	console.log(Object.fromEntries(await headers()));
	const response = NextResponse.next();

	if (
		req.nextUrl.pathname.startsWith("/admin") &&
		userSession?.user?.role !== "admin"
	) {
		return NextResponse.redirect(new URL("/auth/login"));
	}

	if (
		req.nextUrl.pathname === "/auth/login" &&
		userSession &&
		userSession?.session
	) {
		return NextResponse.redirect(new URL("/"));
	}

	return response;
};

export const config = {
	matcher: [
		"/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)"
	]
};

To pass headers I need to manually define the headers () from nextjs, Without that the headers are completely different.

  accept: '*/*',
  accept-encoding: 'gzip, deflate, br, zstd',
  accept-language: 'en-US,en;q=0.5',
  connection: 'keep-alive',
  cookie: '__next_hmr_refresh_hash__=726df19e3771ec55715bb6e22717cc483fbb1af8a9eada5e',
  dnt: '1',
  host: '127.0.0.1:3000',
  priority: 'u=4',
  referer: 'http://127.0.0.1:3000/',
  sec-fetch-dest: 'empty',
  sec-fetch-mode: 'cors',
  sec-fetch-site: 'same-origin',
  sec-gpc: '1',
  user-agent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:136.0) Gecko/20100101 Firefox/136.0',       
  x-forwarded-for: '127.0.0.1',
  x-forwarded-host: '127.0.0.1:3000',
  x-forwarded-port: '3000',
  x-forwarded-proto: 'http'
}

await headers()

Headers(8) {
  'accept' => '*/*',
  'accept-encoding' => 'br, gzip',
  'accept-language' => '*',
  'cache-control' => 'no-cache',
  'host' => '127.0.0.1:8787',
  'pragma' => 'no-cache',
  'sec-fetch-mode' => 'cors',
  'user-agent' => 'node',
  [immutable]: false
}

c.req.raw.headers on the procedure.

And also beacuse only the procedure gets the headers I have a prblem with this c.set() because this one has no session

import { AppContext, j } from "./jstack";
import { emailRouter } from "./routers/email-router";
import { adminRouter } from "./routers/admin-router";
import { aiRouter } from "./routers/ai-router";
import { propertyRouter } from "./routers/property-router";
import { mapsRouter } from "./routers/map-router";
import { blogRouter } from "./routers/blog-router";
import { roomRouter } from "./routers/room-router";
import { cors } from "hono/cors";
import * as Sentry from "@sentry/cloudflare";
import { userRouter } from "./routers/user-router";
import { auth } from "./db/auth/config";
import { env } from "hono/adapter";

export const corsMiddleware = cors({
	origin: (origin) => origin,
	exposeHeaders: ["x-is-superjson", "Content-Length", "X-Kuma-Revision"],
	allowHeaders: [
		"Content-Type",
		"Upgrade-Insecure-Requests",
		"Authorization",
		"x-is-superjson",
		"Access-Control-Allow-Headers",
		"X-Requested-With",
		"X-Custom-Header"
	],
	allowMethods: ["POST", "GET", "OPTIONS"],
	maxAge: 86400,
	credentials: true
});

const api = j
	// eslint-disable-next-line @typescript-eslint/no-explicit-any
	.router<any, AppContext>()
	.basePath("/api")
	.use(corsMiddleware)
	.onError(j.defaults.errorHandler);

const appRouter = j.mergeRouters(api, {
	email: emailRouter,
	admin: adminRouter,
	ai: aiRouter,
	property: propertyRouter,
	map: mapsRouter,
	blog: blogRouter,
	room: roomRouter,
	user: userRouter
});

appRouter.all("/auth/*", async (c) => {
	const envItems = env(c);

	return await auth({ ...envItems }).handler(c.req.raw);
});

appRouter.use("*", async (c, next) => {
	const envItems = env(c);
	const session = await auth({ ...envItems }).api.getSession({
		headers: c.req.raw.headers
	});

	if (!session) {
		c.set("user", null);
		c.set("session", null);
		return next();
	}

	c.set("user", session.user);
	c.set("session", session.session);
	return next();
});

appRouter.on(["POST", "GET"], "/web-callback/*", (c) => {
	const { NEXT_PUBLIC_BASE_URL } = env(c);

	const url = new URL(c.req.url);
	const callbackPath = url.pathname.replace(/^\/api\/web-callback/, "");
	return c.redirect(new URL(NEXT_PUBLIC_BASE_URL + callbackPath));
});

export type AppRouter = typeof appRouter;

export default Sentry.withSentry(
	() => ({
		dsn: "https://2acb62944acc5111edcb23b3c30dcfd0@o4508889302433792.ingest.us.sentry.io/4509021222141952",
		// Set tracesSampleRate to 1.0 to capture 100% of spans for tracing.
		// Learn more at
		// https://docs.sentry.io/platforms/javascript/configuration/options/#traces-sample-rate
		tracesSampleRate: 1.0
	}),
	appRouter
);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions