@hilbras/keystone 1.9.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/CHANGELOG.md +459 -0
  2. package/README.md +163 -32
  3. package/dist/config.d.ts +8 -0
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +8 -0
  6. package/dist/config.js.map +1 -1
  7. package/dist/db/migrations/0015_chief_vargas.sql +7 -0
  8. package/dist/db/migrations/0016_gorgeous_charles_xavier.sql +5 -0
  9. package/dist/db/migrations/0017_flashy_nekra.sql +1 -0
  10. package/dist/db/migrations/meta/0015_snapshot.json +4340 -0
  11. package/dist/db/migrations/meta/0016_snapshot.json +4363 -0
  12. package/dist/db/migrations/meta/0017_snapshot.json +4370 -0
  13. package/dist/db/migrations/meta/_journal.json +21 -0
  14. package/dist/db/schema.d.ts +138 -1
  15. package/dist/db/schema.d.ts.map +1 -1
  16. package/dist/db/schema.js +39 -1
  17. package/dist/db/schema.js.map +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +11 -2
  20. package/dist/index.js.map +1 -1
  21. package/dist/plugins/auth.d.ts +2 -0
  22. package/dist/plugins/auth.d.ts.map +1 -1
  23. package/dist/plugins/auth.js +21 -7
  24. package/dist/plugins/auth.js.map +1 -1
  25. package/dist/plugins/headerSanitization.d.ts +15 -0
  26. package/dist/plugins/headerSanitization.d.ts.map +1 -0
  27. package/dist/plugins/headerSanitization.js +39 -0
  28. package/dist/plugins/headerSanitization.js.map +1 -0
  29. package/dist/plugins/machinePrincipal.d.ts +28 -0
  30. package/dist/plugins/machinePrincipal.d.ts.map +1 -0
  31. package/dist/plugins/machinePrincipal.js +45 -0
  32. package/dist/plugins/machinePrincipal.js.map +1 -0
  33. package/dist/plugins/mtls.d.ts +21 -2
  34. package/dist/plugins/mtls.d.ts.map +1 -1
  35. package/dist/plugins/mtls.js +94 -47
  36. package/dist/plugins/mtls.js.map +1 -1
  37. package/dist/plugins/rateLimit.d.ts +5 -4
  38. package/dist/plugins/rateLimit.d.ts.map +1 -1
  39. package/dist/plugins/rateLimit.js +11 -8
  40. package/dist/plugins/rateLimit.js.map +1 -1
  41. package/dist/repositories/application.d.ts +1 -1
  42. package/dist/repositories/application.d.ts.map +1 -1
  43. package/dist/repositories/application.js +8 -2
  44. package/dist/repositories/application.js.map +1 -1
  45. package/dist/repositories/session.d.ts +1 -0
  46. package/dist/repositories/session.d.ts.map +1 -1
  47. package/dist/repositories/types.d.ts +5 -1
  48. package/dist/repositories/types.d.ts.map +1 -1
  49. package/dist/routes/admin/organizations.d.ts.map +1 -1
  50. package/dist/routes/admin/organizations.js +31 -2
  51. package/dist/routes/admin/organizations.js.map +1 -1
  52. package/dist/routes/apiKeys.d.ts.map +1 -1
  53. package/dist/routes/apiKeys.js +23 -5
  54. package/dist/routes/apiKeys.js.map +1 -1
  55. package/dist/routes/federation.d.ts.map +1 -1
  56. package/dist/routes/federation.js +8 -2
  57. package/dist/routes/federation.js.map +1 -1
  58. package/dist/routes/oauth.d.ts.map +1 -1
  59. package/dist/routes/oauth.js +38 -2
  60. package/dist/routes/oauth.js.map +1 -1
  61. package/dist/routes/oauth2.d.ts.map +1 -1
  62. package/dist/routes/oauth2.js +92 -13
  63. package/dist/routes/oauth2.js.map +1 -1
  64. package/dist/routes/profile.js +2 -2
  65. package/dist/routes/profile.js.map +1 -1
  66. package/dist/routes/saml.d.ts +24 -0
  67. package/dist/routes/saml.d.ts.map +1 -1
  68. package/dist/routes/saml.js +32 -3
  69. package/dist/routes/saml.js.map +1 -1
  70. package/dist/routes/serviceAccounts.d.ts.map +1 -1
  71. package/dist/routes/serviceAccounts.js +78 -2
  72. package/dist/routes/serviceAccounts.js.map +1 -1
  73. package/dist/routes/sessions.js +3 -3
  74. package/dist/routes/sessions.js.map +1 -1
  75. package/dist/routes/smsOtp.d.ts.map +1 -1
  76. package/dist/routes/smsOtp.js +6 -0
  77. package/dist/routes/smsOtp.js.map +1 -1
  78. package/dist/routes/totp.d.ts.map +1 -1
  79. package/dist/routes/totp.js +24 -10
  80. package/dist/routes/totp.js.map +1 -1
  81. package/dist/routes/webauthn.d.ts.map +1 -1
  82. package/dist/routes/webauthn.js +8 -2
  83. package/dist/routes/webauthn.js.map +1 -1
  84. package/dist/sdk/index.d.ts.map +1 -1
  85. package/dist/sdk/index.js.map +1 -1
  86. package/dist/sdk/types.d.ts +4 -1
  87. package/dist/sdk/types.d.ts.map +1 -1
  88. package/dist/services/application/organization.d.ts +5 -1
  89. package/dist/services/application/organization.d.ts.map +1 -1
  90. package/dist/services/application/organization.js.map +1 -1
  91. package/dist/services/connectors/google.d.ts +18 -1
  92. package/dist/services/connectors/google.d.ts.map +1 -1
  93. package/dist/services/connectors/google.js +25 -3
  94. package/dist/services/connectors/google.js.map +1 -1
  95. package/dist/services/connectors/oidc.d.ts +14 -2
  96. package/dist/services/connectors/oidc.d.ts.map +1 -1
  97. package/dist/services/connectors/oidc.js +29 -3
  98. package/dist/services/connectors/oidc.js.map +1 -1
  99. package/dist/services/connectors/types.d.ts +13 -1
  100. package/dist/services/connectors/types.d.ts.map +1 -1
  101. package/dist/services/domain/authentication.d.ts.map +1 -1
  102. package/dist/services/domain/authentication.js +36 -19
  103. package/dist/services/domain/authentication.js.map +1 -1
  104. package/dist/services/domain/organization.d.ts +5 -1
  105. package/dist/services/domain/organization.d.ts.map +1 -1
  106. package/dist/services/domain/organization.js.map +1 -1
  107. package/dist/services/events/types.d.ts +1 -1
  108. package/dist/services/events/types.d.ts.map +1 -1
  109. package/dist/services/events/validate.d.ts.map +1 -1
  110. package/dist/services/events/validate.js +6 -0
  111. package/dist/services/events/validate.js.map +1 -1
  112. package/dist/services/magicLinks.d.ts.map +1 -1
  113. package/dist/services/magicLinks.js +13 -9
  114. package/dist/services/magicLinks.js.map +1 -1
  115. package/dist/services/oauth2.d.ts +72 -2
  116. package/dist/services/oauth2.d.ts.map +1 -1
  117. package/dist/services/oauth2.js +106 -6
  118. package/dist/services/oauth2.js.map +1 -1
  119. package/dist/services/redirectUri.d.ts +56 -0
  120. package/dist/services/redirectUri.d.ts.map +1 -0
  121. package/dist/services/redirectUri.js +129 -0
  122. package/dist/services/redirectUri.js.map +1 -0
  123. package/dist/services/scopes.d.ts +113 -0
  124. package/dist/services/scopes.d.ts.map +1 -0
  125. package/dist/services/scopes.js +138 -0
  126. package/dist/services/scopes.js.map +1 -0
  127. package/dist/services/serviceAccounts.d.ts +20 -0
  128. package/dist/services/serviceAccounts.d.ts.map +1 -1
  129. package/dist/services/serviceAccounts.js +47 -1
  130. package/dist/services/serviceAccounts.js.map +1 -1
  131. package/dist/services/sessionRevocation.d.ts +76 -0
  132. package/dist/services/sessionRevocation.d.ts.map +1 -0
  133. package/dist/services/sessionRevocation.js +86 -0
  134. package/dist/services/sessionRevocation.js.map +1 -0
  135. package/dist/services/singleUse.d.ts +68 -0
  136. package/dist/services/singleUse.d.ts.map +1 -0
  137. package/dist/services/singleUse.js +54 -0
  138. package/dist/services/singleUse.js.map +1 -0
  139. package/dist/services/smsOtp.d.ts.map +1 -1
  140. package/dist/services/smsOtp.js +12 -8
  141. package/dist/services/smsOtp.js.map +1 -1
  142. package/dist/services/tokens.d.ts +2 -0
  143. package/dist/services/tokens.d.ts.map +1 -1
  144. package/dist/services/tokens.js +5 -0
  145. package/dist/services/tokens.js.map +1 -1
  146. package/dist/services/trustedProxies.d.ts +90 -0
  147. package/dist/services/trustedProxies.d.ts.map +1 -0
  148. package/dist/services/trustedProxies.js +283 -0
  149. package/dist/services/trustedProxies.js.map +1 -0
  150. package/dist/setup-server.js +2 -1
  151. package/dist/setup-server.js.map +1 -1
  152. package/dist/types.d.ts +2 -2
  153. package/dist/types.d.ts.map +1 -1
  154. package/dist/types.js.map +1 -1
  155. package/package.json +4 -5
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Hilbras Keystone
2
2
 
