npm package: @ingenimax/auth-client
Description: TypeScript client library for Ingenimax Auth Server
Author: Ingenimax
Latest version: 0.0.21

# @ingenimax/auth-client

**Server-side authentication SDK for Next.js App Router** connecting to Ingenimax Auth Server (Identity Provider).

## Features

- ✅ **Secure by Default** - HTTP-only cookies, no client-side token exposure
- ✅ **OAuth 2.0 / OIDC** - Standard authentication flows
- ✅ **Automatic Token Refresh** - Transparent server-side token management
- ✅ **Next.js App Router** - Built for Server Components and Route Handlers
- ✅ **Edge Middleware** - Route protection at the CDN edge
- ✅ **TypeScript** - Full type safety
- ✅ **Zero Configuration** - Works out of the box with sensible defaults

## Why This SDK?

**Problem:** Storing authentication tokens in `localStorage` or client-side state is vulnerable to XSS attacks.

**Solution:** This SDK uses **server-side session management with encrypted HTTP-only cookies**:
- ✅ Tokens never exposed to JavaScript (XSS-safe)
- ✅ Automatic CSRF protection (SameSite cookies)
- ✅ Server-side token refresh (transparent to users)
- ✅ Works with Next.js Server Components

## Installation

```bash
npm install @ingenimax/auth-client
# or
yarn add @ingenimax/auth-client
# or
pnpm add @ingenimax/auth-client
```

## Quick Start

### 1. Set Environment Variables

```bash
# .env.local
AUTH_SERVER_URL=https://auth.yourdomain.com
CLIENT_ID=your_client_id
CLIENT_SECRET=your_client_secret
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your_32_character_secret_here
```

### 2. Create Auth Handler

```typescript
// app/api/auth/[...auth]/route.ts
import { createAuthHandler } from '@ingenimax/auth-client/nextjs';

export const { GET, POST } = createAuthHandler({
  authServerUrl: process.env.AUTH_SERVER_URL!,
  clientId: process.env.CLIENT_ID!,
  clientSecret: process.env.CLIENT_SECRET!,
});
```

### 3. Add Session Provider

```typescript
// app/layout.tsx
import { SessionProvider } from '@ingenimax/auth-client/nextjs/client';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <SessionProvider>{children}</SessionProvider>
      </body>
    </html>
  );
}
```

### 4. Use in Components

```typescript
// Client Component
'use client';
import { useSession } from '@ingenimax/auth-client/nextjs/client';

export function Profile() {
  const { session, signIn, signOut } = useSession();
  
  if (!session) {
    return <button onClick={() => signIn()}>Sign In</button>;
  }
  
  return (
    <div>
      <p>Welcome, {session.user.name}</p>
      <button onClick={() => signOut()}>Sign Out</button>
    </div>
  );
}
```

```typescript
// Server Component
import { requireAuth } from '@ingenimax/auth-client/nextjs/server';

export default async function DashboardPage() {
  const session = await requireAuth();
  return <div>Welcome, {session.user.name}</div>;
}
```

**That's it!** Your app now has secure authentication.

## Documentation

- **[Integration Guide](./INTEGRATION.md)** - Complete guide for integrating into your Next.js app
- **[Implementation Details](./IMPLEMENTATION.md)** - How the SDK works internally

## Architecture

```
External Next.js App                    Ingenimax Auth Server (IdP)
┌─────────────────────┐                ┌──────────────────────┐
│                     │                │                      │
│  Client Components  │   Session      │  OAuth 2.0 / OIDC   │
│  - useSession()     │─────check─────►│  - Authorization    │
│  - SignIn/OutButton │                │  - Token Exchange   │
│                     │                │  - JWKS (RS256)     │
└──────────┬──────────┘                └──────────┬───────────┘
           │                                      │
           │ HTTP (cookies)                       │ OAuth Flow
           │                                      │
┌──────────▼──────────┐                          │
│                     │    Token Exchange         │
│  Server Layer       │─────(server-to-server)────┘
│  - getSession()     │
│  - requireAuth()    │    ┌─────────────────────┐
│  - API Routes       │    │  HTTP-Only Cookie   │
│  - Middleware       │◄───┤  Encrypted Session  │
│                     │    │  (HS256 JWT)        │
└─────────────────────┘    └─────────────────────┘
```

**Key Security Features:**
- Tokens stored in HTTP-only cookies (JavaScript cannot access)
- Session encrypted with HS256 JWT
- Automatic token refresh (server-side)
- CSRF protection with SameSite cookies
- OAuth state validation

## Usage Examples

### Server Components

```typescript
import { getSession, requireAuth } from '@ingenimax/auth-client/nextjs/server';

// Option 1: Check session
export default async function Page() {
  const session = await getSession();
  if (!session) return <div>Not signed in</div>;
  return <div>Welcome, {session.user.name}</div>;
}

// Option 2: Require auth (throws if not authenticated)
export default async function Page() {
  const session = await requireAuth();
  return <div>Protected: {session.user.email}</div>;
}
```

### Client Components

```typescript
'use client';
import { useSession, useRequireAuth } from '@ingenimax/auth-client/nextjs/client';

// Option 1: Optional auth
export function Component() {
  const { session, signIn, signOut } = useSession();
  if (!session) return <button onClick={() => signIn()}>Sign In</button>;
  return <button onClick={() => signOut()}>Sign Out</button>;
}

// Option 2: Required auth (auto-redirects)
export function Component() {
  const { session } = useRequireAuth();
  return <div>{session.user.name}</div>;
}
```

### Middleware (Route Protection)

