Before hook infinite loop

Hello, I am using the before hook in my better-auth config:
import { PrismaClient } from "@/prisma/generated/prisma";
import { stripe } from "@better-auth/stripe";
import { betterAuth } from "better-auth";
import { emailHarmony } from "better-auth-harmony";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { createAuthMiddleware } from "better-auth/api";
import { magicLink } from "better-auth/plugins";
import Stripe from "stripe";

const stripeClient = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: "2025-08-27.basil",
});

const prisma = new PrismaClient();
export const auth = betterAuth({
database: prismaAdapter(prisma, {
provider: "postgresql",
}),
hooks: {
before: createAuthMiddleware(async (ctx) => {
const session = await auth.api.getSession({
headers: ctx.headers as Headers,
});
console.log("Session in middleware:", session);
if (session?.user) {
const user = await prisma.user.findUnique({
where: { id: session.user.id },
select: { onboardingCompleted: true },
});
if (user && !user.onboardingCompleted) {
return ctx.redirect("/onboarding");
}
}
return ctx;
}),
},
trustedOrigins: [
"https://mail.google.com",
],
cors: {
origin: ["http://localhost:3000", "https://mail.google.com"],
credentials: true,
allowedHeaders: ["Content-Type", "Authorization"],
methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
},
plugins: [
stripe({
stripeClient,
stripeWebhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
createCustomerOnSignUp: true,
}),
emailHarmony(),
magicLink({
sendMagicLink: async ({ email, token, url }) => {
console.log(email, token, url);
},
}),
],
});
import { PrismaClient } from "@/prisma/generated/prisma";
import { stripe } from "@better-auth/stripe";
import { betterAuth } from "better-auth";
import { emailHarmony } from "better-auth-harmony";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { createAuthMiddleware } from "better-auth/api";
import { magicLink } from "better-auth/plugins";
import Stripe from "stripe";

const stripeClient = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: "2025-08-27.basil",
});

