{"id":51524962,"url":"https://github.com/beyondoss/auth","last_synced_at":"2026-07-08T20:30:23.344Z","repository":{"id":366222940,"uuid":"1221766170","full_name":"beyondoss/auth","owner":"beyondoss","description":"Per-project authentication and authorization service for apps running on https://beyond.dev","archived":false,"fork":false,"pushed_at":"2026-06-20T20:52:26.000Z","size":2264,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-20T21:17:16.302Z","etag":null,"topics":["auth","authn","authorization","authz","beyond","beyond-dev","copy-on-write","cow","postgres-extension","zanzibar"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/beyondoss.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-26T16:50:17.000Z","updated_at":"2026-06-20T20:52:29.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/beyondoss/auth","commit_stats":null,"previous_names":["beyondoss/auth"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/beyondoss/auth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyondoss%2Fauth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyondoss%2Fauth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyondoss%2Fauth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyondoss%2Fauth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/beyondoss","download_url":"https://codeload.github.com/beyondoss/auth/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyondoss%2Fauth/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35278166,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-08T02:00:06.796Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auth","authn","authorization","authz","beyond","beyond-dev","copy-on-write","cow","postgres-extension","zanzibar"],"created_at":"2026-07-08T20:30:22.516Z","updated_at":"2026-07-08T20:30:23.336Z","avatar_url":"https://github.com/beyondoss.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# beyond/auth\n\nAuthenticate users, issue tokens, and manage sessions — deployed inside your network, owned by you.\n\nEach project gets its own deployment, its own signing keys, and its own `auth` schema within the project's existing Postgres database. No shared user namespace. Forking a project's database volume forks its auth state automatically — users, sessions, signing keys, all of it.\n\n## What it does\n\n- **Sessions** — opaque bearer tokens validated in one SQL query; JWT exchange opt-in for stateless edge verification\n- **Auth methods** — password, magic links, TOTP (2FA with recovery codes), passkeys (WebAuthn/FIDO2), OAuth (GitHub, Google, Apple, Microsoft, generic OIDC)\n- **Multi-email** — users can attach and verify multiple email addresses\n- **API keys** — server-to-server authentication with `key_` tokens\n- **Organizations** — create orgs, manage members and roles, send and accept invitations\n- **Authorization** — opt-in Zanzibar-style relation engine; define schemas, write relation tuples, check permissions in one query\n- **Stateless** — no in-process state; scale to zero and restart cleanly against the existing DB\n\n## Running\n\nThe service runs migrations automatically on startup. To migrate only:\n\n```sh\nbeyond-auth migrate --database-url \"postgres://...\"\n```\n\n### From source\n\n```sh\nmise run build:release\n./target/release/beyond-auth serve \\\n  --database-url \"postgres://user:pass@host:5432/dbname\" \\\n  --signing-key-encryption-key \"$(openssl rand -base64 32)\" \\\n  --admin-secret \"$(openssl rand -hex 32)\" \\\n  --webauthn-rp-id \"example.com\" \\\n  --webauthn-rp-origin \"https://example.com\"\n```\n\n## Configuration\n\n| Flag / Env                                                            | Default                 | Description                                                                                                                                                                                                                  |\n| --------------------------------------------------------------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `--mmds-endpoint` / `MMDS_ENDPOINT`                                   | —                       | Firecracker MMDS endpoint (e.g. `http://169.254.169.254`). When set, secrets (`DATABASE_URL`, `SIGNING_KEY_ENCRYPTION_KEY`, `ADMIN_SECRET`) are fetched from MMDS instead of env vars; env vars remain as per-key fallbacks. |\n| `--database-url` / `DATABASE_URL`                                     | —                       | Postgres connection string. The service operates within the `auth` schema.                                                                                                                                                   |\n| `--address` / `ADDRESS`                                               | `0.0.0.0:8080`          | Bind address                                                                                                                                                                                                                 |\n| `--signing-key-encryption-key` / `SIGNING_KEY_ENCRYPTION_KEY`         | —                       | Base64url-encoded 32-byte AES-256-GCM key for signing key encryption at rest                                                                                                                                                 |\n| `--signing-key-encryption-key-old` / `SIGNING_KEY_ENCRYPTION_KEY_OLD` | —                       | Comma-separated old KEK values for zero-downtime key rotation                                                                                                                                                                |\n| `--admin-secret` / `ADMIN_SECRET`                                     | —                       | Bearer token required for admin endpoints                                                                                                                                                                                    |\n| `--webauthn-rp-id` / `WEBAUTHN_RP_ID`                                 | —                       | WebAuthn relying party ID (e.g. `example.com`)                                                                                                                                                                               |\n| `--webauthn-rp-origin` / `WEBAUTHN_RP_ORIGIN`                         | —                       | WebAuthn origin (e.g. `https://example.com`)                                                                                                                                                                                 |\n| `--public-url` / `PUBLIC_URL`                                         | —                       | Public base URL for OAuth callbacks                                                                                                                                                                                          |\n| `--oauth-allowed-redirect-origins` / `OAUTH_ALLOWED_REDIRECT_ORIGINS` | —                       | Comma-separated origins allowed as OAuth redirect targets                                                                                                                                                                    |\n| `--authz-cache-size` / `AUTHZ_CACHE_SIZE`                             | `100000`                | Max cached authz check entries                                                                                                                                                                                               |\n| `--authz-cache-ttl-secs` / `AUTHZ_CACHE_TTL_SECS`                     | `1800`                  | Authz cache TTL in seconds                                                                                                                                                                                                   |\n| `--log-level` / `LOG_LEVEL`                                           | `info`                  | Log verbosity                                                                                                                                                                                                                |\n| `--otlp-enabled` / `OTLP_ENABLED`                                     | `false`                 | Enable OpenTelemetry export                                                                                                                                                                                                  |\n| `--otlp-endpoint` / `OTLP_ENDPOINT`                                   | `http://localhost:4317` | OTLP collector endpoint                                                                                                                                                                                                      |\n\nSet `ENVIRONMENT=development` for human-readable logs.\n\n### Generating the encryption key\n\n```sh\nopenssl rand -base64 32\n```\n\nThis key protects signing key material at rest in Postgres. Keep it out of the database. Loss of this key requires key rotation; compromise of the DB alone is not sufficient to forge JWTs.\n\n### Database setup\n\nThe service connects to an existing Postgres database and operates entirely within the `auth` schema. It does not touch other schemas. Run it against your app's existing database, or a dedicated one — either works.\n\nThe `auth` schema is part of the public contract. Migrations are additive-only; no column is ever removed or renamed in a way that breaks existing data.\n\n## Token shapes\n\n| Token               | Format                  | Used for                    | Revoke          |\n| ------------------- | ----------------------- | --------------------------- | --------------- |\n| Session             | `session_{id}_{secret}` | End-user sessions           | Delete row      |\n| Refresh             | `rt_{id}_{secret}`      | Long-lived SDK credential   | Soft-delete row |\n| API key             | `key_{id}_{secret}`     | Server-to-server            | Soft-delete row |\n| Magic link          | `ml_{id}_{secret}`      | Passwordless login          | Expiry          |\n| Password reset      | `pwr_{id}_{secret}`     | Password recovery           | Expiry          |\n| Email verification  | `ev_{id}_{secret}`      | Email confirmation          | Expiry          |\n| Invitation          | `inv_{id}_{secret}`     | Org invitations             | Expiry          |\n| JWT (EdDSA, opt-in) | Standard JWT            | Stateless edge verification | Key rotation    |\n\nWire format: `{prefix}_{uuid_v7_hex}_{32_random_bytes_b64url}`. The DB stores only `SHA-256(secret)` — the raw secret is never persisted.\n\n## OAuth providers\n\nConfigure providers via the admin API (`PUT /v1/admin/oauth-providers`): GitHub, Google, Apple, Microsoft, and generic OpenID Connect. Provider credentials are encrypted at rest.\n\n## JWT verification\n\nProjects that opt in to JWT mode publish their public keys at `/v1/jwks.json`. Tokens are signed with Ed25519 (`EdDSA`). Verify against the JWKS:\n\n```ts\nimport { createRemoteJWKSet, jwtVerify } from \"jose\";\n\nconst JWKS = createRemoteJWKSet(\n  new URL(\"https://auth.yourproject.beyond.dev/v1/jwks.json\"),\n);\n\nconst { payload } = await jwtVerify(token, JWKS);\n```\n\nJWKS responses are cache-controlled (`public, max-age=3600`). Key rotation is additive — old keys remain in the set until all valid tokens issued under them have expired.\n\n## Authorization (opt-in)\n\nThe authz engine is off unless you define a schema. No rows in `authz_relations`, no CPU cost.\n\nDefine resource types, roles, and permissions as JSON:\n\n```json\n{\n  \"version\": 1,\n  \"resources\": [\n    {\n      \"name\": \"document\",\n      \"roles\": [\"owner\", \"viewer\"],\n      \"permissions\": {\n        \"edit\": [\"owner\"],\n        \"view\": [\"owner\", \"viewer\"]\n      }\n    }\n  ]\n}\n```\n\nCheck a single permission (defaults to the current session user):\n\n```\nGET /v1/authz/decisions?resource_type=document\u0026resource_id=123\u0026permission=edit\nGET /v1/authz/decisions?resource_type=document\u0026resource_id=123\u0026permission=edit\u0026user=456\n```\n\nBatch-check multiple permissions in one request:\n\n```sh\nPOST /v1/authz/checks\n{\n  \"checks\": [\n    { \"resource_type\": \"document\", \"resource_id\": \"123\", \"permission\": \"edit\" },\n    { \"resource_type\": \"document\", \"resource_id\": \"123\", \"permission\": \"view\", \"user\": \"789\" }\n  ]\n}\n```\n\nOther authz endpoints: `POST/DELETE/PATCH /v1/authz/relations` (write tuples), `GET/PUT /v1/authz/schema`, `GET /v1/authz/subjects`, `GET /v1/authz/objects`, `GET /v1/authz/traces` (decision audit).\n\n## TypeScript SDK\n\n```sh\nnpm install @beyond.dev/auth\n```\n\n```ts\nimport { createAuthzClient, createSessionVerifier } from \"@beyond.dev/auth\";\n\n// Verify an opaque session token\nconst verifier = createSessionVerifier({\n  baseUrl: \"https://auth.yourproject.beyond.dev\",\n});\nconst session = await verifier.verify(bearerToken); // null if invalid/expired\n\n// Check a permission\nconst authz = createAuthzClient({\n  baseUrl: \"https://auth.yourproject.beyond.dev\",\n  adminSecret: process.env.AUTH_ADMIN_SECRET!,\n});\nconst allowed = await authz.check({\n  resource: \"document\",\n  id: \"123\",\n  permission: \"edit\",\n  subject: session?.userId,\n});\n```\n\nNext.js integration ships in `@beyond.dev/auth/next`: middleware, RSC helpers, and cookie utilities.\n\n## Development\n\n```sh\nmise run format   # format all source files\n```\n\nIntegration tests use [testcontainers](https://github.com/testcontainers/testcontainers-rs) and spin up a real Postgres instance.\n\n## Self-hosting and portability\n\nTo move off Beyond (or any managed host) to your own infrastructure:\n\n1. Export your database: `pg_dump --schema=auth -f auth.sql \"$DATABASE_URL\"`\n2. Stand up `beyond-auth` anywhere that can reach a Postgres instance.\n3. `pg_restore` the auth schema into your target database.\n4. Set `DATABASE_URL`, `SIGNING_KEY_ENCRYPTION_KEY`, `ADMIN_SECRET`, and WebAuthn config, then start the service.\n\nExisting sessions and JWTs remain valid. The same binary, the same schema, the same keys.\n\n## License\n\nAGPLv3. Self-host for any purpose, including commercial use. If you offer this software as a service, you must release your modifications under AGPLv3.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbeyondoss%2Fauth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbeyondoss%2Fauth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbeyondoss%2Fauth/lists"}