@portaidentity/server 1.7.3 → 1.9.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 +28 -0
- package/dist/applications/index.d.ts +2 -2
- package/dist/applications/index.d.ts.map +1 -1
- package/dist/applications/index.js +2 -2
- package/dist/applications/index.js.map +1 -1
- package/dist/applications/repository.d.ts +49 -4
- package/dist/applications/repository.d.ts.map +1 -1
- package/dist/applications/repository.js +148 -10
- package/dist/applications/repository.js.map +1 -1
- package/dist/applications/service.d.ts +35 -17
- package/dist/applications/service.d.ts.map +1 -1
- package/dist/applications/service.js +144 -35
- package/dist/applications/service.js.map +1 -1
- package/dist/applications/types.d.ts +1 -1
- package/dist/applications/types.d.ts.map +1 -1
- package/dist/applications/validators.d.ts +14 -0
- package/dist/applications/validators.d.ts.map +1 -0
- package/dist/applications/validators.js +14 -0
- package/dist/applications/validators.js.map +1 -0
- package/dist/auth/effective-branding.d.ts +35 -0
- package/dist/auth/effective-branding.d.ts.map +1 -0
- package/dist/auth/effective-branding.js +81 -0
- package/dist/auth/effective-branding.js.map +1 -0
- package/dist/auth/email-service.d.ts +3 -8
- package/dist/auth/email-service.d.ts.map +1 -1
- package/dist/auth/email-service.js +22 -30
- package/dist/auth/email-service.js.map +1 -1
- package/dist/auth/i18n.d.ts +5 -0
- package/dist/auth/i18n.d.ts.map +1 -1
- package/dist/auth/i18n.js +6 -5
- package/dist/auth/i18n.js.map +1 -1
- package/dist/auth/rate-limiter.d.ts +6 -10
- package/dist/auth/rate-limiter.d.ts.map +1 -1
- package/dist/auth/rate-limiter.js +12 -16
- package/dist/auth/rate-limiter.js.map +1 -1
- package/dist/auth/recovery-job-processor.d.ts.map +1 -1
- package/dist/auth/recovery-job-processor.js +1 -1
- package/dist/auth/recovery-job-processor.js.map +1 -1
- package/dist/auth/template-engine.d.ts +3 -1
- package/dist/auth/template-engine.d.ts.map +1 -1
- package/dist/auth/template-engine.js +1 -1
- package/dist/auth/template-engine.js.map +1 -1
- package/dist/auth/token-repository.d.ts +9 -3
- package/dist/auth/token-repository.d.ts.map +1 -1
- package/dist/auth/token-repository.js +17 -8
- package/dist/auth/token-repository.js.map +1 -1
- package/dist/cli/commands/init.d.ts +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +12 -12
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/error-handler.d.ts +3 -2
- package/dist/cli/error-handler.d.ts.map +1 -1
- package/dist/cli/error-handler.js +9 -2
- package/dist/cli/error-handler.js.map +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/clients/index.d.ts +1 -1
- package/dist/clients/index.js +1 -1
- package/dist/clients/repository.d.ts +24 -0
- package/dist/clients/repository.d.ts.map +1 -1
- package/dist/clients/repository.js +39 -0
- package/dist/clients/repository.js.map +1 -1
- package/dist/clients/secret-repository.d.ts +35 -8
- package/dist/clients/secret-repository.d.ts.map +1 -1
- package/dist/clients/secret-repository.js +69 -16
- package/dist/clients/secret-repository.js.map +1 -1
- package/dist/clients/secret-service.d.ts +5 -9
- package/dist/clients/secret-service.d.ts.map +1 -1
- package/dist/clients/secret-service.js +13 -22
- package/dist/clients/secret-service.js.map +1 -1
- package/dist/clients/service.d.ts +10 -13
- package/dist/clients/service.d.ts.map +1 -1
- package/dist/clients/service.js +121 -42
- package/dist/clients/service.js.map +1 -1
- package/dist/clients/types.d.ts +14 -1
- package/dist/clients/types.d.ts.map +1 -1
- package/dist/clients/types.js +1 -0
- package/dist/clients/types.js.map +1 -1
- package/dist/clients/validators.d.ts +83 -1
- package/dist/clients/validators.d.ts.map +1 -1
- package/dist/clients/validators.js +110 -0
- package/dist/clients/validators.js.map +1 -1
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/schema.d.ts +1 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +23 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/custom-claims/repository.d.ts +14 -9
- package/dist/custom-claims/repository.d.ts.map +1 -1
- package/dist/custom-claims/repository.js +38 -11
- package/dist/custom-claims/repository.js.map +1 -1
- package/dist/custom-claims/service.d.ts +11 -6
- package/dist/custom-claims/service.d.ts.map +1 -1
- package/dist/custom-claims/service.js +43 -20
- package/dist/custom-claims/service.js.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/admin-permissions.d.ts +12 -7
- package/dist/lib/admin-permissions.d.ts.map +1 -1
- package/dist/lib/admin-permissions.js +26 -16
- package/dist/lib/admin-permissions.js.map +1 -1
- package/dist/lib/audit-log.d.ts +2 -2
- package/dist/lib/audit-log.d.ts.map +1 -1
- package/dist/lib/audit-log.js +1 -1
- package/dist/lib/audit-log.js.map +1 -1
- package/dist/lib/authority-revocation.d.ts +18 -0
- package/dist/lib/authority-revocation.d.ts.map +1 -0
- package/dist/lib/authority-revocation.js +37 -0
- package/dist/lib/authority-revocation.js.map +1 -0
- package/dist/lib/branding-assets.d.ts +35 -5
- package/dist/lib/branding-assets.d.ts.map +1 -1
- package/dist/lib/branding-assets.js +33 -26
- package/dist/lib/branding-assets.js.map +1 -1
- package/dist/lib/bulk-operations.d.ts +1 -1
- package/dist/lib/bulk-operations.d.ts.map +1 -1
- package/dist/lib/bulk-operations.js +1 -13
- package/dist/lib/bulk-operations.js.map +1 -1
- package/dist/lib/cursor.d.ts +2 -0
- package/dist/lib/cursor.d.ts.map +1 -1
- package/dist/lib/cursor.js +2 -7
- package/dist/lib/cursor.js.map +1 -1
- package/dist/lib/database.d.ts.map +1 -1
- package/dist/lib/database.js +5 -0
- package/dist/lib/database.js.map +1 -1
- package/dist/lib/deletion-cleanup.d.ts +43 -0
- package/dist/lib/deletion-cleanup.d.ts.map +1 -0
- package/dist/lib/deletion-cleanup.js +207 -0
- package/dist/lib/deletion-cleanup.js.map +1 -0
- package/dist/lib/image-validator.d.ts +3 -1
- package/dist/lib/image-validator.d.ts.map +1 -1
- package/dist/lib/image-validator.js +32 -19
- package/dist/lib/image-validator.js.map +1 -1
- package/dist/lib/log-format.d.ts +20 -0
- package/dist/lib/log-format.d.ts.map +1 -0
- package/dist/lib/log-format.js +22 -0
- package/dist/lib/log-format.js.map +1 -0
- package/dist/lib/logger.d.ts +3 -1
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +21 -4
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/redis.d.ts.map +1 -1
- package/dist/lib/redis.js +3 -0
- package/dist/lib/redis.js.map +1 -1
- package/dist/lib/session-tracking.d.ts +73 -11
- package/dist/lib/session-tracking.d.ts.map +1 -1
- package/dist/lib/session-tracking.js +76 -32
- package/dist/lib/session-tracking.js.map +1 -1
- package/dist/lib/signing-key-crypto.d.ts.map +1 -1
- package/dist/lib/signing-key-crypto.js +4 -5
- package/dist/lib/signing-key-crypto.js.map +1 -1
- package/dist/lib/signing-keys.d.ts +3 -4
- package/dist/lib/signing-keys.d.ts.map +1 -1
- package/dist/lib/signing-keys.js +66 -41
- package/dist/lib/signing-keys.js.map +1 -1
- package/dist/lib/super-admin-protection.d.ts +5 -5
- package/dist/lib/super-admin-protection.d.ts.map +1 -1
- package/dist/lib/super-admin-protection.js +6 -9
- package/dist/lib/super-admin-protection.js.map +1 -1
- package/dist/lib/system-config-catalog.d.ts +268 -0
- package/dist/lib/system-config-catalog.d.ts.map +1 -0
- package/dist/lib/system-config-catalog.js +90 -0
- package/dist/lib/system-config-catalog.js.map +1 -0
- package/dist/lib/system-config.d.ts +30 -33
- package/dist/lib/system-config.d.ts.map +1 -1
- package/dist/lib/system-config.js +78 -93
- package/dist/lib/system-config.js.map +1 -1
- package/dist/lib/with-timeout.d.ts +32 -0
- package/dist/lib/with-timeout.d.ts.map +1 -0
- package/dist/lib/with-timeout.js +45 -0
- package/dist/lib/with-timeout.js.map +1 -0
- package/dist/middleware/admin-auth.d.ts +6 -5
- package/dist/middleware/admin-auth.d.ts.map +1 -1
- package/dist/middleware/admin-auth.js +30 -20
- package/dist/middleware/admin-auth.js.map +1 -1
- package/dist/middleware/admin-cors.d.ts +3 -3
- package/dist/middleware/admin-cors.js +3 -3
- package/dist/middleware/admin-mutation-audit.d.ts +3 -2
- package/dist/middleware/admin-mutation-audit.d.ts.map +1 -1
- package/dist/middleware/admin-mutation-audit.js +12 -5
- package/dist/middleware/admin-mutation-audit.js.map +1 -1
- package/dist/middleware/admin-rate-limiter.d.ts +7 -8
- package/dist/middleware/admin-rate-limiter.d.ts.map +1 -1
- package/dist/middleware/admin-rate-limiter.js +7 -8
- package/dist/middleware/admin-rate-limiter.js.map +1 -1
- package/dist/middleware/client-secret-hash.d.ts +10 -29
- package/dist/middleware/client-secret-hash.d.ts.map +1 -1
- package/dist/middleware/client-secret-hash.js +161 -59
- package/dist/middleware/client-secret-hash.js.map +1 -1
- package/dist/middleware/health.d.ts +17 -0
- package/dist/middleware/health.d.ts.map +1 -1
- package/dist/middleware/health.js +25 -21
- package/dist/middleware/health.js.map +1 -1
- package/dist/middleware/ready.d.ts.map +1 -1
- package/dist/middleware/ready.js +1 -12
- package/dist/middleware/ready.js.map +1 -1
- package/dist/middleware/require-existing-organization.d.ts +18 -0
- package/dist/middleware/require-existing-organization.d.ts.map +1 -0
- package/dist/middleware/require-existing-organization.js +38 -0
- package/dist/middleware/require-existing-organization.js.map +1 -0
- package/dist/middleware/require-permission.d.ts.map +1 -1
- package/dist/middleware/require-permission.js +35 -1
- package/dist/middleware/require-permission.js.map +1 -1
- package/dist/middleware/require-user-organization.d.ts.map +1 -1
- package/dist/middleware/require-user-organization.js +4 -2
- package/dist/middleware/require-user-organization.js.map +1 -1
- package/dist/middleware/security-headers.d.ts +18 -0
- package/dist/middleware/security-headers.d.ts.map +1 -1
- package/dist/middleware/security-headers.js +32 -1
- package/dist/middleware/security-headers.js.map +1 -1
- package/dist/middleware/tenant-resolver.d.ts +1 -2
- package/dist/middleware/tenant-resolver.d.ts.map +1 -1
- package/dist/middleware/tenant-resolver.js +1 -5
- package/dist/middleware/tenant-resolver.js.map +1 -1
- package/dist/middleware/token-rate-limiter.d.ts +37 -16
- package/dist/middleware/token-rate-limiter.d.ts.map +1 -1
- package/dist/middleware/token-rate-limiter.js +126 -54
- package/dist/middleware/token-rate-limiter.js.map +1 -1
- package/dist/oidc/account-finder.d.ts +5 -5
- package/dist/oidc/account-finder.d.ts.map +1 -1
- package/dist/oidc/account-finder.js +31 -23
- package/dist/oidc/account-finder.js.map +1 -1
- package/dist/oidc/adapter-factory.d.ts.map +1 -1
- package/dist/oidc/adapter-factory.js +83 -3
- package/dist/oidc/adapter-factory.js.map +1 -1
- package/dist/oidc/configuration.d.ts +3 -8
- package/dist/oidc/configuration.d.ts.map +1 -1
- package/dist/oidc/configuration.js +67 -50
- package/dist/oidc/configuration.js.map +1 -1
- package/dist/oidc/provider.d.ts.map +1 -1
- package/dist/oidc/provider.js +7 -0
- package/dist/oidc/provider.js.map +1 -1
- package/dist/oidc/redis-adapter.d.ts +2 -3
- package/dist/oidc/redis-adapter.d.ts.map +1 -1
- package/dist/oidc/redis-adapter.js +54 -46
- package/dist/oidc/redis-adapter.js.map +1 -1
- package/dist/organizations/branding-url.d.ts +17 -0
- package/dist/organizations/branding-url.d.ts.map +1 -0
- package/dist/organizations/branding-url.js +38 -0
- package/dist/organizations/branding-url.js.map +1 -0
- package/dist/organizations/index.d.ts +2 -2
- package/dist/organizations/index.d.ts.map +1 -1
- package/dist/organizations/index.js +1 -1
- package/dist/organizations/index.js.map +1 -1
- package/dist/organizations/repository.d.ts +22 -32
- package/dist/organizations/repository.d.ts.map +1 -1
- package/dist/organizations/repository.js +64 -45
- package/dist/organizations/repository.js.map +1 -1
- package/dist/organizations/service.d.ts +14 -46
- package/dist/organizations/service.d.ts.map +1 -1
- package/dist/organizations/service.js +60 -112
- package/dist/organizations/service.js.map +1 -1
- package/dist/organizations/types.d.ts +1 -15
- package/dist/organizations/types.d.ts.map +1 -1
- package/dist/organizations/validators.d.ts +41 -0
- package/dist/organizations/validators.d.ts.map +1 -0
- package/dist/organizations/validators.js +48 -0
- package/dist/organizations/validators.js.map +1 -0
- package/dist/portability/apply.d.ts +15 -0
- package/dist/portability/apply.d.ts.map +1 -0
- package/dist/portability/apply.js +274 -0
- package/dist/portability/apply.js.map +1 -0
- package/dist/portability/authorization.d.ts +30 -0
- package/dist/portability/authorization.d.ts.map +1 -0
- package/dist/portability/authorization.js +130 -0
- package/dist/portability/authorization.js.map +1 -0
- package/dist/portability/cleanup.d.ts +29 -0
- package/dist/portability/cleanup.d.ts.map +1 -0
- package/dist/portability/cleanup.js +167 -0
- package/dist/portability/cleanup.js.map +1 -0
- package/dist/portability/export.d.ts +18 -0
- package/dist/portability/export.d.ts.map +1 -0
- package/dist/portability/export.js +125 -0
- package/dist/portability/export.js.map +1 -0
- package/dist/portability/import-repository.d.ts +204 -0
- package/dist/portability/import-repository.d.ts.map +1 -0
- package/dist/portability/import-repository.js +348 -0
- package/dist/portability/import-repository.js.map +1 -0
- package/dist/portability/import-user-client-writers.d.ts +40 -0
- package/dist/portability/import-user-client-writers.d.ts.map +1 -0
- package/dist/portability/import-user-client-writers.js +171 -0
- package/dist/portability/import-user-client-writers.js.map +1 -0
- package/dist/portability/index.d.ts +8 -0
- package/dist/portability/index.d.ts.map +1 -0
- package/dist/portability/index.js +8 -0
- package/dist/portability/index.js.map +1 -0
- package/dist/portability/plan-support.d.ts +137 -0
- package/dist/portability/plan-support.d.ts.map +1 -0
- package/dist/portability/plan-support.js +337 -0
- package/dist/portability/plan-support.js.map +1 -0
- package/dist/portability/plan.d.ts +34 -0
- package/dist/portability/plan.d.ts.map +1 -0
- package/dist/portability/plan.js +450 -0
- package/dist/portability/plan.js.map +1 -0
- package/dist/portability/repository.d.ts +95 -0
- package/dist/portability/repository.d.ts.map +1 -0
- package/dist/portability/repository.js +390 -0
- package/dist/portability/repository.js.map +1 -0
- package/dist/portability/schema.d.ts +591 -0
- package/dist/portability/schema.d.ts.map +1 -0
- package/dist/portability/schema.js +459 -0
- package/dist/portability/schema.js.map +1 -0
- package/dist/portability/types.d.ts +382 -0
- package/dist/portability/types.d.ts.map +1 -0
- package/dist/portability/types.js +19 -0
- package/dist/portability/types.js.map +1 -0
- package/dist/rbac/errors.d.ts +4 -0
- package/dist/rbac/errors.d.ts.map +1 -1
- package/dist/rbac/errors.js +7 -0
- package/dist/rbac/errors.js.map +1 -1
- package/dist/rbac/index.d.ts +3 -3
- package/dist/rbac/index.d.ts.map +1 -1
- package/dist/rbac/index.js +3 -3
- package/dist/rbac/index.js.map +1 -1
- package/dist/rbac/mapping-repository.d.ts +84 -9
- package/dist/rbac/mapping-repository.d.ts.map +1 -1
- package/dist/rbac/mapping-repository.js +222 -55
- package/dist/rbac/mapping-repository.js.map +1 -1
- package/dist/rbac/permission-repository.d.ts +36 -19
- package/dist/rbac/permission-repository.d.ts.map +1 -1
- package/dist/rbac/permission-repository.js +93 -35
- package/dist/rbac/permission-repository.js.map +1 -1
- package/dist/rbac/permission-service.d.ts +18 -19
- package/dist/rbac/permission-service.d.ts.map +1 -1
- package/dist/rbac/permission-service.js +100 -57
- package/dist/rbac/permission-service.js.map +1 -1
- package/dist/rbac/role-repository.d.ts +29 -24
- package/dist/rbac/role-repository.d.ts.map +1 -1
- package/dist/rbac/role-repository.js +66 -43
- package/dist/rbac/role-repository.js.map +1 -1
- package/dist/rbac/role-service.d.ts +35 -32
- package/dist/rbac/role-service.d.ts.map +1 -1
- package/dist/rbac/role-service.js +210 -96
- package/dist/rbac/role-service.js.map +1 -1
- package/dist/rbac/slugs.d.ts +16 -27
- package/dist/rbac/slugs.d.ts.map +1 -1
- package/dist/rbac/slugs.js +36 -59
- package/dist/rbac/slugs.js.map +1 -1
- package/dist/rbac/types.d.ts +2 -4
- package/dist/rbac/types.d.ts.map +1 -1
- package/dist/rbac/types.js.map +1 -1
- package/dist/rbac/user-role-service.d.ts +23 -24
- package/dist/rbac/user-role-service.d.ts.map +1 -1
- package/dist/rbac/user-role-service.js +117 -61
- package/dist/rbac/user-role-service.js.map +1 -1
- package/dist/routes/applications.d.ts +4 -2
- package/dist/routes/applications.d.ts.map +1 -1
- package/dist/routes/applications.js +57 -19
- package/dist/routes/applications.js.map +1 -1
- package/dist/routes/audit.js +1 -1
- package/dist/routes/audit.js.map +1 -1
- package/dist/routes/branding.d.ts +3 -3
- package/dist/routes/branding.d.ts.map +1 -1
- package/dist/routes/branding.js +44 -16
- package/dist/routes/branding.js.map +1 -1
- package/dist/routes/bulk.d.ts +0 -5
- package/dist/routes/bulk.d.ts.map +1 -1
- package/dist/routes/bulk.js +3 -5
- package/dist/routes/bulk.js.map +1 -1
- package/dist/routes/clients.d.ts +4 -4
- package/dist/routes/clients.d.ts.map +1 -1
- package/dist/routes/clients.js +113 -52
- package/dist/routes/clients.js.map +1 -1
- package/dist/routes/config.d.ts +17 -12
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +165 -64
- package/dist/routes/config.js.map +1 -1
- package/dist/routes/custom-claims.d.ts.map +1 -1
- package/dist/routes/custom-claims.js +8 -2
- package/dist/routes/custom-claims.js.map +1 -1
- package/dist/routes/exports.d.ts +2 -1
- package/dist/routes/exports.d.ts.map +1 -1
- package/dist/routes/exports.js +57 -1
- package/dist/routes/exports.js.map +1 -1
- package/dist/routes/imports.d.ts +2 -2
- package/dist/routes/imports.d.ts.map +1 -1
- package/dist/routes/imports.js +95 -40
- package/dist/routes/imports.js.map +1 -1
- package/dist/routes/interactions.d.ts.map +1 -1
- package/dist/routes/interactions.js +113 -87
- package/dist/routes/interactions.js.map +1 -1
- package/dist/routes/invitation.d.ts.map +1 -1
- package/dist/routes/invitation.js +28 -27
- package/dist/routes/invitation.js.map +1 -1
- package/dist/routes/keys.d.ts.map +1 -1
- package/dist/routes/keys.js +26 -13
- package/dist/routes/keys.js.map +1 -1
- package/dist/routes/magic-link.d.ts.map +1 -1
- package/dist/routes/magic-link.js +5 -17
- package/dist/routes/magic-link.js.map +1 -1
- package/dist/routes/organizations.d.ts +1 -2
- package/dist/routes/organizations.d.ts.map +1 -1
- package/dist/routes/organizations.js +43 -104
- package/dist/routes/organizations.js.map +1 -1
- package/dist/routes/password-reset.d.ts.map +1 -1
- package/dist/routes/password-reset.js +13 -35
- package/dist/routes/password-reset.js.map +1 -1
- package/dist/routes/permissions.d.ts +1 -1
- package/dist/routes/permissions.d.ts.map +1 -1
- package/dist/routes/permissions.js +58 -17
- package/dist/routes/permissions.js.map +1 -1
- package/dist/routes/public-branding.d.ts +16 -0
- package/dist/routes/public-branding.d.ts.map +1 -0
- package/dist/routes/public-branding.js +52 -0
- package/dist/routes/public-branding.js.map +1 -0
- package/dist/routes/roles.d.ts +1 -1
- package/dist/routes/roles.d.ts.map +1 -1
- package/dist/routes/roles.js +63 -21
- package/dist/routes/roles.js.map +1 -1
- package/dist/routes/sessions.d.ts.map +1 -1
- package/dist/routes/sessions.js +23 -12
- package/dist/routes/sessions.js.map +1 -1
- package/dist/routes/two-factor.d.ts.map +1 -1
- package/dist/routes/two-factor.js +91 -38
- package/dist/routes/two-factor.js.map +1 -1
- package/dist/routes/user-roles.d.ts.map +1 -1
- package/dist/routes/user-roles.js +56 -9
- package/dist/routes/user-roles.js.map +1 -1
- package/dist/routes/users.d.ts +4 -8
- package/dist/routes/users.d.ts.map +1 -1
- package/dist/routes/users.js +108 -265
- package/dist/routes/users.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +53 -37
- package/dist/server.js.map +1 -1
- package/dist/two-factor/errors.d.ts +9 -0
- package/dist/two-factor/errors.d.ts.map +1 -1
- package/dist/two-factor/errors.js +12 -0
- package/dist/two-factor/errors.js.map +1 -1
- package/dist/two-factor/index.d.ts +5 -4
- package/dist/two-factor/index.d.ts.map +1 -1
- package/dist/two-factor/index.js +4 -4
- package/dist/two-factor/index.js.map +1 -1
- package/dist/two-factor/repository.d.ts +17 -6
- package/dist/two-factor/repository.d.ts.map +1 -1
- package/dist/two-factor/repository.js +37 -9
- package/dist/two-factor/repository.js.map +1 -1
- package/dist/two-factor/service.d.ts.map +1 -1
- package/dist/two-factor/service.js +26 -19
- package/dist/two-factor/service.js.map +1 -1
- package/dist/two-factor/totp.d.ts +13 -2
- package/dist/two-factor/totp.d.ts.map +1 -1
- package/dist/two-factor/totp.js +20 -7
- package/dist/two-factor/totp.js.map +1 -1
- package/dist/two-factor/types.d.ts +3 -0
- package/dist/two-factor/types.d.ts.map +1 -1
- package/dist/two-factor/types.js +5 -0
- package/dist/two-factor/types.js.map +1 -1
- package/dist/users/gdpr.d.ts +2 -40
- package/dist/users/gdpr.d.ts.map +1 -1
- package/dist/users/gdpr.js +3 -110
- package/dist/users/gdpr.js.map +1 -1
- package/dist/users/index.d.ts +5 -4
- package/dist/users/index.d.ts.map +1 -1
- package/dist/users/index.js +5 -4
- package/dist/users/index.js.map +1 -1
- package/dist/users/repository.d.ts +49 -3
- package/dist/users/repository.d.ts.map +1 -1
- package/dist/users/repository.js +169 -18
- package/dist/users/repository.js.map +1 -1
- package/dist/users/service.d.ts +19 -51
- package/dist/users/service.d.ts.map +1 -1
- package/dist/users/service.js +72 -122
- package/dist/users/service.js.map +1 -1
- package/dist/users/types.d.ts +4 -5
- package/dist/users/types.d.ts.map +1 -1
- package/dist/users/types.js.map +1 -1
- package/dist/users/validators.d.ts +28 -0
- package/dist/users/validators.d.ts.map +1 -0
- package/dist/users/validators.js +25 -0
- package/dist/users/validators.js.map +1 -0
- package/locales/default/en/errors.json +2 -1
- package/migrations/024_application_client_correction.sql +39 -0
- package/migrations/025_record_deletion_lifecycle.sql +26 -0
- package/migrations/026_simplify_user_lifecycle.sql +33 -0
- package/migrations/027_branding_asset_size_limits.sql +19 -0
- package/migrations/028_totp_replay_protection.sql +17 -0
- package/migrations/029_public_session_identifiers.sql +16 -0
- package/migrations/030_global_configuration_catalog.sql +39 -0
- package/migrations/031_monotonic_updated_at.sql +28 -0
- package/migrations/032_client_require_consent.sql +15 -0
- package/package.json +2 -2
- package/dist/lib/data-import-plan.d.ts +0 -50
- package/dist/lib/data-import-plan.d.ts.map +0 -1
- package/dist/lib/data-import-plan.js +0 -235
- package/dist/lib/data-import-plan.js.map +0 -1
- package/dist/lib/data-import.d.ts +0 -276
- package/dist/lib/data-import.d.ts.map +0 -1
- package/dist/lib/data-import.js +0 -1694
- package/dist/lib/data-import.js.map +0 -1
package/dist/routes/imports.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Data import API routes.
|
|
3
3
|
*
|
|
4
|
-
* Provides
|
|
5
|
-
* Supports
|
|
4
|
+
* Provides the Admin endpoint for previewing or atomically applying a strict portability manifest.
|
|
5
|
+
* Supports dry-run, keep-existing, and update-existing behavior.
|
|
6
6
|
*
|
|
7
7
|
* Route structure:
|
|
8
8
|
* POST /api/admin/import — Import configuration manifest
|
|
@@ -10,21 +10,46 @@
|
|
|
10
10
|
* @see 07-import-export-invitation.md
|
|
11
11
|
*/
|
|
12
12
|
import Router from '@koa/router';
|
|
13
|
-
import
|
|
13
|
+
import bodyParser from 'koa-bodyparser';
|
|
14
14
|
import { requireAdminAuth } from '../middleware/admin-auth.js';
|
|
15
15
|
import { requirePermission } from '../middleware/require-permission.js';
|
|
16
16
|
import { ADMIN_PERMISSIONS } from '../lib/admin-permissions.js';
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
17
|
+
import { logger } from '../lib/logger.js';
|
|
18
|
+
import { applyPortabilityManifest } from '../portability/apply.js';
|
|
19
|
+
import { importManifestRequestSchema, PortabilityError, requirePortabilityAuthorization, } from '../portability/index.js';
|
|
20
|
+
import { buildPortabilityPlan } from '../portability/plan.js';
|
|
21
|
+
/** Route-owned JSON parser used only after authentication and the base import permission. */
|
|
22
|
+
const importManifestBodyParser = bodyParser({
|
|
23
|
+
enableTypes: ['json'],
|
|
24
|
+
jsonLimit: '64mb',
|
|
25
|
+
});
|
|
26
|
+
/** Return the public status carried by a body-parser error, when present. */
|
|
27
|
+
function bodyParserStatus(error) {
|
|
28
|
+
if (typeof error !== 'object' || error === null)
|
|
29
|
+
return undefined;
|
|
30
|
+
const status = Reflect.get(error, 'status');
|
|
31
|
+
return typeof status === 'number' ? status : undefined;
|
|
32
|
+
}
|
|
33
|
+
/** Parse one protected manifest body and map parser failures to fixed safe responses. */
|
|
34
|
+
async function parseImportManifestBody(ctx, next) {
|
|
35
|
+
try {
|
|
36
|
+
await importManifestBodyParser(ctx, next);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
const status = bodyParserStatus(error);
|
|
40
|
+
if (status === 413) {
|
|
41
|
+
ctx.status = 413;
|
|
42
|
+
ctx.body = { error: 'Import manifest is too large', code: 'import_manifest_too_large' };
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (status === 400) {
|
|
46
|
+
ctx.status = 400;
|
|
47
|
+
ctx.body = { error: 'Invalid import manifest', code: 'import_manifest_invalid' };
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
28
53
|
// ---------------------------------------------------------------------------
|
|
29
54
|
// Router factory
|
|
30
55
|
// ---------------------------------------------------------------------------
|
|
@@ -33,40 +58,70 @@ const importRequestSchema = z
|
|
|
33
58
|
* @returns Configured Koa router
|
|
34
59
|
*/
|
|
35
60
|
export function createImportRouter() {
|
|
36
|
-
const router = new Router({
|
|
37
|
-
router.use(requireAdminAuth());
|
|
61
|
+
const router = new Router({ sensitive: false, strict: false });
|
|
38
62
|
// -------------------------------------------------------------------------
|
|
39
63
|
// POST / — Import configuration
|
|
40
64
|
// -------------------------------------------------------------------------
|
|
41
|
-
router.post('/',
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
65
|
+
router.post('/api/admin/import', async (ctx, next) => {
|
|
66
|
+
ctx.set('Cache-Control', 'no-store');
|
|
67
|
+
await next();
|
|
68
|
+
}, requireAdminAuth(), requirePermission(ADMIN_PERMISSIONS.IMPORT_WRITE), parseImportManifestBody, async (ctx) => {
|
|
69
|
+
const parsed = importManifestRequestSchema.safeParse(ctx.request.body);
|
|
70
|
+
if (!parsed.success) {
|
|
71
|
+
ctx.status = 400;
|
|
72
|
+
ctx.body = { error: 'Invalid import manifest', code: 'import_manifest_invalid' };
|
|
73
|
+
return;
|
|
47
74
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
75
|
+
await requirePortabilityAuthorization('import', () => parsed.data.manifest.categories)(ctx, async () => {
|
|
76
|
+
await handleManifestImport(ctx, parsed.data);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
return router;
|
|
80
|
+
}
|
|
81
|
+
/** Preview or apply a validated manifest and expose only fixed safe failures. */
|
|
82
|
+
async function handleManifestImport(ctx, request) {
|
|
83
|
+
try {
|
|
84
|
+
if (request.mode === 'dry-run') {
|
|
85
|
+
const result = await buildPortabilityPlan(request.manifest, request.mode);
|
|
86
|
+
if (result.errors.length > 0) {
|
|
87
|
+
ctx.status = 409;
|
|
88
|
+
ctx.body = { error: 'Import plan rejected', code: 'import_plan_rejected', result };
|
|
61
89
|
return;
|
|
62
90
|
}
|
|
63
|
-
ctx.
|
|
91
|
+
ctx.body = result;
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
ctx.body = await applyPortabilityManifest(request.manifest, request.mode, portabilityActor(ctx));
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
if (error instanceof PortabilityError && error.code === 'import_plan_rejected') {
|
|
98
|
+
ctx.status = 409;
|
|
64
99
|
ctx.body = {
|
|
65
|
-
error: 'Import
|
|
66
|
-
code:
|
|
100
|
+
error: 'Import plan rejected',
|
|
101
|
+
code: error.code,
|
|
102
|
+
result: error.result,
|
|
67
103
|
};
|
|
104
|
+
return;
|
|
68
105
|
}
|
|
69
|
-
|
|
70
|
-
|
|
106
|
+
const requestId = ctx.state.requestId;
|
|
107
|
+
logger.error({
|
|
108
|
+
operation: 'import',
|
|
109
|
+
code: 'import_execution_failed',
|
|
110
|
+
request_id: requestId,
|
|
111
|
+
mode: request.mode,
|
|
112
|
+
}, 'Portability import failed');
|
|
113
|
+
ctx.status = 503;
|
|
114
|
+
ctx.body = { error: 'Import failed', code: 'import_execution_failed', request_id: requestId };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/** Build the audit actor from the authenticated Admin identity. */
|
|
118
|
+
function portabilityActor(ctx) {
|
|
119
|
+
const adminUser = ctx.state.adminUser;
|
|
120
|
+
if (!adminUser)
|
|
121
|
+
throw new Error('Admin identity is unavailable');
|
|
122
|
+
return {
|
|
123
|
+
userId: adminUser.id,
|
|
124
|
+
controlPlaneOrganizationId: adminUser.organizationId,
|
|
125
|
+
};
|
|
71
126
|
}
|
|
72
127
|
//# sourceMappingURL=imports.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imports.js","sourceRoot":"","sources":["../../src/routes/imports.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"imports.js","sourceRoot":"","sources":["../../src/routes/imports.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactions.d.ts","sourceRoot":"","sources":["../../src/routes/interactions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAC1C,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,iBAAiB,EAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,0BAA0B,EAC1B,wBAAwB,EACxB,4BAA4B,EAC7B,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"interactions.d.ts","sourceRoot":"","sources":["../../src/routes/interactions.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,6 +23,7 @@ import Router from '@koa/router';
|
|
|
23
23
|
import { generateCsrfToken, verifyCsrfToken, setCsrfCookie, getCsrfFromCookie, } from '../auth/csrf.js';
|
|
24
24
|
import { checkRateLimit, resetRateLimit, buildLoginRateLimitKey, buildMagicLinkRateLimitKey, loadLoginRateLimitConfig, loadMagicLinkRateLimitConfig, } from '../auth/rate-limiter.js';
|
|
25
25
|
import { sendOtpCodeEmail } from '../auth/email-service.js';
|
|
26
|
+
import { resolveEffectiveBranding } from '../auth/effective-branding.js';
|
|
26
27
|
import { enqueueAccountRecovery } from '../auth/recovery-service.js';
|
|
27
28
|
import { resolveLocale, getTranslationFunction } from '../auth/i18n.js';
|
|
28
29
|
import { renderPage } from '../auth/template-engine.js';
|
|
@@ -61,13 +62,6 @@ const defaultEnumerationDependencies = {
|
|
|
61
62
|
// ---------------------------------------------------------------------------
|
|
62
63
|
// Helpers
|
|
63
64
|
// ---------------------------------------------------------------------------
|
|
64
|
-
/**
|
|
65
|
-
* Build a branding context object from organization data.
|
|
66
|
-
* Used to populate template context with org-specific branding.
|
|
67
|
-
*
|
|
68
|
-
* @param org - Organization with branding fields
|
|
69
|
-
* @returns Branding context for templates
|
|
70
|
-
*/
|
|
71
65
|
/**
|
|
72
66
|
* Resolve the effective login methods for an OIDC provider Client.
|
|
73
67
|
*
|
|
@@ -95,15 +89,6 @@ function resolveLoginMethodsFromOidcClient(client, org) {
|
|
|
95
89
|
const normalized = Array.isArray(raw) ? raw : null;
|
|
96
90
|
return resolveLoginMethods(org, { loginMethods: normalized });
|
|
97
91
|
}
|
|
98
|
-
function buildBrandingFromOrg(org) {
|
|
99
|
-
return {
|
|
100
|
-
logoUrl: org.brandingLogoUrl,
|
|
101
|
-
faviconUrl: org.brandingFaviconUrl,
|
|
102
|
-
primaryColor: org.brandingPrimaryColor ?? '#3B82F6',
|
|
103
|
-
companyName: org.brandingCompanyName ?? org.name,
|
|
104
|
-
customCss: org.brandingCustomCss,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
92
|
/**
|
|
108
93
|
* Build a base template context from an interaction context.
|
|
109
94
|
* Shared across all interaction route handlers to provide consistent
|
|
@@ -113,11 +98,11 @@ function buildBrandingFromOrg(org) {
|
|
|
113
98
|
* @param locale - Resolved locale string
|
|
114
99
|
* @param csrfToken - CSRF token for form protection
|
|
115
100
|
* @param orgSlug - Organization slug for template resolution
|
|
116
|
-
* @returns Base template context (without the `t` translation function)
|
|
101
|
+
* @returns Base template context (without the `t` translation function).
|
|
117
102
|
*/
|
|
118
|
-
function buildBaseContext(ctx, locale, csrfToken, orgSlug) {
|
|
103
|
+
async function buildBaseContext(ctx, locale, csrfToken, orgSlug) {
|
|
119
104
|
return {
|
|
120
|
-
branding:
|
|
105
|
+
branding: await resolveEffectiveBranding(ctx.state.organization),
|
|
121
106
|
locale,
|
|
122
107
|
csrfToken,
|
|
123
108
|
orgSlug,
|
|
@@ -133,6 +118,7 @@ function buildBaseContext(ctx, locale, csrfToken, orgSlug) {
|
|
|
133
118
|
* @param statusCode - HTTP status code (default: 200)
|
|
134
119
|
*/
|
|
135
120
|
async function renderAndRespond(ctx, pageName, context, statusCode = 200, renderer = renderPage) {
|
|
121
|
+
ctx.state.brandingImageSources = context.branding.imageSources;
|
|
136
122
|
const html = await renderer(pageName, context);
|
|
137
123
|
ctx.status = statusCode;
|
|
138
124
|
ctx.type = 'text/html';
|
|
@@ -408,7 +394,7 @@ async function showLogin(ctx, provider) {
|
|
|
408
394
|
const showPassword = effectiveMethods.includes('password');
|
|
409
395
|
const showMagicLink = effectiveMethods.includes('magic_link');
|
|
410
396
|
const context = {
|
|
411
|
-
...buildBaseContext(ctx, locale, csrfToken, org.slug),
|
|
397
|
+
...(await buildBaseContext(ctx, locale, csrfToken, org.slug)),
|
|
412
398
|
t,
|
|
413
399
|
interaction: {
|
|
414
400
|
uid: interaction.uid,
|
|
@@ -451,7 +437,7 @@ async function renderMagicLinkSuccessPage(ctx, org) {
|
|
|
451
437
|
const t = getTranslationFunction(locale, org.slug);
|
|
452
438
|
const csrfToken = generateCsrfToken();
|
|
453
439
|
const context = {
|
|
454
|
-
branding:
|
|
440
|
+
branding: await resolveEffectiveBranding(org),
|
|
455
441
|
locale,
|
|
456
442
|
t,
|
|
457
443
|
csrfToken,
|
|
@@ -577,8 +563,9 @@ async function processLogin(ctx, provider, dependencies) {
|
|
|
577
563
|
email: user.email,
|
|
578
564
|
},
|
|
579
565
|
}, { mergeWithLastSubmission: true });
|
|
580
|
-
//
|
|
581
|
-
|
|
566
|
+
// Enrolled email users can receive their challenge immediately. Unenrolled users receive
|
|
567
|
+
// one only after choosing email during setup, so they are not sent duplicate or unwanted codes.
|
|
568
|
+
if (user.twoFactorEnabled && twoFactorMethod === 'email') {
|
|
582
569
|
try {
|
|
583
570
|
const otpCode = await sendOtpCode(user.id, user.email, org.id);
|
|
584
571
|
// Send the OTP code via email (fire-and-forget)
|
|
@@ -587,13 +574,7 @@ async function processLogin(ctx, provider, dependencies) {
|
|
|
587
574
|
email: user.email,
|
|
588
575
|
givenName: user.givenName,
|
|
589
576
|
familyName: user.familyName,
|
|
590
|
-
},
|
|
591
|
-
id: org.id,
|
|
592
|
-
slug: org.slug,
|
|
593
|
-
brandingLogoUrl: org.brandingLogoUrl,
|
|
594
|
-
brandingPrimaryColor: org.brandingPrimaryColor,
|
|
595
|
-
brandingCompanyName: org.brandingCompanyName,
|
|
596
|
-
}, otpCode, 10, locale);
|
|
577
|
+
}, org, otpCode, 10, locale);
|
|
597
578
|
}
|
|
598
579
|
catch {
|
|
599
580
|
logger.warn({ event: 'login-otp-delivery-failed' }, 'Initial OTP delivery failed');
|
|
@@ -737,7 +718,7 @@ async function handleSendMagicLink(ctx, provider, dependencies) {
|
|
|
737
718
|
// Always render the "check your email" page — prevents user enumeration
|
|
738
719
|
const csrfToken = dependencies.generateCsrfToken();
|
|
739
720
|
const context = {
|
|
740
|
-
...buildBaseContext(ctx, locale, csrfToken, org.slug),
|
|
721
|
+
...(await buildBaseContext(ctx, locale, csrfToken, org.slug)),
|
|
741
722
|
t,
|
|
742
723
|
email,
|
|
743
724
|
loginUrl: `/interaction/${interaction.uid}`,
|
|
@@ -749,12 +730,82 @@ async function handleSendMagicLink(ctx, provider, dependencies) {
|
|
|
749
730
|
await renderErrorPage(ctx, 'errors.interaction_expired');
|
|
750
731
|
}
|
|
751
732
|
}
|
|
733
|
+
/**
|
|
734
|
+
* Report whether the authorization request carries an explicit `prompt=consent`.
|
|
735
|
+
*
|
|
736
|
+
* @param params - Authorization request parameters from the interaction
|
|
737
|
+
* @returns `true` when the client explicitly requested consent
|
|
738
|
+
*/
|
|
739
|
+
function requestedExplicitConsent(params) {
|
|
740
|
+
const prompt = typeof params.prompt === 'string' ? params.prompt : '';
|
|
741
|
+
return prompt.split(' ').includes('consent');
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Report whether the interaction has no scope, claim, or resource left to grant.
|
|
745
|
+
*
|
|
746
|
+
* @param details - The interaction prompt details listing what is missing
|
|
747
|
+
* @returns `true` when nothing remains to consent to
|
|
748
|
+
*/
|
|
749
|
+
function nothingMissing(details) {
|
|
750
|
+
const missingScopes = details.missingOIDCScope ?? [];
|
|
751
|
+
const missingClaims = details.missingOIDCClaims ?? [];
|
|
752
|
+
const missingResources = details.missingResourceScopes ?? {};
|
|
753
|
+
return ([...missingScopes].length === 0 &&
|
|
754
|
+
[...missingClaims].length === 0 &&
|
|
755
|
+
Object.values(missingResources).every((scopes) => [...scopes].length === 0));
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* Persist a consent grant covering the interaction's missing scopes and finish.
|
|
759
|
+
*
|
|
760
|
+
* Grants exactly what the provider listed as missing plus `offline_access` when
|
|
761
|
+
* requested (the provider treats it as a consent signal and may omit it from
|
|
762
|
+
* `missingOIDCScope`, but the grant must include it for a refresh token).
|
|
763
|
+
*
|
|
764
|
+
* @param ctx - Koa context with organization state
|
|
765
|
+
* @param provider - OIDC provider instance
|
|
766
|
+
* @param interaction - Current interaction details
|
|
767
|
+
* @param description - Audit description for the recorded grant
|
|
768
|
+
*/
|
|
769
|
+
async function grantConsentAndFinish(ctx, provider, interaction, description) {
|
|
770
|
+
const params = interaction.params;
|
|
771
|
+
const details = interaction.prompt.details;
|
|
772
|
+
const clientId = params.client_id;
|
|
773
|
+
const grant = new provider.Grant({ accountId: interaction.session?.accountId, clientId });
|
|
774
|
+
if (details.missingOIDCScope) {
|
|
775
|
+
grant.addOIDCScope([...details.missingOIDCScope].join(' '));
|
|
776
|
+
}
|
|
777
|
+
if (details.missingOIDCClaims) {
|
|
778
|
+
grant.addOIDCClaims([...details.missingOIDCClaims]);
|
|
779
|
+
}
|
|
780
|
+
if (details.missingResourceScopes) {
|
|
781
|
+
for (const [indicator, scopes] of Object.entries(details.missingResourceScopes)) {
|
|
782
|
+
grant.addResourceScope(indicator, [...scopes].join(' '));
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
const requestedScope = params.scope ?? '';
|
|
786
|
+
if (requestedScope.includes('offline_access')) {
|
|
787
|
+
grant.addOIDCScope('offline_access');
|
|
788
|
+
}
|
|
789
|
+
const grantId = await grant.save();
|
|
790
|
+
writeAuditLog({
|
|
791
|
+
organizationId: ctx.state.organization.id,
|
|
792
|
+
userId: interaction.session?.accountId,
|
|
793
|
+
eventType: 'user.consent.granted',
|
|
794
|
+
eventCategory: 'authentication',
|
|
795
|
+
description,
|
|
796
|
+
});
|
|
797
|
+
await provider.interactionFinished(ctx.req, ctx.res, { consent: { grantId } }, { mergeWithLastSubmission: true });
|
|
798
|
+
}
|
|
752
799
|
/**
|
|
753
800
|
* Show the consent page for an OIDC interaction.
|
|
754
801
|
*
|
|
755
|
-
*
|
|
756
|
-
*
|
|
757
|
-
*
|
|
802
|
+
* The decision is trust-driven rather than organization-driven:
|
|
803
|
+
* - Nothing is missing → finish without rendering and reuse or create the
|
|
804
|
+
* grant. An explicit `prompt=consent` is ignored so a user who already
|
|
805
|
+
* consented is never asked again.
|
|
806
|
+
* - Something is missing → render the consent page when the client requires
|
|
807
|
+
* consent (`requireConsent`) or explicitly requested `prompt=consent`;
|
|
808
|
+
* otherwise auto-consent the trusted first-party client.
|
|
758
809
|
*
|
|
759
810
|
* @param ctx - Koa context with organization state
|
|
760
811
|
* @param provider - OIDC provider instance
|
|
@@ -766,66 +817,40 @@ async function showConsent(ctx, provider) {
|
|
|
766
817
|
// Resolve organization from the interaction's client_id
|
|
767
818
|
await resolveOrganizationForInteraction(ctx, params.client_id, interaction.uid);
|
|
768
819
|
const org = ctx.state.organization;
|
|
769
|
-
// Resolve locale for the consent page
|
|
770
|
-
const uiLocales = params.ui_locales;
|
|
771
|
-
const acceptLanguage = ctx.get('Accept-Language') || undefined;
|
|
772
|
-
const locale = await resolveLocale(uiLocales, acceptLanguage, org.defaultLocale);
|
|
773
|
-
const t = getTranslationFunction(locale, org.slug);
|
|
774
|
-
// Auto-consent for first-party apps: if the client metadata includes
|
|
775
|
-
// the org ID matching the current tenant, skip the consent screen
|
|
776
820
|
const clientId = params.client_id;
|
|
777
821
|
const client = await provider.Client.find(clientId);
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
grant.addOIDCScope([...scopes].join(' '));
|
|
789
|
-
}
|
|
790
|
-
if (details.missingOIDCClaims) {
|
|
791
|
-
const claims = details.missingOIDCClaims;
|
|
792
|
-
grant.addOIDCClaims([...claims]);
|
|
793
|
-
}
|
|
794
|
-
if (details.missingResourceScopes) {
|
|
795
|
-
for (const [indicator, scopes] of Object.entries(details.missingResourceScopes)) {
|
|
796
|
-
grant.addResourceScope(indicator, [...scopes].join(' '));
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
// Explicitly grant offline_access if requested — node-oidc-provider
|
|
800
|
-
// treats it as a consent signal and may not include it in missingOIDCScope,
|
|
801
|
-
// but the Grant must include it for a refresh_token to be issued.
|
|
802
|
-
const requestedScope = params.scope ?? '';
|
|
803
|
-
if (requestedScope.includes('offline_access')) {
|
|
804
|
-
grant.addOIDCScope('offline_access');
|
|
805
|
-
}
|
|
806
|
-
const grantId = await grant.save();
|
|
807
|
-
const result = {
|
|
808
|
-
consent: { grantId },
|
|
809
|
-
};
|
|
810
|
-
writeAuditLog({
|
|
811
|
-
organizationId: org.id,
|
|
812
|
-
userId: interaction.session?.accountId,
|
|
813
|
-
eventType: 'user.consent.granted',
|
|
814
|
-
eventCategory: 'authentication',
|
|
815
|
-
description: `Auto-consent granted for first-party client ${clientId}`,
|
|
816
|
-
});
|
|
817
|
-
await provider.interactionFinished(ctx.req, ctx.res, result, {
|
|
818
|
-
mergeWithLastSubmission: true,
|
|
819
|
-
});
|
|
822
|
+
const requiresConsent = client?.metadata()?.requireConsent === true;
|
|
823
|
+
const details = prompt.details;
|
|
824
|
+
// Nothing left to grant: finish without rendering, even under prompt=consent.
|
|
825
|
+
// Reuse the provider's resolved grant; creating a new grant here would
|
|
826
|
+
// replace it with an empty one and drop the scopes the user already
|
|
827
|
+
// approved, which would make the provider prompt again.
|
|
828
|
+
if (nothingMissing(details)) {
|
|
829
|
+
const existingGrantId = interaction.grantId;
|
|
830
|
+
if (existingGrantId !== undefined) {
|
|
831
|
+
await provider.interactionFinished(ctx.req, ctx.res, { consent: { grantId: existingGrantId } }, { mergeWithLastSubmission: true });
|
|
820
832
|
return;
|
|
821
833
|
}
|
|
834
|
+
await grantConsentAndFinish(ctx, provider, interaction, `Consent already granted for client ${clientId}`);
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
// A new scope, claim, or resource is requested. Ask only when the client
|
|
838
|
+
// requires consent or explicitly requested it; trusted clients auto-consent.
|
|
839
|
+
const explicitConsent = requestedExplicitConsent(params);
|
|
840
|
+
if (!requiresConsent && !explicitConsent) {
|
|
841
|
+
await grantConsentAndFinish(ctx, provider, interaction, `Auto-consent granted for first-party client ${clientId}`);
|
|
842
|
+
return;
|
|
822
843
|
}
|
|
823
|
-
//
|
|
844
|
+
// Resolve locale for the consent page
|
|
845
|
+
const uiLocales = params.ui_locales;
|
|
846
|
+
const acceptLanguage = ctx.get('Accept-Language') || undefined;
|
|
847
|
+
const locale = await resolveLocale(uiLocales, acceptLanguage, org.defaultLocale);
|
|
848
|
+
const t = getTranslationFunction(locale, org.slug);
|
|
824
849
|
const csrfToken = generateCsrfToken();
|
|
825
850
|
setCsrfCookie(ctx, csrfToken);
|
|
826
851
|
const requestedScopes = (params.scope ?? '').split(' ').filter(Boolean);
|
|
827
852
|
const context = {
|
|
828
|
-
...buildBaseContext(ctx, locale, csrfToken, org.slug),
|
|
853
|
+
...(await buildBaseContext(ctx, locale, csrfToken, org.slug)),
|
|
829
854
|
t,
|
|
830
855
|
interaction: {
|
|
831
856
|
uid: interaction.uid,
|
|
@@ -1008,7 +1033,7 @@ async function renderLoginWithError(ctx, provider, interaction, t, locale, email
|
|
|
1008
1033
|
const showPassword = effectiveMethods.includes('password');
|
|
1009
1034
|
const showMagicLink = effectiveMethods.includes('magic_link');
|
|
1010
1035
|
const context = {
|
|
1011
|
-
...buildBaseContext(ctx, locale, csrfToken, org.slug),
|
|
1036
|
+
...(await buildBaseContext(ctx, locale, csrfToken, org.slug)),
|
|
1012
1037
|
t,
|
|
1013
1038
|
interaction: {
|
|
1014
1039
|
uid: interaction.uid,
|
|
@@ -1048,13 +1073,14 @@ async function renderErrorPage(ctx, errorKey) {
|
|
|
1048
1073
|
const csrfToken = generateCsrfToken();
|
|
1049
1074
|
const context = {
|
|
1050
1075
|
branding: org
|
|
1051
|
-
?
|
|
1076
|
+
? await resolveEffectiveBranding(org)
|
|
1052
1077
|
: {
|
|
1053
1078
|
logoUrl: null,
|
|
1054
1079
|
faviconUrl: null,
|
|
1055
1080
|
primaryColor: '#3B82F6',
|
|
1056
1081
|
companyName: 'Porta',
|
|
1057
1082
|
customCss: null,
|
|
1083
|
+
imageSources: [],
|
|
1058
1084
|
},
|
|
1059
1085
|
locale,
|
|
1060
1086
|
t,
|