Forge authentication (v0.3)
North star: FORGE-ADR-0006 · FORGE-ADR-0010 · OAuth: FORGE-ADR-0011
Pilot behind VPN
FORGE_REQUIRE_AUTH=false — API и Lens без Bearer. Git — SSH keys only.
OAuth Sign in (recommended)
Configure GitHub OAuth on the server:
FORGE_GITHUB_CLIENT_ID=…
FORGE_GITHUB_CLIENT_SECRET=…
Then from workstation or CIDE:
forge auth login --host http://127.0.0.1:8770
# Opens browser → Sign in with GitHub → token in ~/.forge/credentials.json
Cascade IDE: forge_lens.connect tries OAuth first, falls back to device login if OAuth is not configured.
Device login (fallback / bootstrap)
forge auth login --device --host http://127.0.0.1:8770
# Terminal 2 — one-time bootstrap on server
FORGE_BOOTSTRAP_TOKEN=… forge auth approve ABCD-EFGH --host http://127.0.0.1:8770
Credentials land in ~/.forge/credentials.json. AgentForge.Mcp reads them automatically when FORGE_API_TOKEN is unset.
Commands
| Command | Purpose |
|---|---|
forge auth login |
OAuth if configured, else device flow |
forge auth login --oauth github |
Force OAuth |
forge auth login --device |
Force device flow |
forge auth approve <code> |
Approve pending CLI (bootstrap) |
forge auth status |
Show saved login for host |
forge auth logout |
Remove host entry |
forge auth token |
Print token (scripts only) |
Overrides
| Variable | When |
|---|---|
FORGE_BASE_URL |
Default host for CLI / MCP |
FORGE_API_TOKEN |
Wins over credential file (CI/debug) |
FORGE_BOOTSTRAP_TOKEN |
Approve device / create first API token |
Bootstrap (server setup)
curl -X POST http://127.0.0.1:8770/api/v1/admin/tokens \
-H "Authorization: Bearer $FORGE_BOOTSTRAP_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"ops","scopes":"read,write,accept_merge"}'
Prefer forge auth login for workstations instead of copying fg_… into MCP env.
Org catalog admin (no PAT): after login, users with org_members.role = admin (alias owner) and write scope can create repo groups, org-scoped repos, and add members via MCP/API. Bootstrap still required for org create, bulk import, and /admin/*. See FORGE-ADR-0034.
Public AMS (internet-facing showcase)
When the host is reachable by public IP (FORGE_REQUIRE_AUTH=true), treat it as partially open: public repos and /view are intentional; everything else must be locked down.
Required .env on VPS
| Variable | Value | Why |
|---|---|---|
FORGE_REQUIRE_AUTH |
true |
Bearer on MCP invoke and most write API |
FORGE_OAUTH_SIGNIN_POLICY |
invite_only (showcase default) |
OAuth only for identities already in FORGE_DEFAULT_ORG_SLUG members (import or admin add) |
FORGE_ORG_AUTO_MEMBER_ON_LOGIN |
false |
Do not auto-add every GitHub login to the org |
FORGE_GIT_HOOK_SECRET |
random 32+ bytes (openssl rand -hex 32) |
Blocks anonymous POST /api/v1/git/push |
FORGE_REQUIRE_GIT_HOOK_SECRET |
true |
Explicit; also implied when FORGE_REQUIRE_AUTH=true |
FORGE_BOOTSTRAP_TOKEN |
strong secret, server-only | Import, device approve, admin |
FORGE_GITHUB_CLIENT_ID/SECRET |
OAuth app | Human sign-in |
FORGE_GITHUB_IMPORT_TOKEN |
PAT with org repo scope | Private org import |
scripts/deploy-vps-lean.ps1 -Showcase sets auth flags, FORGE_OAUTH_SIGNIN_POLICY=invite_only, FORGE_ORG_AUTO_MEMBER_ON_LOGIN=false, and generates FORGE_GIT_HOOK_SECRET if missing (does not overwrite an existing value).
OAuth sign-in policy (instance-user-management plugin)
FORGE_OAUTH_SIGNIN_POLICY |
Behavior |
|---|---|
open |
Any GitHub user may sign in (local dev default when FORGE_REQUIRE_AUTH=false) |
invite_only |
Identity must already be org member of FORGE_DEFAULT_ORG_SLUG (seed via org-import-github or org-user-management) |
github_org |
Live GitHub org check — set FORGE_OAUTH_GITHUB_ORG=AI-Guiders (requests read:org scope) |
Org member CRUD: org-user-management plugin (POST/GET/PATCH/DELETE /api/v1/orgs/{slug}/members).
Instance admin (instance-user-management plugin)
| Role | Scope | Typical powers |
|---|---|---|
| Instance admin | whole forge host | create orgs, bulk import, /admin/*, manage instance admins; catalog ops in any org |
| Org admin | one org | repo groups, org members, org-scoped repos |
| Org member | one org | read/write repos per token scopes |
Bootstrap (FORGE_BOOTSTRAP_TOKEN) — break-glass / deploy only. Day-to-day host ops → promote instance admins via POST /api/v1/instance/admins (bootstrap or existing instance admin). Instance admins bypass invite_only OAuth gate.
Post-deploy smoke (no token)
curl -sf http://HOST:8770/health # 200
curl -sf http://HOST:8770/view/orgs/ai-guiders # 200
curl -s -o /dev/null -w '%{http_code}\n' -X POST http://HOST:8770/api/v1/git/push \
-H 'Content-Type: application/json' -d '{"repo":"x","commit":"0","branch":"main"}' # 401 or 503, not 200
curl -s -o /dev/null -w '%{http_code}\n' http://HOST:8770/api/v1/admin/plugins/status # 401 when auth on
curl -s -o /dev/null -w '%{http_code}\n' -X POST http://HOST:8770/api/v1/mcp/invoke # 401
Still public by design
/view/orgs/{slug}— public repo catalog/api/v1/orgs— org slugs and repo counts (private repo names hidden)/api/v1/capabilities— MCP tool catalog (invoke still needs token)
Recommended hardening (ops)
- TLS reverse proxy (Caddy/nginx) in front of
:8770 - Firewall: expose
2222(git-ssh) only if needed; never withoutFORGE_GIT_AUTHORIZED_KEYS - Rotate
FORGE_BOOTSTRAP_TOKENafter initial setup; keep off workstations
See also git-transport.md and FORGE-ADR-0024.