# @appdirect/auth-bff

AppDirect OIDC **Backend-for-Frontend (BFF)** SDK for **Node.js** backends.

This package extracts AppDirect OAuth2/OIDC login, FEJWT session management, and token refresh into a reusable library. The browser never sees client secrets — only HttpOnly cookies and controlled API endpoints.

## Features

- Authorization Code flow with AppDirect (`/oauth2/authorize`, `/oauth2/token`, `/oauth2/userinfo`)
- AppDirect session exchange (`/auth/token`, `/auth/refresh`) for application session tokens
- **FEJWT-as-session** — session cookie stores the AppDirect FEJWT (~5 min TTL)
- **Lazy auto-refresh** — refreshes FEJWT only when expired (~once per TTL), via `ensureValidFeJwt()`
- **Single-flight refresh** — concurrent requests share one IdP refresh per warm instance
- Refresh token rotation via HttpOnly `refresh_token` cookie
- OAuth `state` CSRF protection via short-lived `oauth_state` cookie
- **CHIPS (`Partitioned`) cookies** for cross-site iframe embeds (preview, shared links)
- Framework-agnostic core + optional adapters for Next.js and Node route handlers
- Full TypeScript types

## Install

Published to the [public npm registry](https://www.npmjs.com/package/@appdirect/auth-bff):

```bash
npm install @appdirect/auth-bff
```

For local development against this repo:

```bash
npm install file:../appdirect-auth-bff
```

Or install from a packed tarball:

```bash
npm install ./appdirect-auth-bff-0.0.1.tgz
```

## Quick start — core SDK

Use `createAppDirectAuth()` in any Node 18+ backend. Flows return data (cookies, redirects, user) — you wire HTTP yourself:

```typescript
import { createAppDirectAuth } from '@appdirect/auth-bff';

const auth = createAppDirectAuth({
  issuerBaseUrl: process.env.APPDIRECT_ISSUER_BASE_URL!,
  clientId: process.env.APPDIRECT_CLIENT_ID!,
  clientSecret: process.env.APPDIRECT_CLIENT_SECRET!,
  appBaseUrl: process.env.APP_BASE_URL ?? 'http://localhost:3000',
});

// Login: auth.buildLoginRedirect() → authorizeUrl + cookiesToSet
// Callback: auth.handleCallback({ code, state, cookies })
// Session: auth.getMe(), auth.getFeJwt(), auth.refreshSession()
```

See [Usage Reference](docs/USAGE.md) for the full API.

## Quick start — Next.js App Router

**1. Configure auth** (`lib/auth.ts`):

```typescript
import { createNextAuthHandlers } from '@appdirect/auth-bff/next';

export const authHandlers = createNextAuthHandlers({
  issuerBaseUrl: process.env.APPDIRECT_ISSUER_BASE_URL!,
  clientId: process.env.APPDIRECT_CLIENT_ID!,
  clientSecret: process.env.APPDIRECT_CLIENT_SECRET!,
  appBaseUrl: process.env.NEXT_PUBLIC_APP_URL ?? 'http://localhost:3000',
});
```

**2. Add route handlers** (`app/api/auth/login/route.ts`):

```typescript
import { authHandlers } from '@/lib/auth';
export const GET = (req: Request) => authHandlers.login(req);
```

Repeat for `callback`, `me`, `jwt`, `refresh`, and `logout` — see [examples/nextjs-app-router](examples/nextjs-app-router).

Requires `next` as a peer dependency. On Vercel, set `NEXT_PUBLIC_APP_URL` to your public deployment URL so post-login redirects use the correct origin.

## Quick start — Node API route handlers

For file-based `api/auth/*` routes or any Node `(req, res)` serverless handler:

```javascript
import { createAuthRouteHandlers } from '@appdirect/auth-bff/handlers';

export const handlers = createAuthRouteHandlers({
  issuerBaseUrl: process.env.APPDIRECT_ISSUER_BASE_URL,
  clientId: process.env.APPDIRECT_CLIENT_ID,
  clientSecret: process.env.APPDIRECT_CLIENT_SECRET,
  appBaseUrl: process.env.APP_BASE_URL ?? process.env.BASE_URL ?? 'http://localhost:3000',
  // Cross-site iframe embeds (preview, shared links):
  cookieOptions: { partitioned: true },
});

export default function handler(req, res) {
  return handlers.login(req, res);
}
```

See [examples/handlers](examples/handlers).

Custom API routes (e.g. marketplace proxies) can use `readAuthCookies` and `applyCookieMutations` from `@appdirect/auth-bff/handlers` — see [Custom API routes](docs/USAGE.md#custom-api-routes) in the Usage Reference.

The [appdirect-auth-example](../appdirect-auth-example) repo is a full reference app (Next.js UI, Users API, subscription management).

## Cross-site iframe embeds

When the app runs inside a third-party iframe (e.g. App Builder preview or a shared-link viewer), enable CHIPS cookies:

```typescript
cookieOptions: { partitioned: true }
```

The SDK then forces `Secure` and defaults `SameSite` to `None` (required for third-party contexts). See [cookieOptions](docs/USAGE.md#cookieoptions) in the Usage Reference.

## Environment variables

| Variable | Description |
|----------|-------------|
| `APPDIRECT_ISSUER_BASE_URL` | Marketplace base URL (no trailing slash) |
| `APPDIRECT_CLIENT_ID` | OAuth client ID |
| `APPDIRECT_CLIENT_SECRET` | OAuth client secret |
| `APP_BASE_URL` / `BASE_URL` | App origin for OAuth redirect URI |
| `NEXT_PUBLIC_APP_URL` | Next.js public app URL (required on Vercel) |
| `AUTH_BFF_DEBUG` | Set to `true` to enable opt-in `[auth-bff:jwt]` / `[auth-bff:refresh]` debug logs |

Register callback: `{APP_URL}/api/auth/callback`

## API routes provided by adapters

| Route | Method | Purpose |
|-------|--------|---------|
| `/api/auth/login` | GET | Redirect to AppDirect authorize |
| `/api/auth/callback` | GET | OAuth callback, set session cookies |
| `/api/auth/me` | GET | Current user from FEJWT session |
| `/api/auth/jwt` | GET | FEJWT for Global Header (auto-refresh) |
| `/api/auth/refresh` | GET/POST | Manual token refresh |
| `/api/auth/logout` | GET/POST | Clear session cookies |
| `/api/auth/import-session` | POST | Import session tokens into HttpOnly cookies (iframe preview handoff) |

## Documentation

- [Architecture](docs/ARCHITECTURE.md) — design, flows, cookie model, security
- [Implementation Guide](docs/IMPLEMENTATION.md) — step-by-step integration
- [Usage Reference](docs/USAGE.md) — full API, config options, error codes

## Development

```bash
npm install
npm run build
npm test
npm run typecheck
```

## Examples

- [examples/nextjs-app-router](examples/nextjs-app-router) — Next.js 15 App Router (minimal)
- [examples/handlers](examples/handlers) — Node API route handlers
- [appdirect-auth-example](../appdirect-auth-example) — Next.js reference app (Users + Billing API demos)

## License

MIT