3
- **Current version: `1.7.0`**
3
+ **Current version: `2.6.0`**
4
4
 
5
5
  > A provider-agnostic, API-first identity platform for Hilbras products and third-party applications.
6
6
 
@@ -22,6 +22,104 @@ Keystone is a **standalone identity platform**, not a wrapper around another ide
22
22
 
23
23
  ---
24
24
 
25
+ ## What's new in v2.6.0
26
+
27
+ - **API key scopes are now a real registry** — a single list of scope names with descriptions. A scope not in the registry cannot be granted, so there is no string a caller can invent, and a route that needs a scope names it from the list so enforcement cannot quietly drift out of date again.
28
+ - **Unknown scopes are refused, not dropped** — key creation previously stored whatever strings it was given. Silently discarding an unrecognised one hides a typo and leaves the caller believing they hold something they do not, so it now returns `400` listing what was rejected and what is allowed.
29
+ - **The `service_account` wildcard is gone** — the scope guard treated a key as holding *every* scope if its scope list merely contained the string `"service_account"`, and that string was client-suppliable at key creation. It is no longer a scope, and a key holding only it satisfies nothing.
30
+ - **The scope guard fails closed** — it previously returned early whenever `apiKeyScopes` was absent, which is indistinguishable from "this is a session", so a key that resolved without a scope list skipped the check entirely. It now keys off `apiKeyId`, which is set only when a machine credential authenticated.
31
+ - **Scopes are enforced** on key, session, and profile routes, so a key is limited to the operations its grant covers.
32
+ - **Profile and MFA scopes cannot be granted to a service account** — a machine's "profile" is a synthesized object with an id of `sa:<uuid>` that matches no user row, and it has no authenticator to enrol a second factor with.
33
+ - **A stated boundary for machine principals** — `requireHumanPrincipal` refuses a service account on TOTP, WebAuthn, SMS OTP, identity linking, consent, and userinfo routes, with an explicit `403` and an audit record, rather than relying on the synthetic principal happening to match no row.
34
+ - **Personal keys default to read-only** on the caller's own resources. The previous default, `api:read`, was not in any registry — a fair sign that nothing was checking it.
35
+
36
+ > **Note on reachability.** `app.authenticate` is JWT-only, so almost every route still refuses an API key outright. `GET /auth/validate` is the one route that accepts one, and it is where scope enforcement is observable end to end. What this release fixes is the enforcement machinery, so the next route to adopt key authentication inherits a real check.
37
+
38
+ ## What's new in v2.5.0
39
+
40
+ - **The OIDC nonce now reaches the Google connector** — `GoogleConnector.exchangeCode` overrode the base method without forwarding its options, so the nonce added in 2.4.0 was silently discarded for the default provider. Every non-Google OIDC provider validated the nonce; Google, the most likely to be in use, did not.
41
+ - **The unsigned SAML `Issuer` is now validated** — the response-level `<saml:Issuer>` sits outside both signed regions, so rewriting it does not invalidate the signature, and nothing compared it to the registered IdP. An assertion could claim to come from a different identity provider. Keystone now checks it against the connection, as SAML 2.0 §2.5.1.5 requires. The assertion's own issuer is inside the signed region and was always covered.
42
+ - **`RelayState` verification returns false instead of throwing** — a malformed RelayState is a bad request an attacker fully controls, so it produced a 500 rather than a 400.
43
+ - **A missing userinfo endpoint is reported as unconfigured** — it was passed to the fetcher with a non-null assertion, surfacing a misleading "must be a valid URL" for a URL that was never set.
44
+ - **24 adversarial SAML tests** — tampered signatures, untrusted signing keys, rotated-out certificates, unsigned assertions, XML signature wrapping, issuer and audience substitution, destination and recipient prefix/superstring/case variants, expired and not-yet-valid assertions, `InResponseTo` mismatch, transaction replay, and five RelayState tampering scenarios.
45
+ - **[enterprise-sso.md](docs/security/enterprise-sso.md)** — SAML and OIDC setup, every check applied to an assertion or ID token, certificate rotation (and its lack of a grace period), endpoint SSRF policy, organization scoping, and recommendations.
46
+
47
+ ## What's new in v2.4.0
48
+
49
+ > **Breaking.** The `authorization_code` grant now requires client authentication. A client redeeming an authorization code must present its `client_secret`; requests without one now receive `401 invalid_client`. Clients that were relying on the grant working without a secret must send it.
50
+
51
+ - **The authorization code grant now authenticates the client** — it previously looked the client up and redeemed the code without ever checking a secret, so the code and its PKCE verifier were the only factors. This violates RFC 6749 §3.2.1 for confidential clients.
52
+ - **`javascript:` and `data:` are refused as redirect URIs** — validation was `z.string().url()`, which accepts anything the URL parser accepts, including script-bearing schemes. A redirect URI is a value Keystone puts in a `Location` header on its own origin, so an org admin could previously register one and hand any user who authorized their app a redirect toward script execution. Also rejects wildcards, fragments, embedded credentials, and plaintext HTTP to non-loopback hosts.
53
+ - **Public clients are supported and must use PKCE** — a `public` client type is issued no secret at all, rather than a secret it is expected to ignore, and a database constraint keeps the two halves of a client type consistent. PKCE is then mandatory for it, because client authentication is the only thing a secretless client cannot do.
54
+ - **Scopes are intersected, not trusted** — the effective set is registered ∩ requested ∩ consented. A scope outside the registration is refused with `invalid_scope` rather than silently dropped, so a client asking for more than it has is visible instead of quietly downgraded. An empty registration preserves existing behaviour.
55
+ - **OIDC federation sends and verifies a nonce** — `state` already proved the callback belonged to a login this browser started, but nothing bound the *ID token* to it. Any ID token the provider considered valid was accepted, including one minted for a different user or session.
56
+ - **ID token verification is stricter** — algorithms are pinned rather than inferred from key material, and `exp`, `iat`, `iss`, `aud`, `sub` are *required* rather than merely checked when present. A token with no expiry was previously accepted indefinitely.
57
+ - **Refresh tokens carry the granted scope set** — rotation preserves the authorization context instead of dropping it at the first refresh, and a refresh can narrow the grant but never widen it.
58
+
59
+ ## What's new in v2.3.0
60
+
61
+ - **A password reset now actually logs the attacker out** — completing a reset changed the password but left every existing session and refresh token working. A reset is the standard response to a suspected compromise, so this defeated its own purpose: whoever prompted the reset kept their access. Sessions, refresh tokens, and outstanding recovery credentials are now all invalidated.
62
+ - **An intercepted earlier reset email is dead** — reset tokens issued alongside the one used are now spent, so someone who captured a previous reset email cannot complete it after the user has already recovered.
63
+ - **One revocation layer** — `revokeUserSessions`, `revokeRefreshTokens`, `revokeAuthenticationSessions`, and `revokeRecoveryCredentials` live in one place. Revocation was previously open-coded per call site, which is how the reset path came to omit it; the MFA-enable path now routes through the same function so the rule cannot drift.
64
+ - **Recovery is left intact** — resetting revokes access but does not lock the user out: they can immediately log in with the new password. Covered by a test.
65
+
66
+ > **Not revoked on reset:** API keys. They are separately issued, long-lived credentials belonging to integrations rather than to the person, and killing them silently breaks deployments. The residual gap — a key minted by an attacker who already held the password — is real; see [SECURITY.md](docs/SECURITY.md) for why key expiry is the right fix.
67
+
68
+ ## What's new in v2.2.0
69
+
70
+ - **Magic links can no longer be redeemed twice at once** — consumption was a conditional `SELECT` followed by an *unconditional* `UPDATE`. Any number of parallel redemptions passed the check and every one of them logged in. The write is now the gate, so exactly one succeeds.
71
+ - **Password reset tokens are spent exactly once** — the same race meant parallel resets each wrote a different password, last writer winning. This was the most consequential of the three, since whoever won held the account.
72
+ - **SMS OTP codes are spent exactly once** — same shape, same fix.
73
+ - **Replays are reported, not just refused** — a credential presented after it was already used now emits `magic_link_replayed`, `sms_otp_replayed`, or `password_reset_token_replayed`, which reaches the audit log. Previously a replay was indistinguishable from a typo, so a leaked token coming back was invisible. An *expired* credential is deliberately not reported as a replay, since that is not a leak.
74
+ - **One shared primitive** — all consumption goes through a single atomic claim, so the pattern exists once rather than in three places that can drift.
75
+
76
+ ## What's new in v2.1.0
77
+
78
+ - **Dependency tree is clean** — `npm audit` reports zero vulnerabilities across production *and* development trees, including a transitive `esbuild@0.18.20` that `drizzle-kit` was pinning. Resolved with an `overrides` entry rather than `audit fix --force`, which offered only a breaking downgrade of `drizzle-kit`.
79
+ - **Continuous dependency security** — Dependabot for npm, GitHub Actions, and Docker; OSV scanning as an advisory source independent of npm's; enforced `npm audit`; dependency review on pull requests; SBOM generation; container scanning; and a license gate restricted to permissive terms.
80
+ - **Release metadata is verified** — `npm run verify:release` fails the build on a version that disagrees between `package.json` and the lockfile, a missing or malformed license, or a missing `repository` field. Runs in CI and again before `npm publish`.
81
+ - **The container image no longer ships a vulnerable npm** — the runtime image carried 8 HIGH-severity advisories inherited from the base image's bundled `npm@10.9.9`, invisible to `npm audit` and OSV because they are not in the dependency tree. npm is now removed from the production stage, which the app never invokes, clearing all 8 and shrinking the image from 600 MB to 550 MB.
82
+ - **The package now declares its license** — `package.json` had no `license` field despite shipping an MIT `LICENSE` file, so the published package carried no machine-readable terms.
83
+
84
+ ## What's new in v2.0.0
85
+
86
+ > **Breaking.** Two changes affect every deployment. `x-service-account-id` no
87
+ > longer authenticates on its own, and `x-forwarded-for` is no longer believed
88
+ > unless `KEYSTONE_TRUSTED_PROXIES` is set — behind a proxy with it unset, all
89
+ > clients share one rate-limit budget. Read
90
+ > [MIGRATION-2.0.md](docs/MIGRATION-2.0.md) before upgrading.
91
+
92
+ - **A service account cannot be named into existence** — `x-service-account-id` previously authenticated as any service account named in the header, with no certificate and no credential. Identity now comes only from a certificate bound to the account or an authenticated credential.
93
+ - **Certificates are bound to a fingerprint** — a service account authenticates by a client certificate whose SHA-256 fingerprint is bound to it, uniquely. A fingerprint can map to at most one account, and malformed values are rejected before they reach the database.
94
+ - **Client identity headers are stripped from untrusted peers** — an `onRequest` hook removes them before routing and authentication, so no route can read a spoofed identity by accident.
95
+ - **Rate limits can no longer be escaped** — the limiter previously read `x-forwarded-for` unconditionally, so any client could present a fresh address per request and never be limited. Keys come from the peer address unless a trusted proxy forwarded one.
96
+ - **`KEYSTONE_TRUSTED_PROXIES`** names the proxies permitted to set identity headers. Unset by default, which trusts nothing.
97
+ - **Service accounts can be revoked** — `POST /v1/admin/organizations/:id/service-accounts/:accountId/revoke` stops both certificate and API-key authentication.
98
+ - **Documented trust boundaries** — [trust-boundaries.md](docs/security/trust-boundaries.md), [proxy-security.md](docs/security/proxy-security.md), and [mtls.md](docs/security/mtls.md).
99
+
100
+ ## What's new in v1.9.0
101
+
102
+ - **SCIM is organization-scoped** — every SCIM connection belongs to exactly one organization, and every user and group read and write is filtered by it. A cross-tenant target returns `404`, so the endpoint is not a tenant oracle.
103
+ - **SCIM credentials are per organization** — bearer tokens are stored only as a SHA-256 digest, resolved by that digest, and can be expired, rotated, and revoked. Issuing, rotating, and revoking is owner-only.
104
+ - **Deprovisioning no longer reaches outside the tenant** — removing a user removes that organization's membership, and deactivates the account only when no membership remains anywhere. Previously it disabled a shared account in every organization that user belonged to.
105
+ - **Real SCIM groups** — create, read, replace, patch, and delete groups, manage members, and search. Replaces the old synthetic role-bucket projection.
106
+ - **New SCIM surface** — `PATCH /Users/:id`, `Users/.search`, `ServiceProviderConfig`, `ResourceTypes`, and `filter`/`startIndex`/`count`. Unsupported filters are rejected rather than silently ignored.
107
+
108
+ > **Migration:** `SCIM_BEARER_TOKEN` and `SCIM_ORG_ID` are deprecated. If still set they are adopted once into a connection and then ignored — including after a revocation, so a restart cannot resurrect a credential you revoked. See [MIGRATION-1.9.md](docs/MIGRATION-1.9.md).
109
+
110
+ ## What's new in v1.8.0
111
+
112
+ - **MFA is mandatory** — a user with TOTP enabled never receives a token before completing the second factor. Password authentication stops at `requires_mfa`; only `POST /auth/mfa/verify` completes the login.
113
+ - **One-time MFA challenges** — opaque, short-lived, stored only as a hash, single-use, with an attempt budget enforced in the database.
114
+ - **A single token-issuance chokepoint** — a token cannot be minted for an MFA-enabled user without a recorded factor, so no login path can bypass MFA by omission.
115
+ - **TOTP verified against the user's own secret**, and each time-step is accepted exactly once, so a captured code is rejected even against a freshly issued challenge.
116
+ - **Hardened backup codes** — 80 bits of entropy, keyed (peppered) hashing, expiry, and single-use consumption via a conditional update.
117
+ - **Step-up on factor changes** — enrolling, confirming, disabling, or regenerating TOTP codes requires the account password, so a leaked session token cannot take over an account's second factor.
118
+ - **Enabling MFA revokes existing sessions and refresh tokens**, and refresh rotation refuses sessions with no recorded factor.
119
+ - **TOTP secrets are encrypted with AES-256-GCM**; values written by earlier versions remain readable.
120
+
121
+ > **Migration:** `/auth/login` and `/auth/token-login` return `401` with `code: "MFA_REQUIRED"` and a challenge when MFA is required. Clients must render a code step and call `/auth/mfa/verify`. See [MIGRATION-1.8.md](docs/MIGRATION-1.8.md).
122
+
25
123
  ## What's new in v1.7.0
