using-authentication

Use Better Auth for client and server-side authentication. Covers session access, protected routes, sign in/out, and fetching user data.

9 stars

Best use case

using-authentication is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Use Better Auth for client and server-side authentication. Covers session access, protected routes, sign in/out, and fetching user data.

Teams using using-authentication should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/using-authentication/SKILL.md --create-dirs "https://raw.githubusercontent.com/andrelandgraf/fullstackrecipes/main/.agents/skills/using-authentication/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/using-authentication/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How using-authentication Compares

Feature / Agentusing-authenticationStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Use Better Auth for client and server-side authentication. Covers session access, protected routes, sign in/out, and fetching user data.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Working with Authentication

Use Better Auth for client and server-side authentication. Covers session access, protected routes, sign in/out, and fetching user data.

## Implement Working with Authentication

Use Better Auth for client and server-side authentication. Covers session access, protected routes, sign in/out, and fetching user data.

**See:**

- Resource: `using-authentication` in Fullstack Recipes
- URL: https://fullstackrecipes.com/recipes/using-authentication

---

### Client-Side Authentication

Use the auth client hooks in React components:

```tsx
"use client";

import { useSession, signOut } from "@/lib/auth/client";

export function UserMenu() {
  const { data: session, isPending } = useSession();

  if (isPending) return <div>Loading...</div>;
  if (!session) return <a href="/sign-in">Sign In</a>;

  return (
    <div>
      <span>{session.user.name}</span>
      <button onClick={() => signOut()}>Sign Out</button>
    </div>
  );
}
```

### Server-Side Session Access

Get the session in Server Components and API routes:

```typescript
import { auth } from "@/lib/auth/server";
import { headers } from "next/headers";

// In a Server Component
export default async function Page() {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

  if (!session) {
    return <div>Not signed in</div>;
  }

  return <div>Hello, {session.user.name}</div>;
}
```

```typescript
// In an API route
export async function POST(request: Request) {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

  if (!session) {
    return new Response("Unauthorized", { status: 401 });
  }

  // Use session.user.id for queries...
}
```

### Protected Pages Pattern

Redirect unauthenticated users:

```tsx
import { redirect } from "next/navigation";
import { headers } from "next/headers";
import { auth } from "@/lib/auth/server";

export default async function ProtectedPage() {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

  if (!session) {
    redirect("/sign-in");
  }

  return <Dashboard user={session.user} />;
}
```

### Auth Pages Pattern

Redirect authenticated users away from auth pages:

```tsx
import { redirect } from "next/navigation";
import { headers } from "next/headers";
import { auth } from "@/lib/auth/server";

export default async function SignInPage() {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

  if (session) {
    redirect("/chats"); // Already signed in
  }

  return <SignIn />;
}
```

### Signing In

```typescript
import { signIn } from "@/lib/auth/client";

// Email/password
await signIn.email({
  email: "user@example.com",
  password: "password",
  callbackURL: "/chats",
});

// Social provider
await signIn.social({
  provider: "google",
  callbackURL: "/chats",
});
```

### Signing Up

```typescript
import { signUp } from "@/lib/auth/client";

await signUp.email({
  email: "user@example.com",
  password: "password",
  name: "John Doe",
  callbackURL: "/verify-email",
});
```

### Signing Out

```typescript
import { signOut } from "@/lib/auth/client";

await signOut({
  fetchOptions: {
    onSuccess: () => {
      router.push("/");
    },
  },
});
```

### Fetching User Data After Auth

In protected pages, fetch user-specific data after validating the session:

```tsx
export default async function DashboardPage() {
  const session = await auth.api.getSession({
    headers: await headers(),
  });

  if (!session) {
    redirect("/sign-in");
  }

  const [chats, profile] = await Promise.all([
    getUserChats(session.user.id),
    getUserProfile(session.user.id),
  ]);

  return <Dashboard chats={chats} profile={profile} />;
}
```

---

## References

- [Better Auth React](https://www.better-auth.com/docs/react)
- [Better Auth Server](https://www.better-auth.com/docs/server)

Related Skills

authentication

9
from andrelandgraf/fullstackrecipes

Complete authentication system with Better Auth, email verification, password reset, protected routes, and account management.

using-workflows

9
from andrelandgraf/fullstackrecipes

Create and run durable workflows with steps, streaming, and agent execution. Covers starting, resuming, and persisting workflow results.

using-user-stories

9
from andrelandgraf/fullstackrecipes

Document and track feature implementation with user stories. Workflow for authoring stories, building features, and marking acceptance criteria as passing.

using-tests

9
from andrelandgraf/fullstackrecipes

Testing strategy and workflow. Tests run in parallel with isolated data per suite. Prioritize Playwright for UI, integration tests for APIs, unit tests for logic.

using-sentry

9
from andrelandgraf/fullstackrecipes

Capture exceptions, add context, create performance spans, and use structured logging with Sentry.

using-nuqs

9
from andrelandgraf/fullstackrecipes

Manage React state in URL query parameters with nuqs. Covers Suspense boundaries, parsers, clearing state, and deep-linkable dialogs.

using-logging

9
from andrelandgraf/fullstackrecipes

Use structured logging with Pino throughout your application. Covers log levels, context, and workflow-safe logging patterns.

using-drizzle-queries

9
from andrelandgraf/fullstackrecipes

Write type-safe database queries with Drizzle ORM. Covers select, insert, update, delete, relational queries, and adding new tables.

using-analytics

9
from andrelandgraf/fullstackrecipes

Track custom events and conversions with Vercel Web Analytics. Covers common events, form tracking, and development testing.

url-state-management

9
from andrelandgraf/fullstackrecipes

Sync React state to URL query parameters for shareable filters, search, and deep-linkable dialogs with nuqs.

testing

9
from andrelandgraf/fullstackrecipes

Complete testing setup with Neon database branching, Playwright browser tests, integration tests, and unit tests. Isolated branches with automatic TTL cleanup.

stripe-subscriptions

9
from andrelandgraf/fullstackrecipes

Complete subscription billing system with Stripe integration, feature flags for plan gating, webhook handling, and billing portal.