```typescript
// middleware.ts
import { withAuth } from '@ingenimax/auth-client/nextjs/middleware';

export default withAuth({
  secret: process.env.NEXTAUTH_SECRET!,
  publicRoutes: ['/', '/about', '/pricing'],
});

export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};
```

### API Routes

```typescript
// app/api/data/route.ts
import { getSession } from '@ingenimax/auth-client/nextjs/server';
import { NextResponse } from 'next/server';

export async function GET() {
  const session = await getSession();
  
  if (!session) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }
  
  return NextResponse.json({ user: session.user });
}
```

## API Reference

### Server Functions

```typescript
import {
  getSession,
  requireAuth,
  getUser,
  getAccessToken,
  clearSession,
} from '@ingenimax/auth-client/nextjs/server';

// Get current session (returns null if not authenticated)
const session = await getSession();

// Require authentication (throws if not authenticated)
const session = await requireAuth();

// Get user only
const user = await getUser();

// Get access token for API calls
const token = await getAccessToken();

// Clear session (sign out)
await clearSession();
```

### Client Hooks

```typescript
import {
  useSession,
  useRequireAuth,
  useUser,
} from '@ingenimax/auth-client/nextjs/client';

// Main session hook
const { session, isLoading, error, signIn, signOut, refresh } = useSession();

// Require auth (auto-redirects if not authenticated)
const { session } = useRequireAuth();

// Get user only
const user = useUser();
```

### Client Components

```typescript
import {
  SessionProvider,
  SignInButton,
  SignOutButton,
  Protected,
} from '@ingenimax/auth-client/nextjs/client';

// Wrap app to provide session context
<SessionProvider>{children}</SessionProvider>

// Pre-built buttons
<SignInButton>Sign In</SignInButton>
<SignOutButton global={true}>Sign Out</SignOutButton>

// Protected wrapper
<Protected fallback={<div>Sign in required</div>}>
  {children}
</Protected>
```

### Middleware

```typescript
import {
  withAuth,
  requireAuth,
  protectRoutes,
} from '@ingenimax/auth-client/nextjs/middleware';

// Protect all routes except public ones
export default withAuth({
  secret: process.env.NEXTAUTH_SECRET!,
  publicRoutes: ['/', '/about'],
});

// Require auth for all routes
export default requireAuth({
  secret: process.env.NEXTAUTH_SECRET!,
});

// Protect specific routes only
export default protectRoutes({
  secret: process.env.NEXTAUTH_SECRET!,
  protectedRoutes: ['/dashboard', '/profile'],
});
```

## TypeScript Support

Full TypeScript support with type inference:

```typescript
import type { Session, UserInfo } from '@ingenimax/auth-client/nextjs';

const session: Session | null = await getSession();
const user: UserInfo = session.user;
```

## Configuration

### Environment Variables

```bash
# Required
AUTH_SERVER_URL=https://auth.yourdomain.com
CLIENT_ID=your_client_id
CLIENT_SECRET=your_client_secret
NEXTAUTH_URL=https://yourapp.com
NEXTAUTH_SECRET=32_character_minimum_secret

# Optional
OAUTH_SCOPES=openid profile email  # Default scopes
SESSION_MAX_AGE=604800              # 7 days (default)
COOKIE_NAME=auth.session            # Default cookie name
```

### Advanced Options

```typescript
// app/api/auth/[...auth]/route.ts
import { createAuthHandler } from '@ingenimax/auth-client/nextjs';

export const { GET, POST } = createAuthHandler({
  authServerUrl: process.env.AUTH_SERVER_URL!,
  clientId: process.env.CLIENT_ID!,
  clientSecret: process.env.CLIENT_SECRET!,
  
  // Optional: Custom scopes
  scopes: ['openid', 'profile', 'email', 'org'],
  
  // Optional: Custom session duration
  sessionMaxAge: 60 * 60 * 24 * 30, // 30 days
  
  // Optional: Custom pages
  pages: {
    signIn: '/signin',
    signOut: '/goodbye',
    error: '/auth/error',
  },
  
  // Optional: Callbacks
  callbacks: {
    afterSignIn: async (session) => {
      console.log('User signed in:', session.user.email);
    },
    afterSignOut: async () => {
      console.log('User signed out');
    },
  },
});
```

## Security

This SDK follows security best practices:

- ✅ **HTTP-only Cookies** - Tokens never exposed to JavaScript (XSS-safe)
- ✅ **Server-Side Sessions** - All token operations on server
- ✅ **Encrypted Sessions** - HS256 JWT encryption
- ✅ **CSRF Protection** - State parameter + SameSite cookies
- ✅ **Automatic Refresh** - Server-side token refresh
- ✅ **Token Revocation** - Tokens revoked on sign out
- ✅ **HTTPS Only** - Secure cookies in production

**Never do this:**
```typescript
// ❌ Storing tokens in localStorage (XSS vulnerable)
localStorage.setItem('token', accessToken);
```

**Do this instead:**
```typescript
// ✅ SDK handles everything server-side (secure)
const session = await getSession(); // Tokens in HTTP-only cookie
```

## Documentation

- **[Integration Guide](./INTEGRATION.md)** - Step-by-step integration guide
- **[Implementation Details](./IMPLEMENTATION.md)** - How the SDK works internally
- **[Auth Architecture](../../docs/AUTH_ARCHITECTURE_DIAGRAMS.md)** - System architecture diagrams

## Examples

See complete examples:
- Basic setup
- Protected routes
- API integration
- Custom UI

## Support

For issues and questions:
- **GitHub Issues** - [Report bugs or request features]
- **Documentation** - See INTEGRATION.md
- **Email** - support@ingenimax.com

## License

MIT