@authup/server-core 1.0.0-beta.57 → 1.0.0-beta.59
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/dist/adapters/database/logger/module.mjs +2 -4
- package/dist/adapters/database/logger/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/identity-provider/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/entities/identity-provider/module.mjs +1 -1
- package/dist/adapters/http/controllers/entities/identity-provider/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/index.mjs +2 -1
- package/dist/adapters/http/controllers/workflows/account/index.d.ts +2 -0
- package/dist/adapters/http/controllers/workflows/account/index.d.ts.map +1 -0
- package/dist/adapters/http/controllers/workflows/account/index.mjs +5 -0
- package/dist/adapters/http/controllers/workflows/account/module.d.ts +24 -0
- package/dist/adapters/http/controllers/workflows/account/module.d.ts.map +1 -0
- package/dist/adapters/http/controllers/workflows/account/module.mjs +63 -0
- package/dist/adapters/http/controllers/workflows/account/module.mjs.map +1 -0
- package/dist/adapters/http/controllers/workflows/activate/module.mjs +1 -1
- package/dist/adapters/http/controllers/workflows/authorize/module.mjs +2 -2
- package/dist/adapters/http/controllers/workflows/authorize/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/index.d.ts +1 -0
- package/dist/adapters/http/controllers/workflows/index.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/index.mjs +3 -1
- package/dist/adapters/http/controllers/workflows/logout/module.mjs +2 -2
- package/dist/adapters/http/controllers/workflows/logout/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/password-forgot/module.mjs +1 -1
- package/dist/adapters/http/controllers/workflows/password-reset/module.mjs +1 -1
- package/dist/adapters/http/controllers/workflows/register/module.mjs +1 -1
- package/dist/adapters/http/controllers/workflows/userinfo/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/userinfo/module.mjs +5 -1
- package/dist/adapters/http/controllers/workflows/userinfo/module.mjs.map +1 -1
- package/dist/adapters/http/index.mjs +3 -1
- package/dist/adapters/http/middleware/built-in/assets.d.ts +8 -1
- package/dist/adapters/http/middleware/built-in/assets.d.ts.map +1 -1
- package/dist/adapters/http/middleware/built-in/assets.mjs +48 -4
- package/dist/adapters/http/middleware/built-in/assets.mjs.map +1 -1
- package/dist/adapters/http/middleware/built-in/authorization/module.mjs +2 -1
- package/dist/adapters/http/middleware/built-in/authorization/module.mjs.map +1 -1
- package/dist/adapters/http/middleware/built-in/index.d.ts +2 -0
- package/dist/adapters/http/middleware/built-in/index.d.ts.map +1 -1
- package/dist/adapters/http/middleware/built-in/index.mjs +2 -1
- package/dist/adapters/http/middleware/built-in/rate-limit.mjs +2 -2
- package/dist/adapters/http/middleware/built-in/rate-limit.mjs.map +1 -1
- package/dist/adapters/http/middleware/built-in/theme.d.ts +15 -0
- package/dist/adapters/http/middleware/built-in/theme.d.ts.map +1 -0
- package/dist/adapters/http/middleware/built-in/theme.mjs +27 -0
- package/dist/adapters/http/middleware/built-in/theme.mjs.map +1 -0
- package/dist/adapters/http/middleware/built-in/types.d.ts +14 -0
- package/dist/adapters/http/middleware/built-in/types.d.ts.map +1 -0
- package/dist/adapters/http/middleware/built-in/ui-http-client.d.ts +1 -1
- package/dist/adapters/http/middleware/built-in/ui-http-client.mjs +1 -1
- package/dist/adapters/http/middleware/built-in/ui-http-client.mjs.map +1 -1
- package/dist/adapters/http/middleware/index.mjs +2 -1
- package/dist/adapters/http/request/client-certificate.mjs +1 -1
- package/dist/adapters/http/request/client-certificate.mjs.map +1 -1
- package/dist/adapters/http/request/helpers/locations.mjs +1 -3
- package/dist/adapters/http/request/helpers/locations.mjs.map +1 -1
- package/dist/adapters/http/ui/account-console/index.d.ts +4 -0
- package/dist/adapters/http/ui/account-console/index.d.ts.map +1 -0
- package/dist/adapters/http/ui/account-console/index.mjs +6 -0
- package/dist/adapters/http/ui/account-console/module.d.ts +28 -0
- package/dist/adapters/http/ui/account-console/module.d.ts.map +1 -0
- package/dist/adapters/http/ui/account-console/module.mjs +80 -0
- package/dist/adapters/http/ui/account-console/module.mjs.map +1 -0
- package/dist/adapters/http/ui/account-console/ref.d.ts +30 -0
- package/dist/adapters/http/ui/account-console/ref.d.ts.map +1 -0
- package/dist/adapters/http/ui/account-console/ref.mjs +50 -0
- package/dist/adapters/http/ui/account-console/ref.mjs.map +1 -0
- package/dist/adapters/http/ui/account-console/types.d.ts +11 -0
- package/dist/adapters/http/ui/account-console/types.d.ts.map +1 -0
- package/dist/adapters/http/ui/account-console/types.mjs +4 -0
- package/dist/adapters/http/ui/{internal-http-client.d.ts → auth-console/http-client.d.ts} +1 -1
- package/dist/adapters/http/ui/auth-console/http-client.d.ts.map +1 -0
- package/dist/adapters/http/ui/{internal-http-client.mjs → auth-console/http-client.mjs} +2 -2
- package/dist/adapters/http/ui/auth-console/http-client.mjs.map +1 -0
- package/dist/adapters/http/ui/auth-console/index.d.ts +6 -0
- package/dist/adapters/http/ui/auth-console/index.d.ts.map +1 -0
- package/dist/adapters/http/ui/auth-console/index.mjs +8 -0
- package/dist/adapters/http/ui/auth-console/module.d.ts +4 -0
- package/dist/adapters/http/ui/auth-console/module.d.ts.map +1 -0
- package/dist/adapters/http/ui/auth-console/module.mjs +73 -0
- package/dist/adapters/http/ui/auth-console/module.mjs.map +1 -0
- package/dist/adapters/http/ui/auth-console/resolve.d.ts +21 -0
- package/dist/adapters/http/ui/auth-console/resolve.d.ts.map +1 -0
- package/dist/adapters/http/ui/auth-console/resolve.mjs +53 -0
- package/dist/adapters/http/ui/auth-console/resolve.mjs.map +1 -0
- package/dist/adapters/http/ui/{serve.d.ts → auth-console/serve.d.ts} +1 -8
- package/dist/adapters/http/ui/auth-console/serve.d.ts.map +1 -0
- package/dist/adapters/http/ui/{serve.mjs → auth-console/serve.mjs} +5 -5
- package/dist/adapters/http/ui/auth-console/serve.mjs.map +1 -0
- package/dist/adapters/http/ui/auth-console/types.d.ts +26 -0
- package/dist/adapters/http/ui/auth-console/types.d.ts.map +1 -0
- package/dist/adapters/http/ui/auth-console/types.mjs +4 -0
- package/dist/adapters/http/ui/console-packages/index.d.ts +3 -0
- package/dist/adapters/http/ui/console-packages/index.d.ts.map +1 -0
- package/dist/adapters/http/ui/console-packages/index.mjs +5 -0
- package/dist/adapters/http/ui/console-packages/module.d.ts +33 -0
- package/dist/adapters/http/ui/console-packages/module.d.ts.map +1 -0
- package/dist/adapters/http/ui/console-packages/module.mjs +70 -0
- package/dist/adapters/http/ui/console-packages/module.mjs.map +1 -0
- package/dist/adapters/http/ui/console-packages/types.d.ts +12 -0
- package/dist/adapters/http/ui/console-packages/types.d.ts.map +1 -0
- package/dist/adapters/http/ui/console-packages/types.mjs +4 -0
- package/dist/adapters/http/ui/index.d.ts +5 -5
- package/dist/adapters/http/ui/index.d.ts.map +1 -1
- package/dist/adapters/http/ui/index.mjs +22 -5
- package/dist/adapters/http/ui/shared/html.d.ts +76 -0
- package/dist/adapters/http/ui/shared/html.d.ts.map +1 -0
- package/dist/adapters/http/ui/shared/html.mjs +103 -0
- package/dist/adapters/http/ui/shared/html.mjs.map +1 -0
- package/dist/adapters/http/ui/shared/index.d.ts +2 -0
- package/dist/adapters/http/ui/shared/index.d.ts.map +1 -0
- package/dist/adapters/http/ui/shared/index.mjs +5 -0
- package/dist/adapters/http/ui/theme/apply.d.ts +12 -0
- package/dist/adapters/http/ui/theme/apply.d.ts.map +1 -0
- package/dist/adapters/http/ui/theme/apply.mjs +29 -0
- package/dist/adapters/http/ui/theme/apply.mjs.map +1 -0
- package/dist/adapters/http/ui/theme/assets.d.ts +20 -0
- package/dist/adapters/http/ui/theme/assets.d.ts.map +1 -0
- package/dist/adapters/http/ui/theme/assets.mjs +86 -0
- package/dist/adapters/http/ui/theme/assets.mjs.map +1 -0
- package/dist/adapters/http/ui/theme/constants.d.ts +16 -0
- package/dist/adapters/http/ui/theme/constants.d.ts.map +1 -0
- package/dist/adapters/http/ui/theme/constants.mjs +20 -0
- package/dist/adapters/http/ui/theme/constants.mjs.map +1 -0
- package/dist/adapters/http/ui/theme/contract/constants.d.ts +120 -0
- package/dist/adapters/http/ui/theme/contract/constants.d.ts.map +1 -0
- package/dist/adapters/http/ui/theme/contract/constants.mjs +136 -0
- package/dist/adapters/http/ui/theme/contract/constants.mjs.map +1 -0
- package/dist/adapters/http/ui/theme/contract/head.d.ts +12 -0
- package/dist/adapters/http/ui/theme/contract/head.d.ts.map +1 -0
- package/dist/adapters/http/ui/theme/contract/head.mjs +61 -0
- package/dist/adapters/http/ui/theme/contract/head.mjs.map +1 -0
- package/dist/adapters/http/ui/theme/contract/index.d.ts +6 -0
- package/dist/adapters/http/ui/theme/contract/index.d.ts.map +1 -0
- package/dist/adapters/http/ui/theme/contract/index.mjs +8 -0
- package/dist/adapters/http/ui/theme/contract/manifest.d.ts +25 -0
- package/dist/adapters/http/ui/theme/contract/manifest.d.ts.map +1 -0
- package/dist/adapters/http/ui/theme/contract/manifest.mjs +77 -0
- package/dist/adapters/http/ui/theme/contract/manifest.mjs.map +1 -0
- package/dist/adapters/http/ui/theme/contract/types.d.ts +26 -0
- package/dist/adapters/http/ui/theme/contract/types.d.ts.map +1 -0
- package/dist/adapters/http/ui/theme/contract/types.mjs +4 -0
- package/dist/adapters/http/ui/theme/contract/utils.d.ts +11 -0
- package/dist/adapters/http/ui/theme/contract/utils.d.ts.map +1 -0
- package/dist/adapters/http/ui/theme/contract/utils.mjs +22 -0
- package/dist/adapters/http/ui/theme/contract/utils.mjs.map +1 -0
- package/dist/adapters/http/ui/theme/index.d.ts +7 -0
- package/dist/adapters/http/ui/theme/index.d.ts.map +1 -0
- package/dist/adapters/http/ui/theme/index.mjs +13 -0
- package/dist/adapters/http/ui/theme/module.d.ts +79 -0
- package/dist/adapters/http/ui/theme/module.d.ts.map +1 -0
- package/dist/adapters/http/ui/theme/module.mjs +206 -0
- package/dist/adapters/http/ui/theme/module.mjs.map +1 -0
- package/dist/adapters/http/ui/theme/types.d.ts +42 -0
- package/dist/adapters/http/ui/theme/types.d.ts.map +1 -0
- package/dist/adapters/http/ui/theme/types.mjs +4 -0
- package/dist/app/index.mjs +3 -1
- package/dist/app/modules/authentication/module.mjs +6 -3
- package/dist/app/modules/authentication/module.mjs.map +1 -1
- package/dist/app/modules/config/constants.d.ts +5 -0
- package/dist/app/modules/config/constants.d.ts.map +1 -1
- package/dist/app/modules/config/constants.mjs +5 -0
- package/dist/app/modules/config/constants.mjs.map +1 -1
- package/dist/app/modules/config/helpers.mjs +3 -2
- package/dist/app/modules/config/helpers.mjs.map +1 -1
- package/dist/app/modules/config/normalize.d.ts.map +1 -1
- package/dist/app/modules/config/normalize.mjs +8 -0
- package/dist/app/modules/config/normalize.mjs.map +1 -1
- package/dist/app/modules/config/origins.d.ts.map +1 -1
- package/dist/app/modules/config/origins.mjs +2 -0
- package/dist/app/modules/config/origins.mjs.map +1 -1
- package/dist/app/modules/config/read/env.d.ts.map +1 -1
- package/dist/app/modules/config/read/env.mjs +10 -0
- package/dist/app/modules/config/read/env.mjs.map +1 -1
- package/dist/app/modules/config/read/module.mjs +8 -3
- package/dist/app/modules/config/read/module.mjs.map +1 -1
- package/dist/app/modules/config/types.d.ts +63 -3
- package/dist/app/modules/config/types.d.ts.map +1 -1
- package/dist/app/modules/config/validator.d.ts.map +1 -1
- package/dist/app/modules/config/validator.mjs +5 -0
- package/dist/app/modules/config/validator.mjs.map +1 -1
- package/dist/app/modules/database/module.mjs +2 -1
- package/dist/app/modules/database/module.mjs.map +1 -1
- package/dist/app/modules/http/module.d.ts.map +1 -1
- package/dist/app/modules/http/module.mjs +7 -1
- package/dist/app/modules/http/module.mjs.map +1 -1
- package/dist/app/modules/http/modules/controller.d.ts +2 -1
- package/dist/app/modules/http/modules/controller.d.ts.map +1 -1
- package/dist/app/modules/http/modules/controller.mjs +214 -128
- package/dist/app/modules/http/modules/controller.mjs.map +1 -1
- package/dist/app/modules/http/modules/middleware.d.ts +9 -1
- package/dist/app/modules/http/modules/middleware.d.ts.map +1 -1
- package/dist/app/modules/http/modules/middleware.mjs +28 -8
- package/dist/app/modules/http/modules/middleware.mjs.map +1 -1
- package/dist/app/modules/identity/module.mjs +6 -3
- package/dist/app/modules/identity/module.mjs.map +1 -1
- package/dist/app/modules/index.mjs +3 -1
- package/dist/app/modules/oauth2/module.mjs +37 -17
- package/dist/app/modules/oauth2/module.mjs.map +1 -1
- package/dist/app/modules/oauth2/repositories/authorize/state/repository.mjs +1 -1
- package/dist/app/modules/oauth2/repositories/authorize/state/repository.mjs.map +1 -1
- package/dist/app/modules/oauth2/repositories/token/repository.mjs +1 -1
- package/dist/app/modules/oauth2/repositories/token/repository.mjs.map +1 -1
- package/dist/app/modules/provisioning/constants.d.ts +12 -0
- package/dist/app/modules/provisioning/constants.d.ts.map +1 -0
- package/dist/app/modules/provisioning/constants.mjs +16 -0
- package/dist/app/modules/provisioning/constants.mjs.map +1 -0
- package/dist/app/modules/provisioning/index.d.ts +2 -0
- package/dist/app/modules/provisioning/index.d.ts.map +1 -1
- package/dist/app/modules/provisioning/index.mjs +3 -1
- package/dist/app/modules/provisioning/lazy-wildcard.d.ts +15 -0
- package/dist/app/modules/provisioning/lazy-wildcard.d.ts.map +1 -0
- package/dist/app/modules/provisioning/lazy-wildcard.mjs +23 -0
- package/dist/app/modules/provisioning/lazy-wildcard.mjs.map +1 -0
- package/dist/app/modules/provisioning/module.d.ts.map +1 -1
- package/dist/app/modules/provisioning/module.mjs +30 -11
- package/dist/app/modules/provisioning/module.mjs.map +1 -1
- package/dist/app/modules/provisioning/sources/composite/module.d.ts +0 -19
- package/dist/app/modules/provisioning/sources/composite/module.d.ts.map +1 -1
- package/dist/app/modules/provisioning/sources/composite/module.mjs +7 -77
- package/dist/app/modules/provisioning/sources/composite/module.mjs.map +1 -1
- package/dist/app/modules/provisioning/sources/file/module.d.ts.map +1 -1
- package/dist/app/modules/provisioning/sources/file/module.mjs +11 -2
- package/dist/app/modules/provisioning/sources/file/module.mjs.map +1 -1
- package/dist/core/authentication/session/module.mjs +2 -4
- package/dist/core/authentication/session/module.mjs.map +1 -1
- package/dist/core/entities/client/index.d.ts +1 -1
- package/dist/core/entities/client/index.d.ts.map +1 -1
- package/dist/core/entities/client/index.mjs +2 -2
- package/dist/core/entities/client/service.d.ts.map +1 -1
- package/dist/core/entities/client/service.mjs +1 -1
- package/dist/core/entities/client/service.mjs.map +1 -1
- package/dist/core/entities/client/system-clients.d.ts +95 -0
- package/dist/core/entities/client/system-clients.d.ts.map +1 -0
- package/dist/core/entities/client/system-clients.mjs +158 -0
- package/dist/core/entities/client/system-clients.mjs.map +1 -0
- package/dist/core/entities/client/types.d.ts +17 -4
- package/dist/core/entities/client/types.d.ts.map +1 -1
- package/dist/core/entities/client-permission/service.mjs +12 -9
- package/dist/core/entities/client-permission/service.mjs.map +1 -1
- package/dist/core/entities/index.mjs +2 -2
- package/dist/core/entities/key/service.mjs +4 -2
- package/dist/core/entities/key/service.mjs.map +1 -1
- package/dist/core/entities/permission/service.d.ts.map +1 -1
- package/dist/core/entities/permission/service.mjs +1 -1
- package/dist/core/entities/permission/service.mjs.map +1 -1
- package/dist/core/entities/policy/service.d.ts.map +1 -1
- package/dist/core/entities/policy/service.mjs +3 -2
- package/dist/core/entities/policy/service.mjs.map +1 -1
- package/dist/core/entities/realm/service.d.ts +8 -6
- package/dist/core/entities/realm/service.d.ts.map +1 -1
- package/dist/core/entities/realm/service.mjs +6 -9
- package/dist/core/entities/realm/service.mjs.map +1 -1
- package/dist/core/entities/role/service.d.ts.map +1 -1
- package/dist/core/entities/role/service.mjs +1 -1
- package/dist/core/entities/role/service.mjs.map +1 -1
- package/dist/core/entities/role-permission/service.mjs +12 -9
- package/dist/core/entities/role-permission/service.mjs.map +1 -1
- package/dist/core/entities/scope/service.d.ts.map +1 -1
- package/dist/core/entities/scope/service.mjs +1 -1
- package/dist/core/entities/scope/service.mjs.map +1 -1
- package/dist/core/entities/user/service.d.ts.map +1 -1
- package/dist/core/entities/user/service.mjs +1 -1
- package/dist/core/entities/user/service.mjs.map +1 -1
- package/dist/core/entities/user-authenticator/helpers.mjs +1 -1
- package/dist/core/entities/user-authenticator/helpers.mjs.map +1 -1
- package/dist/core/entities/user-authenticator/service.mjs +7 -7
- package/dist/core/entities/user-authenticator/service.mjs.map +1 -1
- package/dist/core/entities/user-permission/service.mjs +12 -9
- package/dist/core/entities/user-permission/service.mjs.map +1 -1
- package/dist/core/identity/password-recovery/service.mjs +1 -1
- package/dist/core/identity/password-recovery/service.mjs.map +1 -1
- package/dist/core/index.mjs +6 -2
- package/dist/core/key/types.d.ts +2 -1
- package/dist/core/key/types.d.ts.map +1 -1
- package/dist/core/oauth2/authorization/code-request/verifier/module.d.ts.map +1 -1
- package/dist/core/oauth2/authorization/code-request/verifier/module.mjs +2 -2
- package/dist/core/oauth2/authorization/code-request/verifier/module.mjs.map +1 -1
- package/dist/core/oauth2/end-session/service.d.ts.map +1 -1
- package/dist/core/oauth2/end-session/service.mjs +2 -2
- package/dist/core/oauth2/end-session/service.mjs.map +1 -1
- package/dist/core/provisioning/constants.d.ts +8 -0
- package/dist/core/provisioning/constants.d.ts.map +1 -0
- package/dist/core/provisioning/constants.mjs +14 -0
- package/dist/core/provisioning/constants.mjs.map +1 -0
- package/dist/core/provisioning/entities/index.mjs +2 -1
- package/dist/core/provisioning/entities/realm/index.d.ts +1 -0
- package/dist/core/provisioning/entities/realm/index.d.ts.map +1 -1
- package/dist/core/provisioning/entities/realm/index.mjs +2 -1
- package/dist/core/provisioning/entities/realm/validator.d.ts +11 -0
- package/dist/core/provisioning/entities/realm/validator.d.ts.map +1 -1
- package/dist/core/provisioning/entities/realm/validator.mjs +14 -0
- package/dist/core/provisioning/entities/realm/validator.mjs.map +1 -1
- package/dist/core/provisioning/entities/realm/wildcard-validator.d.ts +19 -0
- package/dist/core/provisioning/entities/realm/wildcard-validator.d.ts.map +1 -0
- package/dist/core/provisioning/entities/realm/wildcard-validator.mjs +65 -0
- package/dist/core/provisioning/entities/realm/wildcard-validator.mjs.map +1 -0
- package/dist/core/provisioning/index.d.ts +3 -0
- package/dist/core/provisioning/index.d.ts.map +1 -1
- package/dist/core/provisioning/index.mjs +7 -1
- package/dist/core/provisioning/merge/index.d.ts +3 -0
- package/dist/core/provisioning/merge/index.d.ts.map +1 -0
- package/dist/core/provisioning/merge/index.mjs +5 -0
- package/dist/core/provisioning/merge/module.d.ts +18 -0
- package/dist/core/provisioning/merge/module.d.ts.map +1 -0
- package/dist/core/provisioning/merge/module.mjs +82 -0
- package/dist/core/provisioning/merge/module.mjs.map +1 -0
- package/dist/core/provisioning/merge/types.d.ts +34 -0
- package/dist/core/provisioning/merge/types.d.ts.map +1 -0
- package/dist/core/provisioning/merge/types.mjs +4 -0
- package/dist/core/provisioning/synchronizer/client/module.mjs +0 -1
- package/dist/core/provisioning/synchronizer/client/module.mjs.map +1 -1
- package/dist/core/provisioning/synchronizer/permission/module.mjs +0 -1
- package/dist/core/provisioning/synchronizer/permission/module.mjs.map +1 -1
- package/dist/core/provisioning/synchronizer/realm/module.mjs +0 -1
- package/dist/core/provisioning/synchronizer/realm/module.mjs.map +1 -1
- package/dist/core/provisioning/synchronizer/role/module.mjs +0 -1
- package/dist/core/provisioning/synchronizer/role/module.mjs.map +1 -1
- package/dist/core/provisioning/synchronizer/scope/module.mjs +0 -1
- package/dist/core/provisioning/synchronizer/scope/module.mjs.map +1 -1
- package/dist/core/provisioning/synchronizer/user/module.mjs +0 -1
- package/dist/core/provisioning/synchronizer/user/module.mjs.map +1 -1
- package/dist/core/provisioning/types.d.ts +10 -0
- package/dist/core/provisioning/types.d.ts.map +1 -1
- package/dist/core/provisioning/wildcard/index.d.ts +3 -0
- package/dist/core/provisioning/wildcard/index.d.ts.map +1 -0
- package/dist/core/provisioning/wildcard/index.mjs +5 -0
- package/dist/core/provisioning/wildcard/module.d.ts +53 -0
- package/dist/core/provisioning/wildcard/module.d.ts.map +1 -0
- package/dist/core/provisioning/wildcard/module.mjs +91 -0
- package/dist/core/provisioning/wildcard/module.mjs.map +1 -0
- package/dist/core/provisioning/wildcard/types.d.ts +19 -0
- package/dist/core/provisioning/wildcard/types.d.ts.map +1 -0
- package/dist/core/provisioning/wildcard/types.mjs +4 -0
- package/dist/index.mjs +5 -1
- package/dist/path.d.ts +0 -2
- package/dist/path.d.ts.map +1 -1
- package/dist/path.mjs +1 -3
- package/dist/path.mjs.map +1 -1
- package/dist/swagger.json +485 -17
- package/package.json +26 -63
- package/dist/adapters/http/ui/base-path.d.ts +0 -9
- package/dist/adapters/http/ui/base-path.d.ts.map +0 -1
- package/dist/adapters/http/ui/base-path.mjs +0 -18
- package/dist/adapters/http/ui/base-path.mjs.map +0 -1
- package/dist/adapters/http/ui/internal-http-client.d.ts.map +0 -1
- package/dist/adapters/http/ui/internal-http-client.mjs.map +0 -1
- package/dist/adapters/http/ui/render.d.ts +0 -4
- package/dist/adapters/http/ui/render.d.ts.map +0 -1
- package/dist/adapters/http/ui/render.mjs +0 -63
- package/dist/adapters/http/ui/render.mjs.map +0 -1
- package/dist/adapters/http/ui/serve.d.ts.map +0 -1
- package/dist/adapters/http/ui/serve.mjs.map +0 -1
- package/dist/adapters/http/ui/types.d.ts +0 -20
- package/dist/adapters/http/ui/types.d.ts.map +0 -1
- package/dist/core/entities/client/web-client.d.ts +0 -72
- package/dist/core/entities/client/web-client.d.ts.map +0 -1
- package/dist/core/entities/client/web-client.mjs +0 -123
- package/dist/core/entities/client/web-client.mjs.map +0 -1
- package/dist/ui/client/.vite/ssr-manifest.json +0 -54812
- package/dist/ui/client/assets/asap-latin-400-normal-Dc37g3Il.woff +0 -0
- package/dist/ui/client/assets/asap-latin-400-normal-DnZ1MOsG.woff2 +0 -0
- package/dist/ui/client/assets/asap-latin-700-normal-Dqcopq14.woff +0 -0
- package/dist/ui/client/assets/asap-latin-700-normal-l2Y8pi-F.woff2 +0 -0
- package/dist/ui/client/assets/asap-latin-ext-400-normal-C-fcRdtE.woff +0 -0
- package/dist/ui/client/assets/asap-latin-ext-400-normal-DwYtpHbV.woff2 +0 -0
- package/dist/ui/client/assets/asap-latin-ext-700-normal-D00OESsZ.woff +0 -0
- package/dist/ui/client/assets/asap-latin-ext-700-normal-y8bo5aW5.woff2 +0 -0
- package/dist/ui/client/assets/asap-vietnamese-400-normal-DGyJlJLT.woff2 +0 -0
- package/dist/ui/client/assets/asap-vietnamese-400-normal-lfLaoF2x.woff +0 -0
- package/dist/ui/client/assets/asap-vietnamese-700-normal-B-e19ug5.woff +0 -0
- package/dist/ui/client/assets/asap-vietnamese-700-normal-D-SxY94i.woff2 +0 -0
- package/dist/ui/client/assets/index-Bk6-OZy9.css +0 -2
- package/dist/ui/client/assets/index-DO6_7NTJ.js +0 -106
- package/dist/ui/client/assets/nunito-cyrillic-300-normal-BPQV259B.woff2 +0 -0
- package/dist/ui/client/assets/nunito-cyrillic-300-normal-g5qSsvc0.woff +0 -0
- package/dist/ui/client/assets/nunito-cyrillic-400-normal-D1j0u8EH.woff +0 -0
- package/dist/ui/client/assets/nunito-cyrillic-400-normal-xAOo5cBP.woff2 +0 -0
- package/dist/ui/client/assets/nunito-cyrillic-600-normal-BUjmtIuu.woff +0 -0
- package/dist/ui/client/assets/nunito-cyrillic-600-normal-DJGQ2h05.woff2 +0 -0
- package/dist/ui/client/assets/nunito-cyrillic-700-normal-DP36NgGt.woff2 +0 -0
- package/dist/ui/client/assets/nunito-cyrillic-700-normal-DfHRUDv-.woff +0 -0
- package/dist/ui/client/assets/nunito-cyrillic-ext-300-normal-BDHtqmCR.woff +0 -0
- package/dist/ui/client/assets/nunito-cyrillic-ext-300-normal-ChMQLIrm.woff2 +0 -0
- package/dist/ui/client/assets/nunito-cyrillic-ext-400-normal-CuPM9foi.woff2 +0 -0
- package/dist/ui/client/assets/nunito-cyrillic-ext-400-normal-xaE7D4Sw.woff +0 -0
- package/dist/ui/client/assets/nunito-cyrillic-ext-600-normal-CWPPjBOD.woff2 +0 -0
- package/dist/ui/client/assets/nunito-cyrillic-ext-600-normal-vnfu4DTE.woff +0 -0
- package/dist/ui/client/assets/nunito-cyrillic-ext-700-normal-BuR0mlCG.woff2 +0 -0
- package/dist/ui/client/assets/nunito-cyrillic-ext-700-normal-DfoqN4Gs.woff +0 -0
- package/dist/ui/client/assets/nunito-latin-300-normal-C3ZIKvzv.woff +0 -0
- package/dist/ui/client/assets/nunito-latin-300-normal-COoPE5VN.woff2 +0 -0
- package/dist/ui/client/assets/nunito-latin-400-normal-DKg4f3fz.woff +0 -0
- package/dist/ui/client/assets/nunito-latin-400-normal-r8SDr6Up.woff2 +0 -0
- package/dist/ui/client/assets/nunito-latin-600-normal-Br8yIETf.woff2 +0 -0
- package/dist/ui/client/assets/nunito-latin-600-normal-Cd0eNu1l.woff +0 -0
- package/dist/ui/client/assets/nunito-latin-700-normal-Dort48En.woff2 +0 -0
- package/dist/ui/client/assets/nunito-latin-700-normal-OcDqTBcA.woff +0 -0
- package/dist/ui/client/assets/nunito-latin-ext-300-normal-D1SyVuPt.woff2 +0 -0
- package/dist/ui/client/assets/nunito-latin-ext-300-normal-DfqbmdMl.woff +0 -0
- package/dist/ui/client/assets/nunito-latin-ext-400-normal-CjMJVfGn.woff +0 -0
- package/dist/ui/client/assets/nunito-latin-ext-400-normal-i-8OOpdj.woff2 +0 -0
- package/dist/ui/client/assets/nunito-latin-ext-600-normal-BKUpuB78.woff +0 -0
- package/dist/ui/client/assets/nunito-latin-ext-600-normal-Dd9Zuxh1.woff2 +0 -0
- package/dist/ui/client/assets/nunito-latin-ext-700-normal-BWeMsAzO.woff2 +0 -0
- package/dist/ui/client/assets/nunito-latin-ext-700-normal-D4woHhbd.woff +0 -0
- package/dist/ui/client/assets/nunito-vietnamese-300-normal-DATld5Vw.woff +0 -0
- package/dist/ui/client/assets/nunito-vietnamese-300-normal-mLneKULB.woff2 +0 -0
- package/dist/ui/client/assets/nunito-vietnamese-400-normal-BHkVbP3T.woff2 +0 -0
- package/dist/ui/client/assets/nunito-vietnamese-400-normal-DtOtW02z.woff +0 -0
- package/dist/ui/client/assets/nunito-vietnamese-600-normal-BY8O6Cug.woff2 +0 -0
- package/dist/ui/client/assets/nunito-vietnamese-600-normal-DO1RqFw5.woff +0 -0
- package/dist/ui/client/assets/nunito-vietnamese-700-normal-C9SQsXvj.woff +0 -0
- package/dist/ui/client/assets/nunito-vietnamese-700-normal-Ch8EUCfz.woff2 +0 -0
- package/dist/ui/client/index.html +0 -22
- package/dist/ui/server/assets/multipart-parser-BCMy8Xwv.js +0 -181
- package/dist/ui/server/assets/multipart-parser-BVY8pIV2.js +0 -176
- package/dist/ui/server/server.js +0 -158420
- /package/dist/adapters/http/{ui → middleware/built-in}/types.mjs +0 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { CLIENT_ACCOUNT_CONSOLE_NAME, CLIENT_ADMIN_CONSOLE_NAME, ClientAuthMethod, ClientTokenBindingMethod, ScopeName } from "@authup/core-kit";
|
|
5
|
+
//#region src/core/entities/client/system-clients.ts
|
|
6
|
+
/**
|
|
7
|
+
* The scopes every system client is granted.
|
|
8
|
+
*
|
|
9
|
+
* `global` lets the issued token drive the management API (parity with the
|
|
10
|
+
* legacy password-grant admin login); `openid` yields the id-token.
|
|
11
|
+
*/ const SYSTEM_CLIENT_SCOPE_NAMES = [ScopeName.GLOBAL, ScopeName.OPEN_ID];
|
|
12
|
+
/**
|
|
13
|
+
* The public (PKCE) clients provisioned for every realm (plan 079):
|
|
14
|
+
*
|
|
15
|
+
* - `admin-console` — authup's own admin console (apps/client-admin-console),
|
|
16
|
+
* - `account-console` — the account self-service surface (plan 080; each
|
|
17
|
+
* definition gets its own `<origin>/**` patterns from
|
|
18
|
+
* `buildSystemClientAttributes`, so an inert row adds no redirect
|
|
19
|
+
* surface).
|
|
20
|
+
*
|
|
21
|
+
* Downstream RPs register their own clients (per realm, or in every realm
|
|
22
|
+
* via a wildcard realm provisioning entry, plan 082) — the former shared
|
|
23
|
+
* `web` client was removed.
|
|
24
|
+
*
|
|
25
|
+
* `displayName` is seeded at CREATE only and never re-asserted by the
|
|
26
|
+
* MERGE, so an admin may relabel a client without the next boot undoing it.
|
|
27
|
+
*/ const SYSTEM_CLIENT_DEFINITIONS = [{
|
|
28
|
+
name: CLIENT_ADMIN_CONSOLE_NAME,
|
|
29
|
+
displayName: "Admin Console",
|
|
30
|
+
scopeNames: SYSTEM_CLIENT_SCOPE_NAMES
|
|
31
|
+
}, {
|
|
32
|
+
name: CLIENT_ACCOUNT_CONSOLE_NAME,
|
|
33
|
+
displayName: "Account Console",
|
|
34
|
+
scopeNames: SYSTEM_CLIENT_SCOPE_NAMES
|
|
35
|
+
}];
|
|
36
|
+
/**
|
|
37
|
+
* Build the MERGE-owned attribute set for a realm's system client.
|
|
38
|
+
*
|
|
39
|
+
* `builtIn` makes the client auto-consent in the /authorize flow and
|
|
40
|
+
* protects it from the API reserved-name guard.
|
|
41
|
+
*
|
|
42
|
+
* `grantTypes` is an enforced allowlist (`assertClientGrantAllowed` at the
|
|
43
|
+
* /token grants and the /authorize code-request verifier; null = allow-all),
|
|
44
|
+
* so it must list every flow the client uses. `redirectUri` and
|
|
45
|
+
* `postLogoutRedirectUri` are each one `<origin>/**` wildcard per trusted
|
|
46
|
+
* origin (matched by isSimpleMatch) — deliberately the shared app-origin
|
|
47
|
+
* set for every definition: `redirectUri` is re-asserted on each boot, so a
|
|
48
|
+
* separately-hosted surface (plan 078 "relocatable by choice") registers
|
|
49
|
+
* its origin via TRUSTED_ORIGINS rather than editing the client row.
|
|
50
|
+
*
|
|
51
|
+
* The `scope` column is descriptive only. Scope authorization resolves
|
|
52
|
+
* through the `auth_client_scopes` junction, which
|
|
53
|
+
* `SystemClientProvisioner.ensureForRealm` fills from the definition's
|
|
54
|
+
* `scopeNames`.
|
|
55
|
+
*
|
|
56
|
+
* `accessPolicyId` and `displayName` are deliberately NOT part of this set:
|
|
57
|
+
* the MERGE must neither wipe an admin-bound access policy nor undo a
|
|
58
|
+
* relabel.
|
|
59
|
+
*/ function buildSystemClientAttributes(definition, realm, appOrigins) {
|
|
60
|
+
const originPatterns = appOrigins.map((origin) => `${origin}/**`).join(",");
|
|
61
|
+
return {
|
|
62
|
+
name: definition.name,
|
|
63
|
+
realmId: realm.id,
|
|
64
|
+
authMethod: ClientAuthMethod.NONE,
|
|
65
|
+
tokenBindingMethod: ClientTokenBindingMethod.NONE,
|
|
66
|
+
builtIn: true,
|
|
67
|
+
active: true,
|
|
68
|
+
grantTypes: "authorization_code refresh_token",
|
|
69
|
+
scope: definition.scopeNames.join(" "),
|
|
70
|
+
redirectUri: originPatterns,
|
|
71
|
+
postLogoutRedirectUri: originPatterns
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
var SystemClientProvisioner = class {
|
|
75
|
+
clientRepository;
|
|
76
|
+
scopeRepository;
|
|
77
|
+
clientScopeRepository;
|
|
78
|
+
appOrigins;
|
|
79
|
+
logger;
|
|
80
|
+
constructor(ctx) {
|
|
81
|
+
this.clientRepository = ctx.clientRepository;
|
|
82
|
+
this.scopeRepository = ctx.scopeRepository;
|
|
83
|
+
this.clientScopeRepository = ctx.clientScopeRepository;
|
|
84
|
+
this.appOrigins = ctx.appOrigins;
|
|
85
|
+
this.logger = ctx.logger;
|
|
86
|
+
}
|
|
87
|
+
async ensureForRealm(realm) {
|
|
88
|
+
for (const definition of SYSTEM_CLIENT_DEFINITIONS) {
|
|
89
|
+
const client = await this.ensureClient(definition, realm);
|
|
90
|
+
await this.ensureScopes(definition, client);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Upsert the client row itself.
|
|
95
|
+
*
|
|
96
|
+
* Every system client name is reserved (`CLIENT_RESERVED_NAMES`), so the
|
|
97
|
+
* row belongs to the system whatever state it is in. A non-built-in one
|
|
98
|
+
* predates the reservation and is taken over rather than left to shadow
|
|
99
|
+
* the realm's system client.
|
|
100
|
+
*/ async ensureClient(definition, realm) {
|
|
101
|
+
const attributes = buildSystemClientAttributes(definition, realm, this.appOrigins);
|
|
102
|
+
const existing = await this.clientRepository.findOneBy({
|
|
103
|
+
name: definition.name,
|
|
104
|
+
realmId: realm.id
|
|
105
|
+
});
|
|
106
|
+
if (existing) {
|
|
107
|
+
if (!Object.keys(attributes).some((key) => existing[key] !== attributes[key])) return existing;
|
|
108
|
+
let target = existing;
|
|
109
|
+
if (!existing.builtIn) {
|
|
110
|
+
if (this.logger) this.logger.warn(`Taking over the non-built-in client named '${definition.name}' in realm ${realm.id}: the name is reserved for a built-in system client.`);
|
|
111
|
+
target = await this.clientRepository.findOneWithSecret({ id: existing.id }) || existing;
|
|
112
|
+
target.secret = null;
|
|
113
|
+
target.secretHashed = false;
|
|
114
|
+
target.secretEncrypted = false;
|
|
115
|
+
}
|
|
116
|
+
const merged = this.clientRepository.merge(target, attributes);
|
|
117
|
+
return this.clientRepository.save(merged);
|
|
118
|
+
}
|
|
119
|
+
const entity = this.clientRepository.create({
|
|
120
|
+
...attributes,
|
|
121
|
+
displayName: definition.displayName
|
|
122
|
+
});
|
|
123
|
+
return this.clientRepository.save(entity);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Bind the definition's scopes through `auth_client_scopes`. That
|
|
127
|
+
* junction is the only source the /authorize code-request verifier reads
|
|
128
|
+
* scopes from.
|
|
129
|
+
*
|
|
130
|
+
* Additive like the attribute MERGE above: an extra scope an admin bound
|
|
131
|
+
* by hand is left in place.
|
|
132
|
+
*/ async ensureScopes(definition, client) {
|
|
133
|
+
for (const name of definition.scopeNames) {
|
|
134
|
+
const scope = await this.scopeRepository.findOneBy({
|
|
135
|
+
name,
|
|
136
|
+
realmId: null
|
|
137
|
+
});
|
|
138
|
+
if (!scope) {
|
|
139
|
+
if (this.logger) this.logger.warn(`Skipping scope '${name}' for the ${definition.name} client of realm ${client.realmId}: the scope is not provisioned.`);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (await this.clientScopeRepository.findOneBy({
|
|
143
|
+
clientId: client.id,
|
|
144
|
+
scopeId: scope.id
|
|
145
|
+
})) continue;
|
|
146
|
+
await this.clientScopeRepository.save(this.clientScopeRepository.create({
|
|
147
|
+
clientId: client.id,
|
|
148
|
+
clientRealmId: client.realmId,
|
|
149
|
+
scopeId: scope.id,
|
|
150
|
+
scopeRealmId: scope.realmId
|
|
151
|
+
}));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
//#endregion
|
|
156
|
+
export { SYSTEM_CLIENT_DEFINITIONS, SYSTEM_CLIENT_SCOPE_NAMES, SystemClientProvisioner, buildSystemClientAttributes };
|
|
157
|
+
|
|
158
|
+
//# sourceMappingURL=system-clients.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-clients.mjs","names":["CLIENT_ACCOUNT_CONSOLE_NAME","CLIENT_ADMIN_CONSOLE_NAME","ClientAuthMethod","ClientTokenBindingMethod","ScopeName","SYSTEM_CLIENT_SCOPE_NAMES","GLOBAL","OPEN_ID","SYSTEM_CLIENT_DEFINITIONS","name","displayName","scopeNames","buildSystemClientAttributes","definition","realm","appOrigins","originPatterns","map","origin","join","realmId","id","authMethod","NONE","tokenBindingMethod","builtIn","active","grantTypes","scope","redirectUri","postLogoutRedirectUri","SystemClientProvisioner","clientRepository","scopeRepository","clientScopeRepository","logger","ctx","ensureForRealm","client","ensureClient","ensureScopes","attributes","existing","findOneBy","isDirty","Object","keys","some","key","target","warn","findOneWithSecret","secret","secretHashed","secretEncrypted","merged","merge","save","entity","create","clientId","scopeId","clientRealmId","scopeRealmId"],"sources":["../../../../src/core/entities/client/system-clients.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n CLIENT_ACCOUNT_CONSOLE_NAME,\n CLIENT_ADMIN_CONSOLE_NAME,\n ClientAuthMethod,\n ClientTokenBindingMethod,\n ScopeName,\n} from '@authup/core-kit';\nimport type { Client, Realm } from '@authup/core-kit';\nimport type { Logger } from '@authup/server-kit';\nimport type { IClientScopeRepository } from '../client-scope/types.ts';\nimport type { IScopeRepository } from '../scope/types.ts';\nimport type { IClientRepository, ISystemClientProvisioner, SystemClientDefinition } from './types.ts';\n\nexport type SystemClientProvisionerContext = {\n clientRepository: IClientRepository;\n scopeRepository: IScopeRepository;\n clientScopeRepository: IClientScopeRepository;\n appOrigins: string[];\n logger?: Logger;\n};\n\n/**\n * The scopes every system client is granted.\n *\n * `global` lets the issued token drive the management API (parity with the\n * legacy password-grant admin login); `openid` yields the id-token.\n */\nexport const SYSTEM_CLIENT_SCOPE_NAMES: string[] = [\n ScopeName.GLOBAL,\n ScopeName.OPEN_ID,\n];\n\n/**\n * The public (PKCE) clients provisioned for every realm (plan 079):\n *\n * - `admin-console` — authup's own admin console (apps/client-admin-console),\n * - `account-console` — the account self-service surface (plan 080; each\n * definition gets its own `<origin>/**` patterns from\n * `buildSystemClientAttributes`, so an inert row adds no redirect\n * surface).\n *\n * Downstream RPs register their own clients (per realm, or in every realm\n * via a wildcard realm provisioning entry, plan 082) — the former shared\n * `web` client was removed.\n *\n * `displayName` is seeded at CREATE only and never re-asserted by the\n * MERGE, so an admin may relabel a client without the next boot undoing it.\n */\nexport const SYSTEM_CLIENT_DEFINITIONS: SystemClientDefinition[] = [\n {\n name: CLIENT_ADMIN_CONSOLE_NAME,\n displayName: 'Admin Console',\n scopeNames: SYSTEM_CLIENT_SCOPE_NAMES,\n },\n {\n name: CLIENT_ACCOUNT_CONSOLE_NAME,\n displayName: 'Account Console',\n scopeNames: SYSTEM_CLIENT_SCOPE_NAMES,\n },\n];\n\n/**\n * Build the MERGE-owned attribute set for a realm's system client.\n *\n * `builtIn` makes the client auto-consent in the /authorize flow and\n * protects it from the API reserved-name guard.\n *\n * `grantTypes` is an enforced allowlist (`assertClientGrantAllowed` at the\n * /token grants and the /authorize code-request verifier; null = allow-all),\n * so it must list every flow the client uses. `redirectUri` and\n * `postLogoutRedirectUri` are each one `<origin>/**` wildcard per trusted\n * origin (matched by isSimpleMatch) — deliberately the shared app-origin\n * set for every definition: `redirectUri` is re-asserted on each boot, so a\n * separately-hosted surface (plan 078 \"relocatable by choice\") registers\n * its origin via TRUSTED_ORIGINS rather than editing the client row.\n *\n * The `scope` column is descriptive only. Scope authorization resolves\n * through the `auth_client_scopes` junction, which\n * `SystemClientProvisioner.ensureForRealm` fills from the definition's\n * `scopeNames`.\n *\n * `accessPolicyId` and `displayName` are deliberately NOT part of this set:\n * the MERGE must neither wipe an admin-bound access policy nor undo a\n * relabel.\n */\nexport function buildSystemClientAttributes(\n definition: SystemClientDefinition,\n realm: Realm | { id: string },\n appOrigins: string[],\n): Partial<Client> {\n const originPatterns = appOrigins.map((origin) => `${origin}/**`).join(',');\n\n return {\n name: definition.name,\n realmId: realm.id,\n authMethod: ClientAuthMethod.NONE,\n tokenBindingMethod: ClientTokenBindingMethod.NONE,\n builtIn: true,\n active: true,\n grantTypes: 'authorization_code refresh_token',\n scope: definition.scopeNames.join(' '),\n redirectUri: originPatterns,\n postLogoutRedirectUri: originPatterns,\n };\n}\n\nexport class SystemClientProvisioner implements ISystemClientProvisioner {\n protected clientRepository: IClientRepository;\n\n protected scopeRepository: IScopeRepository;\n\n protected clientScopeRepository: IClientScopeRepository;\n\n protected appOrigins: string[];\n\n protected logger?: Logger;\n\n constructor(ctx: SystemClientProvisionerContext) {\n this.clientRepository = ctx.clientRepository;\n this.scopeRepository = ctx.scopeRepository;\n this.clientScopeRepository = ctx.clientScopeRepository;\n this.appOrigins = ctx.appOrigins;\n this.logger = ctx.logger;\n }\n\n async ensureForRealm(realm: Realm | { id: string }): Promise<void> {\n for (const definition of SYSTEM_CLIENT_DEFINITIONS) {\n const client = await this.ensureClient(definition, realm);\n\n // Always run, even when the attributes were already up to date:\n // an instance provisioned before the junction rows existed\n // carries a steady-state client with no scopes at all.\n await this.ensureScopes(definition, client);\n }\n }\n\n /**\n * Upsert the client row itself.\n *\n * Every system client name is reserved (`CLIENT_RESERVED_NAMES`), so the\n * row belongs to the system whatever state it is in. A non-built-in one\n * predates the reservation and is taken over rather than left to shadow\n * the realm's system client.\n */\n protected async ensureClient(\n definition: SystemClientDefinition,\n realm: Realm | { id: string },\n ): Promise<Client> {\n const attributes = buildSystemClientAttributes(definition, realm, this.appOrigins);\n\n const existing = await this.clientRepository.findOneBy({\n name: definition.name,\n realmId: realm.id,\n });\n\n if (existing) {\n // MERGE: refresh attributes (e.g. redirectUri) when config\n // changes. Dirty-check first — the attributes are deterministic\n // from config, so a steady-state boot would otherwise issue one\n // redundant UPDATE (bumping updatedAt) per client and realm.\n const isDirty = (Object.keys(attributes) as (keyof Client)[])\n .some((key) => existing[key] !== attributes[key]);\n if (!isDirty) {\n return existing;\n }\n\n let target = existing;\n\n if (!existing.builtIn) {\n if (this.logger) {\n this.logger.warn(\n `Taking over the non-built-in client named '${definition.name}' in realm ${realm.id}: the name is reserved for a built-in system client.`,\n );\n }\n\n // The takeover makes the client public, so a secret it carried\n // as a confidential client can never authenticate it again.\n // Drop it instead of leaving the material at rest.\n //\n // The row has to be re-read WITH the secret for that: `secret`\n // is a `select: false` column, so the loaded entity carries no\n // value for it and typeorm's changed-column diff would not\n // emit the null. Re-reading is confined to this branch, and\n // the secret stays out of `buildSystemClientAttributes` for\n // the same reason (an undefined-vs-null compare would read as\n // dirty on every boot).\n target = await this.clientRepository.findOneWithSecret({ id: existing.id }) || existing;\n target.secret = null;\n target.secretHashed = false;\n target.secretEncrypted = false;\n }\n\n const merged = this.clientRepository.merge(target, attributes);\n\n return this.clientRepository.save(merged);\n }\n\n const entity = this.clientRepository.create({\n ...attributes,\n displayName: definition.displayName,\n });\n return this.clientRepository.save(entity);\n }\n\n /**\n * Bind the definition's scopes through `auth_client_scopes`. That\n * junction is the only source the /authorize code-request verifier reads\n * scopes from.\n *\n * Additive like the attribute MERGE above: an extra scope an admin bound\n * by hand is left in place.\n */\n protected async ensureScopes(definition: SystemClientDefinition, client: Client): Promise<void> {\n for (const name of definition.scopeNames) {\n const scope = await this.scopeRepository.findOneBy({\n name,\n realmId: null,\n });\n\n if (!scope) {\n if (this.logger) {\n this.logger.warn(\n `Skipping scope '${name}' for the ${definition.name} client of realm ${client.realmId}: the scope is not provisioned.`,\n );\n }\n continue;\n }\n\n const existing = await this.clientScopeRepository.findOneBy({\n clientId: client.id,\n scopeId: scope.id,\n });\n\n if (existing) {\n continue;\n }\n\n await this.clientScopeRepository.save(this.clientScopeRepository.create({\n clientId: client.id,\n clientRealmId: client.realmId,\n scopeId: scope.id,\n scopeRealmId: scope.realmId,\n }));\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -2,12 +2,25 @@ import type { Client, Realm, Role } from '@authup/core-kit';
|
|
|
2
2
|
import type { IQuery } from '@rapiq/core';
|
|
3
3
|
import type { PermissionPolicyBinding } from '@authup/access';
|
|
4
4
|
import type { ActorContext, EntityRepositoryFindManyResult, IEntityRepository } from '@authup/server-kit';
|
|
5
|
+
import type { IRealmProvisioner } from '../../provisioning/types.ts';
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* One system-provisioned public client (plan 079): `admin-console` or
|
|
8
|
+
* `account-console`. `displayName` is seeded at CREATE only; the
|
|
9
|
+
* MERGE-owned attribute set is derived per definition by
|
|
10
|
+
* `buildSystemClientAttributes`.
|
|
9
11
|
*/
|
|
10
|
-
export
|
|
12
|
+
export type SystemClientDefinition = {
|
|
13
|
+
name: string;
|
|
14
|
+
displayName: string;
|
|
15
|
+
scopeNames: string[];
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Ensures a realm has its system-provisioned public clients
|
|
19
|
+
* (`admin-console`, `account-console`). Used by startup provisioning
|
|
20
|
+
* (every realm) and the runtime realm-create hook (a single realm).
|
|
21
|
+
* System-level — never gated on an actor.
|
|
22
|
+
*/
|
|
23
|
+
export interface ISystemClientProvisioner extends IRealmProvisioner {
|
|
11
24
|
ensureForRealm(realm: Realm | {
|
|
12
25
|
id: string;
|
|
13
26
|
}): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/core/entities/client/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B,EAAE,iBAAiB,EAAG,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/core/entities/client/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B,EAAE,iBAAiB,EAAG,MAAM,oBAAoB,CAAC;AAC3G,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,wBAAyB,SAAQ,iBAAiB;IAC/D,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB,CAAC,MAAM,CAAC;IAChE,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzE,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAE5E,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAEtE,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAExD,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAAC;CACpF;AAED,MAAM,WAAW,cAAc;IAC3B,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,8BAA8B,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1G,MAAM,CACF,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,YAAY,EACnB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,OAAO,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1F,IAAI,CACA,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,KAAK,EAAE,YAAY,EACnB,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,GACnC,OAAO,CAAC;QACP,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,OAAO,CAAA;KACnB,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC5D"}
|
|
@@ -54,15 +54,18 @@ var ClientPermissionService = class extends JunctionEntityService {
|
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
56
|
if (validated.client) validated.clientRealmId = validated.client.realmId;
|
|
57
|
-
if (validated.permission && actor.identity)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
57
|
+
if (validated.permission && actor.identity) {
|
|
58
|
+
const grant = await this.identityPermissionProvider.resolveJunctionGrant({
|
|
59
|
+
type: actor.identity.type,
|
|
60
|
+
id: actor.identity.data.id
|
|
61
|
+
}, {
|
|
62
|
+
name: validated.permission.name,
|
|
63
|
+
realmId: validated.permission.realmId,
|
|
64
|
+
clientId: validated.permission.clientId,
|
|
65
|
+
realmScope: validated.realmScope ?? RealmScope.OWN
|
|
66
|
+
});
|
|
67
|
+
applyJunctionCreateGrant(validated, grant);
|
|
68
|
+
}
|
|
66
69
|
await actor.permissionEvaluator.evaluate({
|
|
67
70
|
name: PermissionName.CLIENT_PERMISSION_CREATE,
|
|
68
71
|
data: definePolicyData({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.mjs","names":["BuiltInPolicyType","RealmScope","definePolicyData","EntityConflictError","EntityNotFoundError","ValidatorGroup","ClientPermissionValidator","PermissionName","applyJunctionCreateGrant","buildJunctionUpdateData","JunctionEntityService","decodeQuery","clientPermissionSchema","ClientPermissionService","ownerRealmKey","repository","permissionRepository","identityPermissionProvider","validator","ctx","getMany","query","actor","permissionEvaluator","preEvaluateOneOf","name","CLIENT_PERMISSION_CREATE","CLIENT_PERMISSION_DELETE","findMany","schema","getOne","id","entity","findOneBy","create","data","preEvaluate","validated","run","group","CREATE","validateJoinColumns","existing","clientId","permissionId","permission","permissionRealmId","realmId","client","clientRealmId","identity","grant","resolveJunctionGrant","type","realmScope","OWN","evaluate","ATTRIBUTES","junctionAttributes","REALM_MATCH","junctionResourceRealm","save","update","CLIENT_PERMISSION_UPDATE","UPDATE","findOneById","actorScope","ANY","actorPolicyFree","actorPolicyId","policy","updateData","existingScope","merged","merge","delete","entityId","remove"],"sources":["../../../../src/core/entities/client-permission/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n BuiltInPolicyType,\n RealmScope,\n definePolicyData,\n} from '@authup/access';\nimport { EntityConflictError, EntityNotFoundError } from '@authup/errors';\nimport { ValidatorGroup } from '@authup/kit';\nimport { ClientPermissionValidator, PermissionName } from '@authup/core-kit';\nimport type { ClientPermission, Permission } from '@authup/core-kit';\nimport type { IIdentityPermissionProvider } from '../../identity/permission/types.ts';\nimport { applyJunctionCreateGrant, buildJunctionUpdateData } from '../../identity/permission/junction-grant.ts';\nimport type { ActorContext, EntityRepositoryFindManyResult, IEntityRepository } from '@authup/server-kit';\nimport { JunctionEntityService } from '@authup/server-kit';\nimport type { IClientPermissionRepository, IClientPermissionService } from './types.ts';\nimport { decodeQuery } from '../../query/index.ts';\nimport { clientPermissionSchema } from './schema.ts';\n\nexport type ClientPermissionServiceContext = {\n repository: IClientPermissionRepository;\n permissionRepository: IEntityRepository<Permission>;\n identityPermissionProvider: IIdentityPermissionProvider;\n};\n\nexport class ClientPermissionService extends JunctionEntityService implements IClientPermissionService {\n protected readonly ownerRealmKey = 'clientRealmId';\n\n protected repository: IClientPermissionRepository;\n\n protected permissionRepository: IEntityRepository<Permission>;\n\n protected identityPermissionProvider: IIdentityPermissionProvider;\n\n protected validator: ClientPermissionValidator;\n\n constructor(ctx: ClientPermissionServiceContext) {\n super();\n this.repository = ctx.repository;\n this.permissionRepository = ctx.permissionRepository;\n this.identityPermissionProvider = ctx.identityPermissionProvider;\n this.validator = new ClientPermissionValidator();\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n ): Promise<EntityRepositoryFindManyResult<ClientPermission>> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.CLIENT_PERMISSION_CREATE,\n PermissionName.CLIENT_PERMISSION_DELETE,\n ],\n });\n\n return this.repository.findMany(await decodeQuery(query, { schema: clientPermissionSchema, actor }));\n }\n\n async getOne(\n id: string,\n actor: ActorContext,\n ): Promise<ClientPermission> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.CLIENT_PERMISSION_CREATE,\n PermissionName.CLIENT_PERMISSION_DELETE,\n ],\n });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n return entity;\n }\n\n async create(\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<ClientPermission> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.CLIENT_PERMISSION_CREATE });\n\n const validated = await this.validator.run(data, { group: ValidatorGroup.CREATE });\n\n await this.repository.validateJoinColumns(validated);\n\n const existing = await this.repository.findOneBy({\n clientId: validated.clientId,\n permissionId: validated.permissionId,\n });\n if (existing) {\n throw new EntityConflictError({ entity: 'client-permission' });\n }\n\n if (validated.permission) {\n validated.permissionRealmId = validated.permission.realmId;\n\n await actor.permissionEvaluator.preEvaluate({\n name: validated.permission.name,\n realmId: validated.permission.realmId,\n clientId: validated.permission.clientId,\n });\n }\n\n if (validated.client) {\n validated.clientRealmId = validated.client.realmId;\n }\n\n if (validated.permission && actor.identity) {\n const grant = await this.identityPermissionProvider.resolveJunctionGrant(\n {\n type: actor.identity.type,\n id: actor.identity.data.id,\n },\n {\n name: validated.permission.name,\n realmId: validated.permission.realmId,\n clientId: validated.permission.clientId,\n realmScope: validated.realmScope ?? RealmScope.OWN,\n },\n );\n\n applyJunctionCreateGrant(validated, grant);\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.CLIENT_PERMISSION_CREATE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: this.junctionAttributes(validated),\n [BuiltInPolicyType.REALM_MATCH]: this.junctionResourceRealm(validated),\n }),\n });\n\n let entity = this.repository.create(validated);\n entity = await this.repository.save(entity);\n\n return entity;\n }\n\n async update(\n id: string,\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<ClientPermission> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.CLIENT_PERMISSION_UPDATE });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n const validated = await this.validator.run(data, { group: ValidatorGroup.UPDATE });\n\n const permission = await this.permissionRepository.findOneById(entity.permissionId);\n if (permission) {\n // Member-permission gate: an actor may only modify a binding for a permission it\n // holds (mirrors create()).\n await actor.permissionEvaluator.preEvaluate({\n name: permission.name,\n realmId: permission.realmId,\n clientId: permission.clientId,\n });\n }\n\n let actorScope: `${RealmScope}` = RealmScope.ANY;\n let actorPolicyFree = true;\n let actorPolicyId: string | null = null;\n if (actor.identity && permission) {\n const grant = await this.identityPermissionProvider.resolveJunctionGrant(\n { type: actor.identity.type, id: actor.identity.data.id },\n {\n name: permission.name,\n realmId: permission.realmId,\n clientId: permission.clientId,\n realmScope: validated.realmScope ?? entity.realmScope,\n },\n );\n actorScope = grant.realmScope;\n actorPolicyFree = !grant.policy;\n actorPolicyId = grant.policy ? grant.policy.id : null;\n } else if (actor.identity) {\n actorScope = RealmScope.OWN;\n }\n\n const updateData = buildJunctionUpdateData({\n data: validated,\n existingScope: entity.realmScope,\n actorScope,\n actorPolicyFree,\n actorPolicyId,\n });\n\n await this.repository.validateJoinColumns(updateData);\n\n const merged = this.repository.merge(entity, updateData);\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.CLIENT_PERMISSION_UPDATE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: this.junctionAttributes(merged),\n [BuiltInPolicyType.REALM_MATCH]: this.junctionResourceRealm(merged),\n }),\n });\n\n return this.repository.save(merged);\n }\n\n async delete(\n id: string,\n actor: ActorContext,\n ): Promise<ClientPermission> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.CLIENT_PERMISSION_DELETE });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.CLIENT_PERMISSION_DELETE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: this.junctionAttributes(entity),\n [BuiltInPolicyType.REALM_MATCH]: this.junctionResourceRealm(entity),\n }),\n });\n\n const { id: entityId } = entity;\n await this.repository.remove(entity);\n entity.id = entityId;\n\n return entity;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service.mjs","names":["BuiltInPolicyType","RealmScope","definePolicyData","EntityConflictError","EntityNotFoundError","ValidatorGroup","ClientPermissionValidator","PermissionName","applyJunctionCreateGrant","buildJunctionUpdateData","JunctionEntityService","decodeQuery","clientPermissionSchema","ClientPermissionService","ownerRealmKey","repository","permissionRepository","identityPermissionProvider","validator","ctx","getMany","query","actor","permissionEvaluator","preEvaluateOneOf","name","CLIENT_PERMISSION_CREATE","CLIENT_PERMISSION_DELETE","findMany","schema","getOne","id","entity","findOneBy","create","data","preEvaluate","validated","run","group","CREATE","validateJoinColumns","existing","clientId","permissionId","permission","permissionRealmId","realmId","client","clientRealmId","identity","grant","resolveJunctionGrant","type","realmScope","OWN","evaluate","ATTRIBUTES","junctionAttributes","REALM_MATCH","junctionResourceRealm","save","update","CLIENT_PERMISSION_UPDATE","UPDATE","findOneById","actorScope","ANY","actorPolicyFree","actorPolicyId","policy","updateData","existingScope","merged","merge","delete","entityId","remove"],"sources":["../../../../src/core/entities/client-permission/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n BuiltInPolicyType,\n RealmScope,\n definePolicyData,\n} from '@authup/access';\nimport { EntityConflictError, EntityNotFoundError } from '@authup/errors';\nimport { ValidatorGroup } from '@authup/kit';\nimport { ClientPermissionValidator, PermissionName } from '@authup/core-kit';\nimport type { ClientPermission, Permission } from '@authup/core-kit';\nimport type { IIdentityPermissionProvider } from '../../identity/permission/types.ts';\nimport { applyJunctionCreateGrant, buildJunctionUpdateData } from '../../identity/permission/junction-grant.ts';\nimport type { ActorContext, EntityRepositoryFindManyResult, IEntityRepository } from '@authup/server-kit';\nimport { JunctionEntityService } from '@authup/server-kit';\nimport type { IClientPermissionRepository, IClientPermissionService } from './types.ts';\nimport { decodeQuery } from '../../query/index.ts';\nimport { clientPermissionSchema } from './schema.ts';\n\nexport type ClientPermissionServiceContext = {\n repository: IClientPermissionRepository;\n permissionRepository: IEntityRepository<Permission>;\n identityPermissionProvider: IIdentityPermissionProvider;\n};\n\nexport class ClientPermissionService extends JunctionEntityService implements IClientPermissionService {\n protected readonly ownerRealmKey = 'clientRealmId';\n\n protected repository: IClientPermissionRepository;\n\n protected permissionRepository: IEntityRepository<Permission>;\n\n protected identityPermissionProvider: IIdentityPermissionProvider;\n\n protected validator: ClientPermissionValidator;\n\n constructor(ctx: ClientPermissionServiceContext) {\n super();\n this.repository = ctx.repository;\n this.permissionRepository = ctx.permissionRepository;\n this.identityPermissionProvider = ctx.identityPermissionProvider;\n this.validator = new ClientPermissionValidator();\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n ): Promise<EntityRepositoryFindManyResult<ClientPermission>> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.CLIENT_PERMISSION_CREATE,\n PermissionName.CLIENT_PERMISSION_DELETE,\n ],\n });\n\n return this.repository.findMany(await decodeQuery(query, { schema: clientPermissionSchema, actor }));\n }\n\n async getOne(\n id: string,\n actor: ActorContext,\n ): Promise<ClientPermission> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.CLIENT_PERMISSION_CREATE,\n PermissionName.CLIENT_PERMISSION_DELETE,\n ],\n });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n return entity;\n }\n\n async create(\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<ClientPermission> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.CLIENT_PERMISSION_CREATE });\n\n const validated = await this.validator.run(data, { group: ValidatorGroup.CREATE });\n\n await this.repository.validateJoinColumns(validated);\n\n const existing = await this.repository.findOneBy({\n clientId: validated.clientId,\n permissionId: validated.permissionId,\n });\n if (existing) {\n throw new EntityConflictError({ entity: 'client-permission' });\n }\n\n if (validated.permission) {\n validated.permissionRealmId = validated.permission.realmId;\n\n await actor.permissionEvaluator.preEvaluate({\n name: validated.permission.name,\n realmId: validated.permission.realmId,\n clientId: validated.permission.clientId,\n });\n }\n\n if (validated.client) {\n validated.clientRealmId = validated.client.realmId;\n }\n\n if (validated.permission && actor.identity) {\n const grant = await this.identityPermissionProvider.resolveJunctionGrant(\n {\n type: actor.identity.type,\n id: actor.identity.data.id,\n },\n {\n name: validated.permission.name,\n realmId: validated.permission.realmId,\n clientId: validated.permission.clientId,\n realmScope: validated.realmScope ?? RealmScope.OWN,\n },\n );\n\n applyJunctionCreateGrant(validated, grant);\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.CLIENT_PERMISSION_CREATE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: this.junctionAttributes(validated),\n [BuiltInPolicyType.REALM_MATCH]: this.junctionResourceRealm(validated),\n }),\n });\n\n let entity = this.repository.create(validated);\n entity = await this.repository.save(entity);\n\n return entity;\n }\n\n async update(\n id: string,\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<ClientPermission> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.CLIENT_PERMISSION_UPDATE });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n const validated = await this.validator.run(data, { group: ValidatorGroup.UPDATE });\n\n const permission = await this.permissionRepository.findOneById(entity.permissionId);\n if (permission) {\n // Member-permission gate: an actor may only modify a binding for a permission it\n // holds (mirrors create()).\n await actor.permissionEvaluator.preEvaluate({\n name: permission.name,\n realmId: permission.realmId,\n clientId: permission.clientId,\n });\n }\n\n let actorScope: `${RealmScope}` = RealmScope.ANY;\n let actorPolicyFree = true;\n let actorPolicyId: string | null = null;\n if (actor.identity && permission) {\n const grant = await this.identityPermissionProvider.resolveJunctionGrant(\n { type: actor.identity.type, id: actor.identity.data.id },\n {\n name: permission.name,\n realmId: permission.realmId,\n clientId: permission.clientId,\n realmScope: validated.realmScope ?? entity.realmScope,\n },\n );\n actorScope = grant.realmScope;\n actorPolicyFree = !grant.policy;\n actorPolicyId = grant.policy ? grant.policy.id : null;\n } else if (actor.identity) {\n actorScope = RealmScope.OWN;\n }\n\n const updateData = buildJunctionUpdateData({\n data: validated,\n existingScope: entity.realmScope,\n actorScope,\n actorPolicyFree,\n actorPolicyId,\n });\n\n await this.repository.validateJoinColumns(updateData);\n\n const merged = this.repository.merge(entity, updateData);\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.CLIENT_PERMISSION_UPDATE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: this.junctionAttributes(merged),\n [BuiltInPolicyType.REALM_MATCH]: this.junctionResourceRealm(merged),\n }),\n });\n\n return this.repository.save(merged);\n }\n\n async delete(\n id: string,\n actor: ActorContext,\n ): Promise<ClientPermission> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.CLIENT_PERMISSION_DELETE });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.CLIENT_PERMISSION_DELETE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: this.junctionAttributes(entity),\n [BuiltInPolicyType.REALM_MATCH]: this.junctionResourceRealm(entity),\n }),\n });\n\n const { id: entityId } = entity;\n await this.repository.remove(entity);\n entity.id = entityId;\n\n return entity;\n }\n}\n"],"mappings":"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"}
|
|
@@ -29,7 +29,7 @@ import { userAuthenticatorSchema } from "./user-authenticator/schema.mjs";
|
|
|
29
29
|
import { userPermissionSchema } from "./user-permission/schema.mjs";
|
|
30
30
|
import { userRoleSchema } from "./user-role/schema.mjs";
|
|
31
31
|
import { ClientService } from "./client/service.mjs";
|
|
32
|
-
import {
|
|
32
|
+
import { SYSTEM_CLIENT_DEFINITIONS, SYSTEM_CLIENT_SCOPE_NAMES, SystemClientProvisioner, buildSystemClientAttributes } from "./client/system-clients.mjs";
|
|
33
33
|
import "./client/index.mjs";
|
|
34
34
|
import { ClientPermissionService } from "./client-permission/service.mjs";
|
|
35
35
|
import "./client-permission/index.mjs";
|
|
@@ -83,4 +83,4 @@ import { UserRoleService } from "./user-role/service.mjs";
|
|
|
83
83
|
import "./user-role/index.mjs";
|
|
84
84
|
import { IdentityProviderRoleMappingService } from "./identity-provider-role-mapping/service.mjs";
|
|
85
85
|
import "./identity-provider-role-mapping/index.mjs";
|
|
86
|
-
export { CLIENT_READ_PERMISSIONS, CONSENT_FILTER_KEYS, CONSENT_SCOPE_MAX_LENGTH, ClientPermissionService, ClientRoleService, ClientScopeService, ClientService, ConsentService, EVENT_ACTOR_NAME_MAX_LENGTH, EVENT_DIFF_SECRET_KEY_REGEX, EVENT_DIFF_VALUE_MAX_LENGTH, EVENT_LOG_RETENTION_DAYS_DEFAULT, EntityEventHandler, EventService, IdentityProviderRoleMappingService, KeyService, PermissionPolicyService, PermissionService, PolicyService, RealmService, RoleAttributeService, RolePermissionService, RoleService, ScopeService, SessionService, TrustAnchorService, USER_AUTHENTICATOR_ATTEMPT_CACHE_PREFIX, USER_AUTHENTICATOR_ATTEMPT_LOCK_FACTOR, USER_AUTHENTICATOR_ATTEMPT_LOCK_MAX, USER_AUTHENTICATOR_ATTEMPT_WINDOW, USER_AUTHENTICATOR_EMAIL_CODE_CACHE_PREFIX, USER_AUTHENTICATOR_EMAIL_CODE_EXPIRES_IN_MINUTES, USER_AUTHENTICATOR_EMAIL_CODE_LENGTH, USER_AUTHENTICATOR_EMAIL_SEND_CACHE_PREFIX, USER_AUTHENTICATOR_EMAIL_SEND_COOLDOWN, USER_AUTHENTICATOR_FILTER_KEYS, USER_AUTHENTICATOR_RECOVERY_CODE_COUNT, USER_AUTHENTICATOR_THROTTLE_CACHE_PREFIX, USER_AUTHENTICATOR_TOTP_ALGORITHM, USER_AUTHENTICATOR_TOTP_DIGITS, USER_AUTHENTICATOR_TOTP_PERIOD, USER_AUTHENTICATOR_VERIFY_LOCK_CACHE_PREFIX, USER_AUTHENTICATOR_VERIFY_LOCK_RENEW_INTERVAL, USER_AUTHENTICATOR_VERIFY_LOCK_TTL, USER_AUTHENTICATOR_WEBAUTHN_AUTH_CACHE_PREFIX, USER_AUTHENTICATOR_WEBAUTHN_CHALLENGE_WINDOW, USER_AUTHENTICATOR_WEBAUTHN_REG_CACHE_PREFIX, UserAttributeService, UserAuthenticatorService, UserPermissionService, UserRoleService, UserService,
|
|
86
|
+
export { CLIENT_READ_PERMISSIONS, CONSENT_FILTER_KEYS, CONSENT_SCOPE_MAX_LENGTH, ClientPermissionService, ClientRoleService, ClientScopeService, ClientService, ConsentService, EVENT_ACTOR_NAME_MAX_LENGTH, EVENT_DIFF_SECRET_KEY_REGEX, EVENT_DIFF_VALUE_MAX_LENGTH, EVENT_LOG_RETENTION_DAYS_DEFAULT, EntityEventHandler, EventService, IdentityProviderRoleMappingService, KeyService, PermissionPolicyService, PermissionService, PolicyService, RealmService, RoleAttributeService, RolePermissionService, RoleService, SYSTEM_CLIENT_DEFINITIONS, SYSTEM_CLIENT_SCOPE_NAMES, ScopeService, SessionService, SystemClientProvisioner, TrustAnchorService, USER_AUTHENTICATOR_ATTEMPT_CACHE_PREFIX, USER_AUTHENTICATOR_ATTEMPT_LOCK_FACTOR, USER_AUTHENTICATOR_ATTEMPT_LOCK_MAX, USER_AUTHENTICATOR_ATTEMPT_WINDOW, USER_AUTHENTICATOR_EMAIL_CODE_CACHE_PREFIX, USER_AUTHENTICATOR_EMAIL_CODE_EXPIRES_IN_MINUTES, USER_AUTHENTICATOR_EMAIL_CODE_LENGTH, USER_AUTHENTICATOR_EMAIL_SEND_CACHE_PREFIX, USER_AUTHENTICATOR_EMAIL_SEND_COOLDOWN, USER_AUTHENTICATOR_FILTER_KEYS, USER_AUTHENTICATOR_RECOVERY_CODE_COUNT, USER_AUTHENTICATOR_THROTTLE_CACHE_PREFIX, USER_AUTHENTICATOR_TOTP_ALGORITHM, USER_AUTHENTICATOR_TOTP_DIGITS, USER_AUTHENTICATOR_TOTP_PERIOD, USER_AUTHENTICATOR_VERIFY_LOCK_CACHE_PREFIX, USER_AUTHENTICATOR_VERIFY_LOCK_RENEW_INTERVAL, USER_AUTHENTICATOR_VERIFY_LOCK_TTL, USER_AUTHENTICATOR_WEBAUTHN_AUTH_CACHE_PREFIX, USER_AUTHENTICATOR_WEBAUTHN_CHALLENGE_WINDOW, USER_AUTHENTICATOR_WEBAUTHN_REG_CACHE_PREFIX, UserAttributeService, UserAuthenticatorService, UserPermissionService, UserRoleService, UserService, buildEntityDiff, buildSystemClientAttributes, buildWebauthnAuthenticationOptions, buildWebauthnRegistrationOptions, clientPermissionSchema, clientRoleSchema, clientSchema, clientScopeSchema, consentSchema, eventSchema, generateNumericCode, generateRecoveryCode, guessUserAuthenticatorKindByResponse, identityProviderRoleMappingSchema, identityProviderSchema, keySchema, permissionPolicySchema, permissionSchema, policySchema, realmSchema, roleAttributeSchema, rolePermissionSchema, roleSchema, sanitizeEventData, scopeSchema, sessionSchema, trustAnchorSchema, userAttributeSchema, userAuthenticatorSchema, userPermissionSchema, userRoleSchema, userSchema, verifyWebauthnAuthentication, verifyWebauthnRegistration };
|
|
@@ -121,7 +121,8 @@ var KeyService = class extends AbstractEntityService {
|
|
|
121
121
|
if (certificate) {
|
|
122
122
|
if (!material.encryptionKey) throw new ValidationError("A certificate requires imported signature key material.");
|
|
123
123
|
try {
|
|
124
|
-
|
|
124
|
+
const chain = parseCertificateChain(certificate);
|
|
125
|
+
assertCertificateMatchesKey(chain, material.encryptionKey);
|
|
125
126
|
} catch (e) {
|
|
126
127
|
throw new ValidationError(isError(e) ? e.message : "The certificate could not be matched against the imported key material.");
|
|
127
128
|
}
|
|
@@ -239,7 +240,8 @@ var KeyService = class extends AbstractEntityService {
|
|
|
239
240
|
};
|
|
240
241
|
}
|
|
241
242
|
const algorithm = validated.signatureAlgorithm ?? JWTAlgorithm.RS256;
|
|
242
|
-
const
|
|
243
|
+
const options = this.buildAsymmetricOptions(algorithm);
|
|
244
|
+
const keyPair = await createAsymmetricKeyPair(options);
|
|
243
245
|
return {
|
|
244
246
|
type: algorithm.startsWith("ES") ? JWKType.EC : JWKType.RSA,
|
|
245
247
|
signatureAlgorithm: algorithm,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.mjs","names":["BuiltInPolicyType","definePolicyData","eq","inArray","EntityConflictError","EntityNotFoundError","ValidationError","isError","isRawError","EntityType","EventName","EventScope","KeyStatus","KeyValidator","PermissionName","ValidatorGroup","arrayBufferToBase64","base64ToArrayBuffer","createNanoID","AbstractEntityService","AsymmetricKey","createAsymmetricKeyPair","JWKType","JWKUse","JWTAlgorithm","getRandomValues","buildEntityDiff","assertCertificateMatchesKey","isWrappedKeyMaterial","parseCertificateChain","appendQueryConditions","decodeQuery","keySchema","PERMISSION_NAMES","KEY_READ","KEY_UPDATE","KEY_DELETE","KeyService","repository","validator","eventService","requestContext","ctx","getMany","query","actor","options","permissionEvaluator","preEvaluateOneOf","name","parsed","schema","realmId","compiled","compile","verdict","condition","data","entities","meta","findMany","entity","decryptionKey","total","evaluateOneOf","ATTRIBUTES","resourceRealmMatch","push","getOne","idOrName","findOneByIdOrName","create","preEvaluate","KEY_CREATE","validated","run","group","CREATE","use","validateJoinColumns","identity","actorRealmId","getActorRealmId","evaluate","checkUniqueness","priority","highest","findHighestPriority","status","ACTIVE","certificate","SIGNATURE","material","importMaterial","generateMaterial","encryptionKey","chain","e","message","type","signatureAlgorithm","save","recordEvent","CREATED","update","UPDATE","previous","pickAuditFields","merge","diff","UPDATED","Object","keys","length","delete","id","findOneBy","ENCRYPTION","force","references","countBlobReferences","entityId","remove","forcedCryptoShred","DELETED","undefined","record","scope","ENTITY","refType","KEY","refId","actorType","actorId","actorName","requestPath","requestMethod","requestIpAddress","requestUserAgent","raw","Uint8Array","OCT","buffer","algorithm","RS256","buildAsymmetricOptions","keyPair","startsWith","EC","RSA","privateKey","toBase64","publicKey","trim","normalizeMaterial","byteLength","privateJwk","publicJwk","fromBase64","format","key","toJWK","components","mismatch","some","component","test","buildImportOptionsForJWTAlgorithm","value","includes","replace"],"sources":["../../../../src/core/entities/key/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { BuiltInPolicyType, definePolicyData } from '@authup/access';\nimport { eq, inArray } from '@rapiq/core';\nimport {\n EntityConflictError,\n EntityNotFoundError,\n ValidationError,\n isError as isRawError,\n} from '@authup/errors';\nimport type { Key } from '@authup/core-kit';\nimport {\n EntityType,\n EventName,\n EventScope,\n KeyStatus,\n KeyValidator,\n PermissionName,\n} from '@authup/core-kit';\nimport {\n ValidatorGroup,\n arrayBufferToBase64,\n base64ToArrayBuffer,\n createNanoID,\n} from '@authup/kit';\nimport type { ActorContext, EntityRepositoryFindManyResult } from '@authup/server-kit';\nimport { AbstractEntityService, AsymmetricKey, createAsymmetricKeyPair } from '@authup/server-kit';\nimport { JWKType, JWKUse, JWTAlgorithm } from '@authup/specs';\nimport { getRandomValues } from 'uncrypto';\nimport { buildEntityDiff } from '../event/index.ts';\nimport type { EventRequestContext, IEventService } from '../event/index.ts';\nimport { assertCertificateMatchesKey, isWrappedKeyMaterial, parseCertificateChain } from '../../key/index.ts';\nimport type {\n IKeyRepository, \n IKeyService, \n KeyDeleteOptions, \n KeyServiceReadOptions,\n} from './types.ts';\nimport { appendQueryConditions, decodeQuery } from '../../query/index.ts';\nimport { keySchema } from './schema.ts';\n\nexport type KeyServiceContext = {\n repository: IKeyRepository;\n eventService?: IEventService;\n requestContext?: () => EventRequestContext | undefined;\n};\n\nconst PERMISSION_NAMES = [\n PermissionName.KEY_READ,\n PermissionName.KEY_UPDATE,\n PermissionName.KEY_DELETE,\n];\n\nexport class KeyService extends AbstractEntityService implements IKeyService {\n protected repository: IKeyRepository;\n\n protected validator: KeyValidator;\n\n protected eventService?: IEventService;\n\n protected requestContext?: () => EventRequestContext | undefined;\n\n constructor(ctx: KeyServiceContext) {\n super();\n this.repository = ctx.repository;\n this.validator = new KeyValidator();\n this.eventService = ctx.eventService;\n this.requestContext = ctx.requestContext;\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n options: KeyServiceReadOptions = {},\n ): Promise<EntityRepositoryFindManyResult<Key>> {\n await actor.permissionEvaluator.preEvaluateOneOf({ name: PERMISSION_NAMES });\n\n let parsed = await decodeQuery(query, { schema: keySchema, actor });\n if (options.realmId) {\n parsed = appendQueryConditions(parsed, eq('realmId', options.realmId));\n }\n\n // Compile the read permissions against the knowns (actor identity) into a\n // row condition (issue #3286 phase 3): the authorization runs as WHERE, so\n // pagination and totals stay exact. Non-expressible policies fall back to\n // the per-row post-evaluation below.\n const compiled = await actor.permissionEvaluator.compile({ name: PERMISSION_NAMES });\n if (compiled.verdict === 'deny') {\n // no row can pass — a constant-false condition keeps the meta shape\n parsed = appendQueryConditions(parsed, inArray('id', []));\n } else if (compiled.verdict === 'conditional') {\n parsed = appendQueryConditions(parsed, compiled.condition);\n }\n\n const { data: entities, meta } = await this.repository.findMany(parsed);\n\n if (compiled.verdict !== 'post') {\n for (const entity of entities) {\n // Belt-and-braces: the read projection never selects private\n // material, but null it explicitly so no future adapter change\n // can leak it onto a read surface (cf. authentik CVE-2024-42490).\n entity.decryptionKey = null;\n }\n\n return { data: entities, meta };\n }\n\n const data: Key[] = [];\n let { total } = meta;\n\n for (const entity of entities) {\n try {\n await actor.permissionEvaluator.evaluateOneOf({\n name: PERMISSION_NAMES,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: entity,\n ...this.resourceRealmMatch(entity),\n }),\n });\n entity.decryptionKey = null;\n data.push(entity);\n } catch {\n total -= 1;\n }\n }\n\n return {\n data,\n meta: {\n ...meta,\n total,\n },\n };\n }\n\n async getOne(\n idOrName: string,\n actor: ActorContext,\n realmId?: string,\n ): Promise<Key> {\n await actor.permissionEvaluator.preEvaluateOneOf({ name: PERMISSION_NAMES });\n\n const entity = await this.repository.findOneByIdOrName(idOrName, realmId);\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n await actor.permissionEvaluator.evaluateOneOf({\n name: PERMISSION_NAMES,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: entity,\n ...this.resourceRealmMatch(entity),\n }),\n });\n\n // Belt-and-braces null of private material (see getMany).\n entity.decryptionKey = null;\n\n return entity;\n }\n\n async create(\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<Key> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.KEY_CREATE });\n\n const validated = await this.validator.run(data, { group: ValidatorGroup.CREATE });\n const { use } = validated;\n if (!use) {\n throw new ValidationError('A key use must be specified.');\n }\n\n await this.repository.validateJoinColumns(validated);\n\n if (!validated.realmId && actor.identity) {\n const actorRealmId = this.getActorRealmId(actor);\n if (actorRealmId) {\n validated.realmId = actorRealmId;\n }\n }\n\n // keys are realm-bound infrastructure — no global (null realm) keys\n // via the API.\n if (!validated.realmId) {\n throw new ValidationError('A realm must be specified.');\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.KEY_CREATE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: validated,\n ...this.resourceRealmMatch(validated),\n }),\n });\n\n if (!validated.name) {\n validated.name = `${use}-${createNanoID(10)}`;\n }\n\n await this.repository.checkUniqueness(validated);\n\n if (typeof validated.priority !== 'number') {\n const highest = await this.repository.findHighestPriority(validated.realmId, use);\n // generate doubles as rotate: a new key outranks the current one.\n validated.priority = typeof highest === 'number' ? highest + 1 : 0;\n }\n\n if (!validated.status) {\n validated.status = KeyStatus.ACTIVE;\n }\n\n const certificate = typeof validated.certificate === 'string' ? validated.certificate : null;\n if (certificate && (!validated.decryptionKey || use !== JWKUse.SIGNATURE)) {\n throw new ValidationError('A certificate requires imported signature key material.');\n }\n\n const material = validated.decryptionKey ?\n await this.importMaterial(validated, use) :\n await this.generateMaterial(validated, use);\n\n if (certificate) {\n if (!material.encryptionKey) {\n throw new ValidationError('A certificate requires imported signature key material.');\n }\n\n try {\n const chain = parseCertificateChain(certificate);\n assertCertificateMatchesKey(chain, material.encryptionKey);\n } catch (e) {\n throw new ValidationError(\n isRawError(e) ?\n e.message :\n 'The certificate could not be matched against the imported key material.',\n );\n }\n }\n\n let entity = this.repository.create({\n ...validated,\n type: material.type,\n signatureAlgorithm: material.signatureAlgorithm,\n decryptionKey: material.decryptionKey,\n encryptionKey: material.encryptionKey,\n });\n\n entity = await this.repository.save(entity);\n\n // private material never leaves the server — the response carries\n // metadata + public part only (authentik CVE-2024-42490).\n entity.decryptionKey = null;\n\n await this.recordEvent(EventName.CREATED, entity, actor);\n\n return entity;\n }\n\n async update(\n idOrName: string,\n data: Record<string, any>,\n actor: ActorContext,\n realmId?: string,\n ): Promise<Key> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.KEY_UPDATE });\n\n let entity = await this.repository.findOneByIdOrName(idOrName, realmId);\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n // only name / priority / status are mounted for UPDATE — material,\n // use, type and realm are immutable.\n const validated = await this.validator.run(data, { group: ValidatorGroup.UPDATE });\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.KEY_UPDATE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: {\n ...entity,\n ...validated,\n },\n ...this.resourceRealmMatch(entity),\n }),\n });\n\n if (validated.name && validated.name !== entity.name) {\n await this.repository.checkUniqueness({\n name: validated.name,\n realmId: entity.realmId,\n }, entity);\n }\n\n const previous = this.pickAuditFields(entity);\n\n entity = this.repository.merge(entity, validated);\n await this.repository.save(entity);\n\n entity.decryptionKey = null;\n\n const diff = buildEntityDiff(this.pickAuditFields(entity), previous);\n await this.recordEvent(EventName.UPDATED, entity, actor, { ...(Object.keys(diff).length > 0 ? { diff } : {}) });\n\n return entity;\n }\n\n async delete(\n id: string,\n actor: ActorContext,\n options: KeyDeleteOptions = {},\n ): Promise<Key> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.KEY_DELETE });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.KEY_DELETE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: entity,\n ...this.resourceRealmMatch(entity),\n }),\n });\n\n if (entity.use === JWKUse.ENCRYPTION && !options.force) {\n const references = await this.repository.countBlobReferences(entity.id);\n if (references > 0) {\n throw new EntityConflictError({\n message: `The encryption key is still referenced by ${references} encrypted secret(s) — ` +\n 'deleting it makes them unrecoverable. Repeat with force to crypto-shred them.',\n data: { references },\n });\n }\n }\n\n const { id: entityId } = entity;\n await this.repository.remove(entity);\n entity.id = entityId;\n entity.decryptionKey = null;\n\n // force only carries crypto-shred semantics for encryption keys — a\n // sig-key delete with a stray force flag must not read as a shred.\n const forcedCryptoShred = entity.use === JWKUse.ENCRYPTION && !!options.force;\n await this.recordEvent(EventName.DELETED, entity, actor, { ...(forcedCryptoShred ? { force: true } : {}) });\n\n return entity;\n }\n\n // ------------------------------------------------------------------\n\n /**\n * Metadata-only audit trail for key lifecycle operations (issue #3269) —\n * keys deliberately have no entity subscriber (private material must stay\n * off the realtime/audit bus), so the security-relevant mutations are\n * recorded explicitly. The payload never carries key material.\n */\n protected async recordEvent(\n name: `${EventName}`,\n entity: Key,\n actor: ActorContext,\n data: Record<string, any> = {},\n ): Promise<void> {\n const requestContext = this.requestContext ?\n this.requestContext() :\n undefined;\n\n await this.eventService?.record({\n scope: EventScope.ENTITY,\n name,\n refType: EntityType.KEY,\n refId: entity.id,\n realmId: entity.realmId ?? null,\n actorType: actor.identity?.type ?? null,\n actorId: actor.identity?.data.id ?? null,\n actorName: actor.identity?.data.name ?? null,\n requestPath: requestContext?.requestPath ?? null,\n requestMethod: requestContext?.requestMethod ?? null,\n requestIpAddress: requestContext?.requestIpAddress ?? null,\n requestUserAgent: requestContext?.requestUserAgent ?? null,\n data: {\n name: entity.name,\n use: entity.use,\n status: entity.status,\n ...data,\n },\n });\n }\n\n protected pickAuditFields(entity: Key): Record<string, any> {\n return {\n name: entity.name,\n priority: entity.priority,\n status: entity.status,\n };\n }\n\n protected async generateMaterial(\n validated: Partial<Key>,\n use: `${JWKUse}`,\n ) : Promise<{\n type: `${JWKType}`,\n signatureAlgorithm: `${JWTAlgorithm}` | null,\n decryptionKey: string,\n encryptionKey: string | null,\n }> {\n if (use === JWKUse.ENCRYPTION) {\n if (validated.signatureAlgorithm) {\n throw new ValidationError('An encryption key can not carry a signature algorithm.');\n }\n\n const raw = new Uint8Array(32);\n getRandomValues(raw);\n\n return {\n type: JWKType.OCT,\n signatureAlgorithm: null,\n decryptionKey: arrayBufferToBase64(raw.buffer),\n encryptionKey: null,\n };\n }\n\n const algorithm = validated.signatureAlgorithm ?? JWTAlgorithm.RS256;\n const options = this.buildAsymmetricOptions(algorithm);\n\n const keyPair = await createAsymmetricKeyPair(options);\n\n return {\n type: algorithm.startsWith('ES') ? JWKType.EC : JWKType.RSA,\n signatureAlgorithm: algorithm,\n decryptionKey: await new AsymmetricKey(keyPair.privateKey).toBase64(),\n encryptionKey: await new AsymmetricKey(keyPair.publicKey).toBase64(),\n };\n }\n\n protected async importMaterial(\n validated: Partial<Key>,\n use: `${JWKUse}`,\n ) : Promise<{\n type: `${JWKType}`,\n signatureAlgorithm: `${JWTAlgorithm}` | null,\n decryptionKey: string,\n encryptionKey: string | null,\n }> {\n if (!validated.decryptionKey) {\n throw new ValidationError('Importing key material requires its private part (decryptionKey).');\n }\n\n // Reject material masquerading as an at-rest KEK-wrapped blob — it\n // would be treated as wrapped on the next read (and, with a KEK,\n // fail GCM authentication).\n if (isWrappedKeyMaterial(validated.decryptionKey.trim())) {\n throw new ValidationError('The imported key material is not valid.');\n }\n\n const decryptionKey = this.normalizeMaterial(validated.decryptionKey);\n\n if (use === JWKUse.ENCRYPTION) {\n if (validated.signatureAlgorithm) {\n throw new ValidationError('An encryption key can not carry a signature algorithm.');\n }\n\n if (validated.encryptionKey) {\n throw new ValidationError('An encryption key holds no public part.');\n }\n\n let byteLength : number;\n try {\n byteLength = base64ToArrayBuffer(decryptionKey).byteLength;\n } catch {\n throw new ValidationError('The key material is not valid base64.');\n }\n\n if (byteLength !== 32) {\n throw new ValidationError('The key material must be 32 base64-encoded bytes.');\n }\n\n return {\n type: JWKType.OCT,\n signatureAlgorithm: null,\n decryptionKey,\n encryptionKey: null,\n };\n }\n\n if (!validated.encryptionKey) {\n throw new ValidationError('Importing a signature key requires its public part (encryptionKey, SPKI).');\n }\n\n const encryptionKey = this.normalizeMaterial(validated.encryptionKey);\n const algorithm = validated.signatureAlgorithm ?? JWTAlgorithm.RS256;\n const options = this.buildAsymmetricOptions(algorithm);\n\n let privateJwk : JsonWebKey;\n let publicJwk : JsonWebKey;\n\n try {\n const privateKey = await AsymmetricKey.fromBase64({\n format: 'pkcs8',\n key: decryptionKey,\n options,\n });\n const publicKey = await AsymmetricKey.fromBase64({\n format: 'spki',\n key: encryptionKey,\n options,\n });\n\n privateJwk = await privateKey.toJWK();\n publicJwk = await publicKey.toJWK();\n } catch {\n throw new ValidationError(`The key material could not be imported for ${algorithm}.`);\n }\n\n // the public components (RSA: n/e, EC: crv/x/y) must agree — a\n // private key paired with a foreign public part would publish a\n // wrong JWKS entry and break verification of every token it signs.\n const components : (keyof JsonWebKey)[] = ['kty', 'n', 'e', 'crv', 'x', 'y'];\n const mismatch = components.some(\n (component) => publicJwk[component] !== undefined &&\n publicJwk[component] !== privateJwk[component],\n );\n if (mismatch) {\n throw new ValidationError('The private and public key material do not form a pair.');\n }\n\n return {\n type: algorithm.startsWith('ES') ? JWKType.EC : JWKType.RSA,\n signatureAlgorithm: algorithm,\n decryptionKey,\n encryptionKey,\n };\n }\n\n protected buildAsymmetricOptions(algorithm: `${JWTAlgorithm}`) {\n if (!/^(RS|ES)(256|384|512)$/.test(algorithm)) {\n throw new ValidationError(`The signature algorithm ${algorithm} is not supported for stored keys.`);\n }\n\n return AsymmetricKey.buildImportOptionsForJWTAlgorithm(algorithm);\n }\n\n protected normalizeMaterial(value: string) : string {\n if (value.includes('-----BEGIN')) {\n // PEM body IS base64 DER — strip armor + whitespace.\n return value\n .replace(/-----(BEGIN|END)[^-]+-----/g, '')\n .replace(/\\s+/g, '');\n }\n\n return value.trim();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service.mjs","names":["BuiltInPolicyType","definePolicyData","eq","inArray","EntityConflictError","EntityNotFoundError","ValidationError","isError","isRawError","EntityType","EventName","EventScope","KeyStatus","KeyValidator","PermissionName","ValidatorGroup","arrayBufferToBase64","base64ToArrayBuffer","createNanoID","AbstractEntityService","AsymmetricKey","createAsymmetricKeyPair","JWKType","JWKUse","JWTAlgorithm","getRandomValues","buildEntityDiff","assertCertificateMatchesKey","isWrappedKeyMaterial","parseCertificateChain","appendQueryConditions","decodeQuery","keySchema","PERMISSION_NAMES","KEY_READ","KEY_UPDATE","KEY_DELETE","KeyService","repository","validator","eventService","requestContext","ctx","getMany","query","actor","options","permissionEvaluator","preEvaluateOneOf","name","parsed","schema","realmId","compiled","compile","verdict","condition","data","entities","meta","findMany","entity","decryptionKey","total","evaluateOneOf","ATTRIBUTES","resourceRealmMatch","push","getOne","idOrName","findOneByIdOrName","create","preEvaluate","KEY_CREATE","validated","run","group","CREATE","use","validateJoinColumns","identity","actorRealmId","getActorRealmId","evaluate","checkUniqueness","priority","highest","findHighestPriority","status","ACTIVE","certificate","SIGNATURE","material","importMaterial","generateMaterial","encryptionKey","chain","e","message","type","signatureAlgorithm","save","recordEvent","CREATED","update","UPDATE","previous","pickAuditFields","merge","diff","UPDATED","Object","keys","length","delete","id","findOneBy","ENCRYPTION","force","references","countBlobReferences","entityId","remove","forcedCryptoShred","DELETED","undefined","record","scope","ENTITY","refType","KEY","refId","actorType","actorId","actorName","requestPath","requestMethod","requestIpAddress","requestUserAgent","raw","Uint8Array","OCT","buffer","algorithm","RS256","buildAsymmetricOptions","keyPair","startsWith","EC","RSA","privateKey","toBase64","publicKey","trim","normalizeMaterial","byteLength","privateJwk","publicJwk","fromBase64","format","key","toJWK","components","mismatch","some","component","test","buildImportOptionsForJWTAlgorithm","value","includes","replace"],"sources":["../../../../src/core/entities/key/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { BuiltInPolicyType, definePolicyData } from '@authup/access';\nimport { eq, inArray } from '@rapiq/core';\nimport {\n EntityConflictError,\n EntityNotFoundError,\n ValidationError,\n isError as isRawError,\n} from '@authup/errors';\nimport type { Key } from '@authup/core-kit';\nimport {\n EntityType,\n EventName,\n EventScope,\n KeyStatus,\n KeyValidator,\n PermissionName,\n} from '@authup/core-kit';\nimport {\n ValidatorGroup,\n arrayBufferToBase64,\n base64ToArrayBuffer,\n createNanoID,\n} from '@authup/kit';\nimport type { ActorContext, EntityRepositoryFindManyResult } from '@authup/server-kit';\nimport { AbstractEntityService, AsymmetricKey, createAsymmetricKeyPair } from '@authup/server-kit';\nimport { JWKType, JWKUse, JWTAlgorithm } from '@authup/specs';\nimport { getRandomValues } from 'uncrypto';\nimport { buildEntityDiff } from '../event/index.ts';\nimport type { EventRequestContext, IEventService } from '../event/index.ts';\nimport { assertCertificateMatchesKey, isWrappedKeyMaterial, parseCertificateChain } from '../../key/index.ts';\nimport type {\n IKeyRepository, \n IKeyService, \n KeyDeleteOptions, \n KeyServiceReadOptions,\n} from './types.ts';\nimport { appendQueryConditions, decodeQuery } from '../../query/index.ts';\nimport { keySchema } from './schema.ts';\n\nexport type KeyServiceContext = {\n repository: IKeyRepository;\n eventService?: IEventService;\n requestContext?: () => EventRequestContext | undefined;\n};\n\nconst PERMISSION_NAMES = [\n PermissionName.KEY_READ,\n PermissionName.KEY_UPDATE,\n PermissionName.KEY_DELETE,\n];\n\nexport class KeyService extends AbstractEntityService implements IKeyService {\n protected repository: IKeyRepository;\n\n protected validator: KeyValidator;\n\n protected eventService?: IEventService;\n\n protected requestContext?: () => EventRequestContext | undefined;\n\n constructor(ctx: KeyServiceContext) {\n super();\n this.repository = ctx.repository;\n this.validator = new KeyValidator();\n this.eventService = ctx.eventService;\n this.requestContext = ctx.requestContext;\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n options: KeyServiceReadOptions = {},\n ): Promise<EntityRepositoryFindManyResult<Key>> {\n await actor.permissionEvaluator.preEvaluateOneOf({ name: PERMISSION_NAMES });\n\n let parsed = await decodeQuery(query, { schema: keySchema, actor });\n if (options.realmId) {\n parsed = appendQueryConditions(parsed, eq('realmId', options.realmId));\n }\n\n // Compile the read permissions against the knowns (actor identity) into a\n // row condition (issue #3286 phase 3): the authorization runs as WHERE, so\n // pagination and totals stay exact. Non-expressible policies fall back to\n // the per-row post-evaluation below.\n const compiled = await actor.permissionEvaluator.compile({ name: PERMISSION_NAMES });\n if (compiled.verdict === 'deny') {\n // no row can pass — a constant-false condition keeps the meta shape\n parsed = appendQueryConditions(parsed, inArray('id', []));\n } else if (compiled.verdict === 'conditional') {\n parsed = appendQueryConditions(parsed, compiled.condition);\n }\n\n const { data: entities, meta } = await this.repository.findMany(parsed);\n\n if (compiled.verdict !== 'post') {\n for (const entity of entities) {\n // Belt-and-braces: the read projection never selects private\n // material, but null it explicitly so no future adapter change\n // can leak it onto a read surface (cf. authentik CVE-2024-42490).\n entity.decryptionKey = null;\n }\n\n return { data: entities, meta };\n }\n\n const data: Key[] = [];\n let { total } = meta;\n\n for (const entity of entities) {\n try {\n await actor.permissionEvaluator.evaluateOneOf({\n name: PERMISSION_NAMES,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: entity,\n ...this.resourceRealmMatch(entity),\n }),\n });\n entity.decryptionKey = null;\n data.push(entity);\n } catch {\n total -= 1;\n }\n }\n\n return {\n data,\n meta: {\n ...meta,\n total,\n },\n };\n }\n\n async getOne(\n idOrName: string,\n actor: ActorContext,\n realmId?: string,\n ): Promise<Key> {\n await actor.permissionEvaluator.preEvaluateOneOf({ name: PERMISSION_NAMES });\n\n const entity = await this.repository.findOneByIdOrName(idOrName, realmId);\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n await actor.permissionEvaluator.evaluateOneOf({\n name: PERMISSION_NAMES,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: entity,\n ...this.resourceRealmMatch(entity),\n }),\n });\n\n // Belt-and-braces null of private material (see getMany).\n entity.decryptionKey = null;\n\n return entity;\n }\n\n async create(\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<Key> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.KEY_CREATE });\n\n const validated = await this.validator.run(data, { group: ValidatorGroup.CREATE });\n const { use } = validated;\n if (!use) {\n throw new ValidationError('A key use must be specified.');\n }\n\n await this.repository.validateJoinColumns(validated);\n\n if (!validated.realmId && actor.identity) {\n const actorRealmId = this.getActorRealmId(actor);\n if (actorRealmId) {\n validated.realmId = actorRealmId;\n }\n }\n\n // keys are realm-bound infrastructure — no global (null realm) keys\n // via the API.\n if (!validated.realmId) {\n throw new ValidationError('A realm must be specified.');\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.KEY_CREATE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: validated,\n ...this.resourceRealmMatch(validated),\n }),\n });\n\n if (!validated.name) {\n validated.name = `${use}-${createNanoID(10)}`;\n }\n\n await this.repository.checkUniqueness(validated);\n\n if (typeof validated.priority !== 'number') {\n const highest = await this.repository.findHighestPriority(validated.realmId, use);\n // generate doubles as rotate: a new key outranks the current one.\n validated.priority = typeof highest === 'number' ? highest + 1 : 0;\n }\n\n if (!validated.status) {\n validated.status = KeyStatus.ACTIVE;\n }\n\n const certificate = typeof validated.certificate === 'string' ? validated.certificate : null;\n if (certificate && (!validated.decryptionKey || use !== JWKUse.SIGNATURE)) {\n throw new ValidationError('A certificate requires imported signature key material.');\n }\n\n const material = validated.decryptionKey ?\n await this.importMaterial(validated, use) :\n await this.generateMaterial(validated, use);\n\n if (certificate) {\n if (!material.encryptionKey) {\n throw new ValidationError('A certificate requires imported signature key material.');\n }\n\n try {\n const chain = parseCertificateChain(certificate);\n assertCertificateMatchesKey(chain, material.encryptionKey);\n } catch (e) {\n throw new ValidationError(\n isRawError(e) ?\n e.message :\n 'The certificate could not be matched against the imported key material.',\n );\n }\n }\n\n let entity = this.repository.create({\n ...validated,\n type: material.type,\n signatureAlgorithm: material.signatureAlgorithm,\n decryptionKey: material.decryptionKey,\n encryptionKey: material.encryptionKey,\n });\n\n entity = await this.repository.save(entity);\n\n // private material never leaves the server — the response carries\n // metadata + public part only (authentik CVE-2024-42490).\n entity.decryptionKey = null;\n\n await this.recordEvent(EventName.CREATED, entity, actor);\n\n return entity;\n }\n\n async update(\n idOrName: string,\n data: Record<string, any>,\n actor: ActorContext,\n realmId?: string,\n ): Promise<Key> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.KEY_UPDATE });\n\n let entity = await this.repository.findOneByIdOrName(idOrName, realmId);\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n // only name / priority / status are mounted for UPDATE — material,\n // use, type and realm are immutable.\n const validated = await this.validator.run(data, { group: ValidatorGroup.UPDATE });\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.KEY_UPDATE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: {\n ...entity,\n ...validated,\n },\n ...this.resourceRealmMatch(entity),\n }),\n });\n\n if (validated.name && validated.name !== entity.name) {\n await this.repository.checkUniqueness({\n name: validated.name,\n realmId: entity.realmId,\n }, entity);\n }\n\n const previous = this.pickAuditFields(entity);\n\n entity = this.repository.merge(entity, validated);\n await this.repository.save(entity);\n\n entity.decryptionKey = null;\n\n const diff = buildEntityDiff(this.pickAuditFields(entity), previous);\n await this.recordEvent(EventName.UPDATED, entity, actor, { ...(Object.keys(diff).length > 0 ? { diff } : {}) });\n\n return entity;\n }\n\n async delete(\n id: string,\n actor: ActorContext,\n options: KeyDeleteOptions = {},\n ): Promise<Key> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.KEY_DELETE });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.KEY_DELETE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: entity,\n ...this.resourceRealmMatch(entity),\n }),\n });\n\n if (entity.use === JWKUse.ENCRYPTION && !options.force) {\n const references = await this.repository.countBlobReferences(entity.id);\n if (references > 0) {\n throw new EntityConflictError({\n message: `The encryption key is still referenced by ${references} encrypted secret(s) — ` +\n 'deleting it makes them unrecoverable. Repeat with force to crypto-shred them.',\n data: { references },\n });\n }\n }\n\n const { id: entityId } = entity;\n await this.repository.remove(entity);\n entity.id = entityId;\n entity.decryptionKey = null;\n\n // force only carries crypto-shred semantics for encryption keys — a\n // sig-key delete with a stray force flag must not read as a shred.\n const forcedCryptoShred = entity.use === JWKUse.ENCRYPTION && !!options.force;\n await this.recordEvent(EventName.DELETED, entity, actor, { ...(forcedCryptoShred ? { force: true } : {}) });\n\n return entity;\n }\n\n // ------------------------------------------------------------------\n\n /**\n * Metadata-only audit trail for key lifecycle operations (issue #3269) —\n * keys deliberately have no entity subscriber (private material must stay\n * off the realtime/audit bus), so the security-relevant mutations are\n * recorded explicitly. The payload never carries key material.\n */\n protected async recordEvent(\n name: `${EventName}`,\n entity: Key,\n actor: ActorContext,\n data: Record<string, any> = {},\n ): Promise<void> {\n const requestContext = this.requestContext ?\n this.requestContext() :\n undefined;\n\n await this.eventService?.record({\n scope: EventScope.ENTITY,\n name,\n refType: EntityType.KEY,\n refId: entity.id,\n realmId: entity.realmId ?? null,\n actorType: actor.identity?.type ?? null,\n actorId: actor.identity?.data.id ?? null,\n actorName: actor.identity?.data.name ?? null,\n requestPath: requestContext?.requestPath ?? null,\n requestMethod: requestContext?.requestMethod ?? null,\n requestIpAddress: requestContext?.requestIpAddress ?? null,\n requestUserAgent: requestContext?.requestUserAgent ?? null,\n data: {\n name: entity.name,\n use: entity.use,\n status: entity.status,\n ...data,\n },\n });\n }\n\n protected pickAuditFields(entity: Key): Record<string, any> {\n return {\n name: entity.name,\n priority: entity.priority,\n status: entity.status,\n };\n }\n\n protected async generateMaterial(\n validated: Partial<Key>,\n use: `${JWKUse}`,\n ) : Promise<{\n type: `${JWKType}`,\n signatureAlgorithm: `${JWTAlgorithm}` | null,\n decryptionKey: string,\n encryptionKey: string | null,\n }> {\n if (use === JWKUse.ENCRYPTION) {\n if (validated.signatureAlgorithm) {\n throw new ValidationError('An encryption key can not carry a signature algorithm.');\n }\n\n const raw = new Uint8Array(32);\n getRandomValues(raw);\n\n return {\n type: JWKType.OCT,\n signatureAlgorithm: null,\n decryptionKey: arrayBufferToBase64(raw.buffer),\n encryptionKey: null,\n };\n }\n\n const algorithm = validated.signatureAlgorithm ?? JWTAlgorithm.RS256;\n const options = this.buildAsymmetricOptions(algorithm);\n\n const keyPair = await createAsymmetricKeyPair(options);\n\n return {\n type: algorithm.startsWith('ES') ? JWKType.EC : JWKType.RSA,\n signatureAlgorithm: algorithm,\n decryptionKey: await new AsymmetricKey(keyPair.privateKey).toBase64(),\n encryptionKey: await new AsymmetricKey(keyPair.publicKey).toBase64(),\n };\n }\n\n protected async importMaterial(\n validated: Partial<Key>,\n use: `${JWKUse}`,\n ) : Promise<{\n type: `${JWKType}`,\n signatureAlgorithm: `${JWTAlgorithm}` | null,\n decryptionKey: string,\n encryptionKey: string | null,\n }> {\n if (!validated.decryptionKey) {\n throw new ValidationError('Importing key material requires its private part (decryptionKey).');\n }\n\n // Reject material masquerading as an at-rest KEK-wrapped blob — it\n // would be treated as wrapped on the next read (and, with a KEK,\n // fail GCM authentication).\n if (isWrappedKeyMaterial(validated.decryptionKey.trim())) {\n throw new ValidationError('The imported key material is not valid.');\n }\n\n const decryptionKey = this.normalizeMaterial(validated.decryptionKey);\n\n if (use === JWKUse.ENCRYPTION) {\n if (validated.signatureAlgorithm) {\n throw new ValidationError('An encryption key can not carry a signature algorithm.');\n }\n\n if (validated.encryptionKey) {\n throw new ValidationError('An encryption key holds no public part.');\n }\n\n let byteLength : number;\n try {\n byteLength = base64ToArrayBuffer(decryptionKey).byteLength;\n } catch {\n throw new ValidationError('The key material is not valid base64.');\n }\n\n if (byteLength !== 32) {\n throw new ValidationError('The key material must be 32 base64-encoded bytes.');\n }\n\n return {\n type: JWKType.OCT,\n signatureAlgorithm: null,\n decryptionKey,\n encryptionKey: null,\n };\n }\n\n if (!validated.encryptionKey) {\n throw new ValidationError('Importing a signature key requires its public part (encryptionKey, SPKI).');\n }\n\n const encryptionKey = this.normalizeMaterial(validated.encryptionKey);\n const algorithm = validated.signatureAlgorithm ?? JWTAlgorithm.RS256;\n const options = this.buildAsymmetricOptions(algorithm);\n\n let privateJwk : JsonWebKey;\n let publicJwk : JsonWebKey;\n\n try {\n const privateKey = await AsymmetricKey.fromBase64({\n format: 'pkcs8',\n key: decryptionKey,\n options,\n });\n const publicKey = await AsymmetricKey.fromBase64({\n format: 'spki',\n key: encryptionKey,\n options,\n });\n\n privateJwk = await privateKey.toJWK();\n publicJwk = await publicKey.toJWK();\n } catch {\n throw new ValidationError(`The key material could not be imported for ${algorithm}.`);\n }\n\n // the public components (RSA: n/e, EC: crv/x/y) must agree — a\n // private key paired with a foreign public part would publish a\n // wrong JWKS entry and break verification of every token it signs.\n const components : (keyof JsonWebKey)[] = ['kty', 'n', 'e', 'crv', 'x', 'y'];\n const mismatch = components.some(\n (component) => publicJwk[component] !== undefined &&\n publicJwk[component] !== privateJwk[component],\n );\n if (mismatch) {\n throw new ValidationError('The private and public key material do not form a pair.');\n }\n\n return {\n type: algorithm.startsWith('ES') ? JWKType.EC : JWKType.RSA,\n signatureAlgorithm: algorithm,\n decryptionKey,\n encryptionKey,\n };\n }\n\n protected buildAsymmetricOptions(algorithm: `${JWTAlgorithm}`) {\n if (!/^(RS|ES)(256|384|512)$/.test(algorithm)) {\n throw new ValidationError(`The signature algorithm ${algorithm} is not supported for stored keys.`);\n }\n\n return AsymmetricKey.buildImportOptionsForJWTAlgorithm(algorithm);\n }\n\n protected normalizeMaterial(value: string) : string {\n if (value.includes('-----BEGIN')) {\n // PEM body IS base64 DER — strip armor + whitespace.\n return value\n .replace(/-----(BEGIN|END)[^-]+-----/g, '')\n .replace(/\\s+/g, '');\n }\n\n return value.trim();\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../src/core/entities/permission/service.ts"],"names":[],"mappings":"AAeA,OAAO,EAEH,mBAAmB,EAGtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B,EAAG,MAAM,oBAAoB,CAAC;AACxF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACjF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAyC5E,MAAM,MAAM,wBAAwB,GAAG;IACnC,UAAU,EAAE,qBAAqB,CAAC;IAClC,eAAe,EAAE,gBAAgB,CAAC;IAClC,cAAc,EAAE,eAAe,CAAC;IAChC,wBAAwB,EAAE,yBAAyB,CAAC;IACpD,gBAAgB,EAAE,iBAAiB,CAAC;IACpC,0BAA0B,EAAE,2BAA2B,CAAC;CAC3D,CAAC;AAEF,qBAAa,iBAAkB,SAAQ,qBAAsB,YAAW,kBAAkB;IACtF,SAAS,CAAC,UAAU,EAAE,qBAAqB,CAAC;IAE5C,SAAS,CAAC,eAAe,EAAE,gBAAgB,CAAC;IAE5C,SAAS,CAAC,cAAc,EAAE,eAAe,CAAC;IAE1C,SAAS,CAAC,wBAAwB,EAAE,yBAAyB,CAAC;IAE9D,SAAS,CAAC,gBAAgB,EAAE,iBAAiB,CAAC;IAE9C,SAAS,CAAC,0BAA0B,EAAE,2BAA2B,CAAC;IAElE,SAAS,CAAC,SAAS,EAAE,mBAAmB,CAAC;gBAE7B,GAAG,EAAE,wBAAwB;IAWnC,OAAO,CACT,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1B,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,8BAA8B,CAAC,UAAU,CAAC,CAAC;IAYhD,MAAM,CACR,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,YAAY,EACnB,KAAK,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,UAAU,CAAC;IAiBhB,MAAM,CACR,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,UAAU,CAAC;IAKhB,MAAM,CACR,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,UAAU,CAAC;IAKhB,IAAI,CACN,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAA;KAAO,GACvC,OAAO,CAAC;QACP,MAAM,EAAE,UAAU,CAAC;QACnB,OAAO,EAAE,OAAO,CAAA;KACnB,CAAC;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../src/core/entities/permission/service.ts"],"names":[],"mappings":"AAeA,OAAO,EAEH,mBAAmB,EAGtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B,EAAG,MAAM,oBAAoB,CAAC;AACxF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACjF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAyC5E,MAAM,MAAM,wBAAwB,GAAG;IACnC,UAAU,EAAE,qBAAqB,CAAC;IAClC,eAAe,EAAE,gBAAgB,CAAC;IAClC,cAAc,EAAE,eAAe,CAAC;IAChC,wBAAwB,EAAE,yBAAyB,CAAC;IACpD,gBAAgB,EAAE,iBAAiB,CAAC;IACpC,0BAA0B,EAAE,2BAA2B,CAAC;CAC3D,CAAC;AAEF,qBAAa,iBAAkB,SAAQ,qBAAsB,YAAW,kBAAkB;IACtF,SAAS,CAAC,UAAU,EAAE,qBAAqB,CAAC;IAE5C,SAAS,CAAC,eAAe,EAAE,gBAAgB,CAAC;IAE5C,SAAS,CAAC,cAAc,EAAE,eAAe,CAAC;IAE1C,SAAS,CAAC,wBAAwB,EAAE,yBAAyB,CAAC;IAE9D,SAAS,CAAC,gBAAgB,EAAE,iBAAiB,CAAC;IAE9C,SAAS,CAAC,0BAA0B,EAAE,2BAA2B,CAAC;IAElE,SAAS,CAAC,SAAS,EAAE,mBAAmB,CAAC;gBAE7B,GAAG,EAAE,wBAAwB;IAWnC,OAAO,CACT,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1B,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,8BAA8B,CAAC,UAAU,CAAC,CAAC;IAYhD,MAAM,CACR,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,YAAY,EACnB,KAAK,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,UAAU,CAAC;IAiBhB,MAAM,CACR,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,UAAU,CAAC;IAKhB,MAAM,CACR,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,UAAU,CAAC;IAKhB,IAAI,CACN,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAA;KAAO,GACvC,OAAO,CAAC;QACP,MAAM,EAAE,UAAU,CAAC;QACnB,OAAO,EAAE,OAAO,CAAA;KACnB,CAAC;IAqHI,MAAM,CACR,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,UAAU,CAAC;IAwBtB;;;;OAIG;YACW,mBAAmB;IAuBjC;;;;;;;;OAQG;YACW,iBAAiB;IAyB/B;;;;;;;;;;;;;;OAcG;YACW,uBAAuB;CAuCxC"}
|
|
@@ -101,7 +101,7 @@ var PermissionService = class extends AbstractEntityService {
|
|
|
101
101
|
else where.name = idOrName;
|
|
102
102
|
if (realm) where.realmId = realm.id;
|
|
103
103
|
entity = await this.repository.findOneBy(where);
|
|
104
|
-
if (!entity && options.updateOnly) throw new EntityNotFoundError();
|
|
104
|
+
if (!entity && (options.updateOnly || where.id)) throw new EntityNotFoundError();
|
|
105
105
|
} else if (options.updateOnly) throw new EntityNotFoundError();
|
|
106
106
|
if (entity) {
|
|
107
107
|
await actor.permissionEvaluator.preEvaluate({ name: PermissionName.PERMISSION_UPDATE });
|