Back to Skills

grey-haven-authentication-patterns

verified

Grey Haven's authentication patterns using better-auth - magic links, passkeys, OAuth providers, session management with Redis, JWT claims with tenant_id, and Doppler for auth secrets. Use when implementing authentication features.

View on GitHub

Marketplace

grey-haven-plugins

greyhaven-ai/claude-code-config

Plugin

security

Repository

greyhaven-ai/claude-code-config
17stars

grey-haven-plugins/security/skills/authentication-patterns/SKILL.md

Last Verified

January 21, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/greyhaven-ai/claude-code-config/blob/main/grey-haven-plugins/security/skills/authentication-patterns/SKILL.md -a claude-code --skill grey-haven-authentication-patterns

Installation paths:

Claude
.claude/skills/grey-haven-authentication-patterns/
Powered by add-skill CLI

Instructions

# Grey Haven Authentication Patterns

Follow Grey Haven Studio's authentication patterns using better-auth for TanStack Start projects with multi-tenant support.

## Stack

- **better-auth**: Authentication library for TanStack Start
- **Drizzle ORM**: Database adapter for better-auth
- **Doppler**: Secret management (BETTER_AUTH_SECRET, OAuth keys)
- **Redis**: Session storage (via Upstash)
- **PostgreSQL**: User and session data with RLS

## Critical Requirements

### Multi-Tenant Authentication
**ALWAYS include tenant_id in auth tables**:
```typescript
export const users = pgTable("users", {
  id: uuid("id").primaryKey().defaultRandom(),
  tenant_id: uuid("tenant_id").notNull(), // CRITICAL!
  email_address: text("email_address").notNull().unique(),
  // ... other fields
});

export const sessions = pgTable("sessions", {
  id: uuid("id").primaryKey().defaultRandom(),
  user_id: uuid("user_id").references(() => users.id),
  tenant_id: uuid("tenant_id").notNull(), // CRITICAL!
  // ... other fields
});
```

### Doppler for Secrets
**NEVER commit auth secrets**:
```bash
# Doppler provides these at runtime
BETTER_AUTH_SECRET=<generated-secret>
BETTER_AUTH_URL=https://app.example.com
GOOGLE_CLIENT_ID=<from-google-console>
GOOGLE_CLIENT_SECRET=<from-google-console>
```

## Basic Configuration

```typescript
// lib/server/auth.ts
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "@better-auth/drizzle";
import { db } from "~/lib/server/db";

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: "pg",
    schema,
  }),
  emailAndPassword: {
    enabled: true,
    requireEmailVerification: true,
  },
  secret: process.env.BETTER_AUTH_SECRET!,
  baseURL: process.env.BETTER_AUTH_URL!,
  trustedOrigins: [process.env.BETTER_AUTH_URL!],
});
```

## Authentication Methods

### 1. Email & Password

```typescript
// Sign up with email verification
await auth.signUp.email({
  email: "user@example.com",
  password: "secure-password",

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
6481 chars

Issues Found:

  • name_directory_mismatch