@portaidentity/server 1.7.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.
- package/CHANGELOG.md +11 -0
- package/LICENSE +21 -0
- package/README.md +33 -0
- package/dist/applications/cache.d.ts +64 -0
- package/dist/applications/cache.d.ts.map +1 -0
- package/dist/applications/cache.js +161 -0
- package/dist/applications/cache.js.map +1 -0
- package/dist/applications/errors.d.ts +25 -0
- package/dist/applications/errors.d.ts.map +1 -0
- package/dist/applications/errors.js +31 -0
- package/dist/applications/errors.js.map +1 -0
- package/dist/applications/index.d.ts +17 -0
- package/dist/applications/index.d.ts.map +1 -0
- package/dist/applications/index.js +19 -0
- package/dist/applications/index.js.map +1 -0
- package/dist/applications/repository.d.ts +184 -0
- package/dist/applications/repository.d.ts.map +1 -0
- package/dist/applications/repository.js +367 -0
- package/dist/applications/repository.js.map +1 -0
- package/dist/applications/service.d.ts +160 -0
- package/dist/applications/service.d.ts.map +1 -0
- package/dist/applications/service.js +388 -0
- package/dist/applications/service.js.map +1 -0
- package/dist/applications/slugs.d.ts +61 -0
- package/dist/applications/slugs.d.ts.map +1 -0
- package/dist/applications/slugs.js +115 -0
- package/dist/applications/slugs.js.map +1 -0
- package/dist/applications/types.d.ts +129 -0
- package/dist/applications/types.d.ts.map +1 -0
- package/dist/applications/types.js +62 -0
- package/dist/applications/types.js.map +1 -0
- package/dist/auth/csrf.d.ts +71 -0
- package/dist/auth/csrf.d.ts.map +1 -0
- package/dist/auth/csrf.js +112 -0
- package/dist/auth/csrf.js.map +1 -0
- package/dist/auth/email-renderer.d.ts +37 -0
- package/dist/auth/email-renderer.d.ts.map +1 -0
- package/dist/auth/email-renderer.js +116 -0
- package/dist/auth/email-renderer.js.map +1 -0
- package/dist/auth/email-service.d.ts +154 -0
- package/dist/auth/email-service.d.ts.map +1 -0
- package/dist/auth/email-service.js +415 -0
- package/dist/auth/email-service.js.map +1 -0
- package/dist/auth/email-transport.d.ts +65 -0
- package/dist/auth/email-transport.d.ts.map +1 -0
- package/dist/auth/email-transport.js +82 -0
- package/dist/auth/email-transport.js.map +1 -0
- package/dist/auth/i18n.d.ts +81 -0
- package/dist/auth/i18n.d.ts.map +1 -0
- package/dist/auth/i18n.js +395 -0
- package/dist/auth/i18n.js.map +1 -0
- package/dist/auth/index.d.ts +28 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +31 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/interaction-authority.d.ts +39 -0
- package/dist/auth/interaction-authority.d.ts.map +1 -0
- package/dist/auth/interaction-authority.js +30 -0
- package/dist/auth/interaction-authority.js.map +1 -0
- package/dist/auth/magic-link-session.d.ts +81 -0
- package/dist/auth/magic-link-session.d.ts.map +1 -0
- package/dist/auth/magic-link-session.js +183 -0
- package/dist/auth/magic-link-session.js.map +1 -0
- package/dist/auth/rate-limiter.d.ts +143 -0
- package/dist/auth/rate-limiter.d.ts.map +1 -0
- package/dist/auth/rate-limiter.js +220 -0
- package/dist/auth/rate-limiter.js.map +1 -0
- package/dist/auth/recovery-crypto.d.ts +34 -0
- package/dist/auth/recovery-crypto.d.ts.map +1 -0
- package/dist/auth/recovery-crypto.js +103 -0
- package/dist/auth/recovery-crypto.js.map +1 -0
- package/dist/auth/recovery-job-processor.d.ts +24 -0
- package/dist/auth/recovery-job-processor.d.ts.map +1 -0
- package/dist/auth/recovery-job-processor.js +123 -0
- package/dist/auth/recovery-job-processor.js.map +1 -0
- package/dist/auth/recovery-job-repository.d.ts +219 -0
- package/dist/auth/recovery-job-repository.d.ts.map +1 -0
- package/dist/auth/recovery-job-repository.js +340 -0
- package/dist/auth/recovery-job-repository.js.map +1 -0
- package/dist/auth/recovery-service.d.ts +27 -0
- package/dist/auth/recovery-service.d.ts.map +1 -0
- package/dist/auth/recovery-service.js +53 -0
- package/dist/auth/recovery-service.js.map +1 -0
- package/dist/auth/recovery-worker.d.ts +158 -0
- package/dist/auth/recovery-worker.d.ts.map +1 -0
- package/dist/auth/recovery-worker.js +306 -0
- package/dist/auth/recovery-worker.js.map +1 -0
- package/dist/auth/template-engine.d.ts +134 -0
- package/dist/auth/template-engine.d.ts.map +1 -0
- package/dist/auth/template-engine.js +225 -0
- package/dist/auth/template-engine.js.map +1 -0
- package/dist/auth/token-repository.d.ts +238 -0
- package/dist/auth/token-repository.d.ts.map +1 -0
- package/dist/auth/token-repository.js +475 -0
- package/dist/auth/token-repository.js.map +1 -0
- package/dist/auth/tokens.d.ts +45 -0
- package/dist/auth/tokens.d.ts.map +1 -0
- package/dist/auth/tokens.js +51 -0
- package/dist/auth/tokens.js.map +1 -0
- package/dist/cli/bootstrap.d.ts +55 -0
- package/dist/cli/bootstrap.d.ts.map +1 -0
- package/dist/cli/bootstrap.js +90 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cli/commands/health.d.ts +20 -0
- package/dist/cli/commands/health.d.ts.map +1 -0
- package/dist/cli/commands/health.js +80 -0
- package/dist/cli/commands/health.js.map +1 -0
- package/dist/cli/commands/init.d.ts +48 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +349 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/migrate.d.ts +19 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -0
- package/dist/cli/commands/migrate.js +88 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/commands/seed.d.ts +19 -0
- package/dist/cli/commands/seed.d.ts.map +1 -0
- package/dist/cli/commands/seed.js +71 -0
- package/dist/cli/commands/seed.js.map +1 -0
- package/dist/cli/commands/user-2fa.d.ts +29 -0
- package/dist/cli/commands/user-2fa.d.ts.map +1 -0
- package/dist/cli/commands/user-2fa.js +113 -0
- package/dist/cli/commands/user-2fa.js.map +1 -0
- package/dist/cli/error-handler.d.ts +31 -0
- package/dist/cli/error-handler.d.ts.map +1 -0
- package/dist/cli/error-handler.js +65 -0
- package/dist/cli/error-handler.js.map +1 -0
- package/dist/cli/index.d.ts +48 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +99 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/output.d.ts +94 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +124 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/prompt.d.ts +48 -0
- package/dist/cli/prompt.d.ts.map +1 -0
- package/dist/cli/prompt.js +96 -0
- package/dist/cli/prompt.js.map +1 -0
- package/dist/clients/cache.d.ts +63 -0
- package/dist/clients/cache.d.ts.map +1 -0
- package/dist/clients/cache.js +160 -0
- package/dist/clients/cache.js.map +1 -0
- package/dist/clients/crypto.d.ts +69 -0
- package/dist/clients/crypto.d.ts.map +1 -0
- package/dist/clients/crypto.js +83 -0
- package/dist/clients/crypto.js.map +1 -0
- package/dist/clients/errors.d.ts +27 -0
- package/dist/clients/errors.d.ts.map +1 -0
- package/dist/clients/errors.js +33 -0
- package/dist/clients/errors.js.map +1 -0
- package/dist/clients/index.d.ts +19 -0
- package/dist/clients/index.d.ts.map +1 -0
- package/dist/clients/index.js +23 -0
- package/dist/clients/index.js.map +1 -0
- package/dist/clients/repository.d.ts +161 -0
- package/dist/clients/repository.d.ts.map +1 -0
- package/dist/clients/repository.js +318 -0
- package/dist/clients/repository.js.map +1 -0
- package/dist/clients/resolve-login-methods.d.ts +74 -0
- package/dist/clients/resolve-login-methods.d.ts.map +1 -0
- package/dist/clients/resolve-login-methods.js +68 -0
- package/dist/clients/resolve-login-methods.js.map +1 -0
- package/dist/clients/secret-repository.d.ts +109 -0
- package/dist/clients/secret-repository.d.ts.map +1 -0
- package/dist/clients/secret-repository.js +166 -0
- package/dist/clients/secret-repository.js.map +1 -0
- package/dist/clients/secret-service.d.ts +87 -0
- package/dist/clients/secret-service.d.ts.map +1 -0
- package/dist/clients/secret-service.js +204 -0
- package/dist/clients/secret-service.js.map +1 -0
- package/dist/clients/service.d.ts +158 -0
- package/dist/clients/service.d.ts.map +1 -0
- package/dist/clients/service.js +523 -0
- package/dist/clients/service.js.map +1 -0
- package/dist/clients/types.d.ts +214 -0
- package/dist/clients/types.d.ts.map +1 -0
- package/dist/clients/types.js +77 -0
- package/dist/clients/types.js.map +1 -0
- package/dist/clients/validators.d.ts +87 -0
- package/dist/clients/validators.d.ts.map +1 -0
- package/dist/clients/validators.js +164 -0
- package/dist/clients/validators.js.map +1 -0
- package/dist/config/index.d.ts +23 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +52 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/schema.d.ts +35 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +167 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/custom-claims/cache.d.ts +48 -0
- package/dist/custom-claims/cache.d.ts.map +1 -0
- package/dist/custom-claims/cache.js +122 -0
- package/dist/custom-claims/cache.js.map +1 -0
- package/dist/custom-claims/errors.d.ts +25 -0
- package/dist/custom-claims/errors.d.ts.map +1 -0
- package/dist/custom-claims/errors.js +31 -0
- package/dist/custom-claims/errors.js.map +1 -0
- package/dist/custom-claims/index.d.ts +14 -0
- package/dist/custom-claims/index.d.ts.map +1 -0
- package/dist/custom-claims/index.js +17 -0
- package/dist/custom-claims/index.js.map +1 -0
- package/dist/custom-claims/repository.d.ts +147 -0
- package/dist/custom-claims/repository.d.ts.map +1 -0
- package/dist/custom-claims/repository.js +338 -0
- package/dist/custom-claims/repository.js.map +1 -0
- package/dist/custom-claims/service.d.ts +129 -0
- package/dist/custom-claims/service.d.ts.map +1 -0
- package/dist/custom-claims/service.js +296 -0
- package/dist/custom-claims/service.js.map +1 -0
- package/dist/custom-claims/types.d.ts +132 -0
- package/dist/custom-claims/types.d.ts.map +1 -0
- package/dist/custom-claims/types.js +61 -0
- package/dist/custom-claims/types.js.map +1 -0
- package/dist/custom-claims/validators.d.ts +61 -0
- package/dist/custom-claims/validators.d.ts.map +1 -0
- package/dist/custom-claims/validators.js +136 -0
- package/dist/custom-claims/validators.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/admin-permissions.d.ts +147 -0
- package/dist/lib/admin-permissions.d.ts.map +1 -0
- package/dist/lib/admin-permissions.js +261 -0
- package/dist/lib/admin-permissions.js.map +1 -0
- package/dist/lib/audit-log.d.ts +45 -0
- package/dist/lib/audit-log.d.ts.map +1 -0
- package/dist/lib/audit-log.js +79 -0
- package/dist/lib/audit-log.js.map +1 -0
- package/dist/lib/branding-assets.d.ts +47 -0
- package/dist/lib/branding-assets.d.ts.map +1 -0
- package/dist/lib/branding-assets.js +93 -0
- package/dist/lib/branding-assets.js.map +1 -0
- package/dist/lib/bulk-operations.d.ts +54 -0
- package/dist/lib/bulk-operations.d.ts.map +1 -0
- package/dist/lib/bulk-operations.js +201 -0
- package/dist/lib/bulk-operations.js.map +1 -0
- package/dist/lib/cursor.d.ts +110 -0
- package/dist/lib/cursor.d.ts.map +1 -0
- package/dist/lib/cursor.js +115 -0
- package/dist/lib/cursor.js.map +1 -0
- package/dist/lib/data-export.d.ts +67 -0
- package/dist/lib/data-export.d.ts.map +1 -0
- package/dist/lib/data-export.js +272 -0
- package/dist/lib/data-export.js.map +1 -0
- package/dist/lib/data-import-plan.d.ts +50 -0
- package/dist/lib/data-import-plan.d.ts.map +1 -0
- package/dist/lib/data-import-plan.js +235 -0
- package/dist/lib/data-import-plan.js.map +1 -0
- package/dist/lib/data-import.d.ts +276 -0
- package/dist/lib/data-import.d.ts.map +1 -0
- package/dist/lib/data-import.js +1694 -0
- package/dist/lib/data-import.js.map +1 -0
- package/dist/lib/database.d.ts +22 -0
- package/dist/lib/database.d.ts.map +1 -0
- package/dist/lib/database.js +103 -0
- package/dist/lib/database.js.map +1 -0
- package/dist/lib/entity-history.d.ts +52 -0
- package/dist/lib/entity-history.d.ts.map +1 -0
- package/dist/lib/entity-history.js +121 -0
- package/dist/lib/entity-history.js.map +1 -0
- package/dist/lib/etag.d.ts +92 -0
- package/dist/lib/etag.d.ts.map +1 -0
- package/dist/lib/etag.js +155 -0
- package/dist/lib/etag.js.map +1 -0
- package/dist/lib/image-validator.d.ts +44 -0
- package/dist/lib/image-validator.d.ts.map +1 -0
- package/dist/lib/image-validator.js +204 -0
- package/dist/lib/image-validator.js.map +1 -0
- package/dist/lib/logger.d.ts +15 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +84 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/migrator.d.ts +14 -0
- package/dist/lib/migrator.d.ts.map +1 -0
- package/dist/lib/migrator.js +34 -0
- package/dist/lib/migrator.js.map +1 -0
- package/dist/lib/redis.d.ts +5 -0
- package/dist/lib/redis.d.ts.map +1 -0
- package/dist/lib/redis.js +29 -0
- package/dist/lib/redis.js.map +1 -0
- package/dist/lib/runtime-paths.d.ts +38 -0
- package/dist/lib/runtime-paths.d.ts.map +1 -0
- package/dist/lib/runtime-paths.js +50 -0
- package/dist/lib/runtime-paths.js.map +1 -0
- package/dist/lib/session-tracking.d.ts +81 -0
- package/dist/lib/session-tracking.d.ts.map +1 -0
- package/dist/lib/session-tracking.js +145 -0
- package/dist/lib/session-tracking.js.map +1 -0
- package/dist/lib/signing-key-crypto.d.ts +53 -0
- package/dist/lib/signing-key-crypto.d.ts.map +1 -0
- package/dist/lib/signing-key-crypto.js +108 -0
- package/dist/lib/signing-key-crypto.js.map +1 -0
- package/dist/lib/signing-keys.d.ts +141 -0
- package/dist/lib/signing-keys.d.ts.map +1 -0
- package/dist/lib/signing-keys.js +206 -0
- package/dist/lib/signing-keys.js.map +1 -0
- package/dist/lib/stats.d.ts +83 -0
- package/dist/lib/stats.d.ts.map +1 -0
- package/dist/lib/stats.js +187 -0
- package/dist/lib/stats.js.map +1 -0
- package/dist/lib/super-admin-protection.d.ts +69 -0
- package/dist/lib/super-admin-protection.d.ts.map +1 -0
- package/dist/lib/super-admin-protection.js +102 -0
- package/dist/lib/super-admin-protection.js.map +1 -0
- package/dist/lib/system-config.d.ts +79 -0
- package/dist/lib/system-config.d.ts.map +1 -0
- package/dist/lib/system-config.js +159 -0
- package/dist/lib/system-config.js.map +1 -0
- package/dist/middleware/admin-auth.d.ts +100 -0
- package/dist/middleware/admin-auth.d.ts.map +1 -0
- package/dist/middleware/admin-auth.js +241 -0
- package/dist/middleware/admin-auth.js.map +1 -0
- package/dist/middleware/admin-cors.d.ts +41 -0
- package/dist/middleware/admin-cors.d.ts.map +1 -0
- package/dist/middleware/admin-cors.js +83 -0
- package/dist/middleware/admin-cors.js.map +1 -0
- package/dist/middleware/admin-mutation-audit.d.ts +9 -0
- package/dist/middleware/admin-mutation-audit.d.ts.map +1 -0
- package/dist/middleware/admin-mutation-audit.js +76 -0
- package/dist/middleware/admin-mutation-audit.js.map +1 -0
- package/dist/middleware/admin-rate-limiter.d.ts +56 -0
- package/dist/middleware/admin-rate-limiter.d.ts.map +1 -0
- package/dist/middleware/admin-rate-limiter.js +97 -0
- package/dist/middleware/admin-rate-limiter.js.map +1 -0
- package/dist/middleware/client-secret-hash.d.ts +34 -0
- package/dist/middleware/client-secret-hash.d.ts.map +1 -0
- package/dist/middleware/client-secret-hash.js +74 -0
- package/dist/middleware/client-secret-hash.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +3 -0
- package/dist/middleware/error-handler.d.ts.map +1 -0
- package/dist/middleware/error-handler.js +93 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/health.d.ts +3 -0
- package/dist/middleware/health.d.ts.map +1 -0
- package/dist/middleware/health.js +35 -0
- package/dist/middleware/health.js.map +1 -0
- package/dist/middleware/metrics.d.ts +40 -0
- package/dist/middleware/metrics.d.ts.map +1 -0
- package/dist/middleware/metrics.js +75 -0
- package/dist/middleware/metrics.js.map +1 -0
- package/dist/middleware/oidc-client-tenant.d.ts +37 -0
- package/dist/middleware/oidc-client-tenant.d.ts.map +1 -0
- package/dist/middleware/oidc-client-tenant.js +156 -0
- package/dist/middleware/oidc-client-tenant.js.map +1 -0
- package/dist/middleware/oidc-cors.d.ts +33 -0
- package/dist/middleware/oidc-cors.d.ts.map +1 -0
- package/dist/middleware/oidc-cors.js +68 -0
- package/dist/middleware/oidc-cors.js.map +1 -0
- package/dist/middleware/oidc-preflight-cors.d.ts +54 -0
- package/dist/middleware/oidc-preflight-cors.d.ts.map +1 -0
- package/dist/middleware/oidc-preflight-cors.js +267 -0
- package/dist/middleware/oidc-preflight-cors.js.map +1 -0
- package/dist/middleware/prompt-login-reset.d.ts +103 -0
- package/dist/middleware/prompt-login-reset.d.ts.map +1 -0
- package/dist/middleware/prompt-login-reset.js +204 -0
- package/dist/middleware/prompt-login-reset.js.map +1 -0
- package/dist/middleware/ready.d.ts +23 -0
- package/dist/middleware/ready.d.ts.map +1 -0
- package/dist/middleware/ready.js +60 -0
- package/dist/middleware/ready.js.map +1 -0
- package/dist/middleware/request-logger.d.ts +27 -0
- package/dist/middleware/request-logger.d.ts.map +1 -0
- package/dist/middleware/request-logger.js +46 -0
- package/dist/middleware/request-logger.js.map +1 -0
- package/dist/middleware/require-permission.d.ts +28 -0
- package/dist/middleware/require-permission.d.ts.map +1 -0
- package/dist/middleware/require-permission.js +63 -0
- package/dist/middleware/require-permission.js.map +1 -0
- package/dist/middleware/require-user-organization.d.ts +18 -0
- package/dist/middleware/require-user-organization.d.ts.map +1 -0
- package/dist/middleware/require-user-organization.js +53 -0
- package/dist/middleware/require-user-organization.js.map +1 -0
- package/dist/middleware/root-page.d.ts +62 -0
- package/dist/middleware/root-page.d.ts.map +1 -0
- package/dist/middleware/root-page.js +134 -0
- package/dist/middleware/root-page.js.map +1 -0
- package/dist/middleware/security-headers.d.ts +98 -0
- package/dist/middleware/security-headers.d.ts.map +1 -0
- package/dist/middleware/security-headers.js +159 -0
- package/dist/middleware/security-headers.js.map +1 -0
- package/dist/middleware/tenant-resolver.d.ts +37 -0
- package/dist/middleware/tenant-resolver.d.ts.map +1 -0
- package/dist/middleware/tenant-resolver.js +71 -0
- package/dist/middleware/tenant-resolver.js.map +1 -0
- package/dist/middleware/token-rate-limiter.d.ts +89 -0
- package/dist/middleware/token-rate-limiter.d.ts.map +1 -0
- package/dist/middleware/token-rate-limiter.js +189 -0
- package/dist/middleware/token-rate-limiter.js.map +1 -0
- package/dist/oidc/account-finder.d.ts +52 -0
- package/dist/oidc/account-finder.d.ts.map +1 -0
- package/dist/oidc/account-finder.js +134 -0
- package/dist/oidc/account-finder.js.map +1 -0
- package/dist/oidc/adapter-factory.d.ts +90 -0
- package/dist/oidc/adapter-factory.d.ts.map +1 -0
- package/dist/oidc/adapter-factory.js +165 -0
- package/dist/oidc/adapter-factory.js.map +1 -0
- package/dist/oidc/configuration.d.ts +155 -0
- package/dist/oidc/configuration.d.ts.map +1 -0
- package/dist/oidc/configuration.js +531 -0
- package/dist/oidc/configuration.js.map +1 -0
- package/dist/oidc/postgres-adapter.d.ts +159 -0
- package/dist/oidc/postgres-adapter.d.ts.map +1 -0
- package/dist/oidc/postgres-adapter.js +222 -0
- package/dist/oidc/postgres-adapter.js.map +1 -0
- package/dist/oidc/protocol-security-observer.d.ts +38 -0
- package/dist/oidc/protocol-security-observer.d.ts.map +1 -0
- package/dist/oidc/protocol-security-observer.js +93 -0
- package/dist/oidc/protocol-security-observer.js.map +1 -0
- package/dist/oidc/provider.d.ts +37 -0
- package/dist/oidc/provider.d.ts.map +1 -0
- package/dist/oidc/provider.js +71 -0
- package/dist/oidc/provider.js.map +1 -0
- package/dist/oidc/redis-adapter.d.ts +140 -0
- package/dist/oidc/redis-adapter.d.ts.map +1 -0
- package/dist/oidc/redis-adapter.js +344 -0
- package/dist/oidc/redis-adapter.js.map +1 -0
- package/dist/organizations/cache.d.ts +60 -0
- package/dist/organizations/cache.d.ts.map +1 -0
- package/dist/organizations/cache.js +157 -0
- package/dist/organizations/cache.js.map +1 -0
- package/dist/organizations/errors.d.ts +25 -0
- package/dist/organizations/errors.d.ts.map +1 -0
- package/dist/organizations/errors.js +31 -0
- package/dist/organizations/errors.js.map +1 -0
- package/dist/organizations/index.d.ts +15 -0
- package/dist/organizations/index.d.ts.map +1 -0
- package/dist/organizations/index.js +15 -0
- package/dist/organizations/index.js.map +1 -0
- package/dist/organizations/repository.d.ts +183 -0
- package/dist/organizations/repository.d.ts.map +1 -0
- package/dist/organizations/repository.js +354 -0
- package/dist/organizations/repository.js.map +1 -0
- package/dist/organizations/service.d.ts +168 -0
- package/dist/organizations/service.d.ts.map +1 -0
- package/dist/organizations/service.js +511 -0
- package/dist/organizations/service.js.map +1 -0
- package/dist/organizations/slugs.d.ts +57 -0
- package/dist/organizations/slugs.d.ts.map +1 -0
- package/dist/organizations/slugs.js +130 -0
- package/dist/organizations/slugs.js.map +1 -0
- package/dist/organizations/types.d.ts +146 -0
- package/dist/organizations/types.d.ts.map +1 -0
- package/dist/organizations/types.js +49 -0
- package/dist/organizations/types.js.map +1 -0
- package/dist/rbac/cache.d.ts +110 -0
- package/dist/rbac/cache.d.ts.map +1 -0
- package/dist/rbac/cache.js +271 -0
- package/dist/rbac/cache.js.map +1 -0
- package/dist/rbac/errors.d.ts +34 -0
- package/dist/rbac/errors.d.ts.map +1 -0
- package/dist/rbac/errors.js +43 -0
- package/dist/rbac/errors.js.map +1 -0
- package/dist/rbac/index.d.ts +17 -0
- package/dist/rbac/index.d.ts.map +1 -0
- package/dist/rbac/index.js +21 -0
- package/dist/rbac/index.js.map +1 -0
- package/dist/rbac/mapping-repository.d.ts +121 -0
- package/dist/rbac/mapping-repository.d.ts.map +1 -0
- package/dist/rbac/mapping-repository.js +224 -0
- package/dist/rbac/mapping-repository.js.map +1 -0
- package/dist/rbac/permission-repository.d.ts +100 -0
- package/dist/rbac/permission-repository.d.ts.map +1 -0
- package/dist/rbac/permission-repository.js +190 -0
- package/dist/rbac/permission-repository.js.map +1 -0
- package/dist/rbac/permission-service.d.ts +85 -0
- package/dist/rbac/permission-service.d.ts.map +1 -0
- package/dist/rbac/permission-service.js +179 -0
- package/dist/rbac/permission-service.js.map +1 -0
- package/dist/rbac/role-repository.d.ts +104 -0
- package/dist/rbac/role-repository.d.ts.map +1 -0
- package/dist/rbac/role-repository.js +202 -0
- package/dist/rbac/role-repository.js.map +1 -0
- package/dist/rbac/role-service.d.ts +111 -0
- package/dist/rbac/role-service.d.ts.map +1 -0
- package/dist/rbac/role-service.js +256 -0
- package/dist/rbac/role-service.js.map +1 -0
- package/dist/rbac/slugs.d.ts +116 -0
- package/dist/rbac/slugs.d.ts.map +1 -0
- package/dist/rbac/slugs.js +178 -0
- package/dist/rbac/slugs.js.map +1 -0
- package/dist/rbac/types.d.ts +187 -0
- package/dist/rbac/types.d.ts.map +1 -0
- package/dist/rbac/types.js +75 -0
- package/dist/rbac/types.js.map +1 -0
- package/dist/rbac/user-role-service.d.ts +101 -0
- package/dist/rbac/user-role-service.d.ts.map +1 -0
- package/dist/rbac/user-role-service.js +166 -0
- package/dist/rbac/user-role-service.js.map +1 -0
- package/dist/routes/applications.d.ts +40 -0
- package/dist/routes/applications.d.ts.map +1 -0
- package/dist/routes/applications.js +284 -0
- package/dist/routes/applications.js.map +1 -0
- package/dist/routes/audit.d.ts +31 -0
- package/dist/routes/audit.d.ts.map +1 -0
- package/dist/routes/audit.js +140 -0
- package/dist/routes/audit.js.map +1 -0
- package/dist/routes/branding.d.ts +17 -0
- package/dist/routes/branding.d.ts.map +1 -0
- package/dist/routes/branding.js +104 -0
- package/dist/routes/branding.js.map +1 -0
- package/dist/routes/bulk.d.ts +37 -0
- package/dist/routes/bulk.d.ts.map +1 -0
- package/dist/routes/bulk.js +94 -0
- package/dist/routes/bulk.js.map +1 -0
- package/dist/routes/clients.d.ts +44 -0
- package/dist/routes/clients.d.ts.map +1 -0
- package/dist/routes/clients.js +353 -0
- package/dist/routes/clients.js.map +1 -0
- package/dist/routes/config.d.ts +35 -0
- package/dist/routes/config.d.ts.map +1 -0
- package/dist/routes/config.js +115 -0
- package/dist/routes/config.js.map +1 -0
- package/dist/routes/custom-claims.d.ts +38 -0
- package/dist/routes/custom-claims.d.ts.map +1 -0
- package/dist/routes/custom-claims.js +208 -0
- package/dist/routes/custom-claims.js.map +1 -0
- package/dist/routes/exports.d.ts +21 -0
- package/dist/routes/exports.d.ts.map +1 -0
- package/dist/routes/exports.js +98 -0
- package/dist/routes/exports.js.map +1 -0
- package/dist/routes/imports.d.ts +18 -0
- package/dist/routes/imports.d.ts.map +1 -0
- package/dist/routes/imports.js +72 -0
- package/dist/routes/imports.js.map +1 -0
- package/dist/routes/interactions.d.ts +111 -0
- package/dist/routes/interactions.d.ts.map +1 -0
- package/dist/routes/interactions.js +1074 -0
- package/dist/routes/interactions.js.map +1 -0
- package/dist/routes/invitation.d.ts +31 -0
- package/dist/routes/invitation.d.ts.map +1 -0
- package/dist/routes/invitation.js +342 -0
- package/dist/routes/invitation.js.map +1 -0
- package/dist/routes/keys.d.ts +28 -0
- package/dist/routes/keys.d.ts.map +1 -0
- package/dist/routes/keys.js +91 -0
- package/dist/routes/keys.js.map +1 -0
- package/dist/routes/magic-link.d.ts +43 -0
- package/dist/routes/magic-link.d.ts.map +1 -0
- package/dist/routes/magic-link.js +264 -0
- package/dist/routes/magic-link.js.map +1 -0
- package/dist/routes/organizations.d.ts +38 -0
- package/dist/routes/organizations.d.ts.map +1 -0
- package/dist/routes/organizations.js +347 -0
- package/dist/routes/organizations.js.map +1 -0
- package/dist/routes/password-reset.d.ts +65 -0
- package/dist/routes/password-reset.d.ts.map +1 -0
- package/dist/routes/password-reset.js +493 -0
- package/dist/routes/password-reset.js.map +1 -0
- package/dist/routes/permissions.d.ts +33 -0
- package/dist/routes/permissions.d.ts.map +1 -0
- package/dist/routes/permissions.js +166 -0
- package/dist/routes/permissions.js.map +1 -0
- package/dist/routes/roles.d.ts +37 -0
- package/dist/routes/roles.d.ts.map +1 -0
- package/dist/routes/roles.js +222 -0
- package/dist/routes/roles.js.map +1 -0
- package/dist/routes/sessions.d.ts +37 -0
- package/dist/routes/sessions.d.ts.map +1 -0
- package/dist/routes/sessions.js +121 -0
- package/dist/routes/sessions.js.map +1 -0
- package/dist/routes/stats.d.ts +28 -0
- package/dist/routes/stats.d.ts.map +1 -0
- package/dist/routes/stats.js +65 -0
- package/dist/routes/stats.js.map +1 -0
- package/dist/routes/two-factor-admin.d.ts +54 -0
- package/dist/routes/two-factor-admin.d.ts.map +1 -0
- package/dist/routes/two-factor-admin.js +344 -0
- package/dist/routes/two-factor-admin.js.map +1 -0
- package/dist/routes/two-factor.d.ts +31 -0
- package/dist/routes/two-factor.d.ts.map +1 -0
- package/dist/routes/two-factor.js +595 -0
- package/dist/routes/two-factor.js.map +1 -0
- package/dist/routes/user-roles.d.ts +33 -0
- package/dist/routes/user-roles.d.ts.map +1 -0
- package/dist/routes/user-roles.js +129 -0
- package/dist/routes/user-roles.js.map +1 -0
- package/dist/routes/users.d.ts +61 -0
- package/dist/routes/users.d.ts.map +1 -0
- package/dist/routes/users.js +868 -0
- package/dist/routes/users.js.map +1 -0
- package/dist/security/decision-context.d.ts +52 -0
- package/dist/security/decision-context.d.ts.map +1 -0
- package/dist/security/decision-context.js +150 -0
- package/dist/security/decision-context.js.map +1 -0
- package/dist/security/decision-event.d.ts +128 -0
- package/dist/security/decision-event.d.ts.map +1 -0
- package/dist/security/decision-event.js +225 -0
- package/dist/security/decision-event.js.map +1 -0
- package/dist/security/transport-decision.d.ts +6 -0
- package/dist/security/transport-decision.d.ts.map +1 -0
- package/dist/security/transport-decision.js +37 -0
- package/dist/security/transport-decision.js.map +1 -0
- package/dist/server.d.ts +50 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +491 -0
- package/dist/server.js.map +1 -0
- package/dist/two-factor/cache.d.ts +47 -0
- package/dist/two-factor/cache.d.ts.map +1 -0
- package/dist/two-factor/cache.js +122 -0
- package/dist/two-factor/cache.js.map +1 -0
- package/dist/two-factor/crypto.d.ts +41 -0
- package/dist/two-factor/crypto.d.ts.map +1 -0
- package/dist/two-factor/crypto.js +94 -0
- package/dist/two-factor/crypto.js.map +1 -0
- package/dist/two-factor/errors.d.ts +82 -0
- package/dist/two-factor/errors.d.ts.map +1 -0
- package/dist/two-factor/errors.js +112 -0
- package/dist/two-factor/errors.js.map +1 -0
- package/dist/two-factor/index.d.ts +18 -0
- package/dist/two-factor/index.d.ts.map +1 -0
- package/dist/two-factor/index.js +25 -0
- package/dist/two-factor/index.js.map +1 -0
- package/dist/two-factor/otp.d.ts +43 -0
- package/dist/two-factor/otp.d.ts.map +1 -0
- package/dist/two-factor/otp.js +57 -0
- package/dist/two-factor/otp.js.map +1 -0
- package/dist/two-factor/recovery.d.ts +45 -0
- package/dist/two-factor/recovery.d.ts.map +1 -0
- package/dist/two-factor/recovery.js +104 -0
- package/dist/two-factor/recovery.js.map +1 -0
- package/dist/two-factor/repository.d.ts +156 -0
- package/dist/two-factor/repository.d.ts.map +1 -0
- package/dist/two-factor/repository.js +251 -0
- package/dist/two-factor/repository.js.map +1 -0
- package/dist/two-factor/service.d.ts +232 -0
- package/dist/two-factor/service.d.ts.map +1 -0
- package/dist/two-factor/service.js +599 -0
- package/dist/two-factor/service.js.map +1 -0
- package/dist/two-factor/totp.d.ts +57 -0
- package/dist/two-factor/totp.d.ts.map +1 -0
- package/dist/two-factor/totp.js +96 -0
- package/dist/two-factor/totp.js.map +1 -0
- package/dist/two-factor/types.d.ts +152 -0
- package/dist/two-factor/types.d.ts.map +1 -0
- package/dist/two-factor/types.js +64 -0
- package/dist/two-factor/types.js.map +1 -0
- package/dist/users/cache.d.ts +49 -0
- package/dist/users/cache.d.ts.map +1 -0
- package/dist/users/cache.js +140 -0
- package/dist/users/cache.js.map +1 -0
- package/dist/users/claims.d.ts +67 -0
- package/dist/users/claims.d.ts.map +1 -0
- package/dist/users/claims.js +104 -0
- package/dist/users/claims.js.map +1 -0
- package/dist/users/errors.d.ts +25 -0
- package/dist/users/errors.d.ts.map +1 -0
- package/dist/users/errors.js +31 -0
- package/dist/users/errors.js.map +1 -0
- package/dist/users/gdpr.d.ts +110 -0
- package/dist/users/gdpr.d.ts.map +1 -0
- package/dist/users/gdpr.js +211 -0
- package/dist/users/gdpr.js.map +1 -0
- package/dist/users/index.d.ts +20 -0
- package/dist/users/index.d.ts.map +1 -0
- package/dist/users/index.js +19 -0
- package/dist/users/index.js.map +1 -0
- package/dist/users/password.d.ts +85 -0
- package/dist/users/password.d.ts.map +1 -0
- package/dist/users/password.js +138 -0
- package/dist/users/password.js.map +1 -0
- package/dist/users/repository.d.ts +263 -0
- package/dist/users/repository.d.ts.map +1 -0
- package/dist/users/repository.js +499 -0
- package/dist/users/repository.js.map +1 -0
- package/dist/users/service.d.ts +299 -0
- package/dist/users/service.d.ts.map +1 -0
- package/dist/users/service.js +698 -0
- package/dist/users/service.js.map +1 -0
- package/dist/users/types.d.ts +220 -0
- package/dist/users/types.d.ts.map +1 -0
- package/dist/users/types.js +77 -0
- package/dist/users/types.js.map +1 -0
- package/locales/default/en/common.json +10 -0
- package/locales/default/en/consent.json +13 -0
- package/locales/default/en/emails.json +17 -0
- package/locales/default/en/errors.json +21 -0
- package/locales/default/en/forgot-password.json +11 -0
- package/locales/default/en/invitation.json +18 -0
- package/locales/default/en/login.json +17 -0
- package/locales/default/en/logout.json +9 -0
- package/locales/default/en/magic-link.json +12 -0
- package/locales/default/en/reset-password.json +16 -0
- package/locales/default/en/two-factor.json +29 -0
- package/migrations/.gitkeep +0 -0
- package/migrations/001_extensions.sql +22 -0
- package/migrations/002_organizations.sql +43 -0
- package/migrations/003_applications.sql +50 -0
- package/migrations/004_clients.sql +74 -0
- package/migrations/005_users.sql +119 -0
- package/migrations/006_roles_permissions.sql +80 -0
- package/migrations/007_custom_claims.sql +55 -0
- package/migrations/008_config.sql +51 -0
- package/migrations/009_audit_log.sql +31 -0
- package/migrations/010_oidc_adapter.sql +34 -0
- package/migrations/011_seed.sql +53 -0
- package/migrations/012_two_factor.sql +88 -0
- package/migrations/013_client_secret_sha256.sql +22 -0
- package/migrations/014_login_methods.sql +34 -0
- package/migrations/015_signing_key_encryption.sql +20 -0
- package/migrations/016_failed_login_count.sql +27 -0
- package/migrations/017_audit_retention.sql +11 -0
- package/migrations/018_admin_api_enhancements.sql +78 -0
- package/migrations/019_invitation_details.sql +27 -0
- package/migrations/020_two_factor_admin_permission.sql +108 -0
- package/migrations/021_auth_recovery_jobs.sql +74 -0
- package/migrations/022_recovery_artifact_ownership.sql +25 -0
- package/migrations/023_magic_link_authority.sql +39 -0
- package/package.json +106 -0
- package/templates/default/emails/invitation.hbs +39 -0
- package/templates/default/emails/invitation.txt.hbs +18 -0
- package/templates/default/emails/magic-link.hbs +30 -0
- package/templates/default/emails/magic-link.txt.hbs +11 -0
- package/templates/default/emails/otp-code.hbs +31 -0
- package/templates/default/emails/otp-code.txt.hbs +15 -0
- package/templates/default/emails/password-changed.hbs +24 -0
- package/templates/default/emails/password-changed.txt.hbs +7 -0
- package/templates/default/emails/password-reset.hbs +30 -0
- package/templates/default/emails/password-reset.txt.hbs +11 -0
- package/templates/default/emails/welcome.hbs +25 -0
- package/templates/default/emails/welcome.txt.hbs +9 -0
- package/templates/default/layouts/main.hbs +49 -0
- package/templates/default/pages/accept-invite.hbs +25 -0
- package/templates/default/pages/consent.hbs +27 -0
- package/templates/default/pages/error.hbs +15 -0
- package/templates/default/pages/forgot-password.hbs +21 -0
- package/templates/default/pages/invite-expired.hbs +6 -0
- package/templates/default/pages/invite-success.hbs +9 -0
- package/templates/default/pages/login.hbs +108 -0
- package/templates/default/pages/logout-success.hbs +5 -0
- package/templates/default/pages/logout.hbs +24 -0
- package/templates/default/pages/magic-link-sent.hbs +10 -0
- package/templates/default/pages/magic-link-success.hbs +17 -0
- package/templates/default/pages/reset-password.hbs +20 -0
- package/templates/default/pages/reset-success.hbs +9 -0
- package/templates/default/pages/two-factor-setup.hbs +65 -0
- package/templates/default/pages/two-factor-verify.hbs +77 -0
- package/templates/default/partials/flash-messages.hbs +10 -0
- package/templates/default/partials/footer.hbs +4 -0
- package/templates/default/partials/header.hbs +8 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin API CORS allow-list middleware.
|
|
3
|
+
*
|
|
4
|
+
* Implements a strict CORS policy for `/api/admin/*` endpoints.
|
|
5
|
+
* By default (empty `adminCorsOrigins` config), **no CORS headers are
|
|
6
|
+
* emitted** — all cross-origin requests are blocked by the browser.
|
|
7
|
+
*
|
|
8
|
+
* When `ADMIN_CORS_ORIGINS` is configured with one or more origin URLs,
|
|
9
|
+
* only those exact origins receive CORS headers. This is intended for
|
|
10
|
+
* operators who deploy a web-based admin dashboard on a different origin.
|
|
11
|
+
*
|
|
12
|
+
* Non-browser clients (CLI, same-origin requests) never send an `Origin`
|
|
13
|
+
* header, so they pass through this middleware untouched.
|
|
14
|
+
*
|
|
15
|
+
* Placement: mount after the admin metadata router and before
|
|
16
|
+
* `setAdminAuthProvider()` — preflight `OPTIONS` requests don't carry
|
|
17
|
+
* an `Authorization` header, so CORS must respond before auth runs.
|
|
18
|
+
*
|
|
19
|
+
* @module middleware/admin-cors
|
|
20
|
+
*/
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Constants — exported for test assertions
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
/** HTTP methods allowed for cross-origin admin API requests. */
|
|
25
|
+
export const CORS_ALLOWED_METHODS = 'GET, POST, PUT, PATCH, DELETE, OPTIONS';
|
|
26
|
+
/** HTTP headers allowed in cross-origin admin API requests. */
|
|
27
|
+
export const CORS_ALLOWED_HEADERS = 'Authorization, Content-Type';
|
|
28
|
+
/** Preflight cache duration in seconds (24 hours). */
|
|
29
|
+
export const CORS_MAX_AGE = '86400';
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Middleware factory
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
/**
|
|
34
|
+
* Create admin CORS middleware with the given application config.
|
|
35
|
+
*
|
|
36
|
+
* Uses a `Set` for O(1) origin lookup. The `Vary: Origin` header is
|
|
37
|
+
* required by the CORS specification when `Access-Control-Allow-Origin`
|
|
38
|
+
* is not the wildcard `*` — it tells caches that the response varies by
|
|
39
|
+
* the request's `Origin` header.
|
|
40
|
+
*
|
|
41
|
+
* @param config - Application config (reads `adminCorsOrigins`)
|
|
42
|
+
* @returns Koa middleware that handles CORS for `/api/admin/*` routes
|
|
43
|
+
*/
|
|
44
|
+
export function adminCors(config) {
|
|
45
|
+
// Pre-compute the Set once at middleware creation time —
|
|
46
|
+
// config doesn't change at runtime.
|
|
47
|
+
const allowedOrigins = new Set(config.adminCorsOrigins);
|
|
48
|
+
return async function adminCorsMiddleware(ctx, next) {
|
|
49
|
+
// Only process requests to admin API paths.
|
|
50
|
+
// Non-admin paths (health, OIDC, interactions, etc.) are unaffected.
|
|
51
|
+
if (!ctx.path.startsWith('/api/admin')) {
|
|
52
|
+
return next();
|
|
53
|
+
}
|
|
54
|
+
const origin = ctx.get('Origin');
|
|
55
|
+
// No Origin header → not a cross-origin request (same-origin browser
|
|
56
|
+
// request, CLI tool, or server-to-server call). Pass through.
|
|
57
|
+
if (!origin) {
|
|
58
|
+
return next();
|
|
59
|
+
}
|
|
60
|
+
// Check if the requesting origin is in the allow-list.
|
|
61
|
+
// Only emit CORS headers when there's an explicit match.
|
|
62
|
+
if (allowedOrigins.size > 0 && allowedOrigins.has(origin)) {
|
|
63
|
+
ctx.set('Access-Control-Allow-Origin', origin);
|
|
64
|
+
ctx.set('Access-Control-Allow-Credentials', 'true');
|
|
65
|
+
ctx.set('Access-Control-Allow-Methods', CORS_ALLOWED_METHODS);
|
|
66
|
+
ctx.set('Access-Control-Allow-Headers', CORS_ALLOWED_HEADERS);
|
|
67
|
+
ctx.set('Access-Control-Max-Age', CORS_MAX_AGE);
|
|
68
|
+
// Vary: Origin is required by CORS spec — responses differ per origin.
|
|
69
|
+
ctx.set('Vary', 'Origin');
|
|
70
|
+
}
|
|
71
|
+
// Handle preflight requests — browsers send OPTIONS before the real
|
|
72
|
+
// request to check CORS policy. Respond with 204 regardless of
|
|
73
|
+
// whether the origin matched: if headers weren't set, the browser
|
|
74
|
+
// sees no CORS permission and blocks the follow-up request.
|
|
75
|
+
if (ctx.method === 'OPTIONS') {
|
|
76
|
+
ctx.status = 204;
|
|
77
|
+
ctx.body = '';
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
return next();
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=admin-cors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-cors.js","sourceRoot":"","sources":["../../src/middleware/admin-cors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,8EAA8E;AAC9E,2CAA2C;AAC3C,8EAA8E;AAE9E,gEAAgE;AAChE,MAAM,CAAC,MAAM,oBAAoB,GAAG,wCAAwC,CAAC;AAE7E,+DAA+D;AAC/D,MAAM,CAAC,MAAM,oBAAoB,GAAG,6BAA6B,CAAC;AAElE,sDAAsD;AACtD,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC;AAEpC,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,SAAS,CAAC,MAAiB;IACzC,yDAAyD;IACzD,oCAAoC;IACpC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAExD,OAAO,KAAK,UAAU,mBAAmB,CAAC,GAAG,EAAE,IAAI;QACjD,4CAA4C;QAC5C,qEAAqE;QACrE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YACvC,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QAED,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEjC,qEAAqE;QACrE,+DAA+D;QAC/D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QAED,uDAAuD;QACvD,yDAAyD;QACzD,IAAI,cAAc,CAAC,IAAI,GAAG,CAAC,IAAI,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1D,GAAG,CAAC,GAAG,CAAC,6BAA6B,EAAE,MAAM,CAAC,CAAC;YAC/C,GAAG,CAAC,GAAG,CAAC,kCAAkC,EAAE,MAAM,CAAC,CAAC;YACpD,GAAG,CAAC,GAAG,CAAC,8BAA8B,EAAE,oBAAoB,CAAC,CAAC;YAC9D,GAAG,CAAC,GAAG,CAAC,8BAA8B,EAAE,oBAAoB,CAAC,CAAC;YAC9D,GAAG,CAAC,GAAG,CAAC,wBAAwB,EAAE,YAAY,CAAC,CAAC;YAChD,uEAAuE;YACvE,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC5B,CAAC;QAED,oEAAoE;QACpE,gEAAgE;QAChE,kEAAkE;QAClE,4DAA4D;QAC5D,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;YACd,OAAO;QACT,CAAC;QAED,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Middleware } from 'koa';
|
|
2
|
+
/**
|
|
3
|
+
* Atomically bind successful administrative mutations to one durable audit row.
|
|
4
|
+
*
|
|
5
|
+
* Bulk and import own specialized transaction/result semantics and are excluded here. Every other
|
|
6
|
+
* state-changing admin request shares one request-local PostgreSQL client across repository calls.
|
|
7
|
+
*/
|
|
8
|
+
export declare function adminMutationAudit(): Middleware;
|
|
9
|
+
//# sourceMappingURL=admin-mutation-audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-mutation-audit.d.ts","sourceRoot":"","sources":["../../src/middleware/admin-mutation-audit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AA2BtC;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,UAAU,CA2C/C"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { writeAuditLogInTransaction } from '../lib/audit-log.js';
|
|
2
|
+
import { getDatabaseTransactionClient, runDatabaseTransaction } from '../lib/database.js';
|
|
3
|
+
import { normalizedRouteTemplate, recordSecurityDecision } from '../security/decision-context.js';
|
|
4
|
+
const MUTATION_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);
|
|
5
|
+
const SELF_MANAGED_MUTATION_PREFIXES = ['/api/admin/bulk', '/api/admin/import'];
|
|
6
|
+
/** Internal signal used to roll back a handled non-success response without replacing its body. */
|
|
7
|
+
class HandledMutationRejection extends Error {
|
|
8
|
+
}
|
|
9
|
+
/** Koa-compatible errors retain their public status after the transaction rolls back. */
|
|
10
|
+
function isPublicHttpError(error) {
|
|
11
|
+
if (!(error instanceof Error))
|
|
12
|
+
return false;
|
|
13
|
+
const status = Reflect.get(error, 'status');
|
|
14
|
+
return typeof status === 'number' && status >= 400 && status < 500;
|
|
15
|
+
}
|
|
16
|
+
/** Return whether a request belongs to the generic administrative mutation transaction. */
|
|
17
|
+
function ownsAdministrativeMutation(method, path) {
|
|
18
|
+
return (MUTATION_METHODS.has(method) &&
|
|
19
|
+
path.startsWith('/api/admin/') &&
|
|
20
|
+
!SELF_MANAGED_MUTATION_PREFIXES.some((prefix) => path.startsWith(prefix)));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Atomically bind successful administrative mutations to one durable audit row.
|
|
24
|
+
*
|
|
25
|
+
* Bulk and import own specialized transaction/result semantics and are excluded here. Every other
|
|
26
|
+
* state-changing admin request shares one request-local PostgreSQL client across repository calls.
|
|
27
|
+
*/
|
|
28
|
+
export function adminMutationAudit() {
|
|
29
|
+
return async (ctx, next) => {
|
|
30
|
+
if (!ownsAdministrativeMutation(ctx.method, ctx.path)) {
|
|
31
|
+
await next();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
await runDatabaseTransaction(async () => {
|
|
36
|
+
await next();
|
|
37
|
+
if (ctx.status >= 400)
|
|
38
|
+
throw new HandledMutationRejection();
|
|
39
|
+
const client = getDatabaseTransactionClient();
|
|
40
|
+
if (!client)
|
|
41
|
+
throw new Error('Administrative mutation transaction is unavailable');
|
|
42
|
+
const actor = ctx.state.adminUser;
|
|
43
|
+
if (!actor)
|
|
44
|
+
throw new Error('Administrative mutation actor is unavailable');
|
|
45
|
+
await writeAuditLogInTransaction(client, {
|
|
46
|
+
organizationId: actor.organizationId,
|
|
47
|
+
actorId: actor.id,
|
|
48
|
+
eventType: 'admin.mutation.committed',
|
|
49
|
+
eventCategory: 'admin',
|
|
50
|
+
metadata: {
|
|
51
|
+
method: ctx.method,
|
|
52
|
+
routeTemplate: normalizedRouteTemplate(ctx),
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (error instanceof HandledMutationRejection)
|
|
59
|
+
return;
|
|
60
|
+
if (isPublicHttpError(error))
|
|
61
|
+
throw error;
|
|
62
|
+
recordSecurityDecision(ctx, {
|
|
63
|
+
decisionPoint: 'handler',
|
|
64
|
+
reasonCode: 'handler-failed',
|
|
65
|
+
outcome: 'error',
|
|
66
|
+
});
|
|
67
|
+
ctx.status = 503;
|
|
68
|
+
ctx.body = {
|
|
69
|
+
error: 'Administrative request could not be completed',
|
|
70
|
+
code: 'admin_mutation_unavailable',
|
|
71
|
+
requestId: ctx.state.requestId,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=admin-mutation-audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-mutation-audit.js","sourceRoot":"","sources":["../../src/middleware/admin-mutation-audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin API rate limiter middleware.
|
|
3
|
+
*
|
|
4
|
+
* Protects state-changing admin endpoints (POST/PUT/PATCH/DELETE on
|
|
5
|
+
* `/api/admin/*`) against brute-force attacks and automated abuse.
|
|
6
|
+
* GET requests are read-only and pass through without rate limiting.
|
|
7
|
+
*
|
|
8
|
+
* Key format: `ratelimit:admin:{ip}` — per-IP only since admin-auth
|
|
9
|
+
* already restricts access to authenticated super-admin users. There
|
|
10
|
+
* is no per-user key because the IP-based counter is sufficient:
|
|
11
|
+
* legitimate admins won't make 60 write requests per minute, and
|
|
12
|
+
* attackers from the same IP are blocked regardless of identity.
|
|
13
|
+
*
|
|
14
|
+
* Limit: 60 requests / 60 seconds (sliding window).
|
|
15
|
+
*
|
|
16
|
+
* Reuses `checkRateLimit()` from `src/auth/rate-limiter.ts` which
|
|
17
|
+
* provides Redis INCR+EXPIRE sliding window and graceful degradation
|
|
18
|
+
* on Redis failure (allows request + logs warning).
|
|
19
|
+
*
|
|
20
|
+
* Placement: mount as global middleware in `src/server.ts` before the
|
|
21
|
+
* admin route routers. The path + method check ensures only write
|
|
22
|
+
* requests to `/api/admin/*` are counted.
|
|
23
|
+
*
|
|
24
|
+
* @module middleware/admin-rate-limiter
|
|
25
|
+
*/
|
|
26
|
+
import type { Middleware } from 'koa';
|
|
27
|
+
import type { RateLimitConfig } from '../auth/rate-limiter.js';
|
|
28
|
+
/** Path prefix for admin API routes. */
|
|
29
|
+
export declare const ADMIN_PATH_PREFIX = "/api/admin/";
|
|
30
|
+
/**
|
|
31
|
+
* HTTP methods that are considered state-changing (write operations).
|
|
32
|
+
* Only these methods are rate-limited; GET/HEAD/OPTIONS pass through.
|
|
33
|
+
*/
|
|
34
|
+
export declare const ADMIN_WRITE_METHODS: Set<string>;
|
|
35
|
+
/**
|
|
36
|
+
* Rate limit configuration for admin API write operations.
|
|
37
|
+
*
|
|
38
|
+
* 60 requests per 60-second window — generous enough for admin
|
|
39
|
+
* workflows (bulk operations, rapid CRUD during setup) while catching
|
|
40
|
+
* automated abuse or runaway scripts.
|
|
41
|
+
*/
|
|
42
|
+
export declare const ADMIN_RATE_LIMIT: RateLimitConfig;
|
|
43
|
+
/**
|
|
44
|
+
* Create the admin API rate limiter middleware.
|
|
45
|
+
*
|
|
46
|
+
* Only intercepts requests that match ALL of:
|
|
47
|
+
* - Path starts with `/api/admin/`
|
|
48
|
+
* - Method is POST, PUT, PATCH, or DELETE
|
|
49
|
+
*
|
|
50
|
+
* Sets informational `X-RateLimit-*` headers on every matched response
|
|
51
|
+
* and returns `429` with a JSON error body when the limit is exceeded.
|
|
52
|
+
*
|
|
53
|
+
* @returns Koa middleware that rate-limits admin API write operations
|
|
54
|
+
*/
|
|
55
|
+
export declare function adminRateLimiter(): Middleware;
|
|
56
|
+
//# sourceMappingURL=admin-rate-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-rate-limiter.d.ts","sourceRoot":"","sources":["../../src/middleware/admin-rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAEtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAO/D,wCAAwC;AACxC,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAE/C;;;GAGG;AACH,eAAO,MAAM,mBAAmB,aAA8C,CAAC;AAE/E;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAG9B,CAAC;AAMF;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,IAAI,UAAU,CAyC7C"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin API rate limiter middleware.
|
|
3
|
+
*
|
|
4
|
+
* Protects state-changing admin endpoints (POST/PUT/PATCH/DELETE on
|
|
5
|
+
* `/api/admin/*`) against brute-force attacks and automated abuse.
|
|
6
|
+
* GET requests are read-only and pass through without rate limiting.
|
|
7
|
+
*
|
|
8
|
+
* Key format: `ratelimit:admin:{ip}` — per-IP only since admin-auth
|
|
9
|
+
* already restricts access to authenticated super-admin users. There
|
|
10
|
+
* is no per-user key because the IP-based counter is sufficient:
|
|
11
|
+
* legitimate admins won't make 60 write requests per minute, and
|
|
12
|
+
* attackers from the same IP are blocked regardless of identity.
|
|
13
|
+
*
|
|
14
|
+
* Limit: 60 requests / 60 seconds (sliding window).
|
|
15
|
+
*
|
|
16
|
+
* Reuses `checkRateLimit()` from `src/auth/rate-limiter.ts` which
|
|
17
|
+
* provides Redis INCR+EXPIRE sliding window and graceful degradation
|
|
18
|
+
* on Redis failure (allows request + logs warning).
|
|
19
|
+
*
|
|
20
|
+
* Placement: mount as global middleware in `src/server.ts` before the
|
|
21
|
+
* admin route routers. The path + method check ensures only write
|
|
22
|
+
* requests to `/api/admin/*` are counted.
|
|
23
|
+
*
|
|
24
|
+
* @module middleware/admin-rate-limiter
|
|
25
|
+
*/
|
|
26
|
+
import { checkRateLimit } from '../auth/rate-limiter.js';
|
|
27
|
+
import { logger } from '../lib/logger.js';
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Constants — exported for test assertions and documentation
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
/** Path prefix for admin API routes. */
|
|
32
|
+
export const ADMIN_PATH_PREFIX = '/api/admin/';
|
|
33
|
+
/**
|
|
34
|
+
* HTTP methods that are considered state-changing (write operations).
|
|
35
|
+
* Only these methods are rate-limited; GET/HEAD/OPTIONS pass through.
|
|
36
|
+
*/
|
|
37
|
+
export const ADMIN_WRITE_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);
|
|
38
|
+
/**
|
|
39
|
+
* Rate limit configuration for admin API write operations.
|
|
40
|
+
*
|
|
41
|
+
* 60 requests per 60-second window — generous enough for admin
|
|
42
|
+
* workflows (bulk operations, rapid CRUD during setup) while catching
|
|
43
|
+
* automated abuse or runaway scripts.
|
|
44
|
+
*/
|
|
45
|
+
export const ADMIN_RATE_LIMIT = {
|
|
46
|
+
max: 60,
|
|
47
|
+
windowSeconds: 60,
|
|
48
|
+
};
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Middleware factory
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
/**
|
|
53
|
+
* Create the admin API rate limiter middleware.
|
|
54
|
+
*
|
|
55
|
+
* Only intercepts requests that match ALL of:
|
|
56
|
+
* - Path starts with `/api/admin/`
|
|
57
|
+
* - Method is POST, PUT, PATCH, or DELETE
|
|
58
|
+
*
|
|
59
|
+
* Sets informational `X-RateLimit-*` headers on every matched response
|
|
60
|
+
* and returns `429` with a JSON error body when the limit is exceeded.
|
|
61
|
+
*
|
|
62
|
+
* @returns Koa middleware that rate-limits admin API write operations
|
|
63
|
+
*/
|
|
64
|
+
export function adminRateLimiter() {
|
|
65
|
+
return async function adminRateLimiterMiddleware(ctx, next) {
|
|
66
|
+
// Only rate-limit write methods on admin API paths — GETs and
|
|
67
|
+
// non-admin paths pass through immediately without touching Redis.
|
|
68
|
+
if (!ctx.path.startsWith(ADMIN_PATH_PREFIX) || !ADMIN_WRITE_METHODS.has(ctx.method)) {
|
|
69
|
+
return next();
|
|
70
|
+
}
|
|
71
|
+
// Per-IP key — no user identifier needed since admin-auth already
|
|
72
|
+
// filters out unauthenticated requests, and legitimate admins
|
|
73
|
+
// won't hit 60 writes/minute under normal conditions.
|
|
74
|
+
const key = `ratelimit:admin:${ctx.ip}`;
|
|
75
|
+
const result = await checkRateLimit(key, ADMIN_RATE_LIMIT);
|
|
76
|
+
// Informational headers on all matched responses — helps admin
|
|
77
|
+
// clients (CLI, dashboards) monitor their usage.
|
|
78
|
+
ctx.set('X-RateLimit-Limit', String(ADMIN_RATE_LIMIT.max));
|
|
79
|
+
ctx.set('X-RateLimit-Remaining', String(result.remaining));
|
|
80
|
+
if (!result.allowed) {
|
|
81
|
+
logger.warn({
|
|
82
|
+
action: 'admin_rate_limit_exceeded',
|
|
83
|
+
method: ctx.method,
|
|
84
|
+
}, 'Admin API rate limit exceeded');
|
|
85
|
+
ctx.status = 429;
|
|
86
|
+
ctx.set('Retry-After', String(result.retryAfter));
|
|
87
|
+
ctx.body = {
|
|
88
|
+
error: 'Too Many Requests',
|
|
89
|
+
message: 'Admin API rate limit exceeded. Please try again later.',
|
|
90
|
+
retry_after: result.retryAfter,
|
|
91
|
+
};
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
return next();
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=admin-rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-rate-limiter.js","sourceRoot":"","sources":["../../src/middleware/admin-rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,8EAA8E;AAC9E,6DAA6D;AAC7D,8EAA8E;AAE9E,wCAAwC;AACxC,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAE/C;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AAE/E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAoB;IAC/C,GAAG,EAAE,EAAE;IACP,aAAa,EAAE,EAAE;CAClB,CAAC;AAEF,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,KAAK,UAAU,0BAA0B,CAAC,GAAG,EAAE,IAAI;QACxD,8DAA8D;QAC9D,mEAAmE;QACnE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACpF,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QAED,kEAAkE;QAClE,8DAA8D;QAC9D,sDAAsD;QACtD,MAAM,GAAG,GAAG,mBAAmB,GAAG,CAAC,EAAE,EAAE,CAAC;QAExC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;QAE3D,+DAA+D;QAC/D,iDAAiD;QACjD,GAAG,CAAC,GAAG,CAAC,mBAAmB,EAAE,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,uBAAuB,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QAE3D,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,CACT;gBACE,MAAM,EAAE,2BAA2B;gBACnC,MAAM,EAAE,GAAG,CAAC,MAAM;aACnB,EACD,+BAA+B,CAChC,CAAC;YAEF,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;YAClD,GAAG,CAAC,IAAI,GAAG;gBACT,KAAK,EAAE,mBAAmB;gBAC1B,OAAO,EAAE,wDAAwD;gBACjE,WAAW,EAAE,MAAM,CAAC,UAAU;aAC/B,CAAC;YACF,OAAO;QACT,CAAC;QAED,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SHA-256 client secret pre-hashing middleware.
|
|
3
|
+
*
|
|
4
|
+
* Transforms client_secret values in incoming requests by replacing
|
|
5
|
+
* the plaintext with its SHA-256 hash BEFORE oidc-provider processes them.
|
|
6
|
+
*
|
|
7
|
+
* Supports:
|
|
8
|
+
* - client_secret_basic: Authorization: Basic base64(client_id:secret)
|
|
9
|
+
* - client_secret_post: client_secret in POST body
|
|
10
|
+
*
|
|
11
|
+
* This allows oidc-provider's built-in string comparison to work
|
|
12
|
+
* with our SHA-256-hashed secret storage — no monkey-patching needed.
|
|
13
|
+
*
|
|
14
|
+
* How it works:
|
|
15
|
+
* 1. At secret generation: SHA-256(secret) is stored in the DB
|
|
16
|
+
* 2. At request time: This middleware hashes the presented secret
|
|
17
|
+
* 3. In the adapter: findForOidc() returns SHA-256 hash as client_secret
|
|
18
|
+
* 4. oidc-provider compares: SHA-256(presented) === SHA-256(stored) → ✅ MATCH
|
|
19
|
+
*
|
|
20
|
+
* Security: SHA-256 is appropriate for machine-generated, high-entropy
|
|
21
|
+
* client secrets (48 bytes / 384 bits of randomness).
|
|
22
|
+
*/
|
|
23
|
+
import type { Middleware } from 'koa';
|
|
24
|
+
/**
|
|
25
|
+
* Create middleware that pre-hashes client secrets with SHA-256.
|
|
26
|
+
*
|
|
27
|
+
* Must be mounted BEFORE oidc-provider's callback handler on the
|
|
28
|
+
* OIDC router. Transparently transforms secrets so oidc-provider
|
|
29
|
+
* can compare them against stored SHA-256 hashes.
|
|
30
|
+
*
|
|
31
|
+
* @returns Koa middleware function
|
|
32
|
+
*/
|
|
33
|
+
export declare function clientSecretHash(): Middleware;
|
|
34
|
+
//# sourceMappingURL=client-secret-hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-secret-hash.d.ts","sourceRoot":"","sources":["../../src/middleware/client-secret-hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAStC;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,IAAI,UAAU,CAqC7C"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SHA-256 client secret pre-hashing middleware.
|
|
3
|
+
*
|
|
4
|
+
* Transforms client_secret values in incoming requests by replacing
|
|
5
|
+
* the plaintext with its SHA-256 hash BEFORE oidc-provider processes them.
|
|
6
|
+
*
|
|
7
|
+
* Supports:
|
|
8
|
+
* - client_secret_basic: Authorization: Basic base64(client_id:secret)
|
|
9
|
+
* - client_secret_post: client_secret in POST body
|
|
10
|
+
*
|
|
11
|
+
* This allows oidc-provider's built-in string comparison to work
|
|
12
|
+
* with our SHA-256-hashed secret storage — no monkey-patching needed.
|
|
13
|
+
*
|
|
14
|
+
* How it works:
|
|
15
|
+
* 1. At secret generation: SHA-256(secret) is stored in the DB
|
|
16
|
+
* 2. At request time: This middleware hashes the presented secret
|
|
17
|
+
* 3. In the adapter: findForOidc() returns SHA-256 hash as client_secret
|
|
18
|
+
* 4. oidc-provider compares: SHA-256(presented) === SHA-256(stored) → ✅ MATCH
|
|
19
|
+
*
|
|
20
|
+
* Security: SHA-256 is appropriate for machine-generated, high-entropy
|
|
21
|
+
* client secrets (48 bytes / 384 bits of randomness).
|
|
22
|
+
*/
|
|
23
|
+
import { createHash } from 'node:crypto';
|
|
24
|
+
/**
|
|
25
|
+
* Compute SHA-256 hash of a string, returned as hex.
|
|
26
|
+
*/
|
|
27
|
+
function sha256(input) {
|
|
28
|
+
return createHash('sha256').update(input).digest('hex');
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Create middleware that pre-hashes client secrets with SHA-256.
|
|
32
|
+
*
|
|
33
|
+
* Must be mounted BEFORE oidc-provider's callback handler on the
|
|
34
|
+
* OIDC router. Transparently transforms secrets so oidc-provider
|
|
35
|
+
* can compare them against stored SHA-256 hashes.
|
|
36
|
+
*
|
|
37
|
+
* @returns Koa middleware function
|
|
38
|
+
*/
|
|
39
|
+
export function clientSecretHash() {
|
|
40
|
+
return async (ctx, next) => {
|
|
41
|
+
// Handle client_secret_basic: Authorization: Basic base64(client_id:secret)
|
|
42
|
+
const authHeader = ctx.headers.authorization;
|
|
43
|
+
if (authHeader && authHeader.startsWith('Basic ')) {
|
|
44
|
+
try {
|
|
45
|
+
const encoded = authHeader.slice(6); // strip 'Basic '
|
|
46
|
+
const decoded = Buffer.from(encoded, 'base64').toString('utf8');
|
|
47
|
+
const colonIndex = decoded.indexOf(':');
|
|
48
|
+
if (colonIndex !== -1) {
|
|
49
|
+
const clientId = decoded.slice(0, colonIndex);
|
|
50
|
+
const secret = decoded.slice(colonIndex + 1);
|
|
51
|
+
if (secret.length > 0) {
|
|
52
|
+
// Hash the secret and re-encode the Basic auth header
|
|
53
|
+
const hashedSecret = sha256(secret);
|
|
54
|
+
const newEncoded = Buffer.from(`${clientId}:${hashedSecret}`).toString('base64');
|
|
55
|
+
ctx.headers.authorization = `Basic ${newEncoded}`;
|
|
56
|
+
// Also update the raw request header for oidc-provider
|
|
57
|
+
ctx.req.headers.authorization = `Basic ${newEncoded}`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Malformed Basic auth — let oidc-provider handle the error
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Handle client_secret_post: client_secret in POST body
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
67
|
+
const body = ctx.request.body;
|
|
68
|
+
if (body && typeof body.client_secret === 'string' && body.client_secret.length > 0) {
|
|
69
|
+
body.client_secret = sha256(body.client_secret);
|
|
70
|
+
}
|
|
71
|
+
await next();
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=client-secret-hash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-secret-hash.js","sourceRoot":"","sources":["../../src/middleware/client-secret-hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC;;GAEG;AACH,SAAS,MAAM,CAAC,KAAa;IAC3B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,4EAA4E;QAC5E,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;QAC7C,IAAI,UAAU,IAAI,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClD,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB;gBACtD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAChE,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAExC,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;oBACtB,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;oBAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;oBAE7C,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACtB,sDAAsD;wBACtD,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;wBACpC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,IAAI,YAAY,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;wBACjF,GAAG,CAAC,OAAO,CAAC,aAAa,GAAG,SAAS,UAAU,EAAE,CAAC;wBAClD,uDAAuD;wBACvD,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,GAAG,SAAS,UAAU,EAAE,CAAC;oBACxD,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,4DAA4D;YAC9D,CAAC;QACH,CAAC;QAED,wDAAwD;QACxD,8DAA8D;QAC9D,MAAM,IAAI,GAAI,GAAG,CAAC,OAAe,CAAC,IAAI,CAAC;QACvC,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpF,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAClD,CAAC;QAED,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAItC,wBAAgB,YAAY,IAAI,UAAU,CAsEzC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { logger } from '../lib/logger.js';
|
|
2
|
+
import { recordSecurityDecision } from '../security/decision-context.js';
|
|
3
|
+
export function errorHandler() {
|
|
4
|
+
return async (ctx, next) => {
|
|
5
|
+
try {
|
|
6
|
+
await next();
|
|
7
|
+
}
|
|
8
|
+
catch (err) {
|
|
9
|
+
const error = err;
|
|
10
|
+
ctx.status = error.status || 500;
|
|
11
|
+
ctx.body = {
|
|
12
|
+
error: publicErrorMessage(ctx.status),
|
|
13
|
+
status: ctx.status,
|
|
14
|
+
};
|
|
15
|
+
if (ctx.status === 401) {
|
|
16
|
+
recordSecurityDecision(ctx, {
|
|
17
|
+
decisionPoint: 'authentication',
|
|
18
|
+
reasonCode: 'authentication-required',
|
|
19
|
+
outcome: 'deny',
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
else if (ctx.status === 403) {
|
|
23
|
+
recordSecurityDecision(ctx, {
|
|
24
|
+
decisionPoint: 'permission',
|
|
25
|
+
reasonCode: 'permission-required',
|
|
26
|
+
outcome: 'deny',
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
else if (ctx.status === 413) {
|
|
30
|
+
recordSecurityDecision(ctx, {
|
|
31
|
+
decisionPoint: 'validation',
|
|
32
|
+
reasonCode: 'body-too-large',
|
|
33
|
+
outcome: 'deny',
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
else if (ctx.status === 400) {
|
|
37
|
+
recordSecurityDecision(ctx, {
|
|
38
|
+
decisionPoint: 'validation',
|
|
39
|
+
reasonCode: 'malformed-body',
|
|
40
|
+
outcome: 'deny',
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
else if (ctx.status === 404) {
|
|
44
|
+
recordSecurityDecision(ctx, {
|
|
45
|
+
decisionPoint: 'resource',
|
|
46
|
+
reasonCode: 'resource-not-found',
|
|
47
|
+
outcome: 'deny',
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
else if (ctx.status === 405) {
|
|
51
|
+
recordSecurityDecision(ctx, {
|
|
52
|
+
decisionPoint: 'validation',
|
|
53
|
+
reasonCode: 'method-not-allowed',
|
|
54
|
+
outcome: 'deny',
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
else if (ctx.status < 500) {
|
|
58
|
+
recordSecurityDecision(ctx, {
|
|
59
|
+
decisionPoint: 'validation',
|
|
60
|
+
reasonCode: 'schema-invalid',
|
|
61
|
+
outcome: 'deny',
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
recordSecurityDecision(ctx, {
|
|
66
|
+
decisionPoint: 'handler',
|
|
67
|
+
reasonCode: 'handler-failed',
|
|
68
|
+
outcome: 'error',
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (ctx.status >= 500) {
|
|
72
|
+
logger.error({ event: 'request-handler-failed', requestId: ctx.state.requestId }, 'Request handler failed');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** Return one minimal public error label without exposing a thrown diagnostic. */
|
|
78
|
+
function publicErrorMessage(status) {
|
|
79
|
+
if (status === 400)
|
|
80
|
+
return 'Bad Request';
|
|
81
|
+
if (status === 401)
|
|
82
|
+
return 'Unauthorized';
|
|
83
|
+
if (status === 403)
|
|
84
|
+
return 'Forbidden';
|
|
85
|
+
if (status === 404)
|
|
86
|
+
return 'Not Found';
|
|
87
|
+
if (status === 405)
|
|
88
|
+
return 'Method Not Allowed';
|
|
89
|
+
if (status === 413)
|
|
90
|
+
return 'Payload Too Large';
|
|
91
|
+
return status < 500 ? 'Request Rejected' : 'Internal Server Error';
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=error-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,MAAM,UAAU,YAAY;IAC1B,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,IAAI,CAAC;YACH,MAAM,IAAI,EAAE,CAAC;QACf,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,GAAoD,CAAC;YACnE,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC;YACjC,GAAG,CAAC,IAAI,GAAG;gBACT,KAAK,EAAE,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC;gBACrC,MAAM,EAAE,GAAG,CAAC,MAAM;aACnB,CAAC;YAEF,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACvB,sBAAsB,CAAC,GAAG,EAAE;oBAC1B,aAAa,EAAE,gBAAgB;oBAC/B,UAAU,EAAE,yBAAyB;oBACrC,OAAO,EAAE,MAAM;iBAChB,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC9B,sBAAsB,CAAC,GAAG,EAAE;oBAC1B,aAAa,EAAE,YAAY;oBAC3B,UAAU,EAAE,qBAAqB;oBACjC,OAAO,EAAE,MAAM;iBAChB,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC9B,sBAAsB,CAAC,GAAG,EAAE;oBAC1B,aAAa,EAAE,YAAY;oBAC3B,UAAU,EAAE,gBAAgB;oBAC5B,OAAO,EAAE,MAAM;iBAChB,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC9B,sBAAsB,CAAC,GAAG,EAAE;oBAC1B,aAAa,EAAE,YAAY;oBAC3B,UAAU,EAAE,gBAAgB;oBAC5B,OAAO,EAAE,MAAM;iBAChB,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC9B,sBAAsB,CAAC,GAAG,EAAE;oBAC1B,aAAa,EAAE,UAAU;oBACzB,UAAU,EAAE,oBAAoB;oBAChC,OAAO,EAAE,MAAM;iBAChB,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC9B,sBAAsB,CAAC,GAAG,EAAE;oBAC1B,aAAa,EAAE,YAAY;oBAC3B,UAAU,EAAE,oBAAoB;oBAChC,OAAO,EAAE,MAAM;iBAChB,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBAC5B,sBAAsB,CAAC,GAAG,EAAE;oBAC1B,aAAa,EAAE,YAAY;oBAC3B,UAAU,EAAE,gBAAgB;oBAC5B,OAAO,EAAE,MAAM;iBAChB,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,sBAAsB,CAAC,GAAG,EAAE;oBAC1B,aAAa,EAAE,SAAS;oBACxB,UAAU,EAAE,gBAAgB;oBAC5B,OAAO,EAAE,OAAO;iBACjB,CAAC,CAAC;YACL,CAAC;YAED,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;gBACtB,MAAM,CAAC,KAAK,CACV,EAAE,KAAK,EAAE,wBAAwB,EAAE,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,EACnE,wBAAwB,CACzB,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,kFAAkF;AAClF,SAAS,kBAAkB,CAAC,MAAc;IACxC,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,aAAa,CAAC;IACzC,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,cAAc,CAAC;IAC1C,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,WAAW,CAAC;IACvC,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,WAAW,CAAC;IACvC,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,oBAAoB,CAAC;IAChD,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,mBAAmB,CAAC;IAC/C,OAAO,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,uBAAuB,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/middleware/health.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAItC,wBAAgB,WAAW,IAAI,UAAU,CAgCxC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { getPool } from '../lib/database.js';
|
|
2
|
+
import { getRedis } from '../lib/redis.js';
|
|
3
|
+
export function healthCheck() {
|
|
4
|
+
return async (ctx) => {
|
|
5
|
+
const checks = { server: 'ok' };
|
|
6
|
+
let healthy = true;
|
|
7
|
+
// Check PostgreSQL
|
|
8
|
+
try {
|
|
9
|
+
const pool = getPool();
|
|
10
|
+
await pool.query('SELECT 1');
|
|
11
|
+
checks.database = 'ok';
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
checks.database = 'error';
|
|
15
|
+
healthy = false;
|
|
16
|
+
}
|
|
17
|
+
// Check Redis
|
|
18
|
+
try {
|
|
19
|
+
const redis = getRedis();
|
|
20
|
+
await redis.ping();
|
|
21
|
+
checks.redis = 'ok';
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
checks.redis = 'error';
|
|
25
|
+
healthy = false;
|
|
26
|
+
}
|
|
27
|
+
ctx.status = healthy ? 200 : 503;
|
|
28
|
+
ctx.body = {
|
|
29
|
+
status: healthy ? 'healthy' : 'unhealthy',
|
|
30
|
+
checks,
|
|
31
|
+
timestamp: new Date().toISOString(),
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/middleware/health.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,MAAM,UAAU,WAAW;IACzB,OAAO,KAAK,EAAE,GAAG,EAAE,EAAE;QACnB,MAAM,MAAM,GAA2B,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QACxD,IAAI,OAAO,GAAG,IAAI,CAAC;QAEnB,mBAAmB;QACnB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;YACvB,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC7B,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC;YAC1B,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC;QAED,cAAc;QACd,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;YACzB,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC;YACvB,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC;QAED,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QACjC,GAAG,CAAC,IAAI,GAAG;YACT,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW;YACzC,MAAM;YACN,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|