26
124
 
27
125
  - **Authorization boundary hardening** — platform roles (`owner`/`user`) and organization roles (`owner`/`admin`/`member`) are now separate namespaces.
@@ -489,6 +587,14 @@ services:
489
587
  | `KEYSTONE_QUEUE_PROVIDER` | `in-process`, `bullmq`, or empty to auto-select when Redis is available |
490
588
  | `KEYSTONE_PLUGINS` | Comma-separated module paths of plugins to load at startup |
491
589
  | `KEYSTONE_FEATURE_FLAGS` | Comma-separated `flag=true|false` runtime feature toggles |
590
+ | `KEYSTONE_TOTP_ENCRYPTION_KEY` | Encrypts TOTP secrets and keys the backup-code hash. Falls back to `KEYSTONE_INTERNAL_API_KEY`. Must be stable — changing it invalidates enrolled authenticators |
591
+ | `MFA_CHALLENGE_TTL_SECONDS` | Lifetime of a login MFA challenge (default `300`) |
592
+ | `MFA_MAX_ATTEMPTS` | Factor attempts per challenge before it is locked (default `5`) |
593
+ | `TOTP_BACKUP_CODE_TTL_SECONDS` | Backup-code lifetime (default `7776000`, 90 days) |
594
+ | `SCIM_ROTATION_GRACE_SECONDS` | Grace window for a rotated SCIM token. Defaults to `0`, so rotation revokes the previous token |
595
+ | `SCIM_RATE_LIMIT_MAX` / `SCIM_RATE_LIMIT_WINDOW_SECONDS` | Per-credential SCIM request budget |
596
+ | `SCIM_AUTH_FAILURE_MAX` / `SCIM_AUTH_FAILURE_WINDOW_SECONDS` | Budget for unauthenticated SCIM requests, applied before authentication |
597
+ | `KEYSTONE_TRUSTED_PROXIES` | Comma-separated proxy IPs / CIDRs allowed to set client-identity headers. **Unset means trust nothing** — forwarded headers are stripped and all clients share one rate-limit budget. Required when Keystone runs behind a reverse proxy |
492
598
 
