npm package: @loop8id/auth-nextjs
Description: Next.js App Router authentication for Loop8ID / L8P8 OpenID Connect
Latest version: 1.0.3

# @loop8id/auth-nextjs

Next.js App Router authentication for [Loop8ID](https://auth.l8p8.com) OpenID Connect.

---

## Installation

```bash
npm install @loop8id/auth-nextjs @loop8id/auth-node-js
```

---

## Setup

### 1. Create `lib/auth.ts`

```ts
import { createNextAuth } from '@loop8id/auth-nextjs/server';

export const auth = createNextAuth({
  clientId:      process.env.L8P8_CLIENT_ID!,
  sessionSecret: process.env.SESSION_SECRET!,
  redirectUri:   `${process.env.NEXT_PUBLIC_APP_URL}/api/auth/callback`,
});
```

### 2. Create `app/api/auth/[...loop8auth]/route.ts`

Handles `/api/auth/login`, `/api/auth/callback`, `/api/auth/logout`, `/api/auth/session` automatically.

```ts
import { auth } from '@/lib/auth';
export const { GET } = auth.handlers;
```

### 3. Create `middleware.ts` (project root)

```ts
import { createLoop8Middleware } from '@loop8id/auth-nextjs/middleware';

export default createLoop8Middleware({
  sessionSecret:  process.env.SESSION_SECRET!,
  protectedPaths: ['/dashboard', '/settings', '/api/protected'],
  publicPaths:    ['/'],
});

export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};
```

### 4. Wrap your layout with `AuthProvider`

```tsx
// app/layout.tsx
import { auth } from '@/lib/auth';
import { AuthProvider } from '@loop8id/auth-nextjs/client';

export default async function RootLayout({ children }) {
  const user = await auth.getUser(); // passed to client to skip extra fetch

  return (
    <html><body>
      <AuthProvider initialUser={user}>
        {children}
      </AuthProvider>
    </body></html>
  );
}
```

---

## Server Component Usage

```tsx
// app/dashboard/page.tsx
import { auth } from '@/lib/auth';

export default async function DashboardPage() {
  const user = await auth.requireUser(); // redirects to login if unauthenticated
  return <h1>Hello, {user.name}</h1>;
}
```

## Client Component Usage

```tsx
'use client';
import { useAuth } from '@loop8id/auth-nextjs/client';

export function NavBar() {
  const { user, isAuthenticated, isLoading, login, logout } = useAuth();

  if (isLoading) return <span>Loading…</span>;
  return isAuthenticated
    ? <button onClick={logout}>Logout ({user?.name})</button>
    : <button onClick={() => login()}>Login</button>;
}
```

---

## API — Server

| Export | Description |
|---|---|
| `createNextAuth(options)` | Creates the auth helper. Returns `{ client, getUser, getSession, isAuthenticated, requireUser, handlers }` |
| `loginRouteHandler(client)` | Standalone Route Handler for login |
| `callbackRouteHandler(client)` | Standalone Route Handler for callback |
| `logoutRouteHandler(client)` | Standalone Route Handler for logout |
| `sessionRouteHandler(client)` | Standalone Route Handler for session JSON |

## API — Middleware

| Export | Description |
|---|---|
| `createLoop8Middleware(options)` | Returns a Next.js middleware function |

## API — Client

| Export | Description |
|---|---|
| `AuthProvider` | Context provider — wraps your app |
| `useAuth()` | Returns `{ user, isAuthenticated, isLoading, login, logout, refresh }` |
| `useUser()` | Returns the current user or null |
| `useAuthLoading()` | Returns `true` while session is loading |

---

## Environment Variables

```env
L8P8_CLIENT_ID=your-client-id
SESSION_SECRET=at-least-32-random-characters
NEXT_PUBLIC_APP_URL=http://localhost:3000
```

---

## License

MIT © Loop8ID