# Guide: Auth And Route Policies

SoapJS CLI supports project-level auth capabilities and route-level policies.
Generated auth bootstrap is based on `@soapjs/soap-auth` 1.x recipe configs and `@soapjs/soap-express/auth` helpers. The CLI registers `SoapAuth.create(...)` with the Express app and exposes generated auth routes through `createAuthRouter(...)`.

## Enable Auth

At project creation:

```bash
soap create secure-api --auth jwt --auth api-key --skip-install
```

After project creation:

```bash
soap update config --add-auth jwt
soap update config --add-auth api-key
soap update config --add-oauth-provider google
soap update config --add-oauth-provider github
```

Supported auth capabilities:

- `jwt`
- `api-key`
- `local`
- `oauth`

Supported OAuth provider presets:

- `google`
- `github`
- `facebook`
- `discord`
- `linkedin`
- `twitter`
- `apple`

For routes, `local`, `oauth`, and the legacy `google` auth alias are normalized to `jwt`.

OAuth providers can be selected at create time:

```bash
soap create secure-api --auth oauth --oauth-provider google --oauth-provider github --skip-install
```

Custom providers require explicit OAuth endpoints:

```bash
soap create secure-api \
  --auth oauth \
  --oauth-provider custom:acme \
  --oauth-authorization-url https://auth.example.com/oauth/authorize \
  --oauth-token-url https://auth.example.com/oauth/token \
  --oauth-user-info-url https://auth.example.com/oauth/userinfo \
  --oauth-scope "openid email profile" \
  --oauth-user-id-claim sub \
  --oauth-email-verified-claim none \
  --skip-install
```

Local and OAuth selections automatically include JWT because both issue local access and refresh tokens. API-key-only selection does not generate JWT config, secrets, or routes. Static API keys remain available for development; PostgreSQL and MongoDB projects can instead generate database-backed accounts, identities, refresh sessions, and managed API keys.

```bash
soap create secure-api \
  --db mongo \
  --auth local \
  --auth api-key \
  --auth-storage database \
  --auth-database mongo \
  --api-key-storage database \
  --api-key-scopes \
  --token-delivery cookie \
  --api-client bruno \
  --skip-install
```

Database-backed auth has the same application contract for PostgreSQL and MongoDB: scrypt password hashes, account UUIDs in JWT payloads, hashed refresh tokens/API keys, server-side rotation and logout revocation, session management, registration/password endpoints, admin API-key management, and an API-key demo route. MongoDB generation adds unique, partial, lookup, and TTL indexes; PostgreSQL generation adds equivalent tables and indexes. Run `npm run db:init` and `npm run db:seed` before starting the generated service. When both databases are selected, use `--auth-database postgres|mongo`; otherwise the CLI infers it.

When OAuth is selected in interactive create mode, the CLI asks for provider presets or `Custom provider`, then asks for:

- token delivery for login, refresh, and OAuth: `json`, `cookie`, or `cookie-redirect`
- account provisioning separately for every provider: `auto`, `existing-user-only`, or `verified-email-domain`
- frontend URL when `cookie-redirect` is selected
- allowed email domain immediately after `verified-email-domain` is selected
- custom provider user-id and verified-email claim names; choosing no verified-email claim disables email auto-linking

The same choices are available in non-interactive mode through `--oauth-provider`, `--token-delivery`, `--frontend-url`, `--oauth-provisioning`, `--oauth-allowed-domain`, `--oauth-user-id-claim`, and `--oauth-email-verified-claim`. `--oauth-callback` remains a compatibility alias for `--token-delivery`.

Apple is generated as an advanced preset because Apple returns profile claims through the ID token and does not expose a standard userinfo endpoint. Set `APPLE_USER_INFO_URL` to a compatible profile endpoint/proxy or adjust the generated OAuth mapping before using Apple in production.

In-memory auth projects keep account resolution in `src/features/auth/application/auth-user.resolver.ts`. Database-backed projects generate `AuthAccountService`, PostgreSQL or MongoDB repositories, database lifecycle hooks, and DI wiring in `src/features/auth/`.

Auth projects also enable route-specific throttling for:

- `POST /auth/login`
- `POST /auth/refresh`
- `GET /auth/oauth/:provider/callback`

## Add Protected CRUD Routes

```bash
soap add feature report --crud --auth jwt --zone private
```

Admin zone:

```bash
soap add feature audit-log --crud --auth jwt --zone admin
```

Public route:

```bash
soap add route summary --feature report --method get --path summary --auth none --zone public
```

## Add Policies

Policies require route auth.

```bash
soap add route approve --feature report --method post --path approve --auth jwt --policy roles:admin,editor
soap add route purge --feature report --method delete --path purge --auth api-key --policy admin
soap add route export --feature report --method post --path export --auth jwt --policy custom:report-exporter
```

Generated decorators:

- `admin` -> `@AdminOnly('<strategy>')`
- `roles:a,b` -> `@Auth('<strategy>', { roles: ['a', 'b'] })`
- `custom:name` -> `@Auth('<strategy>', { policy: 'name' })`

Invalid:

```bash
soap add route approve --feature report --auth none --policy admin
```

The CLI fails before writing files because policies require auth.

## CRUD Route Matrix Policies

Use matrix policies when each CRUD operation needs different auth.

```bash
soap add feature report --crud \
  --crud-route list:get:/search:jwt:private:roles=admin,editor:bruno \
  --crud-route create:post:/submit:api-key:private:custom=report-writer:bruno \
  --crud-route delete:delete:/:id:jwt:admin:admin:no-bruno
```

Matrix policy syntax uses `roles=...` and `custom=...` because `:` separates matrix fields.

## Validate Auth Metadata

```bash
soap check routes
```

This checks unknown auth strategies, disabled auth capabilities, invalid zones, policy-without-auth, contracts, and Bruno files.