493
599
  ---
494
600
 
@@ -516,8 +622,9 @@ If Keystone feels slow or uses a lot of memory during development, see [`docs/PE
516
622
  | Method | Path | Description |
517
623
  |--------|------|-------------|
518
624
  | POST | `/auth/register` | Email/password signup (local password hashing) |
519
- | POST | `/auth/login` | Email/password login (sets session cookies) |
625
+ | POST | `/auth/login` | Email/password login (sets session cookies; returns `401 MFA_REQUIRED` + a challenge when MFA is required) |
520
626
  | POST | `/auth/token-login` | Email/password login for SPA/dashboard (returns bearer token) |
627
+ | POST | `/auth/mfa/verify` | Complete a login MFA challenge and receive tokens |
521
628
  | POST | `/auth/logout` | Revoke session |
522
629
  | GET | `/auth/me` | Current user |
523
630
  | POST | `/auth/refresh` | Rotate refresh token |
@@ -525,7 +632,8 @@ If Keystone feels slow or uses a lot of memory during development, see [`docs/PE
525
632
  | GET | `/auth/callback/:provider` | OAuth callback |
526
633
  | POST | `/auth/forgot-password` | Request password reset |
527
634
  | POST | `/auth/reset-password` | Complete password reset |
528
- | POST/GET/DELETE | `/auth/api-keys` | Personal API keys |
635
+ | POST/GET | `/auth/api-keys` | Create / list personal API keys |
636
+ | DELETE | `/auth/api-keys/:id` | Revoke a personal API key |
529
637
  | GET | `/auth/validate` | Internal token/API-key validation |
530
638
 
531
639
  ### Federation
@@ -564,8 +672,10 @@ If Keystone feels slow or uses a lot of memory during development, see [`docs/PE
564
672
  | PATCH | `/v1/admin/platform/users/:userId` | Update non-role platform user fields (**owner only**) |
565
673
  | PATCH | `/v1/admin/platform/users/:userId/role` | Change a platform role (`owner`/`user`, **owner only**) |
566
674
  | GET | `/v1/admin/permissions` | **Owner only** — list all permissions |
567
- | GET/POST/DELETE | `/v1/admin/roles/:role/permissions` | **Owner only** — manage role permissions |
568
- | GET/DELETE | `/v1/admin/organizations/:id/api-keys` | Org-scoped API keys |
675
+ | GET/POST | `/v1/admin/roles/:role/permissions` | **Owner only** — list / assign role permissions |
676
+ | DELETE | `/v1/admin/roles/:role/permissions/:permissionId` | **Owner only** — remove a role permission |
677
+ | GET | `/v1/admin/organizations/:id/api-keys` | List org-scoped API keys |
678
+ | DELETE | `/v1/admin/organizations/:id/api-keys/:keyId` | Revoke an org-scoped API key |
569
679
  | GET | `/v1/admin/organizations/:id/audit-logs` | Paginated audit logs |
570
680
  | GET | `/v1/admin/platform/users` | **Owner only** — list all users |
571
681
  | GET | `/v1/admin/platform/organizations` | **Owner only** — list all organizations |
@@ -577,21 +687,31 @@ If Keystone feels slow or uses a lot of memory during development, see [`docs/PE
577
687
  | GET | `/v1/admin/platform/queue/failed` | **Owner only** — failed jobs |
578
688
  | POST | `/v1/admin/platform/queue/failed/:id/retry` | **Owner only** — retry failed job |
579
689
  | POST | `/v1/admin/platform/queue/retry-all` | **Owner only** — retry all failed jobs |
580
- | GET/POST/PATCH/DELETE | `/v1/admin/platform/webhooks` | **Owner only** — webhook management |
690
+ | GET/POST | `/v1/admin/platform/webhooks` | **Owner only** — list / create webhooks |
691
+ | PATCH | `/v1/admin/platform/webhooks/:id` | **Owner only** — update a webhook |
692
+ | DELETE | `/v1/admin/platform/webhooks/:id` | **Owner only** — delete a webhook |
581
693
  | POST | `/v1/admin/platform/webhooks/:id/rotate-secret` | **Owner only** — rotate webhook secret |
582
- | GET/POST/DELETE | `/v1/admin/organizations/:id/saml-connections` | SAML connection management |
694
+ | GET/POST | `/v1/admin/organizations/:id/saml-connections` | SAML connection management |
695
+ | DELETE | `/v1/admin/organizations/:id/saml-connections/:connectionId` | Delete a SAML connection |
583
696
  | GET | `/v1/admin/organizations/:id/saml-connections/:connectionId/metadata` | SAML SP metadata |
584
- | GET/POST/DELETE | `/v1/admin/organizations/:id/oidc-connections` | OIDC connection management |
697
+ | GET/POST | `/v1/admin/organizations/:id/oidc-connections` | OIDC connection management |
698
+ | DELETE | `/v1/admin/organizations/:id/oidc-connections/:connectionId` | Delete an OIDC connection |
585
699
 
586
700
  ### Enterprise SSO
587
701
 
588
702
  | Method | Path | Description |
589
703
  |--------|------|-------------|
590
- | GET | `/saml/:connectionId` | Start SAML SSO login |
591
- | POST | `/saml/acs` | SAML assertion consumer service |
592
- | GET | `/saml/:connectionId/metadata` | SAML SP metadata |
593
- | GET | `/sso/oidc/:connectionId` | Start enterprise OIDC SSO login |
594
- | GET | `/sso/oidc/:connectionId/callback` | Enterprise OIDC callback |
704
+ | GET | `/sso/saml/:connectionId` | Start SAML SSO login (requires `?orgId=`) |
705
+ | POST | `/sso/saml/acs` | SAML assertion consumer service |
706
+ | GET | `/sso/saml/:connectionId/metadata` | SAML SP metadata (requires `?orgId=`) |
707
+ | GET | `/sso/sso/oidc/:connectionId` | Start enterprise OIDC SSO login (requires `?orgId=`) |
708
+ | GET | `/sso/sso/oidc/:connectionId/callback` | Enterprise OIDC callback (requires `?orgId=`) |
709
+
710
+ > **Note:** the doubled `/sso/sso/oidc` segment is real, not a typo. The OIDC
711
+ > enterprise routes declare `/sso/oidc/...` *and* are mounted under the `/sso`
712
+ > prefix. SAML is mounted the same way but declares `/saml/...`, so it resolves
713
+ > cleanly to `/sso/saml/...`. Changing the OIDC path would break existing
714
+ > deployments, so it is scheduled for a future minor release.
595
715
 
596
716
  ### SCIM Provisioning
597
717
 
@@ -609,7 +729,8 @@ that organization. Cross-tenant targets return `404`.
609
729
  | POST | `/scim/v2/Users/.search` | Search users |
610
730
  | GET | `/scim/v2/Groups` | List groups (filter) |
611
731
  | GET | `/scim/v2/Groups/:groupId` | Get group by ID |
612
- | POST/PUT/PATCH/DELETE | `/scim/v2/Groups/:groupId` | Manage groups |
732
+ | POST | `/scim/v2/Groups` | Create group |
733
+ | PUT/PATCH/DELETE | `/scim/v2/Groups/:groupId` | Manage group |
613
734
  | GET/POST | `/scim/v2/Groups/:groupId/members` | Manage group members |
614
735
  | GET | `/scim/v2/ServiceProviderConfig` | Supported features |
615
736
 
@@ -621,29 +742,31 @@ once and stored only as a digest.
621
742
 
622
743
  | Method | Path | Description |
623
744
  |--------|------|-------------|
624
- | POST | `/mfa/verify` | Complete a login MFA challenge and receive tokens |
625
- | POST | `/totp/enroll` | Begin TOTP enrollment |
626
- | POST | `/totp/verify` | Confirm enrollment; revokes existing sessions |
627
- | POST | `/totp/disable` | Disable TOTP MFA |
628
- | POST | `/totp/backup` | Regenerate backup codes (requires a TOTP code) |
629
- | POST | `/totp/backup/verify` | Consume a backup code |
630
- | POST | `/sms-otp/send` | Send SMS OTP |
631
- | POST | `/sms-otp/verify` | Verify SMS OTP |
632
- | POST | `/magic-link/send` | Send magic link |
633
- | GET | `/magic-link/verify` | Verify magic link |
634
- | POST | `/email-verification/send` | Send verification email |
635
- | POST | `/email-verification/request` | Request verification email |
636
- | GET | `/email-verification/verify` | Verify email token |
637
- | POST | `/webauthn/register` | Register WebAuthn credential |
638
- | POST | `/webauthn/authenticate` | Authenticate with WebAuthn |
745
+ | POST | `/auth/mfa/verify` | Complete a login MFA challenge and receive tokens |
746
+ | POST | `/auth/totp/enroll` | Begin TOTP enrollment (requires `password`) |
747
+ | POST | `/auth/totp/verify` | Confirm enrollment (requires `password` + `code`); revokes existing sessions |
748
+ | POST | `/auth/totp/disable` | Disable TOTP MFA (requires `password` + `code`) |
749
+ | POST | `/auth/totp/backup` | Regenerate backup codes (requires `password` + `code`) |
750
+ | POST | `/auth/totp/backup/verify` | Consume a backup code; never establishes a session |
751
+ | POST | `/auth/sms-otp/send` | Send SMS OTP |
752
+ | POST | `/auth/sms-otp/verify` | Verify SMS OTP |
753
+ | POST | `/auth/magic-link/send` | Send magic link |
754
+ | GET | `/auth/magic-link/verify` | Verify magic link |
755
+ | POST | `/auth/email-verification/send` | Send verification email |
756
+ | POST | `/auth/email-verification/request` | Request verification email |
757
+ | GET | `/auth/email-verification/verify` | Verify email token |
758
+ | GET | `/auth/webauthn/register/options` | WebAuthn creation options |
759
+ | POST | `/auth/webauthn/register/verify` | Register a WebAuthn credential |
760
+ | POST | `/auth/webauthn/authenticate/options` | WebAuthn assertion options |
761
+ | POST | `/auth/webauthn/authenticate/verify` | Authenticate and establish a session |
639
762
 
640
763
  ### Sessions
641
764
 
642
765
  | Method | Path | Description |
643
766
  |--------|------|-------------|
644
- | GET | `/sessions` | List active sessions |
645
- | DELETE | `/sessions/:id` | Revoke session |
646
- | POST | `/sessions/revoke-all` | Revoke all sessions |
767
+ | GET | `/auth/sessions` | List active sessions |
768
+ | DELETE | `/auth/sessions/:id` | Revoke session |
769
+ | POST | `/auth/sessions/revoke-all` | Revoke all sessions |
647
770
 
648
771
  ### Workflows
649
772
 
@@ -712,6 +835,12 @@ npx keystone org:create --name "Acme" --owner-email admin@example.com
712
835
  - Internal implementation details are not exposed in API responses.
713
836
  - Input validation uses Zod schemas on all routes.
714
837
  - Error messages are sanitized in production mode.
838
+ - **MFA is enforced before token issuance.** An account with TOTP enabled cannot receive a token until a second factor is verified, and the check happens at a single chokepoint rather than per route.
839
+ - TOTP secrets are stored encrypted with AES-256-GCM; backup codes are stored as a keyed, peppered hash, expire, and can only be consumed once.
840
+ - Changing how an account proves its identity — enrolling, confirming, disabling TOTP, or registering a passkey — requires the account password in addition to a valid session.
841
+ - **SCIM credentials are per organization.** Tokens are stored only as a digest, and every SCIM read and write is scoped to the credential's organization. A cross-tenant target is reported as not found.
842
+ - SCIM deprovisioning never reaches outside the caller's organization, and cannot remove the last owner of an organization.
843
+ - SCIM credential creation, rotation, and revocation are restricted to organization owners.
715
844
 
716
845
  ---
717
846
 
@@ -726,6 +855,8 @@ Full documentation lives in [`docs/`](docs/README.md):
726
855
  | [Deployment](docs/DEPLOYMENT.md) | Docker Compose, Kubernetes, systemd, hardening |
727
856
  | [Integration guide](docs/INTEGRATION.md) | Connect your apps to Keystone |
728
857
  | [Security model](docs/SECURITY.md) | Threat model and hardening checklist |
858
+ | [v1.8 migration guide](docs/MIGRATION-1.8.md) | Mandatory MFA: new endpoints, response changes, upgrade steps |
859
+ | [v1.9 migration guide](docs/MIGRATION-1.9.md) | SCIM tenancy: per-organization credentials, deprovisioning semantics, upgrade steps |
729
860
  | [Performance](docs/PERFORMANCE.md) | Tuning and load-testing notes |
730
861
  | [Contributing](docs/CONTRIBUTING.md) | Dev environment and PR process |
731
862
  | [Roadmap](docs/ROADMAP.md) | Planned work |
package/dist/config.d.ts CHANGED
@@ -54,6 +54,14 @@ export declare const config: {
54
54
  /** Budget for unauthenticated SCIM requests, which run before the credential limiter. */
55
55
  readonly SCIM_AUTH_FAILURE_MAX: number;
56
56
  readonly SCIM_AUTH_FAILURE_WINDOW_SECONDS: number;
57
+ /**
58
+ * Comma-separated IP addresses and CIDR ranges of reverse proxies allowed to
59
+ * set client-identity headers (`x-forwarded-for`, `x-forwarded-client-cert`,
60
+ * ...). Empty means trust nothing: the peer address is used and those headers
61
+ * are stripped. Set this only when Keystone genuinely sits behind a proxy you
62
+ * control — an over-broad value lets any client behind it forge an identity.
63
+ */
64
+ readonly TRUSTED_PROXIES: string;
57
65
  readonly MFA_CHALLENGE_TTL_SECONDS: number;
58
66
  readonly MFA_MAX_ATTEMPTS: number;
59
67
  readonly TOTP_BACKUP_CODE_TTL_SECONDS: number;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AA6DA,eAAO,MAAM,MAAM;aACjB,QAAQ;aACR,IAAI;aACJ,IAAI;aAEJ,YAAY;aACZ,SAAS;aAGT,cAAc;aACd,cAAc;aACd,kBAAkB;aAGlB,yBAAyB;aACzB,6BAA6B;aAC7B,mBAAmB;aAGnB,iBAAiB;aACjB,qBAAqB;aAGrB,qBAAqB;aACrB,qBAAqB;aAErB,WAAW;aACX,aAAa;aACb,aAAa;aACb,gBAAgB,EAAuG,QAAQ,GAAG,KAAK,GAAG,MAAM;aAChJ,2BAA2B;aAE3B,mBAAmB;aACnB,wBAAwB;aACxB,yBAAyB;aAGzB,eAAe;aACf,cAAc;aAGd,uBAAuB;aAGvB,yBAAyB;aAGzB,uBAAuB;aAGvB,gBAAgB;aAGhB,gBAAgB;aAEhB,gBAAgB;aAEhB,gBAAgB;aAEhB,eAAe;aAEf,mBAAmB;aACnB,yBAAyB;aACzB,qBAAqB;aACrB,wBAAwB;aAExB,yBAAyB;aACzB,gCAAgC;aAEhC,kBAAkB;aAIlB,2BAA2B;aAC3B,sBAAsB;aACtB,sBAAsB;aACtB,WAAW;aACX,mBAAmB;aAInB,iBAAiB;aACjB,WAAW;IACX,uDAAuD;aAGvD,2BAA2B;IAC3B,qEAAqE;aACrE,mBAAmB;aACnB,8BAA8B;IAC9B,yFAAyF;aACzF,qBAAqB;aACrB,gCAAgC;aAChC,yBAAyB;aACzB,gBAAgB;aAChB,4BAA4B;aAC5B,cAAc;aACd,UAAU;aACV,SAAS;aACT,SAAS;aACT,SAAS;aACT,SAAS;aACT,WAAW;aACX,gBAAgB;aAChB,eAAe;aACf,cAAc;aACd,YAAY;aACZ,kBAAkB;aAClB,iBAAiB;aACjB,kBAAkB;aAClB,4BAA4B;aAC5B,2BAA2B;aAC3B,iBAAiB;aACjB,oBAAoB;aACpB,sBAAsB;CACd,CAAC;AAEX,wBAAgB,cAAc,IAAI,MAAM,CAMvC;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AA6DA,eAAO,MAAM,MAAM;aACjB,QAAQ;aACR,IAAI;aACJ,IAAI;aAEJ,YAAY;aACZ,SAAS;aAGT,cAAc;aACd,cAAc;aACd,kBAAkB;aAGlB,yBAAyB;aACzB,6BAA6B;aAC7B,mBAAmB;aAGnB,iBAAiB;aACjB,qBAAqB;aAGrB,qBAAqB;aACrB,qBAAqB;aAErB,WAAW;aACX,aAAa;aACb,aAAa;aACb,gBAAgB,EAAuG,QAAQ,GAAG,KAAK,GAAG,MAAM;aAChJ,2BAA2B;aAE3B,mBAAmB;aACnB,wBAAwB;aACxB,yBAAyB;aAGzB,eAAe;aACf,cAAc;aAGd,uBAAuB;aAGvB,yBAAyB;aAGzB,uBAAuB;aAGvB,gBAAgB;aAGhB,gBAAgB;aAEhB,gBAAgB;aAEhB,gBAAgB;aAEhB,eAAe;aAEf,mBAAmB;aACnB,yBAAyB;aACzB,qBAAqB;aACrB,wBAAwB;aAExB,yBAAyB;aACzB,gCAAgC;aAEhC,kBAAkB;aAIlB,2BAA2B;aAC3B,sBAAsB;aACtB,sBAAsB;aACtB,WAAW;aACX,mBAAmB;aAInB,iBAAiB;aACjB,WAAW;IACX,uDAAuD;aAGvD,2BAA2B;IAC3B,qEAAqE;aACrE,mBAAmB;aACnB,8BAA8B;IAC9B,yFAAyF;aACzF,qBAAqB;aACrB,gCAAgC;IAChC;;;;;;OAMG;aACH,eAAe;aACf,yBAAyB;aACzB,gBAAgB;aAChB,4BAA4B;aAC5B,cAAc;aACd,UAAU;aACV,SAAS;aACT,SAAS;aACT,SAAS;aACT,SAAS;aACT,WAAW;aACX,gBAAgB;aAChB,eAAe;aACf,cAAc;aACd,YAAY;aACZ,kBAAkB;aAClB,iBAAiB;aACjB,kBAAkB;aAClB,4BAA4B;aAC5B,2BAA2B;aAC3B,iBAAiB;aACjB,oBAAoB;aACpB,sBAAsB;CACd,CAAC;AAEX,wBAAgB,cAAc,IAAI,MAAM,CAMvC;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C"}
package/dist/config.js CHANGED
@@ -119,6 +119,14 @@ export const config = {
119
119
  /** Budget for unauthenticated SCIM requests, which run before the credential limiter. */
120
120
  SCIM_AUTH_FAILURE_MAX: positiveInt("SCIM_AUTH_FAILURE_MAX", "60"),
121
121
  SCIM_AUTH_FAILURE_WINDOW_SECONDS: positiveInt("SCIM_AUTH_FAILURE_WINDOW_SECONDS", "60"),
122
+ /**
123
+ * Comma-separated IP addresses and CIDR ranges of reverse proxies allowed to
124
+ * set client-identity headers (`x-forwarded-for`, `x-forwarded-client-cert`,
125
+ * ...). Empty means trust nothing: the peer address is used and those headers
126
+ * are stripped. Set this only when Keystone genuinely sits behind a proxy you
127
+ * control — an over-broad value lets any client behind it forge an identity.
128
+ */
129
+ TRUSTED_PROXIES: getEnv("KEYSTONE_TRUSTED_PROXIES"),
122
130
  MFA_CHALLENGE_TTL_SECONDS: positiveInt("MFA_CHALLENGE_TTL_SECONDS", "300"),
123
131
  MFA_MAX_ATTEMPTS: positiveInt("MFA_MAX_ATTEMPTS", "5"),
124
132
  TOTP_BACKUP_CODE_TTL_SECONDS: positiveInt("TOTP_BACKUP_CODE_TTL_SECONDS", "7776000"),
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ DROP INDEX "scim_connections_token_hash_idx";--> statement-breakpoint
2
+ DROP INDEX "scim_connections_previous_token_hash_idx";--> statement-breakpoint
3
+ ALTER TABLE "service_accounts" ADD COLUMN "cert_fingerprint" text;--> statement-breakpoint
4
+ ALTER TABLE "service_accounts" ADD COLUMN "revoked_at" timestamp with time zone;--> statement-breakpoint
5
+ CREATE UNIQUE INDEX "scim_connections_token_hash_unique" ON "scim_connections" USING btree ("token_hash");--> statement-breakpoint
6
+ CREATE UNIQUE INDEX "scim_connections_previous_token_hash_unique" ON "scim_connections" USING btree ("previous_token_hash") WHERE previous_token_hash is not null;--> statement-breakpoint
7
+ CREATE UNIQUE INDEX "service_accounts_cert_fingerprint_unique" ON "service_accounts" USING btree ("cert_fingerprint") WHERE cert_fingerprint is not null;
@@ -0,0 +1,5 @@
1
+ ALTER TABLE "applications" ALTER COLUMN "client_secret_hash" DROP NOT NULL;--> statement-breakpoint
2
+ ALTER TABLE "applications" ADD COLUMN "client_type" text DEFAULT 'confidential' NOT NULL;--> statement-breakpoint
3
+ ALTER TABLE "applications" ADD COLUMN "allowed_scopes" text[] DEFAULT '{}'::text[] NOT NULL;--> statement-breakpoint
4
+ ALTER TABLE "applications" ADD CONSTRAINT "applications_client_type_check" CHECK ("applications"."client_type" in ('confidential', 'public'));--> statement-breakpoint
5
+ ALTER TABLE "applications" ADD CONSTRAINT "applications_public_client_no_secret_check" CHECK (("applications"."client_type" = 'public' and "applications"."client_secret_hash" is null) or "applications"."client_type" <> 'public');
@@ -0,0 +1 @@
1
+ ALTER TABLE "refresh_tokens" ADD COLUMN "scopes" text[] DEFAULT '{}'::text[] NOT NULL;