# Auth

Scribase includes a full-featured authentication service built on
[GoTrue](https://github.com/supabase/gotrue) — the same battle-tested service
that powers Supabase. Every environment gets its own isolated auth instance.

## How it works

1. A client signs in through GoTrue (email/password, OAuth, SAML, magic link,
   phone OTP).
2. GoTrue issues a signed JWT containing `sub` (user ID), `email`, and custom
   claims.
3. The JWT is sent with data-plane API calls (`Authorization: Bearer <token>`).
4. Postgres row-level security policies use `auth.uid()` and `auth.jwt()` to
   enforce per-row access control.

## Endpoints

All auth calls go to the gateway path `/auth/v1/...`:

| Endpoint | Description |
|---|---|
| `POST /auth/v1/signup` | Create a new user |
| `POST /auth/v1/token?grant_type=password` | Sign in with email + password |
| `GET /auth/v1/authorize?provider=github` | Start OAuth flow |
| `POST /auth/v1/token?grant_type=refresh_token` | Refresh an access token |
| `POST /auth/v1/logout` | Revoke session |
| `GET /auth/v1/user` | Get the current user |

## JWT structure

```json
{
  "sub": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
  "email": "alice@example.com",
  "role": "authenticated",
  "aud": "authenticated",
  "exp": 1775000000,
  "iat": 1774996400,
  "app_metadata": {
    "provider": "github"
  },
  "user_metadata": {
    "full_name": "Alice"
  }
}
```

## Using auth in RLS policies

Access the current user's ID and claims inside Postgres:

```sql
-- auth.uid() returns the `sub` claim as a uuid
-- auth.jwt() returns the full decoded token as jsonb

CREATE POLICY "users can read their own data"
  ON profiles FOR SELECT
  USING (id = auth.uid());

CREATE POLICY "admin role only"
  ON admin_logs FOR SELECT
  USING ((auth.jwt() ->> 'role') = 'admin');
```

The Scribase schema language lets you declare these inline:

```scribase
model profiles {
  id         uuid primary key default auth.uid()
  email      text not null
  created_at timestamptz not null default now()

  policy "owner can read" on select
    using (id = auth.uid())

  policy "owner can update" on update
    using (id = auth.uid())
    with check (id = auth.uid())
}
```

## Providers

Configure providers in the environment's `auth` service settings:

| Provider | Type | Notes |
|---|---|---|
| Email / Password | Built-in | Always available |
| Magic Link | Built-in | Requires SMTP |
| OAuth (GitHub, Google, GitLab, ...) | OAuth 2.0 | Requires app credentials |
| SAML 2.0 | Enterprise SSO | Requires IdP metadata |
| Phone OTP | SMS | Requires Twilio or similar |

## Admin API

The auth admin API (at `/auth/v1/admin/...`) requires the service-role JWT
and allows creating, listing, and managing users server-side:

```ts
const { users } = await scribase.auth.listUsers(ref);
```

## Local development

`scribase dev` starts the auth service automatically. It uses the local
`JWT_SECRET` and `ANON_KEY` configured in `.scribase/`. You can override
these in the `SCRIBASE_DEV_*` environment variables.
