React Scaffold (Custom)

A full-stack React application with custom OAuth and email authentication built on Hono. This scaffold implements all auth flows from scratch — no SDK required.


Overview

This scaffold demonstrates how to integrate AuthGate using raw HTTP requests. It's ideal if you want complete control over your auth implementation or need to understand how the proxy flow works under the hood.

What's included:

  • Hono server with full auth routes (OAuth + email)
  • React 19 frontend with React Router 7
  • HMAC-signed session cookies with timing-safe comparison
  • Nonce-based OAuth state validation (10-minute TTL)
  • Login, signup, forgot password, and reset password pages
  • Protected dashboard route with session guard

Prerequisites

  • Node.js 18+
  • An AuthGate project with at least one provider enabled
  • An API key from the AuthGate dashboard
  • A registered callback URL pointing to /api/auth/callback

Setup

Clone the scaffold from the monorepo and install dependencies:

cd apps/scaffolds/react/custom
cp .env.example .env
# Fill in your AuthGate credentials
pnpm install
pnpm dev

The dev server runs at http://localhost:3003 by default.


Directory structure

src/
├── server/
│   ├── index.ts          # Hono server entry with Vite dev middleware
│   ├── env.ts            # Server-side env validation
│   └── routes/auth.ts    # All auth routes (~340 lines)
├── lib/
│   ├── auth.tsx          # React auth context provider
│   └── authgate.ts       # OAuth URL construction helpers
├── components/
│   ├── AuthGuard.tsx     # Protected route wrapper
│   └── OAuthButtons.tsx  # Provider login buttons
├── pages/
│   ├── Home.tsx
│   ├── Login.tsx
│   ├── Signup.tsx
│   ├── ForgotPassword.tsx
│   ├── ResetPassword.tsx
│   └── Dashboard.tsx
├── App.tsx               # Route definitions
└── main.tsx              # React entry point

Key files

src/server/routes/auth.ts

The core of this scaffold. Implements all auth endpoints:

RouteMethodDescription
/:provider/loginGETRedirects to AuthGate proxy with HMAC-signed state
/callbackGETVerifies state + JWT, sets session cookie
/email/signupPOSTProxies signup to AuthGate, verifies token, sets session
/email/signinPOSTProxies signin to AuthGate, verifies token, sets session
/email/forgot-passwordPOSTRequests password reset email
/email/reset-passwordPOSTConfirms reset with new password
/meGETReturns current session user
/logoutPOSTClears session cookie

OAuth state flow: A random nonce is stored in an httpOnly cookie and combined with a timestamp and HMAC-SHA256 signature to form the state parameter. On callback, the state is verified using timing-safe comparison against the stored nonce.

Session cookies: User data is JSON-serialized, HMAC-signed, and stored as payload.signature in an httpOnly cookie with 7-day expiry.

src/lib/auth.tsx

React context provider that calls /api/auth/me on mount and exposes user, loading, refresh(), and logout() through a useAuth() hook.

src/components/AuthGuard.tsx

Wraps protected routes. Redirects to /login if no session exists, shows a loading state while checking.


Environment variables

VariableServer/ClientDescription
AUTHGATE_URLServerAuthGate API base URL (e.g. https://auth.authgate.dev)
AUTHGATE_API_KEYServerAPI key for token verification
STATE_SECRETServerMin 32 characters, used for HMAC signing
VITE_AUTHGATE_URLClientSame as AUTHGATE_URL (Vite-prefixed for browser)
VITE_APP_URLClientYour app's URL (e.g. http://localhost:3003)

Was this page helpful?