# Frontend Next Auth

> Next.js storefront authentication: js-cookie JWT, useAuth hook, ProfileBootstrap, middleware route protection, Google OAuth, profile store. Use when implementing login, protected routes, auth state, or sign-in/sign-up in Next.js e-commerce apps.

- Skill: `xmuhameed/frontend-next-auth` (Agent Skill)
- Install (CLI): `npx skillmds@latest add xmuhameed/frontend-next-auth`
- Raw SKILL.md: https://api.skillmd.com/api/skills/xmuhameed/frontend-next-auth/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: xmuhameed (https://skillmd.com/u/xmuhameed)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/xmuhameed/frontend-next-auth

---


# Next.js Auth (Storefront)

**Different from backend** — client-side cookie + Zustand, middleware for route protection.

## Token Storage

```typescript
// js-cookie key "token", 90-day expiry
Cookies.set('token', accessToken, { expires: 90 });
```

## useAuth Hook

```typescript
const { login, register, loginWithGoogle, logout, user, isAuthenticated } = useAuth();
// login(credentials, redirectPath?) → set cookie → fetchProfile() → router.push
```

Files: `hooks/useAuth.ts`, `stores/profile.store.ts`, `services/profile.service.ts`

## ProfileBootstrap

Client component returns null — fetches profile on mount (avoids `cookies()` in RSC header).

## API Client Auto-Auth

```typescript
// utils/api.ts — attaches Bearer from cookie on every request
const token = Cookies.get('token');
headers.Authorization = `Bearer ${token}`;
```

## Middleware Protection

```typescript
// middleware.ts
const token = request.cookies.get('token');
if (pathname.includes('/my-profile') && !token) {
  return redirect(`/${locale}/sign-in?redirect=${encodeURIComponent(pathname)}`);
}
// Authenticated on /sign-in → redirect home
```

Protected: `/my-profile`, `/orders`. Legacy `/my-orders` → `/my-profile?tab=orders`.

## Auth Pages

- `app/[locale]/(auth)/sign-in/page.tsx` — client page
- `components/auth/AuthForm.tsx` — email/password (controlled state, not RHF)
- `components/auth/GoogleAuthButton.tsx` — `NEXT_PUBLIC_GOOGLE_CLIENT_ID`
- `components/auth/LoginModal.tsx` — inline auth modal

## API Endpoints

```
POST /auth/login, /auth/register, /auth/oauth/google
GET  /auth/get-profile, /auth/logout
PATCH /auth/update-profile
```

## Login Flow

1. POST login → extract `accessToken` from response
2. `Cookies.set('token')`
3. `fetchProfile()` → Zustand `useProfileStore`
4. `router.push(redirect || '/')`

## Logout

Clear cookie + profile store + favorites → redirect sign-in.

## Env

`NEXT_PUBLIC_GOOGLE_CLIENT_ID`, `NEXT_PUBLIC_API_BASE_URL`

**Do not** duplicate backend JWT/guard logic — frontend only stores token and attaches header.

