@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,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret repository — PostgreSQL data access for client_secrets table.
|
|
3
|
+
*
|
|
4
|
+
* Manages the storage of hashed client secrets. The plaintext secret
|
|
5
|
+
* is NEVER stored — only the Argon2id hash. The secret_hash field
|
|
6
|
+
* is only accessible here in the repository layer; the mapRowToClientSecret
|
|
7
|
+
* function intentionally excludes it from the domain model.
|
|
8
|
+
*
|
|
9
|
+
* Key operations:
|
|
10
|
+
* - Insert hashed secret
|
|
11
|
+
* - List secrets (metadata only, no hashes)
|
|
12
|
+
* - Find active secrets with hashes (for verification only)
|
|
13
|
+
* - Revoke secrets
|
|
14
|
+
* - Update last_used_at timestamp
|
|
15
|
+
* - Cleanup expired secrets
|
|
16
|
+
*/
|
|
17
|
+
import { getPool } from '../lib/database.js';
|
|
18
|
+
import { mapRowToClientSecret } from './types.js';
|
|
19
|
+
/**
|
|
20
|
+
* Insert a new client secret.
|
|
21
|
+
*
|
|
22
|
+
* Stores the Argon2id hash — never the plaintext.
|
|
23
|
+
*
|
|
24
|
+
* @param data - Secret data including the hash
|
|
25
|
+
* @returns The created secret metadata (without hash)
|
|
26
|
+
*/
|
|
27
|
+
export async function insertSecret(data) {
|
|
28
|
+
const pool = getPool();
|
|
29
|
+
const result = await pool.query(`INSERT INTO client_secrets (client_id, secret_hash, secret_sha256, label, expires_at)
|
|
30
|
+
VALUES ($1, $2, $3, $4, $5)
|
|
31
|
+
RETURNING *`, [data.clientId, data.secretHash, data.secretSha256, data.label, data.expiresAt]);
|
|
32
|
+
return mapRowToClientSecret(result.rows[0]);
|
|
33
|
+
}
|
|
34
|
+
// ===========================================================================
|
|
35
|
+
// Find / List
|
|
36
|
+
// ===========================================================================
|
|
37
|
+
/**
|
|
38
|
+
* List all secrets for a client (metadata only, no hashes).
|
|
39
|
+
*
|
|
40
|
+
* @param clientId - Client internal UUID
|
|
41
|
+
* @returns Array of secret metadata
|
|
42
|
+
*/
|
|
43
|
+
export async function listSecretsByClient(clientId) {
|
|
44
|
+
const pool = getPool();
|
|
45
|
+
const result = await pool.query(`SELECT * FROM client_secrets WHERE client_id = $1 ORDER BY created_at DESC`, [clientId]);
|
|
46
|
+
return result.rows.map(mapRowToClientSecret);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Find a specific secret by ID.
|
|
50
|
+
*
|
|
51
|
+
* @param id - Secret UUID
|
|
52
|
+
* @returns Secret metadata or null
|
|
53
|
+
*/
|
|
54
|
+
export async function findSecretById(id) {
|
|
55
|
+
const pool = getPool();
|
|
56
|
+
const result = await pool.query('SELECT * FROM client_secrets WHERE id = $1', [id]);
|
|
57
|
+
if (result.rows.length === 0)
|
|
58
|
+
return null;
|
|
59
|
+
return mapRowToClientSecret(result.rows[0]);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get active secret hashes for verification.
|
|
63
|
+
*
|
|
64
|
+
* This is the ONLY function that returns secret_hash values.
|
|
65
|
+
* Used exclusively by the secret service for Argon2id verification.
|
|
66
|
+
* Returns secrets that are active AND not expired.
|
|
67
|
+
*
|
|
68
|
+
* @param clientId - Client internal UUID
|
|
69
|
+
* @returns Array of {id, hash} pairs for active secrets
|
|
70
|
+
*/
|
|
71
|
+
export async function getActiveSecretHashes(clientId) {
|
|
72
|
+
const pool = getPool();
|
|
73
|
+
const result = await pool.query(`SELECT id, secret_hash FROM client_secrets
|
|
74
|
+
WHERE client_id = $1
|
|
75
|
+
AND status = 'active'
|
|
76
|
+
AND (expires_at IS NULL OR expires_at > NOW())
|
|
77
|
+
ORDER BY created_at DESC`, [clientId]);
|
|
78
|
+
return result.rows.map((row) => ({ id: row.id, hash: row.secret_hash }));
|
|
79
|
+
}
|
|
80
|
+
// ===========================================================================
|
|
81
|
+
// Update
|
|
82
|
+
// ===========================================================================
|
|
83
|
+
/**
|
|
84
|
+
* Revoke a secret (set status = 'revoked').
|
|
85
|
+
*
|
|
86
|
+
* This is a permanent operation — revoked secrets cannot be reactivated.
|
|
87
|
+
*
|
|
88
|
+
* @param id - Secret UUID
|
|
89
|
+
* @returns Updated secret metadata, or null if not found
|
|
90
|
+
*/
|
|
91
|
+
export async function revokeSecret(id) {
|
|
92
|
+
const pool = getPool();
|
|
93
|
+
const result = await pool.query(`UPDATE client_secrets SET status = 'revoked' WHERE id = $1 RETURNING *`, [id]);
|
|
94
|
+
if (result.rows.length === 0)
|
|
95
|
+
return null;
|
|
96
|
+
return mapRowToClientSecret(result.rows[0]);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Update the last_used_at timestamp for a secret.
|
|
100
|
+
*
|
|
101
|
+
* Called after successful secret verification to track usage.
|
|
102
|
+
*
|
|
103
|
+
* @param id - Secret UUID
|
|
104
|
+
*/
|
|
105
|
+
export async function updateLastUsedAt(id) {
|
|
106
|
+
const pool = getPool();
|
|
107
|
+
await pool.query(`UPDATE client_secrets SET last_used_at = NOW() WHERE id = $1`, [id]);
|
|
108
|
+
}
|
|
109
|
+
// ===========================================================================
|
|
110
|
+
// Cleanup
|
|
111
|
+
// ===========================================================================
|
|
112
|
+
/**
|
|
113
|
+
* Delete expired secrets that have been expired for more than the given days.
|
|
114
|
+
*
|
|
115
|
+
* Only deletes secrets where expires_at is in the past by at least `retentionDays`.
|
|
116
|
+
* This prevents premature deletion of recently-expired secrets that might
|
|
117
|
+
* still appear in audit logs.
|
|
118
|
+
*
|
|
119
|
+
* @param retentionDays - Number of days to retain expired secrets (default: 30)
|
|
120
|
+
* @returns Number of deleted secrets
|
|
121
|
+
*/
|
|
122
|
+
export async function cleanupExpiredSecrets(retentionDays = 30) {
|
|
123
|
+
const pool = getPool();
|
|
124
|
+
const result = await pool.query(`DELETE FROM client_secrets
|
|
125
|
+
WHERE status = 'revoked'
|
|
126
|
+
OR (expires_at IS NOT NULL AND expires_at < NOW() - INTERVAL '1 day' * $1)`, [retentionDays]);
|
|
127
|
+
return result.rowCount ?? 0;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Get the SHA-256 hash of the most recent active, non-expired secret.
|
|
131
|
+
*
|
|
132
|
+
* Used by findForOidc() to include the SHA-256 hash as client_secret
|
|
133
|
+
* in oidc-provider metadata. Returns null if no active secret has a
|
|
134
|
+
* SHA-256 hash (e.g., secrets created before migration 013).
|
|
135
|
+
*
|
|
136
|
+
* @param clientId - Client internal UUID
|
|
137
|
+
* @returns SHA-256 hex hash string, or null if none available
|
|
138
|
+
*/
|
|
139
|
+
export async function getLatestActiveSha256(clientId) {
|
|
140
|
+
const pool = getPool();
|
|
141
|
+
const result = await pool.query(`SELECT secret_sha256 FROM client_secrets
|
|
142
|
+
WHERE client_id = $1
|
|
143
|
+
AND status = 'active'
|
|
144
|
+
AND secret_sha256 IS NOT NULL
|
|
145
|
+
AND (expires_at IS NULL OR expires_at > NOW())
|
|
146
|
+
ORDER BY created_at DESC
|
|
147
|
+
LIMIT 1`, [clientId]);
|
|
148
|
+
if (result.rows.length === 0)
|
|
149
|
+
return null;
|
|
150
|
+
return result.rows[0].secret_sha256;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Count active secrets for a client.
|
|
154
|
+
*
|
|
155
|
+
* @param clientId - Client internal UUID
|
|
156
|
+
* @returns Number of active (non-revoked, non-expired) secrets
|
|
157
|
+
*/
|
|
158
|
+
export async function countActiveSecrets(clientId) {
|
|
159
|
+
const pool = getPool();
|
|
160
|
+
const result = await pool.query(`SELECT COUNT(*) as count FROM client_secrets
|
|
161
|
+
WHERE client_id = $1
|
|
162
|
+
AND status = 'active'
|
|
163
|
+
AND (expires_at IS NULL OR expires_at > NOW())`, [clientId]);
|
|
164
|
+
return parseInt(result.rows[0].count, 10);
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=secret-repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-repository.js","sourceRoot":"","sources":["../../src/clients/secret-repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret service — client secret lifecycle management.
|
|
3
|
+
*
|
|
4
|
+
* Handles the full lifecycle of OIDC client secrets:
|
|
5
|
+
* - Generate and store new secrets (Argon2id hashed)
|
|
6
|
+
* - Verify secrets during token endpoint authentication
|
|
7
|
+
* - Revoke secrets permanently
|
|
8
|
+
* - List secrets (metadata only, never hashes)
|
|
9
|
+
* - Cleanup expired secrets
|
|
10
|
+
*
|
|
11
|
+
* Security model:
|
|
12
|
+
* - Plaintext is returned ONCE at generation, never stored
|
|
13
|
+
* - Only Argon2id hashes are persisted in the database
|
|
14
|
+
* - Verification iterates ALL active secrets (no short-circuit)
|
|
15
|
+
* - Failed verifications are logged as security events
|
|
16
|
+
* - All operations use fire-and-forget audit logging
|
|
17
|
+
*
|
|
18
|
+
* This service is consumed by:
|
|
19
|
+
* - The client service (initial secret on confidential client creation)
|
|
20
|
+
* - The API routes (secret rotation, revocation)
|
|
21
|
+
* - The OIDC token endpoint (secret verification via admin API)
|
|
22
|
+
*/
|
|
23
|
+
import type { ClientSecret, SecretWithPlaintext, CreateSecretInput } from './types.js';
|
|
24
|
+
/**
|
|
25
|
+
* Generate a new client secret, hash it, and store it.
|
|
26
|
+
*
|
|
27
|
+
* Flow:
|
|
28
|
+
* 1. Generate cryptographically random plaintext (48 bytes, base64url)
|
|
29
|
+
* 2. Hash with Argon2id (OWASP-recommended parameters)
|
|
30
|
+
* 3. Insert hashed secret into database
|
|
31
|
+
* 4. Write audit log entry
|
|
32
|
+
* 5. Return SecretWithPlaintext (plaintext shown once, then discarded)
|
|
33
|
+
*
|
|
34
|
+
* @param clientDbId - Client internal UUID (FK to clients.id)
|
|
35
|
+
* @param input - Optional label and expiration
|
|
36
|
+
* @param actorId - UUID of the user performing the action
|
|
37
|
+
* @returns Secret metadata with plaintext (shown once)
|
|
38
|
+
*/
|
|
39
|
+
export declare function generateAndStore(clientDbId: string, input?: CreateSecretInput, actorId?: string): Promise<SecretWithPlaintext>;
|
|
40
|
+
/**
|
|
41
|
+
* Verify a plaintext secret against all active secrets for a client.
|
|
42
|
+
*
|
|
43
|
+
* Called during OIDC token endpoint authentication. Iterates through
|
|
44
|
+
* ALL active (non-revoked, non-expired) secrets and checks each one.
|
|
45
|
+
*
|
|
46
|
+
* Security notes:
|
|
47
|
+
* - Iterates all secrets to prevent timing-based enumeration
|
|
48
|
+
* - Updates last_used_at on successful match
|
|
49
|
+
* - Logs failed verification as a security event
|
|
50
|
+
* - Returns false on any error (fail closed)
|
|
51
|
+
*
|
|
52
|
+
* @param clientDbId - Client internal UUID
|
|
53
|
+
* @param plaintext - The secret to verify
|
|
54
|
+
* @returns true if the secret matches any active secret
|
|
55
|
+
*/
|
|
56
|
+
export declare function verify(clientDbId: string, plaintext: string): Promise<boolean>;
|
|
57
|
+
/**
|
|
58
|
+
* Revoke a client secret permanently.
|
|
59
|
+
*
|
|
60
|
+
* Revocation is irreversible — once revoked, a secret cannot be
|
|
61
|
+
* reactivated. The revoked secret remains in the database for
|
|
62
|
+
* audit trail purposes until cleanup removes it.
|
|
63
|
+
*
|
|
64
|
+
* @param secretId - Secret UUID
|
|
65
|
+
* @param actorId - UUID of the user performing the action
|
|
66
|
+
* @throws ClientNotFoundError if secret not found
|
|
67
|
+
* @throws ClientValidationError if secret already revoked
|
|
68
|
+
*/
|
|
69
|
+
export declare function revoke(secretId: string, actorId?: string): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* List all secrets for a client (metadata only, never hashes).
|
|
72
|
+
*
|
|
73
|
+
* @param clientDbId - Client internal UUID
|
|
74
|
+
* @returns Array of secret metadata
|
|
75
|
+
*/
|
|
76
|
+
export declare function listByClient(clientDbId: string): Promise<ClientSecret[]>;
|
|
77
|
+
/**
|
|
78
|
+
* Delete expired and revoked secrets older than the retention period.
|
|
79
|
+
*
|
|
80
|
+
* This is a maintenance operation that should be run periodically
|
|
81
|
+
* (e.g., via cron) to clean up old secrets that are no longer needed.
|
|
82
|
+
*
|
|
83
|
+
* @param retentionDays - Days to retain expired secrets (default: 30)
|
|
84
|
+
* @returns Number of deleted secrets
|
|
85
|
+
*/
|
|
86
|
+
export declare function cleanupExpired(retentionDays?: number): Promise<number>;
|
|
87
|
+
//# sourceMappingURL=secret-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-service.d.ts","sourceRoot":"","sources":["../../src/clients/secret-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAmBvF;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,KAAK,GAAE,iBAAsB,EAC7B,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,mBAAmB,CAAC,CAyC9B;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,MAAM,CAC1B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAyClB;AAMD;;;;;;;;;;;GAWG;AACH,wBAAsB,MAAM,CAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAMD;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAE9E;AAMD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE5E"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret service — client secret lifecycle management.
|
|
3
|
+
*
|
|
4
|
+
* Handles the full lifecycle of OIDC client secrets:
|
|
5
|
+
* - Generate and store new secrets (Argon2id hashed)
|
|
6
|
+
* - Verify secrets during token endpoint authentication
|
|
7
|
+
* - Revoke secrets permanently
|
|
8
|
+
* - List secrets (metadata only, never hashes)
|
|
9
|
+
* - Cleanup expired secrets
|
|
10
|
+
*
|
|
11
|
+
* Security model:
|
|
12
|
+
* - Plaintext is returned ONCE at generation, never stored
|
|
13
|
+
* - Only Argon2id hashes are persisted in the database
|
|
14
|
+
* - Verification iterates ALL active secrets (no short-circuit)
|
|
15
|
+
* - Failed verifications are logged as security events
|
|
16
|
+
* - All operations use fire-and-forget audit logging
|
|
17
|
+
*
|
|
18
|
+
* This service is consumed by:
|
|
19
|
+
* - The client service (initial secret on confidential client creation)
|
|
20
|
+
* - The API routes (secret rotation, revocation)
|
|
21
|
+
* - The OIDC token endpoint (secret verification via admin API)
|
|
22
|
+
*/
|
|
23
|
+
import { insertSecret, listSecretsByClient, findSecretById, getActiveSecretHashes, revokeSecret as repoRevokeSecret, updateLastUsedAt, cleanupExpiredSecrets, } from './secret-repository.js';
|
|
24
|
+
import { generateSecret, hashSecret, sha256Secret, verifySecretHash } from './crypto.js';
|
|
25
|
+
import { writeAuditLog } from '../lib/audit-log.js';
|
|
26
|
+
import { logger } from '../lib/logger.js';
|
|
27
|
+
import { ClientNotFoundError, ClientValidationError } from './errors.js';
|
|
28
|
+
// ===========================================================================
|
|
29
|
+
// Secret generation
|
|
30
|
+
// ===========================================================================
|
|
31
|
+
/**
|
|
32
|
+
* Generate a new client secret, hash it, and store it.
|
|
33
|
+
*
|
|
34
|
+
* Flow:
|
|
35
|
+
* 1. Generate cryptographically random plaintext (48 bytes, base64url)
|
|
36
|
+
* 2. Hash with Argon2id (OWASP-recommended parameters)
|
|
37
|
+
* 3. Insert hashed secret into database
|
|
38
|
+
* 4. Write audit log entry
|
|
39
|
+
* 5. Return SecretWithPlaintext (plaintext shown once, then discarded)
|
|
40
|
+
*
|
|
41
|
+
* @param clientDbId - Client internal UUID (FK to clients.id)
|
|
42
|
+
* @param input - Optional label and expiration
|
|
43
|
+
* @param actorId - UUID of the user performing the action
|
|
44
|
+
* @returns Secret metadata with plaintext (shown once)
|
|
45
|
+
*/
|
|
46
|
+
export async function generateAndStore(clientDbId, input = {}, actorId) {
|
|
47
|
+
// Generate plaintext secret
|
|
48
|
+
const plaintext = generateSecret();
|
|
49
|
+
// Hash with Argon2id — only the hash is stored
|
|
50
|
+
const secretHash = await hashSecret(plaintext);
|
|
51
|
+
// Compute SHA-256 for oidc-provider client authentication
|
|
52
|
+
const secretSha256 = sha256Secret(plaintext);
|
|
53
|
+
// Insert into database
|
|
54
|
+
const secret = await insertSecret({
|
|
55
|
+
clientId: clientDbId,
|
|
56
|
+
secretHash,
|
|
57
|
+
secretSha256,
|
|
58
|
+
label: input.label ?? null,
|
|
59
|
+
expiresAt: input.expiresAt ?? null,
|
|
60
|
+
});
|
|
61
|
+
// Audit log (fire-and-forget)
|
|
62
|
+
await writeAuditLog({
|
|
63
|
+
eventType: 'client.secret.generated',
|
|
64
|
+
eventCategory: 'admin',
|
|
65
|
+
actorId,
|
|
66
|
+
metadata: {
|
|
67
|
+
clientId: clientDbId,
|
|
68
|
+
secretId: secret.id,
|
|
69
|
+
label: secret.label,
|
|
70
|
+
expiresAt: secret.expiresAt?.toISOString() ?? null,
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
// Return with plaintext — this is the ONLY time it's available
|
|
74
|
+
return {
|
|
75
|
+
id: secret.id,
|
|
76
|
+
clientId: secret.clientId,
|
|
77
|
+
label: secret.label,
|
|
78
|
+
plaintext,
|
|
79
|
+
expiresAt: secret.expiresAt,
|
|
80
|
+
createdAt: secret.createdAt,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// ===========================================================================
|
|
84
|
+
// Secret verification
|
|
85
|
+
// ===========================================================================
|
|
86
|
+
/**
|
|
87
|
+
* Verify a plaintext secret against all active secrets for a client.
|
|
88
|
+
*
|
|
89
|
+
* Called during OIDC token endpoint authentication. Iterates through
|
|
90
|
+
* ALL active (non-revoked, non-expired) secrets and checks each one.
|
|
91
|
+
*
|
|
92
|
+
* Security notes:
|
|
93
|
+
* - Iterates all secrets to prevent timing-based enumeration
|
|
94
|
+
* - Updates last_used_at on successful match
|
|
95
|
+
* - Logs failed verification as a security event
|
|
96
|
+
* - Returns false on any error (fail closed)
|
|
97
|
+
*
|
|
98
|
+
* @param clientDbId - Client internal UUID
|
|
99
|
+
* @param plaintext - The secret to verify
|
|
100
|
+
* @returns true if the secret matches any active secret
|
|
101
|
+
*/
|
|
102
|
+
export async function verify(clientDbId, plaintext) {
|
|
103
|
+
try {
|
|
104
|
+
// Load all active, non-expired secret hashes
|
|
105
|
+
const activeSecrets = await getActiveSecretHashes(clientDbId);
|
|
106
|
+
if (activeSecrets.length === 0) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
// Try each active secret — Argon2id verify is async and non-blocking
|
|
110
|
+
for (const secret of activeSecrets) {
|
|
111
|
+
const matches = await verifySecretHash(secret.hash, plaintext);
|
|
112
|
+
if (matches) {
|
|
113
|
+
// Update last_used_at timestamp (fire-and-forget)
|
|
114
|
+
await updateLastUsedAt(secret.id);
|
|
115
|
+
// Audit log: successful verification
|
|
116
|
+
await writeAuditLog({
|
|
117
|
+
eventType: 'client.secret.verified',
|
|
118
|
+
eventCategory: 'authentication',
|
|
119
|
+
metadata: { clientId: clientDbId, secretId: secret.id },
|
|
120
|
+
});
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// No match found — log as security event
|
|
125
|
+
await writeAuditLog({
|
|
126
|
+
eventType: 'client.secret.failed',
|
|
127
|
+
eventCategory: 'security',
|
|
128
|
+
metadata: { clientId: clientDbId, activeSecretCount: activeSecrets.length },
|
|
129
|
+
});
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
// Fail closed — any error during verification results in rejection
|
|
134
|
+
logger.error({ err, clientDbId }, 'Error during secret verification');
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// ===========================================================================
|
|
139
|
+
// Secret revocation
|
|
140
|
+
// ===========================================================================
|
|
141
|
+
/**
|
|
142
|
+
* Revoke a client secret permanently.
|
|
143
|
+
*
|
|
144
|
+
* Revocation is irreversible — once revoked, a secret cannot be
|
|
145
|
+
* reactivated. The revoked secret remains in the database for
|
|
146
|
+
* audit trail purposes until cleanup removes it.
|
|
147
|
+
*
|
|
148
|
+
* @param secretId - Secret UUID
|
|
149
|
+
* @param actorId - UUID of the user performing the action
|
|
150
|
+
* @throws ClientNotFoundError if secret not found
|
|
151
|
+
* @throws ClientValidationError if secret already revoked
|
|
152
|
+
*/
|
|
153
|
+
export async function revoke(secretId, actorId) {
|
|
154
|
+
// Validate secret exists
|
|
155
|
+
const secret = await findSecretById(secretId);
|
|
156
|
+
if (!secret) {
|
|
157
|
+
throw new ClientNotFoundError(secretId);
|
|
158
|
+
}
|
|
159
|
+
// Validate secret is not already revoked
|
|
160
|
+
if (secret.status === 'revoked') {
|
|
161
|
+
throw new ClientValidationError('Secret is already revoked');
|
|
162
|
+
}
|
|
163
|
+
// Revoke in database
|
|
164
|
+
await repoRevokeSecret(secretId);
|
|
165
|
+
// Audit log (fire-and-forget)
|
|
166
|
+
await writeAuditLog({
|
|
167
|
+
eventType: 'client.secret.revoked',
|
|
168
|
+
eventCategory: 'admin',
|
|
169
|
+
actorId,
|
|
170
|
+
metadata: {
|
|
171
|
+
clientId: secret.clientId,
|
|
172
|
+
secretId: secret.id,
|
|
173
|
+
label: secret.label,
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
// ===========================================================================
|
|
178
|
+
// Secret listing
|
|
179
|
+
// ===========================================================================
|
|
180
|
+
/**
|
|
181
|
+
* List all secrets for a client (metadata only, never hashes).
|
|
182
|
+
*
|
|
183
|
+
* @param clientDbId - Client internal UUID
|
|
184
|
+
* @returns Array of secret metadata
|
|
185
|
+
*/
|
|
186
|
+
export async function listByClient(clientDbId) {
|
|
187
|
+
return listSecretsByClient(clientDbId);
|
|
188
|
+
}
|
|
189
|
+
// ===========================================================================
|
|
190
|
+
// Secret cleanup
|
|
191
|
+
// ===========================================================================
|
|
192
|
+
/**
|
|
193
|
+
* Delete expired and revoked secrets older than the retention period.
|
|
194
|
+
*
|
|
195
|
+
* This is a maintenance operation that should be run periodically
|
|
196
|
+
* (e.g., via cron) to clean up old secrets that are no longer needed.
|
|
197
|
+
*
|
|
198
|
+
* @param retentionDays - Days to retain expired secrets (default: 30)
|
|
199
|
+
* @returns Number of deleted secrets
|
|
200
|
+
*/
|
|
201
|
+
export async function cleanupExpired(retentionDays) {
|
|
202
|
+
return cleanupExpiredSecrets(retentionDays);
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=secret-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-service.js","sourceRoot":"","sources":["../../src/clients/secret-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client service — business logic orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Composes the repository, cache, validators, crypto utilities, and audit log
|
|
5
|
+
* to provide the complete client management API. All write operations follow:
|
|
6
|
+
* 1. Validate inputs (org, app, URIs)
|
|
7
|
+
* 2. Perform DB operation (via repository)
|
|
8
|
+
* 3. Invalidate + re-cache (via cache)
|
|
9
|
+
* 4. Write audit log (fire-and-forget)
|
|
10
|
+
*
|
|
11
|
+
* Read operations check cache first, fall back to DB on miss.
|
|
12
|
+
*
|
|
13
|
+
* Status lifecycle:
|
|
14
|
+
* - activate: inactive → active
|
|
15
|
+
* - deactivate: active → inactive
|
|
16
|
+
* - revoke: active|inactive → revoked (permanent, cannot be undone)
|
|
17
|
+
*
|
|
18
|
+
* The findForOidc() function maps internal Client objects to oidc-provider
|
|
19
|
+
* metadata format, used by the adapter factory during OIDC operations.
|
|
20
|
+
*/
|
|
21
|
+
import type { Client, ClientWithSecret, CreateClientInput, UpdateClientInput, ListClientsOptions, PaginatedResult } from './types.js';
|
|
22
|
+
import type { ListClientsCursorOptions } from './repository.js';
|
|
23
|
+
import type { CursorPaginatedResult } from '../lib/cursor.js';
|
|
24
|
+
/**
|
|
25
|
+
* Create a new OIDC client.
|
|
26
|
+
*
|
|
27
|
+
* Flow:
|
|
28
|
+
* 1. Validate organization exists and is active
|
|
29
|
+
* 2. Validate application exists and is active
|
|
30
|
+
* 3. Validate redirect URIs
|
|
31
|
+
* 4. Apply defaults (grant types, response types, scope, auth method, PKCE)
|
|
32
|
+
* 5. Generate cryptographically random client_id
|
|
33
|
+
* 6. Insert client row
|
|
34
|
+
* 7. Cache the client
|
|
35
|
+
* 8. Write audit log
|
|
36
|
+
* 9. Return ClientWithSecret (secret is null for public clients;
|
|
37
|
+
* for confidential clients, the caller must generate the initial
|
|
38
|
+
* secret separately via the secret service)
|
|
39
|
+
*
|
|
40
|
+
* @param input - Client creation data
|
|
41
|
+
* @param actorId - UUID of the user performing the action (for audit)
|
|
42
|
+
* @returns Created client wrapped in ClientWithSecret (secret always null here)
|
|
43
|
+
* @throws ClientValidationError if org/app invalid or URIs fail validation
|
|
44
|
+
*/
|
|
45
|
+
export declare function createClient(input: CreateClientInput, actorId?: string): Promise<ClientWithSecret>;
|
|
46
|
+
/**
|
|
47
|
+
* Find a client by internal UUID.
|
|
48
|
+
* Checks Redis cache first, falls back to database on miss.
|
|
49
|
+
*
|
|
50
|
+
* @param id - Client internal UUID
|
|
51
|
+
* @returns Client or null if not found
|
|
52
|
+
*/
|
|
53
|
+
export declare function getClientById(id: string): Promise<Client | null>;
|
|
54
|
+
/**
|
|
55
|
+
* Find a client by OIDC client_id.
|
|
56
|
+
* Checks Redis cache first, falls back to database on miss.
|
|
57
|
+
*
|
|
58
|
+
* @param clientId - OIDC client_id (public identifier)
|
|
59
|
+
* @returns Client or null if not found
|
|
60
|
+
*/
|
|
61
|
+
export declare function getClientByClientId(clientId: string): Promise<Client | null>;
|
|
62
|
+
/**
|
|
63
|
+
* Update a client's configurable fields.
|
|
64
|
+
*
|
|
65
|
+
* Validates redirect URIs if they are being changed.
|
|
66
|
+
*
|
|
67
|
+
* @param id - Client internal UUID
|
|
68
|
+
* @param input - Fields to update
|
|
69
|
+
* @param actorId - UUID of the user performing the action
|
|
70
|
+
* @returns Updated client
|
|
71
|
+
* @throws ClientNotFoundError if client not found
|
|
72
|
+
* @throws ClientValidationError if redirect URIs are invalid
|
|
73
|
+
*/
|
|
74
|
+
export declare function updateClient(id: string, input: UpdateClientInput, actorId?: string): Promise<Client>;
|
|
75
|
+
/**
|
|
76
|
+
* List clients by organization with pagination.
|
|
77
|
+
*
|
|
78
|
+
* @param organizationId - Organization UUID
|
|
79
|
+
* @param options - Pagination and sort options
|
|
80
|
+
* @returns Paginated result
|
|
81
|
+
*/
|
|
82
|
+
export declare function listClientsByOrganization(organizationId: string, options: Omit<ListClientsOptions, 'organizationId'>): Promise<PaginatedResult<Client>>;
|
|
83
|
+
/**
|
|
84
|
+
* List clients by application with pagination.
|
|
85
|
+
*
|
|
86
|
+
* @param applicationId - Application UUID
|
|
87
|
+
* @param options - Pagination and sort options
|
|
88
|
+
* @returns Paginated result
|
|
89
|
+
*/
|
|
90
|
+
export declare function listClientsByApplication(applicationId: string, options: Omit<ListClientsOptions, 'applicationId'>): Promise<PaginatedResult<Client>>;
|
|
91
|
+
/**
|
|
92
|
+
* List clients with cursor-based keyset pagination.
|
|
93
|
+
* Supports all existing filters (org, app, status, search).
|
|
94
|
+
*
|
|
95
|
+
* @param options - Cursor, limit, filter, and sort options
|
|
96
|
+
* @returns Cursor-paginated result with nextCursor/hasMore
|
|
97
|
+
*/
|
|
98
|
+
export declare function listClientsCursor(options: ListClientsCursorOptions): Promise<CursorPaginatedResult<Client>>;
|
|
99
|
+
/**
|
|
100
|
+
* Deactivate a client (active → inactive).
|
|
101
|
+
*
|
|
102
|
+
* @param id - Client internal UUID
|
|
103
|
+
* @param actorId - UUID of the user performing the action
|
|
104
|
+
* @throws ClientNotFoundError if not found
|
|
105
|
+
* @throws ClientValidationError if not currently active
|
|
106
|
+
*/
|
|
107
|
+
export declare function deactivateClient(id: string, actorId?: string): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* Activate a client (inactive → active).
|
|
110
|
+
*
|
|
111
|
+
* @param id - Client internal UUID
|
|
112
|
+
* @param actorId - UUID of the user performing the action
|
|
113
|
+
* @throws ClientNotFoundError if not found
|
|
114
|
+
* @throws ClientValidationError if not currently inactive
|
|
115
|
+
*/
|
|
116
|
+
export declare function activateClient(id: string, actorId?: string): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Revoke a client (active or inactive → revoked).
|
|
119
|
+
*
|
|
120
|
+
* Revocation is permanent — revoked clients cannot be reactivated.
|
|
121
|
+
* This effectively disables the client for all OIDC operations.
|
|
122
|
+
*
|
|
123
|
+
* @param id - Client internal UUID
|
|
124
|
+
* @param actorId - UUID of the user performing the action
|
|
125
|
+
* @throws ClientNotFoundError if not found
|
|
126
|
+
* @throws ClientValidationError if already revoked
|
|
127
|
+
*/
|
|
128
|
+
export declare function revokeClient(id: string, actorId?: string): Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* Find a client by OIDC client_id and return oidc-provider metadata format.
|
|
131
|
+
*
|
|
132
|
+
* This function is the bridge between Porta's internal client model and
|
|
133
|
+
* the metadata shape expected by node-oidc-provider. It's called by the
|
|
134
|
+
* adapter factory during OIDC flows (authorization, token exchange, etc.).
|
|
135
|
+
*
|
|
136
|
+
* Returns undefined (not null) for compatibility with oidc-provider which
|
|
137
|
+
* expects undefined for "client not found".
|
|
138
|
+
*
|
|
139
|
+
* @param clientId - OIDC client_id
|
|
140
|
+
* @returns OIDC client metadata object, or undefined if not found/inactive
|
|
141
|
+
*/
|
|
142
|
+
export declare function findForOidc(clientId: string): Promise<Record<string, unknown> | undefined>;
|
|
143
|
+
/**
|
|
144
|
+
* Verify a client secret for OIDC authentication.
|
|
145
|
+
*
|
|
146
|
+
* Convenience wrapper around secret-service.verify() that resolves the
|
|
147
|
+
* internal DB id from the OIDC client_id and performs guard checks:
|
|
148
|
+
* - Client must exist and be active
|
|
149
|
+
* - Client must be confidential (public clients have no secrets)
|
|
150
|
+
*
|
|
151
|
+
* Used during token endpoint authentication via the admin API.
|
|
152
|
+
*
|
|
153
|
+
* @param clientId - The OIDC client_id (external identifier)
|
|
154
|
+
* @param plaintext - The presented secret to verify
|
|
155
|
+
* @returns true if secret matches any active hash, false otherwise
|
|
156
|
+
*/
|
|
157
|
+
export declare function verifyClientSecret(clientId: string, plaintext: string): Promise<boolean>;
|
|
158
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/clients/service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EACV,MAAM,EACN,gBAAgB,EAChB,iBAAiB,EAEjB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EAChB,MAAM,YAAY,CAAC;AAUpB,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AA4E9D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,iBAAiB,EACxB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,gBAAgB,CAAC,CA2F3B;AAOD;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWtE;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWlF;AAMD;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAChC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,iBAAiB,EACxB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CA6EjB;AAOD;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,GAClD,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAElC;AAED;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,IAAI,CAAC,kBAAkB,EAAE,eAAe,CAAC,GACjD,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAElC;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAExC;AAgBD;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAqBf;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,CAoD9C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAWlB"}
|