const prisma = new PrismaClient();
export const auth = betterAuth({
database: prismaAdapter(prisma, {
provider: "postgresql",
}),
hooks: {
before: createAuthMiddleware(async (ctx) => {
const session = await auth.api.getSession({
headers: ctx.headers as Headers,
});
console.log("Session in middleware:", session);
if (session?.user) {
const user = await prisma.user.findUnique({
where: { id: session.user.id },
select: { onboardingCompleted: true },
});
if (user && !user.onboardingCompleted) {
return ctx.redirect("/onboarding");
}
}
return ctx;
}),
},
trustedOrigins: [
"https://mail.google.com",
],
cors: {
origin: ["http://localhost:3000", "https://mail.google.com"],
credentials: true,
allowedHeaders: ["Content-Type", "Authorization"],
methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
},
plugins: [
stripe({
stripeClient,
stripeWebhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
createCustomerOnSignUp: true,
}),
emailHarmony(),
magicLink({
sendMagicLink: async ({ email, token, url }) => {
console.log(email, token, url);
},
}),
],
});
but when I load any page, it just runs into an infinite loop but it does compile the page though, anyone has an idea?
4 Replies
Better Auth
Better Auth2w ago
Hi there! It sounds like you’re looking for a summary of common Better Auth questions and some best practices from our community. Here are some of the frequently asked topics along with expert insights: • Passkey Registration & Error Handling:
Many users ask how to handle errors during passkey registration. Recent updates now include specific error codes for the passkey client to help quickly diagnose issues during authentication flows [1]. In addition, there are enhancements for client-side configuration—like specifying the authenticator attachment and global authenticator settings—that provide greater control and consistency [15], [19]. • Social Provider Integrations:
A number of inquiries focus on integrating various social providers (e.g., LINE, 42, and OAuth 2.1 standard providers). Better Auth now supports a wide range, including new add-ons for 42 authentication as well as reliable implementations for providers like LINE to ensure regional and global support [11], [12], [23]. This standardization means you can confidently extend your app’s social login features using our familiar provider pattern. • OAuth & OIDC Improvements:
Developers are also interested in how Better Auth manages OAuth flows. Updates include a new OAuth 2.1 compliant provider plugin that supports secure defaults for authorization code, client credentials, and refresh flows – all in line with modern security best practices [8]. For OIDC, public clients now have proper support by
GitHub
Build software better, together
GitHub is where people build software. More than 150 million people use GitHub to discover, fork, and contribute to over 420 million projects.
From An unknown user
From An unknown user
From An unknown user
GitHub
Build software better, together
GitHub is where people build software. More than 150 million people use GitHub to discover, fork, and contribute to over 420 million projects.
From An unknown user
From An unknown user
From An unknown user
GitHub
better-auth/better-auth
The most comprehensive authentication framework for TypeScript - better-auth/better-auth
Better Auth
Better Auth2w ago
skipping unnecessary client_secret verifications and requiring PKCE, which improves the overall security model [30]. • Machine-to-Machine (M2M) Authentication:
For backend services and API-to-API communication, the new M2M authorization plugin implements the OAuth 2.0 client credentials grant flow. This helps you secure machine interactions with features like scope-based permissions, secure secret storage, and built-in rate limiting [18]. • Server-Side Admin & Adapter Enhancements:
Several community questions have also been about using admin endpoints directly from the server and ensuring that adapters provide consistent transaction support. Recent updates make it easier to call admin endpoints internally without an HTTP request [28], and each adapter now guarantees a valid transaction function with a safe fallback to prevent runtime errors [20]. By keeping these points in mind and checking out the latest documentation and releases, you’ll be better equipped to integrate and customize Better Auth in your TypeScript projects. If you have any more questions or need help with a specific configuration, feel free to ask!
GitHub
Build software better, together
GitHub is where people build software. More than 150 million people use GitHub to discover, fork, and contribute to over 420 million projects.
From An unknown user
From An unknown user
From An unknown user
GitHub
Build software better, together
GitHub is where people build software. More than 150 million people use GitHub to discover, fork, and contribute to over 420 million projects.
From An unknown user
From An unknown user
From An unknown user
GitHub
Build software better, together
GitHub is where people build software. More than 150 million people use GitHub to discover, fork, and contribute to over 420 million projects.
From An unknown user
From An unknown user
From An unknown user
Better Auth
Better Auth2w ago
GitHub
feat(passkey): error codes in passkey client by frectonz · Pull Re...
closes #3879 Summary by cubic Added error codes to passkey client error responses to make it easier to identify and handle specific authentication errors. This addresses the requirements in Linea...
GitHub
feat(oauth-provider): an oauth 2.1 compliant plugin by dvanmali · ...
oAuth 2.1 Provider An upgrade to oidc-provider plugin that makes it oauth2.1 compliant and has a configuration that is secure by default. Plans for the deprecation of oidc-provider plugin due to ma...
GitHub
Add 42 provider · Issue #2000 · better-auth/better-auth
Is this suited for github? Yes, this is suited for github Is your feature request related to a problem? Please describe. The current better-auth package lacks support for 42 (École 42) authenticati...
GitHub
Feat/42 provider by awbx · Pull Request #2001 · better-auth/bette...
Add 42 (École 42) Authentication Provider Resolves #2000 This PR adds support for 42 (École 42) as an authentication provider in better-auth. Users can now authenticate with their 42 accounts using...
GitHub
feat: Passkey Plugin with Client-Side authenticatorAttachment and...
Description This PR addresses Issue #1311 by enhancing the Passkey plugin in better-auth to allow clients to specify the authenticatorAttachment (platform or cross-platform) during passkey registra...
frost
frostOP2w ago
fixed it by fetching session like this instead:
import { getSessionFromCtx } from "better-auth/api";

const session = await getSessionFromCtx(ctx);
import { getSessionFromCtx } from "better-auth/api";

const session = await getSessionFromCtx(ctx);

Did you find this page helpful?