Multi-tenant identity, authentication, and authorization template for Phoenix APIs. This is a reusable foundation — it contains no product logic, only auth/tenancy/identity primitives.
- Elixir 1.19.5 + OTP 28 (pinned in
.tool-versions) - PostgreSQL 15+
- Docker (for local Postgres via docker-compose)
# Start Postgres
docker-compose up -d
# Install deps, create DB, run migrations, seed
mix setup
# Run the dev server
mix phx.serverThe API is available at http://localhost:4000.
# Run all tests (auto-creates and migrates test DB)
mix test
# Run a single test file
mix test test/elixir_api_core/auth/tokens_test.exs
# Run a single test by line number
mix test test/elixir_api_core/auth/tokens_test.exs:42# Compile warnings, unused deps, formatting, tests, dialyzer
mix precommitAll auth/user endpoints are under /api/v1. Health endpoints are at the root.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /healthz |
No | Health check |
| GET | /readyz |
No | Readiness check (DB) |
| POST | /api/v1/auth/register |
No | Register with email/password |
| POST | /api/v1/auth/login |
No | Login with email/password |
| POST | /api/v1/auth/refresh |
No | Rotate refresh token |
| POST | /api/v1/auth/logout |
No | Revoke refresh token |
| GET | /api/v1/auth/google/start |
No | Get Google OAuth URL |
| GET | /api/v1/auth/google/callback |
No | Handle Google OAuth callback |
| POST | /api/v1/auth/switch_account |
Yes | Switch to another account |
| GET | /api/v1/me |
Yes | Current user context |
See priv/openapi/v1.yaml for the full OpenAPI 3.1 spec.
- Contexts:
Accounts(users, accounts, memberships),Auth(tokens, identities, OAuth, rate limiting),Audit(event log) - Token strategy: Short-lived JWT access tokens (15 min) + opaque refresh tokens (30 day, rotated on use)
- Multi-tenancy: Users belong to accounts via memberships with roles (
owner | admin | member) - Background jobs: Oban with
defaultandmaintenancequeues - Config validation: Fail-fast on boot if required secrets are missing or unsafe defaults are used in production
See docs/ARCHITECTURE.md for detailed design and docs/DECISIONS.md for the decision log.
Dev/test use plaintext defaults in config/config.exs. Production requires these environment variables:
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection URL |
SECRET_KEY_BASE |
Phoenix secret (generate with mix phx.gen.secret) |
JWT_SECRET |
JWT signing secret (must not be the dev default) |
REFRESH_TOKEN_PEPPER |
Refresh token hashing pepper (must not be the dev default) |
PHX_HOST |
Production hostname |
PORT |
HTTP port (default: 4000) |
This is one of three reusable service templates. They share API conventions and response envelopes but are otherwise independent.
| Template | Purpose | Stack |
|---|---|---|
| elixir-api-core (this repo) | Core backend APIs | Elixir, Phoenix, PostgreSQL |
| node-edge-core | Edge/integration services | TypeScript, Fastify, Zod |
| web-app-core | Frontend SPA | TypeScript, React, Vite, Tailwind |
Product apps are created from these templates and then diverge freely with domain logic. They're designed to work together — a frontend built from web-app-core calls a backend API built from elixir-api-core, while edge services built from node-edge-core handle integrations.
This repo is intended to work as a standalone starting point. It does not require the companion templates to exist locally in the same directory. If you want to pair it with the related frontend or edge templates, use the GitHub repos above rather than assuming a shared workspace layout.
See CHANGELOG.md for the versioned task tracker.