Modern Authentication Solutions for JavaScript Developers

Javascript | Nexsaar

Smart Prototyping in Figma: If-Else Logic & Conditionals

Nexsaar Technologies - React JS, Node JS, Odoo, Salesforce, Java Development Services

Let’s be honest authentication in the JavaScript world has always felt… messy. You either hack together a bunch of libraries that barely fit, or hand over everything to a SaaS and hope you don’t regret the vendor lock-in (or the bill).

That’s where Better Auth steps in. It’s not just “yet another auth library.” It’s framework-agnostic, lives inside your app, keeps user data in your database, and comes with a plugin system for advanced features all without charging you per user.

In this post, I’ll walk you through why Better Auth feels different, how to get started with dead-simple snippets, and some real-world flows you’ll actually use daily.

Why devs are hyped about Better Auth

  • Works anywhere: Next.js, Remix, Nuxt, SvelteKit, Express, Hono, Fastify bring your own framework.

  • Ready out of the box: Email+password, social logins, 2FA, passkeys, multi-session support, orgs/roles, rate limiting the works.

  • Plugin-first mindset: Add features via plugins instead of reinventing the wheel.

  • Your data, your rules: Users live in your DB. No “per-MAU” billing nonsense.

  • Full control: Tweak flows, cookies, endpoints, and types however you want.

Quick start with Next.js (zero → sign-in)

Step 1: Install it

pnpm add better-auth
# npm i better-auth
# yarn add better-auth
# bun add better-auth

Step 2: Create your auth instance

// lib/auth.ts
import { betterAuth } from "better-auth";
import { nextCookies } from "better-auth/next-js";

export const auth = betterAuth({
emailAndPassword: {
  enabled: true,
  autoSignIn: false, // sign-in after sign-up is manual now
},
plugins: [nextCookies()], // last plugin sets Next.js cookies automatically
});

Step 3: Hook it up to Next.js routes

// app/api/auth/[...all]/route.ts
import { auth } from "@/lib/auth";
import { toNextJsHandler } from "better-auth/next-js";

export const { GET, POST } = toNextJsHandler(auth.handler)

Core flows you’ll actually use

Email & Password (Next.js + Server Actions)

// app/(auth)/actions.ts
"use server";
import { auth } from "@/lib/auth";

export async function signUp(formData: FormData) {
await auth.api.signUpEmail({
  body: {
    email: String(formData.get("email")),
    password: String(formData.get("password")),
  },
});
}

export async function signIn(formData: FormData) {
await auth.api.signInEmail({
  body: {
    email: String(formData.get("email")),
    password: String(formData.get("password")),
  },
});
}

Social Login (GitHub example)

// lib/auth.ts
export const auth = betterAuth({
socialProviders: {
  github: {
    clientId: process.env.GITHUB_CLIENT_ID!,
    clientSecret: process.env.GITHUB_CLIENT_SECRET!,
  },
},
});

Client button:

// app/sign-in/SignInButtons.tsx
"use client";
import { authClient } from "@/lib/auth-client";

export function SignInButtons() {
return (
  <button
    onClick={() =>
      authClient.signIn.social({
        provider: 'github',
        callbackURL: '/dashboard',
        errorCallbackURL: '/error',
        newUserCallbackURL: '/welcome',
      })
    }
  >
    Continue with GitHub
  </button>
)
}

Session handling

Client side:

// app/_components/User.tsx
"use client";
import { authClient } from "@/lib/auth-client";

export function User() {
const { data: session, isPending } = authClient.useSession()
if (isPending) return null
return session ? (
  <span>{session.user.email}</span>
) : (
  <button onClick={() => authClient.signOut()}>Sign out</button>
)
}

Server side:

// app/dashboard/page.tsx
import { auth } from "@/lib/auth";
import { headers } from "next/headers";

export default async function DashboardPage() {
const session = await auth.api.getSession({ headers: await headers() })
if (!session) return null // or redirect("/sign-in")
return <div>Welcome {session.user.email}</div>
}

Leveling up with plugins

Want 2FA? Drop it in.

Need passkeys? One line.

API keys? Done.

// lib/auth.ts
import { betterAuth } from "better-auth";
import { twoFactor } from "better-auth/plugins";

export const auth = betterAuth({
plugins: [twoFactor()],
});

On the client:

// lib/auth-client.ts
import { createAuthClient } from "better-auth/react";
import { twoFactorClient } from "better-auth/client/plugins";

export const authClient = createAuthClient({
plugins: [twoFactorClient({ twoFactorPage: "/two-factor" })],
});

Production tips for Next.js

  • Mount routes with toNextJsHandler(auth.handler) under /api/auth/[...all].

  • Cookies are secure + httpOnly by default. Tweak useSecureCookies if needed.

  • Cross-domain? Configure trustedOrigins and your framework’s CORS.

  • Use middleware for fast redirects; use auth.api.getSession() for strict validation.

  • Full TypeScript support, with types inferred from your auth instance.

Why Better Auth feels like a game-changer

  • One mental model across frameworks move code without rewriting auth.

  • Batteries included but still extensible.

  • No lock-in, no surprise costs you own your stack.

If you’re kicking off a new project or tired of bending Auth0/Clerk/NextAuth to your will, Better Auth makes authentication less painful, more flexible, and dev-friendly from day one.

More articles

Real-Time Chat App with MERN and Socket.IO

Learn how to build a real-time chat application using the MERN stack (MongoDB, Express, React, Node.js) and Socket.IO. This step-by-step guide covers backend and frontend integration, real-time messaging, and key enhancements like authentication, private chats, and user tracking. Perfect for developers looking to create scalable and modern chat apps.

Read more

Odoo 19 Feature: What’s New Features and Why It Matters

The world of business software is in constant motion, and Odoo, the leading open-source ERP platform, is once again at the forefront of this evolution. As the highly anticipated Odoo 19 release approaches, a wave of powerful updates is set to redefine how businesses operate.

Read more