README.md

# couchdb_auth

Authentication helpers for the Apache CouchDB REST API, written in Elixir.

* Tested with:
  - Elixir 1.18.x / Erlang OTP 27
  - CouchDB 3.x

# Overview

Apache CouchDB REST API client for Elixir.

Small, focused API surface that builds pre-configured `Tesla.Client`s for the
main CouchDB interfaces.

### Features

* HTTP REST client
* HTTP Authentication:
  * Basic Auth
  * Cookie Auth
  * OAuth 1.0a
  * Bearer / JWT tokens
  * Proxy authentication headers
* Cluster/admin helpers for `_nodes` endpoints
* Local document helpers for `_local/<doc_id>`

## Installation

Add to mix.exs

```elixir
  def deps do
    [{:couchdb_auth, "~> 0.2.4"}]
  end
```

## Configuration

Project settings live in `config/*.exs` and can be overridden with environment
variables prefixed with `COUCHDB_`. A minimal configuration looks like:

```elixir
config :couchdb_auth,
  protocol: "http",
  hostname: "localhost",
  port: "5984",
  backend_port: "5986",
  database: "couchdb_test",
  auth_type: :admin_party
```

## Authentication Modes

Choose an `auth_type` that matches your CouchDB deployment. The library accepts
`:admin_party`, `:basic`, `:cookie`, `:oauth`, `:bearer`, and `:proxy`. Each mode
reuses the same `CouchDB.client/2` API; only the configuration changes.

### Basic authentication

```elixir
config :couchdb_auth,
  auth_type: :basic,
  username: "admin",
  password: "supersecret"
```

```elixir
CouchDB.get("/_up")
```

The middleware adds an `Authorization: Basic <base64>` header to every request.

### Cookie (session) authentication

```elixir
config :couchdb_auth,
  auth_type: :cookie,
  username: "cookie",
  password: "monster"
```

```elixir
CouchDB.get("/_users")
```

The middleware logs in via `/_session`, caches the `Set-Cookie` value, and
reuses it on subsequent calls.

### OAuth 1.0a

```elixir
config :couchdb_auth,
  auth_type: :oauth,
  consumer_key: "...",
  consumer_secret: "...",
  token: "...",
  token_secret: "..."
```

```elixir
CouchDB.get("/_membership")
```

The middleware signs each request and injects the `Authorization: OAuth ...`
header. See the detailed setup guide below for provisioning CouchDB credentials.

### Bearer / JWT

```elixir
config :couchdb_auth,
  auth_type: :bearer,
  bearer_token: "eyJhbGciOi..."
```

```elixir
CouchDB.get("/_up")
```

A static `Authorization: Bearer <token>` header is attached to each call.

### Proxy authentication

```elixir
config :couchdb_auth,
  auth_type: :proxy,
  proxy_user: "carol",
  proxy_roles: ["_admin", "developers"],
  proxy_secret: "shared-secret"
```

```elixir
CouchDB.get("/_all_dbs")
```

Requests carry the `X-Auth-CouchDB-*` headers expected by CouchDB’s proxy
authentication. Provide `proxy_secret` to let the middleware derive the token,
or set `proxy_token` yourself when a precomputed value is required.

## Admin & Cluster Helpers

Use the admin interface for `_nodes` configuration endpoints. When clustering is
enabled (`cluster: true`), the client automatically prefixes `/_nodes/<node>`:

```elixir
CouchDB.admin_get("/_config")
```

## Local Documents

Local documents live under `/_local/<id>` and never replicate. The convenience
helpers wrap the correct routing:

```elixir
CouchDB.LocalDocs.get("cache")
CouchDB.LocalDocs.put("cache", %{rev: "1-abc"})
```

## OAuth 1.0a CouchDB setup

Provisioning OAuth credentials requires a few one-time changes on the CouchDB
node (defaults assume Docker networking with the host at `172.17.0.1`):

1. **Expose the backend interface:** open `http://localhost:5986/_utils`, locate
   the `httpd` section, and set the `bind_address` (or `bind`) value to
   `0.0.0.0`. Save the change.
2. **Create an admin user to close admin party:**

   ```bash
   curl -X PUT http://172.17.0.1:5986/_config/admins/admin -d '"supersecret"'
   ```

3. **Generate four random secrets** (consumer key, consumer secret, token, token
   secret). Repeat the command four times and record each digest:

   ```bash
   < /dev/urandom tr -dc _A-Za-z0-9 | head -c ${1:-2048} | sha256sum
   ```

4. **Register the consumer credentials:**

   ```bash
   curl -X PUT \
     http://admin:supersecret@172.17.0.1:5986/_config/oauth_consumer_secrets/<consumer_key> \
     -d '"<consumer_secret>"'
   ```

5. **Register the token credentials:**

   ```bash
   curl -X PUT \
     http://admin:supersecret@172.17.0.1:5986/_config/oauth_token_secrets/<token> \
     -d '"<token_secret>"'
   ```

6. **Map the token to the admin user:**

   ```bash
   curl -X PUT \
     http://admin:supersecret@172.17.0.1:5986/_config/oauth_token_users/<token> \
     -d '"admin"'
   ```

Each successful write returns an empty JSON string (`""`). Once the configuration
is in place, copy the four values into `config/*.exs` (or `COUCHDB_*`
environment variables) as shown in the OAuth example above.

## Contributing

Authenticate GitHub CLI before using the automated PR command:

```bash
gh auth login
gh pr create --base master --head <your-branch> --title "feat: expand auth coverage for couchdb" --body "## Summary\n..."
```