Skip to content

feat(auth): IP allow-list — network gating on auth routes (ADR-0069 D5, P2) - #2401

Merged
os-zhuang merged 1 commit into
mainfrom
auth/adr-0069-ip-allowlist
Jun 27, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
auth/adr-0069-ip-allowlist

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

ADR-0069 P2 / D5 — IP allow-list (network gating).

What

New allowed_ip_ranges auth setting (CIDR ranges or exact IPs, one per line / comma-separated; empty = no restriction). A Hono middleware registered ahead of the better-auth handler in the auth-route registration rejects auth requests from a client IP outside the ranges with 403 IP_NOT_ALLOWED — the exact seam ADR-0069 D5 names.

  • Client IP is read trust-proxy-aware: x-forwarded-for (first hop) → cf-connecting-ip → x-real-ip.
  • /config + /bootstrap-status are exempt so a blocked client still gets a clean login page + a clear error (rather than a broken page).
  • Fails OPEN when the client IP can't be determined (no proxy header) — a misconfigured proxy is a no-op, not a lockout. An admin enabling this must ensure forwarded headers are trusted.
  • IPv4 CIDR (a.b.c.d/n) + exact IPv4/IPv6 matching (ipMatchesRange / isClientIpAllowed, unit-tested).

ADR-0049

Default-off / additive (no upgrade behavior change); the setting ships with its enforcement.

Verification

  • Unit: plugin-auth 208 + service-settings 129 green; full build incl. strict DTS green. Tests cover CIDR/exact matching, in-range vs out-of-range, no-ranges-allows-all, and fail-open on undetermined IP.
  • Live dogfood (allowed_ip_ranges=203.0.113.0/24):
    • sign-in with X-Forwarded-For: 8.8.8.8 → 403 IP_NOT_ALLOWED
    • sign-in with X-Forwarded-For: 203.0.113.50 → 200 + token
    • /config from a disallowed IP → 200 (login still renders)
    • no proxy header → 200 (fail-open; admin not locked out)

Scope / follow-ups (#2375)

This gates the auth routes (sign-in / session), per the ADR's D5 seam. Gating all data requests by IP, per-org sys_organization.allowed_ip_ranges, and the require_ip_match session-pinning toggle are follow-ups. Remaining ADR-0069 work: P3 SAML (needs a @better-auth/sso vs custom plugin decision). (OIDC trust-list UI / D6 verified already shipped via the SSO-provider surface.)

🤖 Generated with Claude Code

…5, P2)

- service-settings: new `allowed_ip_ranges` setting (Network group; CIDR/IP list).
- plugin-auth: a Hono middleware registered ahead of the better-auth handler
  rejects auth requests from a client IP outside the ranges with 403
  IP_NOT_ALLOWED. Client IP read trust-proxy-aware (x-forwarded-for first hop /
  cf-connecting-ip / x-real-ip). /config + /bootstrap-status exempt so a blocked
  client still gets a clean login + error. Fails OPEN when the IP can't be
  determined (missing proxy header = no-op, not a lockout). IPv4 CIDR + exact
  match (ipMatchesRange + isClientIpAllowed).

Default-off / additive; ADR-0049.

Verified live (dogfood, allowed=203.0.113.0/24): sign-in with XFF 8.8.8.8 -> 403
IP_NOT_ALLOWED; XFF 203.0.113.50 -> 200 + token; /config from a disallowed IP ->
200 (login renders); no XFF -> 200 (fail-open, admin not locked out). Unit:
plugin-auth 208 + service-settings 129 green; full build incl. strict DTS green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 27, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 27, 2026 6:21pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/m labels Jun 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/plugin-auth, packages/services.

14 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/concepts/implementation-status.mdx (via @objectstack/plugin-auth)
  • content/docs/concepts/packages.mdx (via @objectstack/plugin-auth)
  • content/docs/getting-started/cli.mdx (via @objectstack/plugin-auth)
  • content/docs/guides/auth-sso.mdx (via @objectstack/plugin-auth)
  • content/docs/guides/authentication.mdx (via @objectstack/plugin-auth)
  • content/docs/guides/kernel-services.mdx (via @objectstack/plugin-auth)
  • content/docs/guides/packages.mdx (via @objectstack/plugin-auth, packages/services)
  • content/docs/guides/plugins.mdx (via @objectstack/plugin-auth)
  • content/docs/guides/production-readiness.mdx (via @objectstack/plugin-auth)
  • content/docs/guides/runtime-services/audit-service.mdx (via packages/services)
  • content/docs/guides/runtime-services/index.mdx (via packages/services)
  • content/docs/guides/runtime-services/settings-service.mdx (via packages/services)
  • content/docs/protocol/objectos/i18n-standard.mdx (via packages/services)
  • content/docs/releases/v9.mdx (via @objectstack/plugin-auth)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang merged commit 8c84c97 into main Jun 27, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the auth/adr-0069-ip-allowlist branch June 27, 2026 18:21
os-zhuang added a commit that referenced this pull request Jul 13, 2026
feat(plugin-detail,app-shell): Edit as primary CTA; enter inline edit by double-clicking a field (#2401) (#2402)

objectui@839536b1f4c0c0c1853cbc89f832fe7a431b2a9c

This branch was successfully deployed

1 active deployment
Preview — f2ed9762 Deployed Jun 27, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant