@robelest/convex-auth 0.0.4-preview.25 → 0.0.4-preview.28
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/README.md +43 -36
- package/dist/bin.js +5765 -4880
- package/dist/browser/index.d.ts +30 -0
- package/dist/browser/index.js +93 -0
- package/dist/browser/locks.js +11 -0
- package/dist/browser/navigation.js +14 -0
- package/dist/{factors → browser}/passkey.js +23 -32
- package/dist/browser/runtime.js +92 -0
- package/dist/client/core/types.d.ts +452 -5
- package/dist/client/core/types.js +17 -0
- package/dist/client/errors.js +19 -0
- package/dist/client/factors/device.js +94 -0
- package/dist/{factors → client/factors}/totp.js +12 -4
- package/dist/client/index.d.ts +47 -1
- package/dist/client/index.js +269 -232
- package/dist/client/runtime/mutex.js +24 -0
- package/dist/client/runtime/proxy.js +30 -0
- package/dist/client/runtime/storage.js +45 -0
- package/dist/client/services/adapters.js +7 -0
- package/dist/client/services/http.js +6 -0
- package/dist/client/services/resolve.js +13 -0
- package/dist/client/services/runtime.js +6 -0
- package/dist/component/_generated/component.d.ts +1355 -1399
- package/dist/component/convex.config.d.ts +2 -2
- package/dist/component/index.d.ts +4 -26
- package/dist/component/index.js +1 -1
- package/dist/component/model.d.ts +26 -112
- package/dist/component/model.js +76 -54
- package/dist/component/modules.js +38 -0
- package/dist/component/public/factors/devices.js +1 -1
- package/dist/component/public/factors/passkeys.js +1 -1
- package/dist/component/public/factors/totp.js +1 -1
- package/dist/component/public/groups/core.js +2 -2
- package/dist/component/public/groups/invites.js +1 -1
- package/dist/component/public/groups/members.js +1 -1
- package/dist/component/public/identity/accounts.js +1 -1
- package/dist/component/public/identity/codes.js +1 -1
- package/dist/component/public/identity/sessions.js +39 -2
- package/dist/component/public/identity/tokens.js +82 -4
- package/dist/component/public/identity/users.js +1 -1
- package/dist/component/public/identity/verifiers.js +10 -4
- package/dist/component/public/security/keys.js +1 -1
- package/dist/component/public/security/limits.js +1 -1
- package/dist/component/public/{enterprise → sso}/audit.js +26 -26
- package/dist/component/public/sso/core.js +263 -0
- package/dist/component/public/sso/domains.js +280 -0
- package/dist/component/public/{enterprise → sso}/scim.js +87 -87
- package/dist/component/public/sso/secrets.js +125 -0
- package/dist/component/public/{enterprise → sso}/webhooks.js +59 -59
- package/dist/component/public.js +9 -9
- package/dist/component/schema.d.ts +472 -393
- package/dist/component/schema.js +36 -35
- package/dist/core/index.d.ts +380 -0
- package/dist/core/index.js +83 -0
- package/dist/otel.d.ts +69 -0
- package/dist/otel.js +82 -0
- package/dist/providers/anonymous.d.ts +15 -34
- package/dist/providers/anonymous.js +27 -35
- package/dist/providers/apple.d.ts +59 -0
- package/dist/providers/apple.js +58 -0
- package/dist/providers/credentials.d.ts +18 -34
- package/dist/providers/credentials.js +16 -27
- package/dist/providers/custom.d.ts +94 -0
- package/dist/providers/custom.js +119 -0
- package/dist/providers/device.d.ts +15 -49
- package/dist/providers/device.js +17 -34
- package/dist/providers/email.d.ts +21 -38
- package/dist/providers/email.js +36 -55
- package/dist/providers/github.d.ts +54 -0
- package/dist/providers/github.js +75 -0
- package/dist/providers/google.d.ts +54 -0
- package/dist/providers/google.js +61 -0
- package/dist/providers/index.d.ts +16 -12
- package/dist/providers/index.js +15 -11
- package/dist/providers/microsoft.d.ts +57 -0
- package/dist/providers/microsoft.js +101 -0
- package/dist/providers/passkey.d.ts +19 -35
- package/dist/providers/passkey.js +20 -30
- package/dist/providers/password.d.ts +17 -18
- package/dist/providers/password.js +121 -143
- package/dist/providers/phone.d.ts +13 -28
- package/dist/providers/phone.js +21 -46
- package/dist/providers/sso.d.ts +16 -36
- package/dist/providers/sso.js +21 -22
- package/dist/providers/totp.d.ts +13 -29
- package/dist/providers/totp.js +17 -27
- package/dist/server/auth-context.d.ts +204 -0
- package/dist/server/auth-context.js +76 -0
- package/dist/server/auth.d.ts +99 -244
- package/dist/server/auth.js +56 -152
- package/dist/server/componentContext.d.ts +12 -0
- package/dist/server/componentContext.js +1 -0
- package/dist/server/config.js +6 -67
- package/dist/server/constants.js +6 -0
- package/dist/server/contract.d.ts +105 -0
- package/dist/server/contract.js +43 -0
- package/dist/server/cookies.js +3 -2
- package/dist/server/core.js +31 -36
- package/dist/server/crypto.js +34 -44
- package/dist/server/db.js +6 -1
- package/dist/server/device.js +96 -130
- package/dist/server/env.js +48 -0
- package/dist/server/errors.js +20 -0
- package/dist/server/http.d.ts +15 -59
- package/dist/server/http.js +136 -120
- package/dist/server/identity.js +2 -2
- package/dist/server/index.d.ts +5 -4
- package/dist/server/index.js +3 -3
- package/dist/server/keys.js +10 -1
- package/dist/server/limits.js +26 -26
- package/dist/server/log.js +28 -0
- package/dist/server/mounts.d.ts +1107 -296
- package/dist/server/mounts.js +315 -196
- package/dist/server/mutations/account.js +11 -14
- package/dist/server/mutations/code.js +6 -5
- package/dist/server/mutations/invalidate.js +9 -11
- package/dist/server/mutations/oauth.js +112 -73
- package/dist/server/mutations/refresh.js +47 -97
- package/dist/server/mutations/register.js +37 -35
- package/dist/server/mutations/retrieve.js +16 -16
- package/dist/server/mutations/signature.js +15 -18
- package/dist/server/mutations/signin.js +10 -5
- package/dist/server/mutations/signout.js +11 -14
- package/dist/server/mutations/store.js +25 -18
- package/dist/server/mutations/verifier.js +11 -8
- package/dist/server/mutations/verify.js +53 -41
- package/dist/server/oauth/factory.js +44 -0
- package/dist/server/oauth/index.js +12 -0
- package/dist/server/oauth/runtime.js +248 -0
- package/dist/server/passkey.js +331 -365
- package/dist/server/payloads.d.ts +16 -0
- package/dist/server/payloads.js +30 -0
- package/dist/server/{ssr.d.ts → prefetch.d.ts} +2 -2
- package/dist/server/prefetch.js +635 -0
- package/dist/server/random.js +19 -0
- package/dist/server/redirects.js +10 -5
- package/dist/server/refresh.js +14 -86
- package/dist/server/runtime.d.ts +531 -31
- package/dist/server/runtime.js +106 -267
- package/dist/server/secret.js +44 -0
- package/dist/server/services/config.js +10 -0
- package/dist/server/services/group.js +211 -0
- package/dist/server/services/logger.js +8 -0
- package/dist/server/services/providers.js +22 -0
- package/dist/server/services/refresh.js +8 -0
- package/dist/server/services/resolve.js +27 -0
- package/dist/server/services/signin.js +8 -0
- package/dist/server/sessions.js +35 -34
- package/dist/server/signin.js +229 -140
- package/dist/server/{enterprise → sso}/config.js +10 -3
- package/dist/server/sso/domain.d.ts +614 -0
- package/dist/server/sso/domain.js +1175 -0
- package/dist/server/sso/http.js +1060 -0
- package/dist/server/sso/oidc.js +324 -0
- package/dist/server/sso/policies.js +59 -0
- package/dist/server/sso/policy.js +139 -0
- package/dist/server/sso/profile.js +22 -0
- package/dist/server/sso/provision.js +179 -0
- package/dist/{component/server/enterprise → server/sso}/saml.js +142 -56
- package/dist/{component/server/enterprise → server/sso}/scim.js +13 -7
- package/dist/server/sso/shared.js +74 -0
- package/dist/server/sso/validators.js +88 -0
- package/dist/server/sso/webhook.js +94 -0
- package/dist/server/tokens.js +16 -4
- package/dist/server/totp.js +155 -164
- package/dist/server/types.d.ts +306 -296
- package/dist/server/types.js +1 -30
- package/dist/server/url.js +32 -0
- package/dist/server/users.js +74 -40
- package/dist/server/utils/cache.js +51 -0
- package/dist/server/utils/dispatch.js +36 -0
- package/dist/server/utils/retry.js +24 -0
- package/dist/server/utils/span.js +32 -0
- package/dist/shared/errors.js +19 -0
- package/dist/shared/log.js +45 -0
- package/{src/test.ts → dist/test.d.ts} +21 -22
- package/dist/test.js +51 -0
- package/package.json +70 -42
- package/dist/authorization/index.d.ts.map +0 -1
- package/dist/authorization/index.js.map +0 -1
- package/dist/client/core/types.d.ts.map +0 -1
- package/dist/client/index.d.ts.map +0 -1
- package/dist/client/index.js.map +0 -1
- package/dist/component/_generated/api.d.ts +0 -75
- package/dist/component/_generated/api.d.ts.map +0 -1
- package/dist/component/_generated/api.js.map +0 -1
- package/dist/component/_generated/component.d.ts.map +0 -1
- package/dist/component/_generated/dataModel.d.ts +0 -42
- package/dist/component/_generated/dataModel.d.ts.map +0 -1
- package/dist/component/_generated/server.d.ts +0 -117
- package/dist/component/_generated/server.d.ts.map +0 -1
- package/dist/component/_generated/server.js.map +0 -1
- package/dist/component/_virtual/rolldown_runtime.js +0 -18
- package/dist/component/client/core/types.d.ts +0 -2
- package/dist/component/client/index.d.ts +0 -1
- package/dist/component/convex.config.d.ts.map +0 -1
- package/dist/component/convex.config.js.map +0 -1
- package/dist/component/functions.d.ts +0 -25
- package/dist/component/functions.d.ts.map +0 -1
- package/dist/component/functions.js.map +0 -1
- package/dist/component/index.d.ts.map +0 -1
- package/dist/component/model.d.ts.map +0 -1
- package/dist/component/model.js.map +0 -1
- package/dist/component/providers/anonymous.d.ts +0 -54
- package/dist/component/providers/anonymous.d.ts.map +0 -1
- package/dist/component/providers/credentials.d.ts +0 -38
- package/dist/component/providers/credentials.d.ts.map +0 -1
- package/dist/component/providers/device.d.ts +0 -67
- package/dist/component/providers/device.d.ts.map +0 -1
- package/dist/component/providers/email.d.ts +0 -62
- package/dist/component/providers/email.d.ts.map +0 -1
- package/dist/component/providers/oauth.d.ts +0 -25
- package/dist/component/providers/oauth.d.ts.map +0 -1
- package/dist/component/providers/oauth.js +0 -13
- package/dist/component/providers/oauth.js.map +0 -1
- package/dist/component/providers/passkey.d.ts +0 -57
- package/dist/component/providers/passkey.d.ts.map +0 -1
- package/dist/component/providers/password.d.ts +0 -88
- package/dist/component/providers/password.d.ts.map +0 -1
- package/dist/component/providers/phone.d.ts +0 -48
- package/dist/component/providers/phone.d.ts.map +0 -1
- package/dist/component/providers/sso.d.ts +0 -50
- package/dist/component/providers/sso.d.ts.map +0 -1
- package/dist/component/providers/totp.d.ts +0 -45
- package/dist/component/providers/totp.d.ts.map +0 -1
- package/dist/component/public/enterprise/audit.d.ts +0 -73
- package/dist/component/public/enterprise/audit.d.ts.map +0 -1
- package/dist/component/public/enterprise/audit.js.map +0 -1
- package/dist/component/public/enterprise/core.d.ts +0 -176
- package/dist/component/public/enterprise/core.d.ts.map +0 -1
- package/dist/component/public/enterprise/core.js +0 -292
- package/dist/component/public/enterprise/core.js.map +0 -1
- package/dist/component/public/enterprise/domains.d.ts +0 -174
- package/dist/component/public/enterprise/domains.d.ts.map +0 -1
- package/dist/component/public/enterprise/domains.js +0 -271
- package/dist/component/public/enterprise/domains.js.map +0 -1
- package/dist/component/public/enterprise/scim.d.ts +0 -245
- package/dist/component/public/enterprise/scim.d.ts.map +0 -1
- package/dist/component/public/enterprise/scim.js.map +0 -1
- package/dist/component/public/enterprise/secrets.d.ts +0 -78
- package/dist/component/public/enterprise/secrets.d.ts.map +0 -1
- package/dist/component/public/enterprise/secrets.js +0 -118
- package/dist/component/public/enterprise/secrets.js.map +0 -1
- package/dist/component/public/enterprise/webhooks.d.ts +0 -211
- package/dist/component/public/enterprise/webhooks.d.ts.map +0 -1
- package/dist/component/public/enterprise/webhooks.js.map +0 -1
- package/dist/component/public/factors/devices.d.ts +0 -157
- package/dist/component/public/factors/devices.d.ts.map +0 -1
- package/dist/component/public/factors/devices.js.map +0 -1
- package/dist/component/public/factors/passkeys.d.ts +0 -175
- package/dist/component/public/factors/passkeys.d.ts.map +0 -1
- package/dist/component/public/factors/passkeys.js.map +0 -1
- package/dist/component/public/factors/totp.d.ts +0 -189
- package/dist/component/public/factors/totp.d.ts.map +0 -1
- package/dist/component/public/factors/totp.js.map +0 -1
- package/dist/component/public/groups/core.d.ts +0 -137
- package/dist/component/public/groups/core.d.ts.map +0 -1
- package/dist/component/public/groups/core.js.map +0 -1
- package/dist/component/public/groups/invites.d.ts +0 -217
- package/dist/component/public/groups/invites.d.ts.map +0 -1
- package/dist/component/public/groups/invites.js.map +0 -1
- package/dist/component/public/groups/members.d.ts +0 -204
- package/dist/component/public/groups/members.d.ts.map +0 -1
- package/dist/component/public/groups/members.js.map +0 -1
- package/dist/component/public/identity/accounts.d.ts +0 -147
- package/dist/component/public/identity/accounts.d.ts.map +0 -1
- package/dist/component/public/identity/accounts.js.map +0 -1
- package/dist/component/public/identity/codes.d.ts +0 -104
- package/dist/component/public/identity/codes.d.ts.map +0 -1
- package/dist/component/public/identity/codes.js.map +0 -1
- package/dist/component/public/identity/sessions.d.ts +0 -128
- package/dist/component/public/identity/sessions.d.ts.map +0 -1
- package/dist/component/public/identity/sessions.js.map +0 -1
- package/dist/component/public/identity/tokens.d.ts +0 -169
- package/dist/component/public/identity/tokens.d.ts.map +0 -1
- package/dist/component/public/identity/tokens.js.map +0 -1
- package/dist/component/public/identity/users.d.ts +0 -212
- package/dist/component/public/identity/users.d.ts.map +0 -1
- package/dist/component/public/identity/users.js.map +0 -1
- package/dist/component/public/identity/verifiers.d.ts +0 -116
- package/dist/component/public/identity/verifiers.d.ts.map +0 -1
- package/dist/component/public/identity/verifiers.js.map +0 -1
- package/dist/component/public/security/keys.d.ts +0 -209
- package/dist/component/public/security/keys.d.ts.map +0 -1
- package/dist/component/public/security/keys.js.map +0 -1
- package/dist/component/public/security/limits.d.ts +0 -114
- package/dist/component/public/security/limits.d.ts.map +0 -1
- package/dist/component/public/security/limits.js.map +0 -1
- package/dist/component/public.d.ts +0 -28
- package/dist/component/public.d.ts.map +0 -1
- package/dist/component/schema.d.ts.map +0 -1
- package/dist/component/schema.js.map +0 -1
- package/dist/component/server/auth.d.ts +0 -447
- package/dist/component/server/auth.d.ts.map +0 -1
- package/dist/component/server/auth.js +0 -254
- package/dist/component/server/auth.js.map +0 -1
- package/dist/component/server/config.js +0 -121
- package/dist/component/server/config.js.map +0 -1
- package/dist/component/server/context.js +0 -53
- package/dist/component/server/context.js.map +0 -1
- package/dist/component/server/cookies.js +0 -47
- package/dist/component/server/cookies.js.map +0 -1
- package/dist/component/server/core.js +0 -576
- package/dist/component/server/core.js.map +0 -1
- package/dist/component/server/crypto.js +0 -56
- package/dist/component/server/crypto.js.map +0 -1
- package/dist/component/server/db.js +0 -87
- package/dist/component/server/db.js.map +0 -1
- package/dist/component/server/device.js +0 -152
- package/dist/component/server/device.js.map +0 -1
- package/dist/component/server/enterprise/config.js +0 -46
- package/dist/component/server/enterprise/config.js.map +0 -1
- package/dist/component/server/enterprise/domain.js +0 -974
- package/dist/component/server/enterprise/domain.js.map +0 -1
- package/dist/component/server/enterprise/http.js +0 -787
- package/dist/component/server/enterprise/http.js.map +0 -1
- package/dist/component/server/enterprise/oidc.js +0 -248
- package/dist/component/server/enterprise/oidc.js.map +0 -1
- package/dist/component/server/enterprise/policy.js +0 -85
- package/dist/component/server/enterprise/policy.js.map +0 -1
- package/dist/component/server/enterprise/saml.js.map +0 -1
- package/dist/component/server/enterprise/scim.js.map +0 -1
- package/dist/component/server/enterprise/shared.js +0 -51
- package/dist/component/server/enterprise/shared.js.map +0 -1
- package/dist/component/server/http.d.ts +0 -85
- package/dist/component/server/http.d.ts.map +0 -1
- package/dist/component/server/http.js +0 -351
- package/dist/component/server/http.js.map +0 -1
- package/dist/component/server/identity.js +0 -16
- package/dist/component/server/identity.js.map +0 -1
- package/dist/component/server/keys.js +0 -96
- package/dist/component/server/keys.js.map +0 -1
- package/dist/component/server/limits.js +0 -52
- package/dist/component/server/limits.js.map +0 -1
- package/dist/component/server/mutations/account.js +0 -46
- package/dist/component/server/mutations/account.js.map +0 -1
- package/dist/component/server/mutations/code.js +0 -68
- package/dist/component/server/mutations/code.js.map +0 -1
- package/dist/component/server/mutations/invalidate.js +0 -32
- package/dist/component/server/mutations/invalidate.js.map +0 -1
- package/dist/component/server/mutations/oauth.js +0 -116
- package/dist/component/server/mutations/oauth.js.map +0 -1
- package/dist/component/server/mutations/refresh.js +0 -119
- package/dist/component/server/mutations/refresh.js.map +0 -1
- package/dist/component/server/mutations/register.js +0 -87
- package/dist/component/server/mutations/register.js.map +0 -1
- package/dist/component/server/mutations/retrieve.js +0 -61
- package/dist/component/server/mutations/retrieve.js.map +0 -1
- package/dist/component/server/mutations/signature.js +0 -38
- package/dist/component/server/mutations/signature.js.map +0 -1
- package/dist/component/server/mutations/signin.js +0 -27
- package/dist/component/server/mutations/signin.js.map +0 -1
- package/dist/component/server/mutations/signout.js +0 -27
- package/dist/component/server/mutations/signout.js.map +0 -1
- package/dist/component/server/mutations/store/refs.js +0 -15
- package/dist/component/server/mutations/store/refs.js.map +0 -1
- package/dist/component/server/mutations/store.js +0 -70
- package/dist/component/server/mutations/store.js.map +0 -1
- package/dist/component/server/mutations/verifier.js +0 -18
- package/dist/component/server/mutations/verifier.js.map +0 -1
- package/dist/component/server/mutations/verify.js +0 -98
- package/dist/component/server/mutations/verify.js.map +0 -1
- package/dist/component/server/oauth.js +0 -242
- package/dist/component/server/oauth.js.map +0 -1
- package/dist/component/server/passkey.js +0 -415
- package/dist/component/server/passkey.js.map +0 -1
- package/dist/component/server/redirects.js +0 -40
- package/dist/component/server/redirects.js.map +0 -1
- package/dist/component/server/refresh.js +0 -99
- package/dist/component/server/refresh.js.map +0 -1
- package/dist/component/server/runtime.d.ts +0 -136
- package/dist/component/server/runtime.d.ts.map +0 -1
- package/dist/component/server/runtime.js +0 -456
- package/dist/component/server/runtime.js.map +0 -1
- package/dist/component/server/sessions.js +0 -71
- package/dist/component/server/sessions.js.map +0 -1
- package/dist/component/server/signin.js +0 -225
- package/dist/component/server/signin.js.map +0 -1
- package/dist/component/server/tokens.js +0 -17
- package/dist/component/server/tokens.js.map +0 -1
- package/dist/component/server/totp.js +0 -208
- package/dist/component/server/totp.js.map +0 -1
- package/dist/component/server/types.d.ts +0 -949
- package/dist/component/server/types.d.ts.map +0 -1
- package/dist/component/server/types.js +0 -79
- package/dist/component/server/types.js.map +0 -1
- package/dist/component/server/users.js +0 -123
- package/dist/component/server/users.js.map +0 -1
- package/dist/component/server/utils.js +0 -140
- package/dist/component/server/utils.js.map +0 -1
- package/dist/core/types.d.ts +0 -361
- package/dist/core/types.d.ts.map +0 -1
- package/dist/factors/device.js +0 -104
- package/dist/factors/device.js.map +0 -1
- package/dist/factors/passkey.js.map +0 -1
- package/dist/factors/totp.js.map +0 -1
- package/dist/providers/anonymous.d.ts.map +0 -1
- package/dist/providers/anonymous.js.map +0 -1
- package/dist/providers/credentials.d.ts.map +0 -1
- package/dist/providers/credentials.js.map +0 -1
- package/dist/providers/device.d.ts.map +0 -1
- package/dist/providers/device.js.map +0 -1
- package/dist/providers/email.d.ts.map +0 -1
- package/dist/providers/email.js.map +0 -1
- package/dist/providers/oauth.d.ts +0 -69
- package/dist/providers/oauth.d.ts.map +0 -1
- package/dist/providers/oauth.js +0 -43
- package/dist/providers/oauth.js.map +0 -1
- package/dist/providers/passkey.d.ts.map +0 -1
- package/dist/providers/passkey.js.map +0 -1
- package/dist/providers/password.d.ts.map +0 -1
- package/dist/providers/password.js.map +0 -1
- package/dist/providers/phone.d.ts.map +0 -1
- package/dist/providers/phone.js.map +0 -1
- package/dist/providers/sso.d.ts.map +0 -1
- package/dist/providers/sso.js.map +0 -1
- package/dist/providers/totp.d.ts.map +0 -1
- package/dist/providers/totp.js.map +0 -1
- package/dist/runtime/browser.js +0 -68
- package/dist/runtime/browser.js.map +0 -1
- package/dist/runtime/invite.js.map +0 -1
- package/dist/runtime/proxy.js +0 -70
- package/dist/runtime/proxy.js.map +0 -1
- package/dist/runtime/storage.js +0 -37
- package/dist/runtime/storage.js.map +0 -1
- package/dist/server/auth.d.ts.map +0 -1
- package/dist/server/auth.js.map +0 -1
- package/dist/server/config.d.ts +0 -1
- package/dist/server/config.js.map +0 -1
- package/dist/server/context.d.ts +0 -1
- package/dist/server/context.js.map +0 -1
- package/dist/server/cookies.d.ts +0 -1
- package/dist/server/cookies.js.map +0 -1
- package/dist/server/core.d.ts +0 -1315
- package/dist/server/core.d.ts.map +0 -1
- package/dist/server/core.js.map +0 -1
- package/dist/server/crypto.d.ts +0 -8
- package/dist/server/crypto.d.ts.map +0 -1
- package/dist/server/crypto.js.map +0 -1
- package/dist/server/db.d.ts +0 -1
- package/dist/server/db.js.map +0 -1
- package/dist/server/device.d.ts +0 -1
- package/dist/server/device.js.map +0 -1
- package/dist/server/enterprise/config.d.ts +0 -1
- package/dist/server/enterprise/config.js.map +0 -1
- package/dist/server/enterprise/domain.d.ts +0 -401
- package/dist/server/enterprise/domain.d.ts.map +0 -1
- package/dist/server/enterprise/domain.js +0 -974
- package/dist/server/enterprise/domain.js.map +0 -1
- package/dist/server/enterprise/http.d.ts +0 -26
- package/dist/server/enterprise/http.d.ts.map +0 -1
- package/dist/server/enterprise/http.js +0 -787
- package/dist/server/enterprise/http.js.map +0 -1
- package/dist/server/enterprise/oidc.d.ts +0 -1
- package/dist/server/enterprise/oidc.js +0 -248
- package/dist/server/enterprise/oidc.js.map +0 -1
- package/dist/server/enterprise/policy.d.ts +0 -1
- package/dist/server/enterprise/policy.js +0 -85
- package/dist/server/enterprise/policy.js.map +0 -1
- package/dist/server/enterprise/saml.d.ts +0 -1
- package/dist/server/enterprise/saml.js +0 -338
- package/dist/server/enterprise/saml.js.map +0 -1
- package/dist/server/enterprise/scim.d.ts +0 -1
- package/dist/server/enterprise/scim.js +0 -97
- package/dist/server/enterprise/scim.js.map +0 -1
- package/dist/server/enterprise/shared.d.ts +0 -5
- package/dist/server/enterprise/shared.d.ts.map +0 -1
- package/dist/server/enterprise/shared.js +0 -51
- package/dist/server/enterprise/shared.js.map +0 -1
- package/dist/server/enterprise/validators.d.ts +0 -1
- package/dist/server/enterprise/validators.js +0 -60
- package/dist/server/enterprise/validators.js.map +0 -1
- package/dist/server/http.d.ts.map +0 -1
- package/dist/server/http.js.map +0 -1
- package/dist/server/identity.d.ts +0 -1
- package/dist/server/identity.js.map +0 -1
- package/dist/server/keys.d.ts +0 -1
- package/dist/server/keys.js.map +0 -1
- package/dist/server/limits.d.ts +0 -1
- package/dist/server/limits.js.map +0 -1
- package/dist/server/mounts.d.ts.map +0 -1
- package/dist/server/mounts.js.map +0 -1
- package/dist/server/mutations/account.d.ts +0 -29
- package/dist/server/mutations/account.d.ts.map +0 -1
- package/dist/server/mutations/account.js.map +0 -1
- package/dist/server/mutations/code.d.ts +0 -30
- package/dist/server/mutations/code.d.ts.map +0 -1
- package/dist/server/mutations/code.js.map +0 -1
- package/dist/server/mutations/index.d.ts +0 -14
- package/dist/server/mutations/invalidate.d.ts +0 -20
- package/dist/server/mutations/invalidate.d.ts.map +0 -1
- package/dist/server/mutations/invalidate.js.map +0 -1
- package/dist/server/mutations/oauth.d.ts +0 -30
- package/dist/server/mutations/oauth.d.ts.map +0 -1
- package/dist/server/mutations/oauth.js.map +0 -1
- package/dist/server/mutations/refresh.d.ts +0 -21
- package/dist/server/mutations/refresh.d.ts.map +0 -1
- package/dist/server/mutations/refresh.js.map +0 -1
- package/dist/server/mutations/register.d.ts +0 -38
- package/dist/server/mutations/register.d.ts.map +0 -1
- package/dist/server/mutations/register.js.map +0 -1
- package/dist/server/mutations/retrieve.d.ts +0 -33
- package/dist/server/mutations/retrieve.d.ts.map +0 -1
- package/dist/server/mutations/retrieve.js.map +0 -1
- package/dist/server/mutations/signature.d.ts +0 -21
- package/dist/server/mutations/signature.d.ts.map +0 -1
- package/dist/server/mutations/signature.js.map +0 -1
- package/dist/server/mutations/signin.d.ts +0 -22
- package/dist/server/mutations/signin.d.ts.map +0 -1
- package/dist/server/mutations/signin.js.map +0 -1
- package/dist/server/mutations/signout.d.ts +0 -16
- package/dist/server/mutations/signout.d.ts.map +0 -1
- package/dist/server/mutations/signout.js.map +0 -1
- package/dist/server/mutations/store/refs.d.ts +0 -12
- package/dist/server/mutations/store/refs.d.ts.map +0 -1
- package/dist/server/mutations/store/refs.js.map +0 -1
- package/dist/server/mutations/store.d.ts +0 -306
- package/dist/server/mutations/store.d.ts.map +0 -1
- package/dist/server/mutations/store.js.map +0 -1
- package/dist/server/mutations/verifier.d.ts +0 -13
- package/dist/server/mutations/verifier.d.ts.map +0 -1
- package/dist/server/mutations/verifier.js.map +0 -1
- package/dist/server/mutations/verify.d.ts +0 -26
- package/dist/server/mutations/verify.d.ts.map +0 -1
- package/dist/server/mutations/verify.js.map +0 -1
- package/dist/server/oauth.d.ts +0 -1
- package/dist/server/oauth.js +0 -242
- package/dist/server/oauth.js.map +0 -1
- package/dist/server/passkey.d.ts +0 -27
- package/dist/server/passkey.d.ts.map +0 -1
- package/dist/server/passkey.js.map +0 -1
- package/dist/server/redirects.d.ts +0 -1
- package/dist/server/redirects.js.map +0 -1
- package/dist/server/refresh.d.ts +0 -1
- package/dist/server/refresh.js.map +0 -1
- package/dist/server/runtime.d.ts.map +0 -1
- package/dist/server/runtime.js.map +0 -1
- package/dist/server/sessions.d.ts +0 -1
- package/dist/server/sessions.js.map +0 -1
- package/dist/server/signin.d.ts +0 -1
- package/dist/server/signin.js.map +0 -1
- package/dist/server/ssr.d.ts.map +0 -1
- package/dist/server/ssr.js +0 -777
- package/dist/server/ssr.js.map +0 -1
- package/dist/server/templates.d.ts +0 -1
- package/dist/server/templates.js.map +0 -1
- package/dist/server/tokens.d.ts +0 -1
- package/dist/server/tokens.js.map +0 -1
- package/dist/server/totp.d.ts +0 -1
- package/dist/server/totp.js.map +0 -1
- package/dist/server/types.d.ts.map +0 -1
- package/dist/server/types.js.map +0 -1
- package/dist/server/users.d.ts +0 -1
- package/dist/server/users.js.map +0 -1
- package/dist/server/utils.d.ts +0 -1
- package/dist/server/utils.js +0 -140
- package/dist/server/utils.js.map +0 -1
- package/src/authorization/index.ts +0 -83
- package/src/cli/bin.ts +0 -5
- package/src/cli/command.ts +0 -70
- package/src/cli/index.ts +0 -1112
- package/src/cli/keys.ts +0 -23
- package/src/client/core/types.ts +0 -437
- package/src/client/factors/device.ts +0 -158
- package/src/client/factors/passkey.ts +0 -279
- package/src/client/factors/totp.ts +0 -150
- package/src/client/index.ts +0 -1124
- package/src/client/runtime/browser.ts +0 -112
- package/src/client/runtime/invite.ts +0 -63
- package/src/client/runtime/proxy.ts +0 -111
- package/src/client/runtime/storage.ts +0 -79
- package/src/component/_generated/api.ts +0 -96
- package/src/component/_generated/component.ts +0 -3774
- package/src/component/_generated/dataModel.ts +0 -60
- package/src/component/_generated/server.ts +0 -156
- package/src/component/convex.config.ts +0 -5
- package/src/component/functions.ts +0 -104
- package/src/component/index.ts +0 -42
- package/src/component/model.ts +0 -449
- package/src/component/public/enterprise/audit.ts +0 -125
- package/src/component/public/enterprise/core.ts +0 -355
- package/src/component/public/enterprise/domains.ts +0 -327
- package/src/component/public/enterprise/scim.ts +0 -397
- package/src/component/public/enterprise/secrets.ts +0 -133
- package/src/component/public/enterprise/webhooks.ts +0 -307
- package/src/component/public/factors/devices.ts +0 -224
- package/src/component/public/factors/passkeys.ts +0 -243
- package/src/component/public/factors/totp.ts +0 -259
- package/src/component/public/groups/core.ts +0 -481
- package/src/component/public/groups/invites.ts +0 -608
- package/src/component/public/groups/members.ts +0 -410
- package/src/component/public/identity/accounts.ts +0 -207
- package/src/component/public/identity/codes.ts +0 -149
- package/src/component/public/identity/sessions.ts +0 -210
- package/src/component/public/identity/tokens.ts +0 -251
- package/src/component/public/identity/users.ts +0 -355
- package/src/component/public/identity/verifiers.ts +0 -158
- package/src/component/public/security/keys.ts +0 -366
- package/src/component/public/security/limits.ts +0 -174
- package/src/component/public.ts +0 -27
- package/src/component/schema.ts +0 -505
- package/src/providers/anonymous.ts +0 -99
- package/src/providers/credentials.ts +0 -102
- package/src/providers/device.ts +0 -87
- package/src/providers/email.ts +0 -99
- package/src/providers/index.ts +0 -31
- package/src/providers/oauth.ts +0 -117
- package/src/providers/passkey.ts +0 -77
- package/src/providers/password.ts +0 -441
- package/src/providers/phone.ts +0 -93
- package/src/providers/sso.ts +0 -54
- package/src/providers/totp.ts +0 -62
- package/src/samlify.d.ts +0 -53
- package/src/server/auth.ts +0 -949
- package/src/server/config.ts +0 -200
- package/src/server/context.ts +0 -90
- package/src/server/cookies.ts +0 -49
- package/src/server/core.ts +0 -2004
- package/src/server/crypto.ts +0 -90
- package/src/server/db.ts +0 -203
- package/src/server/device.ts +0 -254
- package/src/server/enterprise/config.ts +0 -51
- package/src/server/enterprise/domain.ts +0 -1739
- package/src/server/enterprise/http.ts +0 -1331
- package/src/server/enterprise/oidc.ts +0 -500
- package/src/server/enterprise/policy.ts +0 -128
- package/src/server/enterprise/saml.ts +0 -578
- package/src/server/enterprise/scim.ts +0 -135
- package/src/server/enterprise/shared.ts +0 -134
- package/src/server/enterprise/validators.ts +0 -93
- package/src/server/http.ts +0 -790
- package/src/server/identity.ts +0 -18
- package/src/server/index.ts +0 -40
- package/src/server/keys.ts +0 -158
- package/src/server/limits.ts +0 -107
- package/src/server/mounts.ts +0 -924
- package/src/server/mutations/account.ts +0 -62
- package/src/server/mutations/code.ts +0 -119
- package/src/server/mutations/index.ts +0 -13
- package/src/server/mutations/invalidate.ts +0 -50
- package/src/server/mutations/oauth.ts +0 -243
- package/src/server/mutations/refresh.ts +0 -299
- package/src/server/mutations/register.ts +0 -155
- package/src/server/mutations/retrieve.ts +0 -109
- package/src/server/mutations/signature.ts +0 -57
- package/src/server/mutations/signin.ts +0 -54
- package/src/server/mutations/signout.ts +0 -43
- package/src/server/mutations/store/refs.ts +0 -10
- package/src/server/mutations/store.ts +0 -123
- package/src/server/mutations/verifier.ts +0 -34
- package/src/server/mutations/verify.ts +0 -200
- package/src/server/oauth.ts +0 -418
- package/src/server/passkey.ts +0 -838
- package/src/server/redirects.ts +0 -59
- package/src/server/refresh.ts +0 -218
- package/src/server/runtime.ts +0 -918
- package/src/server/sessions.ts +0 -132
- package/src/server/signin.ts +0 -445
- package/src/server/ssr.ts +0 -1747
- package/src/server/templates.ts +0 -82
- package/src/server/tokens.ts +0 -35
- package/src/server/totp.ts +0 -399
- package/src/server/types.ts +0 -1942
- package/src/server/users.ts +0 -291
- package/src/server/utils.ts +0 -220
- /package/dist/{runtime → client/runtime}/invite.js +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","names":["serializeCookie","state"],"sources":["../../../../src/server/enterprise/http.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\nimport { Cv } from \"@robelest/fx/convex\";\nimport type { GenericActionCtx, HttpRouter } from \"convex/server\";\nimport { ConvexError } from \"convex/values\";\nimport { serialize as serializeCookie } from \"cookie\";\n\nimport { redirectToParamCookie, useRedirectToParam } from \"../cookies\";\nimport { addSSORoutes, convertErrorsToResponse, getCookies } from \"../http\";\nimport type { SSORuntimeRoute } from \"../http\";\nimport { createOAuthAuthorizationURL, handleOAuthCallback } from \"../oauth\";\nimport { redirectAbsoluteUrl, setURLSearchParam } from \"../redirects\";\nimport { createEnterpriseOidcRuntime } from \"./oidc\";\nimport {\n createEnterpriseSamlMetadataXml,\n createEnterpriseSamlSignInRequest,\n createSamlPostBindingResponse,\n encodeEnterpriseSamlRelayState,\n parseEnterpriseSamlLoginResponse,\n parseEnterpriseSamlLogoutMessage,\n profileFromSamlExtract,\n validateEnterpriseSamlLoginRelayState,\n} from \"./saml\";\nimport {\n parseScimListRequest,\n scimError,\n scimJson,\n serializeScimGroup,\n serializeScimUser,\n} from \"./scim\";\nimport {\n enterpriseSamlProviderId,\n SCIM_GROUP_SCHEMA_ID,\n SCIM_USER_SCHEMA_ID,\n} from \"./shared\";\n\nexport type EnterpriseHttpRuntimeDeps = {\n http: HttpRouter;\n hasSSO: boolean;\n auth: any;\n config: any;\n routeBase: string;\n requireEnv: (name: string) => string;\n loadActiveEnterpriseSamlOrThrow: any;\n loadEnterpriseOidcOrThrow: any;\n getEnterpriseScimContext: any;\n getPolicyFromEnterprise: any;\n normalizeEnterprisePolicy: any;\n recordEnterpriseAuditEvent: any;\n emitEnterpriseWebhookDeliveries: any;\n generateRandomString: (length: number, alphabet: string) => string;\n inviteTokenAlphabet: string;\n callUserOAuth: any;\n callVerifierSignature: any;\n};\n\nexport function addEnterpriseHttpRuntime(deps: EnterpriseHttpRuntimeDeps) {\n if (!deps.hasSSO) {\n return;\n }\n\n const {\n http,\n auth,\n config,\n requireEnv,\n loadActiveEnterpriseSamlOrThrow,\n loadEnterpriseOidcOrThrow,\n getEnterpriseScimContext,\n getPolicyFromEnterprise,\n recordEnterpriseAuditEvent,\n emitEnterpriseWebhookDeliveries,\n generateRandomString,\n inviteTokenAlphabet: INVITE_TOKEN_ALPHABET,\n callUserOAuth,\n callVerifierSignature,\n } = deps;\n const ENTERPRISE_CONTROL_ROUTE_BASE = deps.routeBase;\n\n type ScimState = {\n ctx: any;\n request: Request;\n url: URL;\n parsedPath: Awaited<\n ReturnType<typeof getEnterpriseScimContext>\n >[\"parsedPath\"];\n enterprise: Awaited<\n ReturnType<typeof getEnterpriseScimContext>\n >[\"enterprise\"];\n scimConfig: Awaited<\n ReturnType<typeof getEnterpriseScimContext>\n >[\"scimConfig\"];\n policy: any;\n recordScimEvent: (\n eventType: string,\n ok: boolean,\n subjectType: string,\n subjectId?: string,\n metadata?: Record<string, unknown>,\n ) => Promise<void>;\n };\n\n type ScimHandler = (state: ScimState) => Promise<Response>;\n\n const SCIM_SCHEMAS = [\n {\n id: SCIM_USER_SCHEMA_ID,\n name: \"User\",\n description: \"User Account\",\n attributes: [\n { name: \"userName\", type: \"string\", required: true },\n { name: \"displayName\", type: \"string\" },\n { name: \"active\", type: \"boolean\" },\n { name: \"emails\", type: \"complex\", multiValued: true },\n ],\n },\n {\n id: SCIM_GROUP_SCHEMA_ID,\n name: \"Group\",\n description: \"Group\",\n attributes: [\n { name: \"displayName\", type: \"string\", required: true },\n { name: \"members\", type: \"complex\", multiValued: true },\n ],\n },\n ] as const;\n\n const SCIM_RESOURCE_TYPES = [\n {\n id: \"User\",\n name: \"User\",\n endpoint: \"/Users\",\n schema: SCIM_USER_SCHEMA_ID,\n },\n {\n id: \"Group\",\n name: \"Group\",\n endpoint: \"/Groups\",\n schema: SCIM_GROUP_SCHEMA_ID,\n },\n ] as const;\n\n const handleStaticScimCollection = <T extends { id?: string; name?: string }>(\n items: readonly T[],\n resourceId: string | undefined,\n opts: { by: \"id\" | \"name\"; notFound: string },\n ) => {\n if (resourceId !== undefined) {\n const item = items.find(\n (entry) => entry[opts.by] === decodeURIComponent(resourceId),\n );\n return item ? scimJson(item) : scimError(404, \"notFound\", opts.notFound);\n }\n return scimJson({\n schemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n Resources: items,\n totalResults: items.length,\n startIndex: 1,\n itemsPerPage: items.length,\n });\n };\n\n const filterScimCollection = <T>(\n items: T[],\n filter: ReturnType<typeof parseScimListRequest>[\"filter\"],\n filters: Record<string, (item: T, value: string) => boolean>,\n ) => {\n if (!filter) {\n return items;\n }\n const predicate = filters[filter.attribute];\n if (!predicate) {\n throw new Error(\"Unsupported SCIM filter.\");\n }\n return items.filter((item) => predicate(item, filter.value));\n };\n\n const paginateScimCollection = <T>(\n items: T[],\n listRequest: ReturnType<typeof parseScimListRequest>,\n ) => {\n const start = listRequest.startIndex - 1;\n return items.slice(start, start + listRequest.count);\n };\n\n const requireScimResourceId = (\n resourceId: string | undefined,\n label: string,\n ) => {\n if (!resourceId) {\n return scimError(400, \"invalidPath\", `${label} resource ID is required.`);\n }\n return null;\n };\n\n const readScimJson = async (request: Request) =>\n (await request.json()) as Record<string, any>;\n\n const handleSamlAcs = async (\n ctx: GenericActionCtx<any>,\n request: Request,\n runtimeRoute: SSORuntimeRoute,\n ) =>\n Fx.run(\n Fx.gen(function* () {\n yield* Fx.guard(\n runtimeRoute.protocol !== \"saml\" ||\n runtimeRoute.rest.length !== 1 ||\n runtimeRoute.rest[0] !== \"acs\",\n Cv.fail({\n code: \"INVALID_PARAMETERS\",\n message: \"Invalid enterprise runtime path.\",\n }),\n );\n\n const enterpriseId = runtimeRoute.enterpriseId;\n const { loaded, enterprise, saml } = yield* Fx.from({\n ok: () => loadActiveEnterpriseSamlOrThrow(ctx, enterpriseId),\n err: (e) => e,\n });\n\n const parsedResponse = yield* Fx.from({\n ok: () =>\n parseEnterpriseSamlLoginResponse({\n request,\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: { kind: \"enterprise\", id: enterprise._id },\n config: loaded.config,\n }),\n err: (e) =>\n Cv.error({\n code: \"OAUTH_PROVIDER_ERROR\",\n message: `SAML response parse failed: ${e instanceof Error ? e.message : String(e)}`,\n }),\n });\n\n yield* Fx.from({\n ok: () => {\n validateEnterpriseSamlLoginRelayState({\n relayState: parsedResponse.relayState,\n source: { kind: \"enterprise\", id: enterprise._id },\n inResponseTo:\n parsedResponse.parsed.extract?.response?.inResponseTo,\n });\n return Promise.resolve();\n },\n err: () =>\n Cv.error({\n code: \"OAUTH_INVALID_STATE\",\n message:\n \"SAML RelayState did not match the pending login request.\",\n }),\n });\n\n const { samlAttributes, samlSessionIndex, ...userProfile } =\n profileFromSamlExtract(\n parsedResponse.parsed.extract,\n saml.attributeMapping,\n );\n const profile = userProfile as Record<string, unknown> & {\n id: string;\n };\n\n const maybeRedirectTo = useRedirectToParam(\n enterpriseSamlProviderId(enterprise._id),\n getCookies(request),\n );\n\n const verificationCode = yield* Fx.from({\n ok: () =>\n callUserOAuth(ctx, {\n provider: enterpriseSamlProviderId(enterprise._id),\n providerAccountId: profile.id,\n profile,\n signature: parsedResponse.relayState.signature,\n accountExtend: {\n identity: {\n protocol: \"saml\",\n enterpriseId: enterprise._id,\n subject: profile.id,\n entityId:\n typeof saml.entityId === \"string\"\n ? saml.entityId\n : undefined,\n },\n saml: {\n attributes: samlAttributes,\n sessionIndex: samlSessionIndex,\n },\n },\n }),\n err: (e) => e,\n });\n\n const destinationUrl = yield* Fx.from({\n ok: () =>\n redirectAbsoluteUrl(config, {\n redirectTo:\n maybeRedirectTo?.redirectTo ??\n (typeof parsedResponse.relayState.redirectTo === \"string\"\n ? parsedResponse.relayState.redirectTo\n : undefined),\n }),\n err: (e) => e,\n });\n\n const vurl = setURLSearchParam(\n destinationUrl,\n \"code\",\n verificationCode,\n );\n const vheaders = new Headers({ Location: vurl });\n vheaders.set(\"Cache-Control\", \"must-revalidate\");\n for (const { name, value, options } of maybeRedirectTo !== null\n ? [maybeRedirectTo.updatedCookie]\n : []) {\n vheaders.append(\"Set-Cookie\", serializeCookie(name, value, options));\n }\n return new Response(null, { status: 302, headers: vheaders });\n }).pipe(Fx.recover((e) => Fx.fatal(e))),\n );\n\n const handleSamlSlo = async (\n ctx: GenericActionCtx<any>,\n request: Request,\n runtimeRoute: SSORuntimeRoute,\n ) => {\n if (\n runtimeRoute.protocol !== \"saml\" ||\n runtimeRoute.rest.length !== 1 ||\n runtimeRoute.rest[0] !== \"slo\"\n ) {\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Invalid enterprise runtime path.\",\n });\n }\n const { loaded, enterprise } = await loadActiveEnterpriseSamlOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n const parsedMessage = await parseEnterpriseSamlLogoutMessage({\n request,\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: { kind: \"enterprise\", id: enterprise._id },\n config: loaded.config,\n });\n if (parsedMessage.hasSamlRequest && parsedMessage.parsedRequest) {\n const responseContext = (\n parsedMessage.runtime.sp as any\n ).createLogoutResponse(\n parsedMessage.runtime.idp as any,\n parsedMessage.parsedRequest.extract,\n parsedMessage.binding as any,\n parsedMessage.relayState ?? \"\",\n ) as any;\n if (parsedMessage.binding === \"redirect\") {\n return new Response(null, {\n status: 302,\n headers: { Location: responseContext.context },\n });\n }\n return createSamlPostBindingResponse({\n endpoint: responseContext.entityEndpoint,\n parameter: \"SAMLResponse\",\n value: responseContext.context,\n relayState: parsedMessage.relayState,\n });\n }\n if (parsedMessage.hasSamlResponse) {\n return new Response(null, { status: 204 });\n }\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Missing SAML logout payload.\",\n });\n };\n\n const handleScimRequest = async (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => {\n try {\n const { scimConfig, enterprise, parsedPath } =\n await getEnterpriseScimContext(ctx, request);\n const url = new URL(request.url);\n const state: ScimState = {\n ctx,\n request,\n url,\n parsedPath,\n enterprise,\n scimConfig,\n policy: getPolicyFromEnterprise(enterprise),\n recordScimEvent: async (\n eventType,\n ok,\n subjectType,\n subjectId,\n metadata,\n ) => {\n const auditEventId = await recordEnterpriseAuditEvent(ctx, {\n enterpriseId: enterprise._id,\n groupId: enterprise.groupId,\n eventType,\n actorType: \"scim\",\n subjectType,\n subjectId,\n ok,\n metadata,\n });\n await emitEnterpriseWebhookDeliveries(ctx, {\n enterpriseId: enterprise._id,\n eventType,\n auditEventId,\n payload: {\n enterpriseId: enterprise._id,\n subjectId,\n metadata,\n },\n });\n },\n };\n\n const handleUsersGet: ScimHandler = async (state) => {\n const members = await auth.member.list(state.ctx, {\n where: { groupId: state.enterprise.groupId },\n limit: 100,\n });\n const identities = await state.ctx.runQuery(\n config.component.public.enterpriseScimIdentityListByEnterprise,\n { enterpriseId: state.enterprise._id },\n );\n const identityByUserId = new Map(\n identities\n .filter((identity: any) => identity.userId !== undefined)\n .map((identity: any) => [identity.userId, identity]),\n );\n const users = (\n await Promise.all(\n members.items.map(async (member: any) => {\n const user = await auth.user.get(state.ctx, member.userId);\n return user\n ? {\n user,\n member,\n identity: identityByUserId.get(user._id),\n }\n : null;\n }),\n )\n ).filter(Boolean) as Array<{\n user: any;\n member: any;\n identity?: any;\n }>;\n const listRequest = parseScimListRequest(state.url);\n const filtered = filterScimCollection(users, listRequest.filter, {\n id: (item: { user: any }, value: string) => item.user._id === value,\n externalId: (item: { identity?: any }, value: string) =>\n item.identity?.externalId === value,\n userName: (item: { user: any }, value: string) =>\n item.user.email === value,\n \"emails.value\": (item: { user: any }, value: string) =>\n item.user.email === value,\n active: (item: { identity?: any; member: any }, value: string) =>\n String(item.identity?.active ?? item.member.status === \"active\") ===\n value,\n });\n if (state.parsedPath.resourceId) {\n const resource = filtered.find(\n ({ user }) => user._id === state.parsedPath.resourceId,\n );\n return resource\n ? scimJson(\n serializeScimUser({\n id: resource.user._id,\n user: resource.user,\n externalId: resource.identity?.externalId,\n location: `${state.url.origin}${state.url.pathname.replace(/\\/[^/]+$/, \"\")}/${resource.user._id}`,\n active:\n resource.identity?.active ??\n resource.member.status === \"active\",\n }),\n 200,\n {\n Location: `${state.url.origin}${state.url.pathname.replace(/\\/[^/]+$/, \"\")}/${resource.user._id}`,\n },\n )\n : scimError(404, \"notFound\", \"User not found.\");\n }\n const paged = paginateScimCollection(filtered, listRequest);\n await state.recordScimEvent(\n \"enterprise.scim.read\",\n true,\n \"enterprise_scim\",\n state.scimConfig._id,\n );\n return scimJson({\n schemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n Resources: paged.map(({ user, identity, member }) =>\n serializeScimUser({\n id: user._id,\n user,\n externalId: identity?.externalId,\n location: `${state.url.origin}${state.url.pathname}/${user._id}`,\n active: identity?.active ?? member.status === \"active\",\n }),\n ),\n totalResults: filtered.length,\n startIndex: listRequest.startIndex,\n itemsPerPage: paged.length,\n });\n };\n\n const handleUsersPost: ScimHandler = async (state) => {\n const body = await readScimJson(state.request);\n const primaryEmail = Array.isArray(body.emails)\n ? (body.emails.find((entry) => entry.primary === true)?.value ??\n body.emails[0]?.value)\n : undefined;\n const phone = Array.isArray(body.phoneNumbers)\n ? body.phoneNumbers[0]?.value\n : undefined;\n const userId = (await state.ctx.runMutation(\n config.component.public.userInsert,\n {\n data: {\n name: body.displayName ?? body.name?.formatted,\n email: primaryEmail ?? body.userName,\n ...(typeof (primaryEmail ?? body.userName) === \"string\"\n ? { emailVerificationTime: Date.now() }\n : {}),\n phone,\n ...(typeof phone === \"string\"\n ? { phoneVerificationTime: Date.now() }\n : {}),\n },\n },\n )) as string;\n try {\n await auth.member.create(state.ctx, {\n groupId: state.enterprise.groupId,\n userId,\n roleIds: state.policy.provisioning.jit.defaultRoleIds,\n status: body.active === false ? \"inactive\" : \"active\",\n });\n } catch {}\n if (typeof body.externalId === \"string\") {\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n {\n enterpriseId: state.enterprise._id,\n groupId: state.enterprise.groupId,\n resourceType: \"user\",\n externalId: body.externalId,\n userId,\n active: body.active !== false,\n raw: body,\n lastProvisionedAt: Date.now(),\n },\n );\n }\n await state.recordScimEvent(\n \"enterprise.scim.user.created\",\n true,\n \"user\",\n userId,\n );\n const createdUser = await auth.user.get(state.ctx, userId);\n const location = `${state.url.origin}${state.url.pathname}/${userId}`;\n return scimJson(\n serializeScimUser({\n id: userId,\n user: createdUser ?? {},\n externalId: body.externalId,\n location,\n active: body.active !== false,\n }),\n 201,\n { Location: location },\n );\n };\n\n const handleUsersUpsert: ScimHandler = async (state) => {\n const missing = requireScimResourceId(\n state.parsedPath.resourceId,\n \"User\",\n );\n if (missing) return missing;\n const userId = state.parsedPath.resourceId!;\n const existingUser = await auth.user.get(state.ctx, userId);\n if (!existingUser) {\n return scimError(404, \"notFound\", \"User not found.\");\n }\n const body = await readScimJson(state.request);\n const patchData: Record<string, unknown> = {};\n let nextActive: boolean | undefined;\n if (state.request.method === \"PUT\") {\n patchData.name = body.displayName ?? body.name?.formatted;\n patchData.email =\n body.userName ??\n (Array.isArray(body.emails) ? body.emails[0]?.value : undefined);\n patchData.phone = Array.isArray(body.phoneNumbers)\n ? body.phoneNumbers[0]?.value\n : undefined;\n if (typeof patchData.email === \"string\") {\n patchData.emailVerificationTime = Date.now();\n }\n if (typeof patchData.phone === \"string\") {\n patchData.phoneVerificationTime = Date.now();\n }\n } else {\n for (const operation of Array.isArray(body.Operations)\n ? body.Operations\n : []) {\n if (operation.path === \"active\") {\n nextActive = operation.value;\n }\n if (\n operation.path === \"displayName\" ||\n operation.path === \"name.formatted\"\n ) {\n patchData.name = operation.value;\n }\n if (\n operation.path === \"userName\" ||\n operation.path === \"emails.value\"\n ) {\n patchData.email = operation.value;\n if (typeof operation.value === \"string\") {\n patchData.emailVerificationTime = Date.now();\n }\n }\n if (operation.path === \"phoneNumbers.value\") {\n patchData.phone = operation.value;\n if (typeof operation.value === \"string\") {\n patchData.phoneVerificationTime = Date.now();\n }\n }\n }\n }\n await state.ctx.runMutation(config.component.public.userPatch, {\n userId,\n data: patchData,\n });\n const resolution = await auth.member.inspect(state.ctx, {\n groupId: state.enterprise.groupId,\n userId,\n });\n if (resolution.membership) {\n await auth.member.update(state.ctx, resolution.membership._id, {\n status:\n body.active === false || nextActive === false\n ? \"inactive\"\n : \"active\",\n });\n }\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n {\n enterpriseId: state.enterprise._id,\n groupId: state.enterprise.groupId,\n resourceType: \"user\",\n externalId:\n typeof body.externalId === \"string\"\n ? body.externalId\n : ((\n await state.ctx.runQuery(\n config.component.public\n .enterpriseScimIdentityGetByEnterpriseAndUser,\n {\n enterpriseId: state.enterprise._id,\n userId,\n },\n )\n )?.externalId ?? userId),\n userId,\n active: body.active !== false && nextActive !== false,\n raw: body,\n lastProvisionedAt: Date.now(),\n },\n );\n await state.recordScimEvent(\n \"enterprise.scim.user.updated\",\n true,\n \"user\",\n userId,\n );\n const updatedUser = await auth.user.get(state.ctx, userId);\n const location = `${state.url.origin}${state.url.pathname}`;\n return scimJson(\n serializeScimUser({\n id: userId,\n user: updatedUser ?? existingUser,\n externalId:\n typeof body.externalId === \"string\" ? body.externalId : undefined,\n location,\n active: body.active !== false && nextActive !== false,\n }),\n 200,\n { Location: location },\n );\n };\n\n const handleUsersDelete: ScimHandler = async (state) => {\n const missing = requireScimResourceId(\n state.parsedPath.resourceId,\n \"User\",\n );\n if (missing) return missing;\n const userId = state.parsedPath.resourceId!;\n const resolution = await auth.member.inspect(state.ctx, {\n groupId: state.enterprise.groupId,\n userId,\n });\n if (resolution.membership) {\n await auth.member.delete(state.ctx, resolution.membership._id);\n }\n const identity = await state.ctx.runQuery(\n config.component.public.enterpriseScimIdentityGetByEnterpriseAndUser,\n {\n enterpriseId: state.enterprise._id,\n userId,\n },\n );\n if (identity) {\n if (state.policy.provisioning.deprovision.mode === \"hard\") {\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityDelete,\n { identityId: identity._id },\n );\n } else {\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n {\n enterpriseId: identity.enterpriseId,\n groupId: identity.groupId,\n resourceType: identity.resourceType,\n externalId: identity.externalId,\n userId: identity.userId,\n mappedGroupId: identity.mappedGroupId,\n active: false,\n raw: identity.raw,\n lastProvisionedAt: Date.now(),\n },\n );\n }\n }\n await state.recordScimEvent(\n \"enterprise.scim.user.deleted\",\n true,\n \"user\",\n userId,\n );\n return new Response(null, { status: 204 });\n };\n\n const handleGroupsGet: ScimHandler = async (state) => {\n const groupsList = await auth.group.list(state.ctx, {\n where: { parentGroupId: state.enterprise.groupId },\n limit: 100,\n });\n const identities = await state.ctx.runQuery(\n config.component.public.enterpriseScimIdentityListByEnterprise,\n { enterpriseId: state.enterprise._id },\n );\n const identityByGroupId = new Map(\n identities\n .filter((identity: any) => identity.mappedGroupId !== undefined)\n .map((identity: any) => [identity.mappedGroupId, identity]),\n );\n const groups = groupsList.items.map((group: any) => ({\n group,\n identity: identityByGroupId.get(group._id),\n }));\n const listRequest = parseScimListRequest(state.url);\n const filtered = filterScimCollection<{\n group: any;\n identity?: any;\n }>(groups, listRequest.filter, {\n id: (item: { group: any }, value: string) => item.group._id === value,\n externalId: (item: { identity?: any }, value: string) =>\n item.identity?.externalId === value,\n displayName: (item: { group: any }, value: string) =>\n item.group.name === value,\n });\n if (state.parsedPath.resourceId) {\n const resource = filtered.find(\n ({ group }) => group._id === state.parsedPath.resourceId,\n );\n if (!resource) {\n return scimError(404, \"notFound\", \"Group not found.\");\n }\n const members = (\n await auth.member.list(state.ctx, {\n where: {\n groupId: resource.group._id,\n status: \"active\",\n },\n limit: 100,\n })\n ).items.map((member: any) => ({ value: member.userId }));\n const location = `${state.url.origin}${state.url.pathname.replace(/\\/[^/]+$/, \"\")}/${resource.group._id}`;\n return scimJson(\n serializeScimGroup({\n id: resource.group._id,\n group: resource.group,\n externalId: resource.identity?.externalId,\n location,\n members,\n }),\n 200,\n { Location: location },\n );\n }\n const paged = paginateScimCollection(filtered, listRequest);\n return scimJson({\n schemas: [\"urn:ietf:params:scim:api:messages:2.0:ListResponse\"],\n Resources: paged.map(({ group, identity }) =>\n serializeScimGroup({\n id: group._id,\n group,\n externalId: identity?.externalId,\n location: `${state.url.origin}${state.url.pathname}/${group._id}`,\n }),\n ),\n totalResults: filtered.length,\n startIndex: listRequest.startIndex,\n itemsPerPage: paged.length,\n });\n };\n\n const handleGroupsPost: ScimHandler = async (state) => {\n const body = await readScimJson(state.request);\n const { groupId } = await auth.group.create(state.ctx, {\n name: String(body.displayName ?? \"Group\"),\n parentGroupId: state.enterprise.groupId,\n type: \"organization\",\n });\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityUpsert,\n {\n enterpriseId: state.enterprise._id,\n groupId: state.enterprise.groupId,\n resourceType: \"group\",\n externalId: body.externalId ?? groupId,\n mappedGroupId: groupId,\n active: true,\n raw: body,\n lastProvisionedAt: Date.now(),\n },\n );\n for (const member of Array.isArray(body.members) ? body.members : []) {\n try {\n await auth.member.create(state.ctx, {\n groupId,\n userId: String(member.value),\n roleIds: state.policy.provisioning.jit.defaultRoleIds,\n status: \"active\",\n });\n } catch {}\n }\n await state.recordScimEvent(\n \"enterprise.scim.group.created\",\n true,\n \"group\",\n groupId,\n );\n const group = await auth.group.get(state.ctx, groupId);\n const location = `${state.url.origin}${state.url.pathname}/${groupId}`;\n return scimJson(\n serializeScimGroup({\n id: groupId,\n group: group ?? {},\n externalId: body.externalId,\n location,\n members: (\n await auth.member.list(state.ctx, {\n where: { groupId, status: \"active\" },\n limit: 100,\n })\n ).items.map((member: any) => ({ value: member.userId })),\n }),\n 201,\n { Location: location },\n );\n };\n\n const handleGroupsPatch: ScimHandler = async (state) => {\n const missing = requireScimResourceId(\n state.parsedPath.resourceId,\n \"Group\",\n );\n if (missing) return missing;\n const groupId = state.parsedPath.resourceId!;\n const body = await readScimJson(state.request);\n for (const operation of Array.isArray(body.Operations)\n ? body.Operations\n : []) {\n if (operation.path === \"displayName\") {\n await auth.group.update(state.ctx, groupId, {\n name: operation.value,\n });\n }\n if (operation.path === \"members\" && operation.op === \"add\") {\n for (const member of Array.isArray(operation.value)\n ? operation.value\n : []) {\n try {\n await auth.member.create(state.ctx, {\n groupId,\n userId: String(member.value),\n roleIds: state.policy.provisioning.jit.defaultRoleIds,\n status: \"active\",\n });\n } catch {}\n }\n }\n if (operation.path === \"members\" && operation.op === \"replace\") {\n const currentMembers = (\n await auth.member.list(state.ctx, {\n where: { groupId, status: \"active\" },\n limit: 100,\n })\n ).items as Array<{ _id: string; userId: string }>;\n const currentUserIds = new Set<string>(\n currentMembers.map((member) => member.userId),\n );\n const nextUserIds = new Set<string>(\n (Array.isArray(operation.value) ? operation.value : []).map(\n (member: any) => String(member.value),\n ),\n );\n for (const member of currentMembers) {\n if (!nextUserIds.has(member.userId)) {\n await auth.member.delete(state.ctx, member._id);\n }\n }\n for (const userId of nextUserIds.values()) {\n if (!currentUserIds.has(userId)) {\n try {\n await auth.member.create(state.ctx, {\n groupId,\n userId,\n roleIds: state.policy.provisioning.jit.defaultRoleIds,\n status: \"active\",\n });\n } catch {}\n }\n }\n }\n if (\n typeof operation.path === \"string\" &&\n operation.op === \"remove\" &&\n operation.path.startsWith(\"members[\")\n ) {\n const match = operation.path.match(\n /^members\\[value eq \"([^\"]+)\"\\]$/,\n );\n const userId = match?.[1];\n if (userId) {\n const resolution = await auth.member.inspect(state.ctx, {\n groupId,\n userId,\n });\n if (resolution.membership) {\n await auth.member.delete(state.ctx, resolution.membership._id);\n }\n }\n }\n }\n await state.recordScimEvent(\n \"enterprise.scim.group.updated\",\n true,\n \"group\",\n groupId,\n );\n const group = await auth.group.get(state.ctx, groupId);\n const location = `${state.url.origin}${state.url.pathname}`;\n const members = (\n await auth.member.list(state.ctx, {\n where: { groupId, status: \"active\" },\n limit: 100,\n })\n ).items as Array<{ userId: string }>;\n return scimJson(\n serializeScimGroup({\n id: groupId,\n group: group ?? {},\n location,\n members: members.map((member) => ({\n value: member.userId,\n })),\n }),\n 200,\n { Location: location },\n );\n };\n\n const handleGroupsDelete: ScimHandler = async (state) => {\n const missing = requireScimResourceId(\n state.parsedPath.resourceId,\n \"Group\",\n );\n if (missing) return missing;\n const groupId = state.parsedPath.resourceId!;\n await auth.group.delete(state.ctx, groupId);\n const identity = await state.ctx.runQuery(\n config.component.public.enterpriseScimIdentityGetByMappedGroup,\n { mappedGroupId: groupId },\n );\n if (identity) {\n await state.ctx.runMutation(\n config.component.public.enterpriseScimIdentityDelete,\n { identityId: identity._id },\n );\n }\n await state.recordScimEvent(\n \"enterprise.scim.group.deleted\",\n true,\n \"group\",\n groupId,\n );\n return new Response(null, { status: 204 });\n };\n\n const scimHandlers: Record<\n string,\n Partial<Record<string, ScimHandler>>\n > = {\n ServiceProviderConfig: {\n GET: async () =>\n scimJson({\n schemas: [\n \"urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig\",\n ],\n patch: { supported: true },\n bulk: {\n supported: false,\n maxOperations: 0,\n maxPayloadSize: 0,\n },\n filter: { supported: true, maxResults: 100 },\n changePassword: { supported: false },\n sort: { supported: false },\n etag: { supported: false },\n authenticationSchemes: [\n {\n type: \"oauthbearertoken\",\n name: \"Bearer Token\",\n description:\n \"Use the SCIM token generated by Convex Auth enterprise.\",\n },\n ],\n }),\n },\n Schemas: {\n GET: async (state) =>\n handleStaticScimCollection(\n SCIM_SCHEMAS,\n state.parsedPath.resourceId,\n {\n by: \"id\",\n notFound: \"Schema not found.\",\n },\n ),\n },\n ResourceTypes: {\n GET: async (state) =>\n handleStaticScimCollection(\n SCIM_RESOURCE_TYPES,\n state.parsedPath.resourceId,\n { by: \"name\", notFound: \"Resource type not found.\" },\n ),\n },\n Users: {\n GET: handleUsersGet,\n POST: handleUsersPost,\n PATCH: handleUsersUpsert,\n PUT: handleUsersUpsert,\n DELETE: handleUsersDelete,\n },\n Groups: {\n GET: handleGroupsGet,\n POST: handleGroupsPost,\n PATCH: handleGroupsPatch,\n DELETE: handleGroupsDelete,\n },\n };\n\n const handler =\n scimHandlers[state.parsedPath.resource]?.[state.request.method];\n return handler\n ? await handler(state)\n : scimError(404, \"notFound\", \"SCIM resource not found.\");\n } catch (error) {\n if (\n error instanceof Error &&\n error.message === \"Unsupported SCIM filter.\"\n ) {\n return scimError(400, \"invalidFilter\", error.message);\n }\n if (\n error instanceof ConvexError &&\n typeof error.data === \"object\" &&\n error.data !== null &&\n \"code\" in error.data &&\n \"message\" in error.data\n ) {\n const code = error.data.code as string;\n const status =\n code === \"MISSING_BEARER_TOKEN\" || code === \"INVALID_API_KEY\"\n ? 401\n : 400;\n return scimError(status, code, error.data.message);\n }\n throw error;\n }\n };\n\n addSSORoutes(http, {\n routeBase: ENTERPRISE_CONTROL_ROUTE_BASE,\n convertErrorsToResponse,\n handleSamlMetadata: async (ctx, _request, runtimeRoute) => {\n const { loaded } = await loadActiveEnterpriseSamlOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n return new Response(\n createEnterpriseSamlMetadataXml({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: loaded.source,\n config: loaded.config,\n }),\n {\n status: 200,\n headers: { \"Content-Type\": \"application/xml\" },\n },\n );\n },\n handleSamlSignIn: async (ctx, request, runtimeRoute) => {\n const url = new URL(request.url);\n const verifier = url.searchParams.get(\"code\");\n if (!verifier) {\n throw Cv.error({\n code: \"OAUTH_MISSING_VERIFIER\",\n message: \"Missing sign-in verifier.\",\n });\n }\n const { loaded, enterprise } = await loadActiveEnterpriseSamlOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n const state = generateRandomString(24, INVITE_TOKEN_ALPHABET);\n const signInRequest = createEnterpriseSamlSignInRequest({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n source: { kind: \"enterprise\", id: enterprise._id },\n config: loaded.config,\n state,\n signature: `saml ${enterprise._id} pending ${state}`,\n redirectTo: url.searchParams.get(\"redirectTo\") ?? undefined,\n });\n const signature = `saml ${enterprise._id} ${signInRequest.requestId} ${state}`;\n await callVerifierSignature(ctx, { verifier, signature });\n const redirectTo = url.searchParams.get(\"redirectTo\");\n const redirectCookies =\n redirectTo !== null\n ? [\n redirectToParamCookie(\n enterpriseSamlProviderId(enterprise._id),\n redirectTo,\n ),\n ]\n : [];\n const relayState = encodeEnterpriseSamlRelayState({\n source: { kind: \"enterprise\", id: enterprise._id },\n signature,\n requestId: signInRequest.requestId,\n state,\n redirectTo: url.searchParams.get(\"redirectTo\") ?? undefined,\n });\n if (signInRequest.binding === \"redirect\" && signInRequest.redirectUrl) {\n const redirectUrl = new URL(signInRequest.redirectUrl);\n redirectUrl.searchParams.set(\"RelayState\", relayState);\n const headers = new Headers({\n Location: redirectUrl.toString(),\n });\n for (const { name, value, options } of redirectCookies as any) {\n headers.append(\"Set-Cookie\", serializeCookie(name, value, options));\n }\n return new Response(null, { status: 302, headers });\n }\n const response = createSamlPostBindingResponse({\n endpoint: signInRequest.post!.endpoint,\n parameter: \"SAMLRequest\",\n value: signInRequest.post!.value,\n relayState,\n });\n for (const { name, value, options } of redirectCookies as any) {\n response.headers.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options),\n );\n }\n return response;\n },\n handleOidcSignIn: async (ctx, request, runtimeRoute) => {\n const url = new URL(request.url);\n const verifier = url.searchParams.get(\"code\");\n if (!verifier) {\n throw Cv.error({\n code: \"OAUTH_MISSING_VERIFIER\",\n message: \"Missing sign-in verifier.\",\n });\n }\n const { enterprise, oidc } = await loadEnterpriseOidcOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n const { providerId, provider, oauthConfig } =\n await createEnterpriseOidcRuntime({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n enterpriseId: enterprise._id,\n oidc,\n });\n const { redirect, cookies, signature } =\n await createOAuthAuthorizationURL(providerId, provider, oauthConfig);\n await callVerifierSignature(ctx, { verifier, signature });\n const redirectTo = url.searchParams.get(\"redirectTo\");\n const headers_ = new Headers({ Location: redirect });\n for (const { name, value, options } of [\n ...cookies,\n ...(redirectTo !== null\n ? [redirectToParamCookie(providerId, redirectTo)]\n : []),\n ] as any) {\n headers_.append(\"Set-Cookie\", serializeCookie(name, value, options));\n }\n return new Response(null, {\n status: 302,\n headers: headers_,\n });\n },\n handleOidcCallback: async (ctx, request, runtimeRoute) => {\n const url = new URL(request.url);\n const { enterprise, oidc } = await loadEnterpriseOidcOrThrow(\n ctx,\n runtimeRoute.enterpriseId,\n );\n const { providerId, provider, oauthConfig } =\n await createEnterpriseOidcRuntime({\n rootUrl: requireEnv(\"CONVEX_SITE_URL\"),\n enterpriseId: enterprise._id,\n oidc,\n });\n const cookies = getCookies(request);\n const maybeRedirectTo = useRedirectToParam(providerId, cookies);\n const destinationUrl = await redirectAbsoluteUrl(config, {\n redirectTo: maybeRedirectTo?.redirectTo,\n });\n const params = url.searchParams;\n const result = (await Fx.run(\n handleOAuthCallback(\n providerId,\n provider,\n oauthConfig,\n Object.fromEntries(params.entries()),\n cookies,\n ),\n )) as any;\n const extraFields = oidc.extraFields as\n | Record<string, string>\n | undefined;\n let profile = result.profile as Record<string, unknown>;\n if (extraFields && typeof profile === \"object\" && profile) {\n const extend: Record<string, unknown> = {};\n for (const [claimName, fieldName] of Object.entries(extraFields)) {\n if (claimName in profile) {\n extend[fieldName] = profile[claimName];\n }\n }\n if (Object.keys(extend).length > 0) {\n profile = { ...profile, extend };\n }\n }\n\n const verificationCode = await callUserOAuth(ctx, {\n provider: providerId,\n providerAccountId: result.providerAccountId,\n profile,\n signature: result.signature,\n accountExtend: {\n identity: {\n protocol: \"oidc\",\n enterpriseId: enterprise._id,\n subject: result.providerAccountId,\n issuer: typeof oidc.issuer === \"string\" ? oidc.issuer : undefined,\n discoveryUrl:\n typeof oidc.discoveryUrl === \"string\"\n ? oidc.discoveryUrl\n : undefined,\n },\n },\n });\n const headers = new Headers({\n Location: setURLSearchParam(destinationUrl, \"code\", verificationCode),\n });\n for (const { name, value, options } of result.cookies) {\n headers.append(\n \"Set-Cookie\",\n serializeCookie(name, value, options as any),\n );\n }\n if (maybeRedirectTo) {\n headers.append(\n \"Set-Cookie\",\n serializeCookie(\n maybeRedirectTo.updatedCookie.name,\n maybeRedirectTo.updatedCookie.value,\n maybeRedirectTo.updatedCookie.options as any,\n ),\n );\n }\n return new Response(null, { status: 302, headers });\n },\n handleSamlAcs,\n handleSamlSlo,\n handleScimRequest,\n scimError,\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
import { enterpriseOidcProviderId, getEnterpriseOidcUrls } from "./shared.js";
|
|
2
|
-
import { Fx } from "@robelest/fx";
|
|
3
|
-
import { sha256 } from "@oslojs/crypto/sha2";
|
|
4
|
-
import { encodeBase64urlNoPadding } from "@oslojs/encoding";
|
|
5
|
-
import { createRemoteJWKSet, customFetch, decodeProtectedHeader, jwtVerify } from "jose";
|
|
6
|
-
import { decodeIdToken } from "arctic";
|
|
7
|
-
|
|
8
|
-
//#region src/server/enterprise/oidc.ts
|
|
9
|
-
const OIDC_JWKS_CACHE = /* @__PURE__ */ new Map();
|
|
10
|
-
async function discoverOidcConfiguration(config) {
|
|
11
|
-
const discoveryUrl = typeof config.discoveryUrl === "string" ? config.discoveryUrl : typeof config.issuer === "string" ? `${config.issuer.replace(/\/$/, "")}/.well-known/openid-configuration` : null;
|
|
12
|
-
if (!discoveryUrl) throw new Error("Enterprise OIDC requires an issuer or discoveryUrl.");
|
|
13
|
-
const oidcFetch = createEnterpriseOidcFetch(config, config.issuer);
|
|
14
|
-
return await Fx.run(Fx.defer(() => Fx.from({
|
|
15
|
-
ok: async () => {
|
|
16
|
-
const response = await oidcFetch(discoveryUrl);
|
|
17
|
-
if (!response.ok) throw new Error(`Failed to discover OIDC configuration: ${response.status}`);
|
|
18
|
-
const discovery = await response.json();
|
|
19
|
-
if (typeof discovery.issuer !== "string" || typeof discovery.authorization_endpoint !== "string" || typeof discovery.token_endpoint !== "string" || typeof discovery.jwks_uri !== "string") throw new Error("OIDC discovery document is missing required fields.");
|
|
20
|
-
return discovery;
|
|
21
|
-
},
|
|
22
|
-
err: (error) => error instanceof Error ? error : new Error(String(error))
|
|
23
|
-
})).pipe(Fx.timeout(1e4), Fx.retry(Fx.retry.compose(Fx.retry.jittered(Fx.retry.exponential(200)), Fx.retry.recurs(2))), Fx.recover((error) => Fx.fail(error instanceof Error ? error : new Error(String(error))))));
|
|
24
|
-
}
|
|
25
|
-
function createEnterpriseOidcFetch(config, discoveredIssuer) {
|
|
26
|
-
const runtimeOrigin = typeof config.discoveryUrl === "string" ? new URL(config.discoveryUrl).origin : void 0;
|
|
27
|
-
const externalHost = typeof config.issuer === "string" ? new URL(config.issuer).host : typeof discoveredIssuer === "string" ? new URL(discoveredIssuer).host : void 0;
|
|
28
|
-
return async (input, init) => {
|
|
29
|
-
const url = new URL(typeof input === "string" ? input : input.toString());
|
|
30
|
-
const rewrittenUrl = runtimeOrigin !== void 0 && url.origin !== runtimeOrigin ? new URL(`${runtimeOrigin}${url.pathname}${url.search}`) : url;
|
|
31
|
-
const headers = new Headers(init?.headers);
|
|
32
|
-
if (runtimeOrigin !== void 0 && externalHost !== void 0) headers.set("host", externalHost);
|
|
33
|
-
return await fetch(rewrittenUrl, {
|
|
34
|
-
...init,
|
|
35
|
-
headers
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
function getOidcJwks(url, fetchImpl) {
|
|
40
|
-
const cacheKey = fetchImpl ? `${url}::custom` : url;
|
|
41
|
-
let jwks = OIDC_JWKS_CACHE.get(cacheKey);
|
|
42
|
-
if (!jwks) {
|
|
43
|
-
jwks = fetchImpl ? createRemoteJWKSet(new URL(url), { [customFetch]: fetchImpl }) : createRemoteJWKSet(new URL(url));
|
|
44
|
-
OIDC_JWKS_CACHE.set(cacheKey, jwks);
|
|
45
|
-
}
|
|
46
|
-
return jwks;
|
|
47
|
-
}
|
|
48
|
-
function userInfoProfileFx(opts) {
|
|
49
|
-
return Fx.from({
|
|
50
|
-
ok: async () => {
|
|
51
|
-
const response = await (opts.fetchImpl ?? fetch)(opts.endpoint, { headers: { Authorization: `Bearer ${opts.accessToken}` } });
|
|
52
|
-
if (!response.ok) throw new Error(`OIDC userinfo request failed: ${response.status}`);
|
|
53
|
-
return await response.json();
|
|
54
|
-
},
|
|
55
|
-
err: (error) => ({
|
|
56
|
-
kind: "transport",
|
|
57
|
-
error
|
|
58
|
-
})
|
|
59
|
-
}).pipe(Fx.chain((userInfo) => {
|
|
60
|
-
const userInfoSubject = typeof userInfo.sub === "string" ? userInfo.sub : void 0;
|
|
61
|
-
const tokenSubject = typeof opts.verifiedClaims.sub === "string" ? opts.verifiedClaims.sub : void 0;
|
|
62
|
-
return userInfoSubject !== void 0 && tokenSubject !== void 0 && userInfoSubject !== tokenSubject ? Fx.fail({ kind: "subject-mismatch" }) : Fx.succeed({
|
|
63
|
-
id: userInfoSubject ?? (typeof opts.verifiedClaims.sub === "string" ? opts.verifiedClaims.sub : void 0) ?? crypto.randomUUID(),
|
|
64
|
-
email: typeof userInfo.email === "string" ? userInfo.email : opts.verifiedProfile.email,
|
|
65
|
-
emailVerified: typeof userInfo.email_verified === "boolean" ? userInfo.email_verified : opts.verifiedProfile.emailVerified,
|
|
66
|
-
name: typeof userInfo.name === "string" ? userInfo.name : opts.verifiedProfile.name,
|
|
67
|
-
image: typeof userInfo.picture === "string" ? userInfo.picture : opts.verifiedProfile.image
|
|
68
|
-
});
|
|
69
|
-
}), Fx.recover((failure) => {
|
|
70
|
-
if (failure.kind === "transport") return Fx.succeed(null);
|
|
71
|
-
return Fx.fail(/* @__PURE__ */ new Error("OIDC userinfo subject does not match ID token subject."));
|
|
72
|
-
}));
|
|
73
|
-
}
|
|
74
|
-
/** @internal */
|
|
75
|
-
async function createEnterpriseOidcProvider(config, redirectUri) {
|
|
76
|
-
const discovery = await discoverOidcConfiguration(config);
|
|
77
|
-
const expectedIssuer = String(config.issuer ?? discovery.issuer).replace(/\/$/, "");
|
|
78
|
-
const discoveredIssuer = String(discovery.issuer).replace(/\/$/, "");
|
|
79
|
-
const strictIssuer = config.strictIssuer === true;
|
|
80
|
-
if (typeof config.issuer === "string" && expectedIssuer !== discoveredIssuer) {
|
|
81
|
-
if (strictIssuer) throw new Error(`Configured OIDC issuer mismatch. configured=${expectedIssuer} discovery=${discoveredIssuer}`);
|
|
82
|
-
console.warn("Configured OIDC issuer differs from discovery issuer; accepting both for token verification.", {
|
|
83
|
-
configuredIssuer: expectedIssuer,
|
|
84
|
-
discoveryIssuer: discoveredIssuer
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
const authorizationEndpoint = discovery.authorization_endpoint;
|
|
88
|
-
const tokenEndpoint = discovery.token_endpoint;
|
|
89
|
-
const jwksUri = String(config.jwksUri ?? discovery.jwks_uri);
|
|
90
|
-
const supportedIdTokenSigningAlgs = Array.isArray(discovery.id_token_signing_alg_values_supported) ? discovery.id_token_signing_alg_values_supported.filter((value) => typeof value === "string") : [];
|
|
91
|
-
const userinfoEndpoint = discovery.userinfo_endpoint ?? void 0;
|
|
92
|
-
const oidcFetch = createEnterpriseOidcFetch(config, discovery.issuer);
|
|
93
|
-
const scopes = Array.isArray(config.scopes) ? config.scopes.filter((value) => typeof value === "string") : [
|
|
94
|
-
"openid",
|
|
95
|
-
"profile",
|
|
96
|
-
"email"
|
|
97
|
-
];
|
|
98
|
-
const expectedAudience = config.audience ?? String(config.clientId);
|
|
99
|
-
const getIssuerCandidates = (issuer) => {
|
|
100
|
-
const candidates = [issuer];
|
|
101
|
-
if (issuer.startsWith("https://")) candidates.push(`http://${issuer.slice(8)}`);
|
|
102
|
-
else if (issuer.startsWith("http://")) candidates.push(`https://${issuer.slice(7)}`);
|
|
103
|
-
return candidates;
|
|
104
|
-
};
|
|
105
|
-
const expectedIssuers = strictIssuer ? [expectedIssuer] : Array.from(new Set([...getIssuerCandidates(expectedIssuer), ...getIssuerCandidates(discoveredIssuer)]));
|
|
106
|
-
const jwks = getOidcJwks(jwksUri, oidcFetch);
|
|
107
|
-
let verifiedClaims = null;
|
|
108
|
-
let verifiedProfile = null;
|
|
109
|
-
const normalizeProfile = (claims) => ({
|
|
110
|
-
id: typeof claims.sub === "string" ? claims.sub : crypto.randomUUID(),
|
|
111
|
-
email: typeof claims.email === "string" ? claims.email : void 0,
|
|
112
|
-
emailVerified: typeof claims.email_verified === "boolean" ? claims.email_verified : void 0,
|
|
113
|
-
name: typeof claims.name === "string" ? claims.name : void 0,
|
|
114
|
-
image: typeof claims.picture === "string" ? claims.picture : void 0
|
|
115
|
-
});
|
|
116
|
-
return {
|
|
117
|
-
provider: {
|
|
118
|
-
createAuthorizationURL(state, codeVerifier, requestedScopes) {
|
|
119
|
-
const url = new URL(authorizationEndpoint);
|
|
120
|
-
url.searchParams.set("response_type", "code");
|
|
121
|
-
url.searchParams.set("client_id", String(config.clientId));
|
|
122
|
-
url.searchParams.set("redirect_uri", redirectUri);
|
|
123
|
-
url.searchParams.set("scope", (requestedScopes.length > 0 ? requestedScopes : scopes).join(" "));
|
|
124
|
-
url.searchParams.set("state", state);
|
|
125
|
-
url.searchParams.set("code_challenge_method", "S256");
|
|
126
|
-
url.searchParams.set("code_challenge", encodeBase64urlNoPadding(sha256(new TextEncoder().encode(codeVerifier))));
|
|
127
|
-
const authorizationParams = typeof config.authorizationParams === "object" && config.authorizationParams !== null ? config.authorizationParams : {};
|
|
128
|
-
for (const [key, value] of Object.entries(authorizationParams)) if (typeof value === "string") url.searchParams.set(key, value);
|
|
129
|
-
return url;
|
|
130
|
-
},
|
|
131
|
-
async validateAuthorizationCode(code, codeVerifier) {
|
|
132
|
-
const body = new URLSearchParams({
|
|
133
|
-
grant_type: "authorization_code",
|
|
134
|
-
code,
|
|
135
|
-
redirect_uri: redirectUri,
|
|
136
|
-
client_id: String(config.clientId)
|
|
137
|
-
});
|
|
138
|
-
if (typeof config.clientSecret === "string") body.set("client_secret", config.clientSecret);
|
|
139
|
-
if (codeVerifier) body.set("code_verifier", codeVerifier);
|
|
140
|
-
const response = await oidcFetch(tokenEndpoint, {
|
|
141
|
-
method: "POST",
|
|
142
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
143
|
-
body
|
|
144
|
-
});
|
|
145
|
-
if (!response.ok) throw new Error(`OIDC token exchange failed: ${response.status}`);
|
|
146
|
-
const data = await response.json();
|
|
147
|
-
return {
|
|
148
|
-
data,
|
|
149
|
-
idToken() {
|
|
150
|
-
if (typeof data.id_token !== "string") throw new Error("OIDC response is missing id_token.");
|
|
151
|
-
return data.id_token;
|
|
152
|
-
},
|
|
153
|
-
accessToken() {
|
|
154
|
-
if (typeof data.access_token !== "string") throw new Error("OIDC response is missing access_token.");
|
|
155
|
-
return data.access_token;
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
},
|
|
160
|
-
oauthConfig: {
|
|
161
|
-
scopes,
|
|
162
|
-
nonce: true,
|
|
163
|
-
validateTokens: async (tokens, ctx) => {
|
|
164
|
-
const verified = await Fx.run(Fx.gen(function* () {
|
|
165
|
-
yield* Fx.guard(ctx.nonce === void 0, Fx.fail(/* @__PURE__ */ new Error("OIDC nonce is required.")));
|
|
166
|
-
const idToken = tokens.idToken();
|
|
167
|
-
const tokenAlg = decodeProtectedHeader(idToken).alg;
|
|
168
|
-
const useSymmetricValidation = typeof tokenAlg === "string" && (tokenAlg === "HS256" || tokenAlg === "HS384" || tokenAlg === "HS512") && supportedIdTokenSigningAlgs.includes(tokenAlg);
|
|
169
|
-
const verificationOptions = {
|
|
170
|
-
audience: expectedAudience,
|
|
171
|
-
requiredClaims: [
|
|
172
|
-
"iss",
|
|
173
|
-
"sub",
|
|
174
|
-
"aud",
|
|
175
|
-
"exp",
|
|
176
|
-
"iat"
|
|
177
|
-
],
|
|
178
|
-
clockTolerance: config.clockToleranceSeconds ?? 10
|
|
179
|
-
};
|
|
180
|
-
const payload = (yield* Fx.from({
|
|
181
|
-
ok: () => useSymmetricValidation ? jwtVerify(idToken, (() => {
|
|
182
|
-
if (typeof config.clientSecret !== "string") throw new Error("OIDC provider uses symmetric ID token signatures but clientSecret is missing.");
|
|
183
|
-
return new TextEncoder().encode(config.clientSecret);
|
|
184
|
-
})(), verificationOptions) : jwtVerify(idToken, jwks, verificationOptions),
|
|
185
|
-
err: (error) => error instanceof Error ? error : new Error(String(error))
|
|
186
|
-
})).payload;
|
|
187
|
-
const tokenIssuerRaw = typeof payload.iss === "string" ? payload.iss : void 0;
|
|
188
|
-
const tokenIssuer = typeof tokenIssuerRaw === "string" ? tokenIssuerRaw.replace(/\/$/, "") : void 0;
|
|
189
|
-
yield* Fx.guard(!tokenIssuer || !expectedIssuers.includes(tokenIssuer), Fx.fail(/* @__PURE__ */ new Error(`OIDC token issuer mismatch. Received: ${tokenIssuer ?? "<missing>"}. Expected one of: ${expectedIssuers.join(", ")}`)));
|
|
190
|
-
yield* Fx.guard(payload.nonce !== ctx.nonce, Fx.fail(/* @__PURE__ */ new Error("OIDC nonce mismatch.")));
|
|
191
|
-
yield* Fx.guard(Array.isArray(payload.aud) && payload.aud.length > 1 && payload.azp !== String(config.clientId), Fx.fail(/* @__PURE__ */ new Error("OIDC authorized party does not match client ID.")));
|
|
192
|
-
return payload;
|
|
193
|
-
}));
|
|
194
|
-
verifiedClaims = verified;
|
|
195
|
-
verifiedProfile = normalizeProfile(verified);
|
|
196
|
-
},
|
|
197
|
-
accountLinking: config.accountLinking,
|
|
198
|
-
profile: async (tokens) => {
|
|
199
|
-
if (verifiedProfile === null || verifiedClaims === null) {
|
|
200
|
-
const claims = decodeIdToken(tokens.idToken());
|
|
201
|
-
verifiedClaims = claims;
|
|
202
|
-
verifiedProfile = normalizeProfile(claims);
|
|
203
|
-
}
|
|
204
|
-
if (userinfoEndpoint && typeof tokens.accessToken === "function") {
|
|
205
|
-
const userInfoProfile = await Fx.run(userInfoProfileFx({
|
|
206
|
-
endpoint: userinfoEndpoint,
|
|
207
|
-
accessToken: tokens.accessToken(),
|
|
208
|
-
verifiedClaims,
|
|
209
|
-
verifiedProfile,
|
|
210
|
-
fetchImpl: oidcFetch
|
|
211
|
-
}));
|
|
212
|
-
if (userInfoProfile !== null) return userInfoProfile;
|
|
213
|
-
}
|
|
214
|
-
return verifiedProfile;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
/** @internal */
|
|
220
|
-
function createSyntheticOAuthMaterializedConfig(providerId, options) {
|
|
221
|
-
return {
|
|
222
|
-
id: providerId,
|
|
223
|
-
type: "oauth",
|
|
224
|
-
provider: null,
|
|
225
|
-
scopes: [],
|
|
226
|
-
accountLinking: options?.accountLinking ?? "verifiedEmail"
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
/** @internal */
|
|
230
|
-
async function createEnterpriseOidcRuntime(opts) {
|
|
231
|
-
const providerId = enterpriseOidcProviderId(opts.enterpriseId);
|
|
232
|
-
const urls = getEnterpriseOidcUrls({
|
|
233
|
-
rootUrl: opts.rootUrl,
|
|
234
|
-
enterpriseId: opts.enterpriseId
|
|
235
|
-
});
|
|
236
|
-
const { provider, oauthConfig } = await createEnterpriseOidcProvider(opts.oidc, urls.callbackUrl);
|
|
237
|
-
return {
|
|
238
|
-
oidc: opts.oidc,
|
|
239
|
-
providerId,
|
|
240
|
-
provider,
|
|
241
|
-
oauthConfig,
|
|
242
|
-
...urls
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
//#endregion
|
|
247
|
-
export { createEnterpriseOidcRuntime, createSyntheticOAuthMaterializedConfig };
|
|
248
|
-
//# sourceMappingURL=oidc.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"oidc.js","names":[],"sources":["../../../../src/server/enterprise/oidc.ts"],"sourcesContent":["import { sha256 } from \"@oslojs/crypto/sha2\";\nimport { encodeBase64urlNoPadding } from \"@oslojs/encoding\";\nimport { Fx } from \"@robelest/fx\";\nimport { decodeIdToken } from \"arctic\";\nimport {\n createRemoteJWKSet,\n customFetch,\n decodeProtectedHeader,\n jwtVerify,\n} from \"jose\";\n\nimport type { OAuthMaterializedConfig, OAuthProfile } from \"../types\";\nimport { enterpriseOidcProviderId, getEnterpriseOidcUrls } from \"./shared\";\n\nconst OIDC_JWKS_CACHE = new Map<\n string,\n ReturnType<typeof createRemoteJWKSet>\n>();\n\nasync function discoverOidcConfiguration(config: Record<string, any>) {\n const discoveryUrl =\n typeof config.discoveryUrl === \"string\"\n ? config.discoveryUrl\n : typeof config.issuer === \"string\"\n ? `${config.issuer.replace(/\\/$/, \"\")}/.well-known/openid-configuration`\n : null;\n\n if (!discoveryUrl) {\n throw new Error(\"Enterprise OIDC requires an issuer or discoveryUrl.\");\n }\n\n const oidcFetch = createEnterpriseOidcFetch(config, config.issuer);\n\n return await Fx.run(\n Fx.defer(() =>\n Fx.from({\n ok: async () => {\n const response = await oidcFetch(discoveryUrl);\n if (!response.ok) {\n throw new Error(\n `Failed to discover OIDC configuration: ${response.status}`,\n );\n }\n const discovery = (await response.json()) as Record<string, any>;\n if (\n typeof discovery.issuer !== \"string\" ||\n typeof discovery.authorization_endpoint !== \"string\" ||\n typeof discovery.token_endpoint !== \"string\" ||\n typeof discovery.jwks_uri !== \"string\"\n ) {\n throw new Error(\n \"OIDC discovery document is missing required fields.\",\n );\n }\n return discovery;\n },\n err: (error) =>\n error instanceof Error ? error : new Error(String(error)),\n }),\n ).pipe(\n Fx.timeout(10_000),\n Fx.retry(\n Fx.retry.compose(\n Fx.retry.jittered(Fx.retry.exponential(200)),\n Fx.retry.recurs(2),\n ),\n ),\n Fx.recover((error) =>\n Fx.fail(error instanceof Error ? error : new Error(String(error))),\n ),\n ),\n );\n}\n\nfunction createEnterpriseOidcFetch(\n config: Record<string, any>,\n discoveredIssuer?: string,\n) {\n const runtimeOrigin =\n typeof config.discoveryUrl === \"string\"\n ? new URL(config.discoveryUrl).origin\n : undefined;\n const externalHost =\n typeof config.issuer === \"string\"\n ? new URL(config.issuer).host\n : typeof discoveredIssuer === \"string\"\n ? new URL(discoveredIssuer).host\n : undefined;\n\n return async (input: string | URL, init?: RequestInit) => {\n const url = new URL(typeof input === \"string\" ? input : input.toString());\n const rewrittenUrl =\n runtimeOrigin !== undefined && url.origin !== runtimeOrigin\n ? new URL(`${runtimeOrigin}${url.pathname}${url.search}`)\n : url;\n const headers = new Headers(init?.headers);\n if (runtimeOrigin !== undefined && externalHost !== undefined) {\n headers.set(\"host\", externalHost);\n }\n return await fetch(rewrittenUrl, { ...init, headers });\n };\n}\n\nfunction getOidcJwks(\n url: string,\n fetchImpl?: ReturnType<typeof createEnterpriseOidcFetch>,\n) {\n const cacheKey = fetchImpl ? `${url}::custom` : url;\n let jwks = OIDC_JWKS_CACHE.get(cacheKey);\n if (!jwks) {\n jwks = fetchImpl\n ? createRemoteJWKSet(new URL(url), { [customFetch]: fetchImpl })\n : createRemoteJWKSet(new URL(url));\n OIDC_JWKS_CACHE.set(cacheKey, jwks);\n }\n return jwks;\n}\n\ntype UserInfoFetchFailure =\n | { kind: \"transport\"; error: unknown }\n | { kind: \"subject-mismatch\" };\n\nfunction userInfoProfileFx(opts: {\n endpoint: string;\n accessToken: string;\n verifiedClaims: Record<string, unknown>;\n verifiedProfile: OAuthProfile & { emailVerified?: boolean };\n fetchImpl?: ReturnType<typeof createEnterpriseOidcFetch>;\n}) {\n return Fx.from({\n ok: async () => {\n const response = await (opts.fetchImpl ?? fetch)(opts.endpoint, {\n headers: { Authorization: `Bearer ${opts.accessToken}` },\n });\n if (!response.ok) {\n throw new Error(`OIDC userinfo request failed: ${response.status}`);\n }\n return (await response.json()) as Record<string, unknown>;\n },\n err: (error): UserInfoFetchFailure => ({ kind: \"transport\", error }),\n }).pipe(\n Fx.chain((userInfo) => {\n const userInfoSubject =\n typeof userInfo.sub === \"string\" ? userInfo.sub : undefined;\n const tokenSubject =\n typeof opts.verifiedClaims.sub === \"string\"\n ? opts.verifiedClaims.sub\n : undefined;\n return userInfoSubject !== undefined &&\n tokenSubject !== undefined &&\n userInfoSubject !== tokenSubject\n ? Fx.fail({ kind: \"subject-mismatch\" } as const)\n : Fx.succeed({\n id:\n userInfoSubject ??\n (typeof opts.verifiedClaims.sub === \"string\"\n ? opts.verifiedClaims.sub\n : undefined) ??\n crypto.randomUUID(),\n email:\n typeof userInfo.email === \"string\"\n ? userInfo.email\n : opts.verifiedProfile.email,\n emailVerified:\n typeof userInfo.email_verified === \"boolean\"\n ? userInfo.email_verified\n : opts.verifiedProfile.emailVerified,\n name:\n typeof userInfo.name === \"string\"\n ? userInfo.name\n : opts.verifiedProfile.name,\n image:\n typeof userInfo.picture === \"string\"\n ? userInfo.picture\n : opts.verifiedProfile.image,\n } as OAuthProfile & { emailVerified?: boolean });\n }),\n Fx.recover((failure) => {\n if (failure.kind === \"transport\") {\n return Fx.succeed(null);\n }\n return Fx.fail(\n new Error(\"OIDC userinfo subject does not match ID token subject.\"),\n );\n }),\n );\n}\n\n/** @internal */\nexport async function createEnterpriseOidcProvider(\n config: Record<string, any>,\n redirectUri: string,\n) {\n const discovery = await discoverOidcConfiguration(config);\n const expectedIssuer = String(config.issuer ?? discovery.issuer).replace(\n /\\/$/,\n \"\",\n );\n const discoveredIssuer = String(discovery.issuer).replace(/\\/$/, \"\");\n const strictIssuer = config.strictIssuer === true;\n if (\n typeof config.issuer === \"string\" &&\n expectedIssuer !== discoveredIssuer\n ) {\n if (strictIssuer) {\n throw new Error(\n `Configured OIDC issuer mismatch. configured=${expectedIssuer} discovery=${discoveredIssuer}`,\n );\n }\n console.warn(\n \"Configured OIDC issuer differs from discovery issuer; accepting both for token verification.\",\n {\n configuredIssuer: expectedIssuer,\n discoveryIssuer: discoveredIssuer,\n },\n );\n }\n const authorizationEndpoint = discovery.authorization_endpoint as string;\n const tokenEndpoint = discovery.token_endpoint as string;\n const jwksUri = String(config.jwksUri ?? discovery.jwks_uri);\n const supportedIdTokenSigningAlgs = Array.isArray(\n discovery.id_token_signing_alg_values_supported,\n )\n ? discovery.id_token_signing_alg_values_supported.filter(\n (value: unknown): value is string => typeof value === \"string\",\n )\n : [];\n const userinfoEndpoint =\n (discovery.userinfo_endpoint as string | undefined) ?? undefined;\n const oidcFetch = createEnterpriseOidcFetch(\n config,\n discovery.issuer as string,\n );\n const scopes = Array.isArray(config.scopes)\n ? config.scopes.filter(\n (value: unknown): value is string => typeof value === \"string\",\n )\n : [\"openid\", \"profile\", \"email\"];\n const expectedAudience = config.audience ?? String(config.clientId);\n const getIssuerCandidates = (issuer: string) => {\n const candidates = [issuer];\n if (issuer.startsWith(\"https://\")) {\n candidates.push(`http://${issuer.slice(\"https://\".length)}`);\n } else if (issuer.startsWith(\"http://\")) {\n candidates.push(`https://${issuer.slice(\"http://\".length)}`);\n }\n return candidates;\n };\n const expectedIssuers = strictIssuer\n ? [expectedIssuer]\n : Array.from(\n new Set([\n ...getIssuerCandidates(expectedIssuer),\n ...getIssuerCandidates(discoveredIssuer),\n ]),\n );\n const jwks = getOidcJwks(jwksUri, oidcFetch);\n let verifiedClaims: Record<string, unknown> | null = null;\n let verifiedProfile: (OAuthProfile & { emailVerified?: boolean }) | null =\n null;\n const normalizeProfile = (claims: Record<string, unknown>) => ({\n id: typeof claims.sub === \"string\" ? claims.sub : crypto.randomUUID(),\n email: typeof claims.email === \"string\" ? claims.email : undefined,\n emailVerified:\n typeof claims.email_verified === \"boolean\"\n ? claims.email_verified\n : undefined,\n name: typeof claims.name === \"string\" ? claims.name : undefined,\n image: typeof claims.picture === \"string\" ? claims.picture : undefined,\n });\n\n const provider = {\n createAuthorizationURL(\n state: string,\n codeVerifier: string,\n requestedScopes: string[],\n ) {\n const url = new URL(authorizationEndpoint);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"client_id\", String(config.clientId));\n url.searchParams.set(\"redirect_uri\", redirectUri);\n url.searchParams.set(\n \"scope\",\n (requestedScopes.length > 0 ? requestedScopes : scopes).join(\" \"),\n );\n url.searchParams.set(\"state\", state);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n url.searchParams.set(\n \"code_challenge\",\n encodeBase64urlNoPadding(\n sha256(new TextEncoder().encode(codeVerifier)),\n ),\n );\n const authorizationParams =\n typeof config.authorizationParams === \"object\" &&\n config.authorizationParams !== null\n ? (config.authorizationParams as Record<string, unknown>)\n : {};\n for (const [key, value] of Object.entries(authorizationParams)) {\n if (typeof value === \"string\") {\n url.searchParams.set(key, value);\n }\n }\n return url;\n },\n async validateAuthorizationCode(code: string, codeVerifier?: string) {\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n redirect_uri: redirectUri,\n client_id: String(config.clientId),\n });\n if (typeof config.clientSecret === \"string\") {\n body.set(\"client_secret\", config.clientSecret);\n }\n if (codeVerifier) {\n body.set(\"code_verifier\", codeVerifier);\n }\n const response = await oidcFetch(tokenEndpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body,\n });\n if (!response.ok) {\n throw new Error(`OIDC token exchange failed: ${response.status}`);\n }\n const data = (await response.json()) as Record<string, any>;\n return {\n data,\n idToken() {\n if (typeof data.id_token !== \"string\") {\n throw new Error(\"OIDC response is missing id_token.\");\n }\n return data.id_token;\n },\n accessToken() {\n if (typeof data.access_token !== \"string\") {\n throw new Error(\"OIDC response is missing access_token.\");\n }\n return data.access_token;\n },\n };\n },\n };\n\n const oauthConfig = {\n scopes,\n nonce: true,\n validateTokens: async (tokens: any, ctx: { nonce?: string }) => {\n const verified = await Fx.run(\n Fx.gen(function* () {\n yield* Fx.guard(\n ctx.nonce === undefined,\n Fx.fail(new Error(\"OIDC nonce is required.\")),\n );\n\n const idToken = tokens.idToken();\n const protectedHeader = decodeProtectedHeader(idToken);\n const tokenAlg = protectedHeader.alg;\n const useSymmetricValidation =\n typeof tokenAlg === \"string\" &&\n (tokenAlg === \"HS256\" ||\n tokenAlg === \"HS384\" ||\n tokenAlg === \"HS512\") &&\n supportedIdTokenSigningAlgs.includes(tokenAlg);\n\n const verificationOptions = {\n audience: expectedAudience,\n requiredClaims: [\"iss\", \"sub\", \"aud\", \"exp\", \"iat\"],\n clockTolerance: config.clockToleranceSeconds ?? 10,\n } as const;\n\n const verification = yield* Fx.from({\n ok: () =>\n useSymmetricValidation\n ? jwtVerify(\n idToken,\n (() => {\n if (typeof config.clientSecret !== \"string\") {\n throw new Error(\n \"OIDC provider uses symmetric ID token signatures but clientSecret is missing.\",\n );\n }\n return new TextEncoder().encode(config.clientSecret);\n })(),\n verificationOptions as any,\n )\n : jwtVerify(idToken, jwks as any, verificationOptions as any),\n err: (error) =>\n error instanceof Error ? error : new Error(String(error)),\n });\n\n const payload = verification.payload as Record<string, unknown>;\n const tokenIssuerRaw =\n typeof payload.iss === \"string\" ? payload.iss : undefined;\n const tokenIssuer =\n typeof tokenIssuerRaw === \"string\"\n ? tokenIssuerRaw.replace(/\\/$/, \"\")\n : undefined;\n\n yield* Fx.guard(\n !tokenIssuer || !expectedIssuers.includes(tokenIssuer),\n Fx.fail(\n new Error(\n `OIDC token issuer mismatch. Received: ${tokenIssuer ?? \"<missing>\"}. Expected one of: ${expectedIssuers.join(\", \")}`,\n ),\n ),\n );\n\n yield* Fx.guard(\n payload.nonce !== ctx.nonce,\n Fx.fail(new Error(\"OIDC nonce mismatch.\")),\n );\n\n yield* Fx.guard(\n Array.isArray(payload.aud) &&\n payload.aud.length > 1 &&\n payload.azp !== String(config.clientId),\n Fx.fail(\n new Error(\"OIDC authorized party does not match client ID.\"),\n ),\n );\n\n return payload;\n }),\n );\n\n verifiedClaims = verified;\n verifiedProfile = normalizeProfile(verified);\n },\n accountLinking: config.accountLinking,\n profile: async (tokens: any): Promise<OAuthProfile> => {\n if (verifiedProfile === null || verifiedClaims === null) {\n const claims = decodeIdToken(tokens.idToken()) as Record<\n string,\n unknown\n >;\n verifiedClaims = claims;\n verifiedProfile = normalizeProfile(claims);\n }\n if (userinfoEndpoint && typeof tokens.accessToken === \"function\") {\n const userInfoProfile = await Fx.run(\n userInfoProfileFx({\n endpoint: userinfoEndpoint,\n accessToken: tokens.accessToken(),\n verifiedClaims,\n verifiedProfile,\n fetchImpl: oidcFetch,\n }),\n );\n if (userInfoProfile !== null) {\n return userInfoProfile;\n }\n }\n return verifiedProfile;\n },\n } as const;\n\n return { provider, oauthConfig };\n}\n\n/** @internal */\nexport function createSyntheticOAuthMaterializedConfig(\n providerId: string,\n options?: {\n accountLinking?: OAuthMaterializedConfig[\"accountLinking\"];\n },\n): OAuthMaterializedConfig {\n return {\n id: providerId,\n type: \"oauth\",\n provider: null,\n scopes: [],\n accountLinking: options?.accountLinking ?? \"verifiedEmail\",\n };\n}\n\n/** @internal */\nexport async function createEnterpriseOidcRuntime(opts: {\n rootUrl: string;\n enterpriseId: string;\n oidc: Record<string, any>;\n}) {\n const providerId = enterpriseOidcProviderId(opts.enterpriseId);\n const urls = getEnterpriseOidcUrls({\n rootUrl: opts.rootUrl,\n enterpriseId: opts.enterpriseId,\n });\n const { provider, oauthConfig } = await createEnterpriseOidcProvider(\n opts.oidc,\n urls.callbackUrl,\n );\n return {\n oidc: opts.oidc,\n providerId,\n provider,\n oauthConfig,\n ...urls,\n };\n}\n"],"mappings":";;;;;;;;AAcA,MAAM,kCAAkB,IAAI,KAGzB;AAEH,eAAe,0BAA0B,QAA6B;CACpE,MAAM,eACJ,OAAO,OAAO,iBAAiB,WAC3B,OAAO,eACP,OAAO,OAAO,WAAW,WACvB,GAAG,OAAO,OAAO,QAAQ,OAAO,GAAG,CAAC,qCACpC;AAER,KAAI,CAAC,aACH,OAAM,IAAI,MAAM,sDAAsD;CAGxE,MAAM,YAAY,0BAA0B,QAAQ,OAAO,OAAO;AAElE,QAAO,MAAM,GAAG,IACd,GAAG,YACD,GAAG,KAAK;EACN,IAAI,YAAY;GACd,MAAM,WAAW,MAAM,UAAU,aAAa;AAC9C,OAAI,CAAC,SAAS,GACZ,OAAM,IAAI,MACR,0CAA0C,SAAS,SACpD;GAEH,MAAM,YAAa,MAAM,SAAS,MAAM;AACxC,OACE,OAAO,UAAU,WAAW,YAC5B,OAAO,UAAU,2BAA2B,YAC5C,OAAO,UAAU,mBAAmB,YACpC,OAAO,UAAU,aAAa,SAE9B,OAAM,IAAI,MACR,sDACD;AAEH,UAAO;;EAET,MAAM,UACJ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC;EAC5D,CAAC,CACH,CAAC,KACA,GAAG,QAAQ,IAAO,EAClB,GAAG,MACD,GAAG,MAAM,QACP,GAAG,MAAM,SAAS,GAAG,MAAM,YAAY,IAAI,CAAC,EAC5C,GAAG,MAAM,OAAO,EAAE,CACnB,CACF,EACD,GAAG,SAAS,UACV,GAAG,KAAK,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,CAAC,CACnE,CACF,CACF;;AAGH,SAAS,0BACP,QACA,kBACA;CACA,MAAM,gBACJ,OAAO,OAAO,iBAAiB,WAC3B,IAAI,IAAI,OAAO,aAAa,CAAC,SAC7B;CACN,MAAM,eACJ,OAAO,OAAO,WAAW,WACrB,IAAI,IAAI,OAAO,OAAO,CAAC,OACvB,OAAO,qBAAqB,WAC1B,IAAI,IAAI,iBAAiB,CAAC,OAC1B;AAER,QAAO,OAAO,OAAqB,SAAuB;EACxD,MAAM,MAAM,IAAI,IAAI,OAAO,UAAU,WAAW,QAAQ,MAAM,UAAU,CAAC;EACzE,MAAM,eACJ,kBAAkB,UAAa,IAAI,WAAW,gBAC1C,IAAI,IAAI,GAAG,gBAAgB,IAAI,WAAW,IAAI,SAAS,GACvD;EACN,MAAM,UAAU,IAAI,QAAQ,MAAM,QAAQ;AAC1C,MAAI,kBAAkB,UAAa,iBAAiB,OAClD,SAAQ,IAAI,QAAQ,aAAa;AAEnC,SAAO,MAAM,MAAM,cAAc;GAAE,GAAG;GAAM;GAAS,CAAC;;;AAI1D,SAAS,YACP,KACA,WACA;CACA,MAAM,WAAW,YAAY,GAAG,IAAI,YAAY;CAChD,IAAI,OAAO,gBAAgB,IAAI,SAAS;AACxC,KAAI,CAAC,MAAM;AACT,SAAO,YACH,mBAAmB,IAAI,IAAI,IAAI,EAAE,GAAG,cAAc,WAAW,CAAC,GAC9D,mBAAmB,IAAI,IAAI,IAAI,CAAC;AACpC,kBAAgB,IAAI,UAAU,KAAK;;AAErC,QAAO;;AAOT,SAAS,kBAAkB,MAMxB;AACD,QAAO,GAAG,KAAK;EACb,IAAI,YAAY;GACd,MAAM,WAAW,OAAO,KAAK,aAAa,OAAO,KAAK,UAAU,EAC9D,SAAS,EAAE,eAAe,UAAU,KAAK,eAAe,EACzD,CAAC;AACF,OAAI,CAAC,SAAS,GACZ,OAAM,IAAI,MAAM,iCAAiC,SAAS,SAAS;AAErE,UAAQ,MAAM,SAAS,MAAM;;EAE/B,MAAM,WAAiC;GAAE,MAAM;GAAa;GAAO;EACpE,CAAC,CAAC,KACD,GAAG,OAAO,aAAa;EACrB,MAAM,kBACJ,OAAO,SAAS,QAAQ,WAAW,SAAS,MAAM;EACpD,MAAM,eACJ,OAAO,KAAK,eAAe,QAAQ,WAC/B,KAAK,eAAe,MACpB;AACN,SAAO,oBAAoB,UACzB,iBAAiB,UACjB,oBAAoB,eAClB,GAAG,KAAK,EAAE,MAAM,oBAAoB,CAAU,GAC9C,GAAG,QAAQ;GACT,IACE,oBACC,OAAO,KAAK,eAAe,QAAQ,WAChC,KAAK,eAAe,MACpB,WACJ,OAAO,YAAY;GACrB,OACE,OAAO,SAAS,UAAU,WACtB,SAAS,QACT,KAAK,gBAAgB;GAC3B,eACE,OAAO,SAAS,mBAAmB,YAC/B,SAAS,iBACT,KAAK,gBAAgB;GAC3B,MACE,OAAO,SAAS,SAAS,WACrB,SAAS,OACT,KAAK,gBAAgB;GAC3B,OACE,OAAO,SAAS,YAAY,WACxB,SAAS,UACT,KAAK,gBAAgB;GAC5B,CAA+C;GACpD,EACF,GAAG,SAAS,YAAY;AACtB,MAAI,QAAQ,SAAS,YACnB,QAAO,GAAG,QAAQ,KAAK;AAEzB,SAAO,GAAG,qBACR,IAAI,MAAM,yDAAyD,CACpE;GACD,CACH;;;AAIH,eAAsB,6BACpB,QACA,aACA;CACA,MAAM,YAAY,MAAM,0BAA0B,OAAO;CACzD,MAAM,iBAAiB,OAAO,OAAO,UAAU,UAAU,OAAO,CAAC,QAC/D,OACA,GACD;CACD,MAAM,mBAAmB,OAAO,UAAU,OAAO,CAAC,QAAQ,OAAO,GAAG;CACpE,MAAM,eAAe,OAAO,iBAAiB;AAC7C,KACE,OAAO,OAAO,WAAW,YACzB,mBAAmB,kBACnB;AACA,MAAI,aACF,OAAM,IAAI,MACR,+CAA+C,eAAe,aAAa,mBAC5E;AAEH,UAAQ,KACN,gGACA;GACE,kBAAkB;GAClB,iBAAiB;GAClB,CACF;;CAEH,MAAM,wBAAwB,UAAU;CACxC,MAAM,gBAAgB,UAAU;CAChC,MAAM,UAAU,OAAO,OAAO,WAAW,UAAU,SAAS;CAC5D,MAAM,8BAA8B,MAAM,QACxC,UAAU,sCACX,GACG,UAAU,sCAAsC,QAC7C,UAAoC,OAAO,UAAU,SACvD,GACD,EAAE;CACN,MAAM,mBACH,UAAU,qBAA4C;CACzD,MAAM,YAAY,0BAChB,QACA,UAAU,OACX;CACD,MAAM,SAAS,MAAM,QAAQ,OAAO,OAAO,GACvC,OAAO,OAAO,QACX,UAAoC,OAAO,UAAU,SACvD,GACD;EAAC;EAAU;EAAW;EAAQ;CAClC,MAAM,mBAAmB,OAAO,YAAY,OAAO,OAAO,SAAS;CACnE,MAAM,uBAAuB,WAAmB;EAC9C,MAAM,aAAa,CAAC,OAAO;AAC3B,MAAI,OAAO,WAAW,WAAW,CAC/B,YAAW,KAAK,UAAU,OAAO,MAAM,EAAkB,GAAG;WACnD,OAAO,WAAW,UAAU,CACrC,YAAW,KAAK,WAAW,OAAO,MAAM,EAAiB,GAAG;AAE9D,SAAO;;CAET,MAAM,kBAAkB,eACpB,CAAC,eAAe,GAChB,MAAM,KACJ,IAAI,IAAI,CACN,GAAG,oBAAoB,eAAe,EACtC,GAAG,oBAAoB,iBAAiB,CACzC,CAAC,CACH;CACL,MAAM,OAAO,YAAY,SAAS,UAAU;CAC5C,IAAI,iBAAiD;CACrD,IAAI,kBACF;CACF,MAAM,oBAAoB,YAAqC;EAC7D,IAAI,OAAO,OAAO,QAAQ,WAAW,OAAO,MAAM,OAAO,YAAY;EACrE,OAAO,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ;EACzD,eACE,OAAO,OAAO,mBAAmB,YAC7B,OAAO,iBACP;EACN,MAAM,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO;EACtD,OAAO,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU;EAC9D;AA6LD,QAAO;EAAE,UA3LQ;GACf,uBACE,OACA,cACA,iBACA;IACA,MAAM,MAAM,IAAI,IAAI,sBAAsB;AAC1C,QAAI,aAAa,IAAI,iBAAiB,OAAO;AAC7C,QAAI,aAAa,IAAI,aAAa,OAAO,OAAO,SAAS,CAAC;AAC1D,QAAI,aAAa,IAAI,gBAAgB,YAAY;AACjD,QAAI,aAAa,IACf,UACC,gBAAgB,SAAS,IAAI,kBAAkB,QAAQ,KAAK,IAAI,CAClE;AACD,QAAI,aAAa,IAAI,SAAS,MAAM;AACpC,QAAI,aAAa,IAAI,yBAAyB,OAAO;AACrD,QAAI,aAAa,IACf,kBACA,yBACE,OAAO,IAAI,aAAa,CAAC,OAAO,aAAa,CAAC,CAC/C,CACF;IACD,MAAM,sBACJ,OAAO,OAAO,wBAAwB,YACtC,OAAO,wBAAwB,OAC1B,OAAO,sBACR,EAAE;AACR,SAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,oBAAoB,CAC5D,KAAI,OAAO,UAAU,SACnB,KAAI,aAAa,IAAI,KAAK,MAAM;AAGpC,WAAO;;GAET,MAAM,0BAA0B,MAAc,cAAuB;IACnE,MAAM,OAAO,IAAI,gBAAgB;KAC/B,YAAY;KACZ;KACA,cAAc;KACd,WAAW,OAAO,OAAO,SAAS;KACnC,CAAC;AACF,QAAI,OAAO,OAAO,iBAAiB,SACjC,MAAK,IAAI,iBAAiB,OAAO,aAAa;AAEhD,QAAI,aACF,MAAK,IAAI,iBAAiB,aAAa;IAEzC,MAAM,WAAW,MAAM,UAAU,eAAe;KAC9C,QAAQ;KACR,SAAS,EAAE,gBAAgB,qCAAqC;KAChE;KACD,CAAC;AACF,QAAI,CAAC,SAAS,GACZ,OAAM,IAAI,MAAM,+BAA+B,SAAS,SAAS;IAEnE,MAAM,OAAQ,MAAM,SAAS,MAAM;AACnC,WAAO;KACL;KACA,UAAU;AACR,UAAI,OAAO,KAAK,aAAa,SAC3B,OAAM,IAAI,MAAM,qCAAqC;AAEvD,aAAO,KAAK;;KAEd,cAAc;AACZ,UAAI,OAAO,KAAK,iBAAiB,SAC/B,OAAM,IAAI,MAAM,yCAAyC;AAE3D,aAAO,KAAK;;KAEf;;GAEJ;EAmHkB,aAjHC;GAClB;GACA,OAAO;GACP,gBAAgB,OAAO,QAAa,QAA4B;IAC9D,MAAM,WAAW,MAAM,GAAG,IACxB,GAAG,IAAI,aAAa;AAClB,YAAO,GAAG,MACR,IAAI,UAAU,QACd,GAAG,qBAAK,IAAI,MAAM,0BAA0B,CAAC,CAC9C;KAED,MAAM,UAAU,OAAO,SAAS;KAEhC,MAAM,WADkB,sBAAsB,QAAQ,CACrB;KACjC,MAAM,yBACJ,OAAO,aAAa,aACnB,aAAa,WACZ,aAAa,WACb,aAAa,YACf,4BAA4B,SAAS,SAAS;KAEhD,MAAM,sBAAsB;MAC1B,UAAU;MACV,gBAAgB;OAAC;OAAO;OAAO;OAAO;OAAO;OAAM;MACnD,gBAAgB,OAAO,yBAAyB;MACjD;KAsBD,MAAM,WApBe,OAAO,GAAG,KAAK;MAClC,UACE,yBACI,UACE,gBACO;AACL,WAAI,OAAO,OAAO,iBAAiB,SACjC,OAAM,IAAI,MACR,gFACD;AAEH,cAAO,IAAI,aAAa,CAAC,OAAO,OAAO,aAAa;UAClD,EACJ,oBACD,GACD,UAAU,SAAS,MAAa,oBAA2B;MACjE,MAAM,UACJ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC;MAC5D,CAAC,EAE2B;KAC7B,MAAM,iBACJ,OAAO,QAAQ,QAAQ,WAAW,QAAQ,MAAM;KAClD,MAAM,cACJ,OAAO,mBAAmB,WACtB,eAAe,QAAQ,OAAO,GAAG,GACjC;AAEN,YAAO,GAAG,MACR,CAAC,eAAe,CAAC,gBAAgB,SAAS,YAAY,EACtD,GAAG,qBACD,IAAI,MACF,yCAAyC,eAAe,YAAY,qBAAqB,gBAAgB,KAAK,KAAK,GACpH,CACF,CACF;AAED,YAAO,GAAG,MACR,QAAQ,UAAU,IAAI,OACtB,GAAG,qBAAK,IAAI,MAAM,uBAAuB,CAAC,CAC3C;AAED,YAAO,GAAG,MACR,MAAM,QAAQ,QAAQ,IAAI,IACxB,QAAQ,IAAI,SAAS,KACrB,QAAQ,QAAQ,OAAO,OAAO,SAAS,EACzC,GAAG,qBACD,IAAI,MAAM,kDAAkD,CAC7D,CACF;AAED,YAAO;MACP,CACH;AAED,qBAAiB;AACjB,sBAAkB,iBAAiB,SAAS;;GAE9C,gBAAgB,OAAO;GACvB,SAAS,OAAO,WAAuC;AACrD,QAAI,oBAAoB,QAAQ,mBAAmB,MAAM;KACvD,MAAM,SAAS,cAAc,OAAO,SAAS,CAAC;AAI9C,sBAAiB;AACjB,uBAAkB,iBAAiB,OAAO;;AAE5C,QAAI,oBAAoB,OAAO,OAAO,gBAAgB,YAAY;KAChE,MAAM,kBAAkB,MAAM,GAAG,IAC/B,kBAAkB;MAChB,UAAU;MACV,aAAa,OAAO,aAAa;MACjC;MACA;MACA,WAAW;MACZ,CAAC,CACH;AACD,SAAI,oBAAoB,KACtB,QAAO;;AAGX,WAAO;;GAEV;EAE+B;;;AAIlC,SAAgB,uCACd,YACA,SAGyB;AACzB,QAAO;EACL,IAAI;EACJ,MAAM;EACN,UAAU;EACV,QAAQ,EAAE;EACV,gBAAgB,SAAS,kBAAkB;EAC5C;;;AAIH,eAAsB,4BAA4B,MAI/C;CACD,MAAM,aAAa,yBAAyB,KAAK,aAAa;CAC9D,MAAM,OAAO,sBAAsB;EACjC,SAAS,KAAK;EACd,cAAc,KAAK;EACpB,CAAC;CACF,MAAM,EAAE,UAAU,gBAAgB,MAAM,6BACtC,KAAK,MACL,KAAK,YACN;AACD,QAAO;EACL,MAAM,KAAK;EACX;EACA;EACA;EACA,GAAG;EACJ"}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { asRecord } from "./shared.js";
|
|
2
|
-
|
|
3
|
-
//#region src/server/enterprise/policy.ts
|
|
4
|
-
/** @internal */
|
|
5
|
-
const DEFAULT_ENTERPRISE_POLICY = {
|
|
6
|
-
version: 1,
|
|
7
|
-
identity: { accountLinking: {
|
|
8
|
-
oidc: "verifiedEmail",
|
|
9
|
-
saml: "verifiedEmail"
|
|
10
|
-
} },
|
|
11
|
-
provisioning: {
|
|
12
|
-
scimReuse: { user: "externalId" },
|
|
13
|
-
jit: {
|
|
14
|
-
mode: "createUserAndMembership",
|
|
15
|
-
defaultRoleIds: []
|
|
16
|
-
},
|
|
17
|
-
deprovision: { mode: "soft" }
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
/** @internal */
|
|
21
|
-
function normalizeEnterprisePolicy(policy) {
|
|
22
|
-
const input = asRecord(policy) ?? {};
|
|
23
|
-
const accountLinking = asRecord((asRecord(input.identity) ?? {}).accountLinking) ?? {};
|
|
24
|
-
const provisioning = asRecord(input.provisioning) ?? {};
|
|
25
|
-
const scimReuse = asRecord(provisioning.scimReuse) ?? {};
|
|
26
|
-
const jit = asRecord(provisioning.jit) ?? {};
|
|
27
|
-
const deprovision = asRecord(provisioning.deprovision) ?? {};
|
|
28
|
-
const extend = asRecord(input.extend) ?? void 0;
|
|
29
|
-
return {
|
|
30
|
-
version: 1,
|
|
31
|
-
identity: { accountLinking: {
|
|
32
|
-
oidc: accountLinking.oidc === "none" ? "none" : DEFAULT_ENTERPRISE_POLICY.identity.accountLinking.oidc,
|
|
33
|
-
saml: accountLinking.saml === "none" ? "none" : DEFAULT_ENTERPRISE_POLICY.identity.accountLinking.saml
|
|
34
|
-
} },
|
|
35
|
-
provisioning: {
|
|
36
|
-
scimReuse: { user: scimReuse.user === "none" ? "none" : DEFAULT_ENTERPRISE_POLICY.provisioning.scimReuse.user },
|
|
37
|
-
jit: {
|
|
38
|
-
mode: jit.mode === "off" || jit.mode === "createUser" || jit.mode === "createUserAndMembership" ? jit.mode : DEFAULT_ENTERPRISE_POLICY.provisioning.jit.mode,
|
|
39
|
-
defaultRoleIds: Array.isArray(jit.defaultRoleIds) ? Array.from(new Set(jit.defaultRoleIds.filter((value) => typeof value === "string" && value.length > 0))) : typeof jit.defaultRole === "string" && jit.defaultRole.length > 0 ? [jit.defaultRole] : DEFAULT_ENTERPRISE_POLICY.provisioning.jit.defaultRoleIds
|
|
40
|
-
},
|
|
41
|
-
deprovision: { mode: deprovision.mode === "hard" ? "hard" : DEFAULT_ENTERPRISE_POLICY.provisioning.deprovision.mode }
|
|
42
|
-
},
|
|
43
|
-
...extend ? { extend } : {}
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
/** @internal */
|
|
47
|
-
function patchEnterprisePolicy(current, patch) {
|
|
48
|
-
const base = normalizeEnterprisePolicy(current);
|
|
49
|
-
return normalizeEnterprisePolicy({
|
|
50
|
-
...base,
|
|
51
|
-
...patch,
|
|
52
|
-
identity: {
|
|
53
|
-
...base.identity,
|
|
54
|
-
...patch.identity,
|
|
55
|
-
accountLinking: {
|
|
56
|
-
...base.identity.accountLinking,
|
|
57
|
-
...patch.identity?.accountLinking
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
provisioning: {
|
|
61
|
-
...base.provisioning,
|
|
62
|
-
...patch.provisioning,
|
|
63
|
-
scimReuse: {
|
|
64
|
-
...base.provisioning.scimReuse,
|
|
65
|
-
...patch.provisioning?.scimReuse
|
|
66
|
-
},
|
|
67
|
-
jit: {
|
|
68
|
-
...base.provisioning.jit,
|
|
69
|
-
...patch.provisioning?.jit
|
|
70
|
-
},
|
|
71
|
-
deprovision: {
|
|
72
|
-
...base.provisioning.deprovision,
|
|
73
|
-
...patch.provisioning?.deprovision
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
extend: patch.extend === void 0 ? base.extend : {
|
|
77
|
-
...base.extend,
|
|
78
|
-
...patch.extend
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
//#endregion
|
|
84
|
-
export { normalizeEnterprisePolicy, patchEnterprisePolicy };
|
|
85
|
-
//# sourceMappingURL=policy.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"policy.js","names":[],"sources":["../../../../src/server/enterprise/policy.ts"],"sourcesContent":["import type { EnterprisePolicy, EnterprisePolicyPatch } from \"../types\";\nimport { asRecord } from \"./shared\";\n\n/** @internal */\nexport const DEFAULT_ENTERPRISE_POLICY: EnterprisePolicy = {\n version: 1,\n identity: {\n accountLinking: {\n oidc: \"verifiedEmail\",\n saml: \"verifiedEmail\",\n },\n },\n provisioning: {\n scimReuse: {\n user: \"externalId\",\n },\n jit: {\n mode: \"createUserAndMembership\",\n defaultRoleIds: [],\n },\n deprovision: {\n mode: \"soft\",\n },\n },\n};\n\n/** @internal */\nexport function normalizeEnterprisePolicy(policy: unknown): EnterprisePolicy {\n const input = asRecord(policy) ?? {};\n const identity = asRecord(input.identity) ?? {};\n const accountLinking = asRecord(identity.accountLinking) ?? {};\n const provisioning = asRecord(input.provisioning) ?? {};\n const scimReuse = asRecord(provisioning.scimReuse) ?? {};\n const jit = asRecord(provisioning.jit) ?? {};\n const deprovision = asRecord(provisioning.deprovision) ?? {};\n const extend = asRecord(input.extend) ?? undefined;\n\n return {\n version: 1,\n identity: {\n accountLinking: {\n oidc:\n accountLinking.oidc === \"none\"\n ? \"none\"\n : DEFAULT_ENTERPRISE_POLICY.identity.accountLinking.oidc,\n saml:\n accountLinking.saml === \"none\"\n ? \"none\"\n : DEFAULT_ENTERPRISE_POLICY.identity.accountLinking.saml,\n },\n },\n provisioning: {\n scimReuse: {\n user:\n scimReuse.user === \"none\"\n ? \"none\"\n : DEFAULT_ENTERPRISE_POLICY.provisioning.scimReuse.user,\n },\n jit: {\n mode:\n jit.mode === \"off\" ||\n jit.mode === \"createUser\" ||\n jit.mode === \"createUserAndMembership\"\n ? jit.mode\n : DEFAULT_ENTERPRISE_POLICY.provisioning.jit.mode,\n defaultRoleIds: Array.isArray(jit.defaultRoleIds)\n ? Array.from(\n new Set(\n jit.defaultRoleIds.filter(\n (value): value is string =>\n typeof value === \"string\" && value.length > 0,\n ),\n ),\n )\n : typeof jit.defaultRole === \"string\" && jit.defaultRole.length > 0\n ? [jit.defaultRole]\n : DEFAULT_ENTERPRISE_POLICY.provisioning.jit.defaultRoleIds,\n },\n deprovision: {\n mode:\n deprovision.mode === \"hard\"\n ? \"hard\"\n : DEFAULT_ENTERPRISE_POLICY.provisioning.deprovision.mode,\n },\n },\n ...(extend ? { extend } : {}),\n };\n}\n\n/** @internal */\nexport function patchEnterprisePolicy(\n current: unknown,\n patch: EnterprisePolicyPatch,\n): EnterprisePolicy {\n const base = normalizeEnterprisePolicy(current);\n return normalizeEnterprisePolicy({\n ...base,\n ...patch,\n identity: {\n ...base.identity,\n ...patch.identity,\n accountLinking: {\n ...base.identity.accountLinking,\n ...patch.identity?.accountLinking,\n },\n },\n provisioning: {\n ...base.provisioning,\n ...patch.provisioning,\n scimReuse: {\n ...base.provisioning.scimReuse,\n ...patch.provisioning?.scimReuse,\n },\n jit: {\n ...base.provisioning.jit,\n ...patch.provisioning?.jit,\n },\n deprovision: {\n ...base.provisioning.deprovision,\n ...patch.provisioning?.deprovision,\n },\n },\n extend:\n patch.extend === undefined\n ? base.extend\n : { ...base.extend, ...patch.extend },\n });\n}\n"],"mappings":";;;;AAIA,MAAa,4BAA8C;CACzD,SAAS;CACT,UAAU,EACR,gBAAgB;EACd,MAAM;EACN,MAAM;EACP,EACF;CACD,cAAc;EACZ,WAAW,EACT,MAAM,cACP;EACD,KAAK;GACH,MAAM;GACN,gBAAgB,EAAE;GACnB;EACD,aAAa,EACX,MAAM,QACP;EACF;CACF;;AAGD,SAAgB,0BAA0B,QAAmC;CAC3E,MAAM,QAAQ,SAAS,OAAO,IAAI,EAAE;CAEpC,MAAM,iBAAiB,UADN,SAAS,MAAM,SAAS,IAAI,EAAE,EACN,eAAe,IAAI,EAAE;CAC9D,MAAM,eAAe,SAAS,MAAM,aAAa,IAAI,EAAE;CACvD,MAAM,YAAY,SAAS,aAAa,UAAU,IAAI,EAAE;CACxD,MAAM,MAAM,SAAS,aAAa,IAAI,IAAI,EAAE;CAC5C,MAAM,cAAc,SAAS,aAAa,YAAY,IAAI,EAAE;CAC5D,MAAM,SAAS,SAAS,MAAM,OAAO,IAAI;AAEzC,QAAO;EACL,SAAS;EACT,UAAU,EACR,gBAAgB;GACd,MACE,eAAe,SAAS,SACpB,SACA,0BAA0B,SAAS,eAAe;GACxD,MACE,eAAe,SAAS,SACpB,SACA,0BAA0B,SAAS,eAAe;GACzD,EACF;EACD,cAAc;GACZ,WAAW,EACT,MACE,UAAU,SAAS,SACf,SACA,0BAA0B,aAAa,UAAU,MACxD;GACD,KAAK;IACH,MACE,IAAI,SAAS,SACb,IAAI,SAAS,gBACb,IAAI,SAAS,4BACT,IAAI,OACJ,0BAA0B,aAAa,IAAI;IACjD,gBAAgB,MAAM,QAAQ,IAAI,eAAe,GAC7C,MAAM,KACJ,IAAI,IACF,IAAI,eAAe,QAChB,UACC,OAAO,UAAU,YAAY,MAAM,SAAS,EAC/C,CACF,CACF,GACD,OAAO,IAAI,gBAAgB,YAAY,IAAI,YAAY,SAAS,IAC9D,CAAC,IAAI,YAAY,GACjB,0BAA0B,aAAa,IAAI;IAClD;GACD,aAAa,EACX,MACE,YAAY,SAAS,SACjB,SACA,0BAA0B,aAAa,YAAY,MAC1D;GACF;EACD,GAAI,SAAS,EAAE,QAAQ,GAAG,EAAE;EAC7B;;;AAIH,SAAgB,sBACd,SACA,OACkB;CAClB,MAAM,OAAO,0BAA0B,QAAQ;AAC/C,QAAO,0BAA0B;EAC/B,GAAG;EACH,GAAG;EACH,UAAU;GACR,GAAG,KAAK;GACR,GAAG,MAAM;GACT,gBAAgB;IACd,GAAG,KAAK,SAAS;IACjB,GAAG,MAAM,UAAU;IACpB;GACF;EACD,cAAc;GACZ,GAAG,KAAK;GACR,GAAG,MAAM;GACT,WAAW;IACT,GAAG,KAAK,aAAa;IACrB,GAAG,MAAM,cAAc;IACxB;GACD,KAAK;IACH,GAAG,KAAK,aAAa;IACrB,GAAG,MAAM,cAAc;IACxB;GACD,aAAa;IACX,GAAG,KAAK,aAAa;IACrB,GAAG,MAAM,cAAc;IACxB;GACF;EACD,QACE,MAAM,WAAW,SACb,KAAK,SACL;GAAE,GAAG,KAAK;GAAQ,GAAG,MAAM;GAAQ;EAC1C,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"saml.js","names":[],"sources":["../../../../src/server/enterprise/saml.ts"],"sourcesContent":["import {\n decodeBase64urlIgnorePadding,\n encodeBase64urlNoPadding,\n} from \"@oslojs/encoding\";\nimport {\n Constants,\n IdentityProvider,\n ServiceProvider,\n setSchemaValidator,\n} from \"@robelest/samlify\";\n\nimport type { SAMLAttributeMapping } from \"../types\";\nimport { getSamlConfig } from \"./config\";\nimport type {\n EnterpriseSamlHttpRequest,\n EnterpriseSamlRelayState,\n EnterpriseSamlSource,\n ParsedSamlMetadata,\n} from \"./shared\";\nimport { asRecord, getEnterpriseSamlUrls } from \"./shared\";\n\n// Samlify requires a schema validator to be registered before parsing any SAML\n// response. We use a permissive validator that always resolves because Convex's\n// edge runtime has no file-system access for XML schema files, and structural\n// correctness is already ensured by the XML parser. This is called directly\n// before each parse operation since Convex can restart the V8 isolate between\n// requests, resetting module-level state.\nconst _samlifyPermissiveValidator = {\n validate: (_xml: string) => Promise.resolve(\"OK\"),\n};\nfunction ensureSamlifyValidator() {\n setSchemaValidator(_samlifyPermissiveValidator);\n}\n\n/** @internal */\nexport function createSamlPostBindingResponse(opts: {\n endpoint: string;\n parameter: \"SAMLRequest\" | \"SAMLResponse\";\n value: string;\n relayState?: string;\n}) {\n const fields = [\n `<input type=\"hidden\" name=\"${opts.parameter}\" value=\"${opts.value.replace(/\"/g, \""\")}\" />`,\n opts.relayState\n ? `<input type=\"hidden\" name=\"RelayState\" value=\"${opts.relayState.replace(/\"/g, \""\")}\" />`\n : \"\",\n ].join(\"\");\n return new Response(\n `<!doctype html><html><body><form method=\"POST\" action=\"${opts.endpoint}\">${fields}</form><script>document.forms[0].submit();</script></body></html>`,\n { status: 200, headers: { \"Content-Type\": \"text/html; charset=utf-8\" } },\n );\n}\n\n/** @internal */\nexport function decodeRelayState(\n value: string | null,\n): Record<string, unknown> {\n if (!value) {\n return {};\n }\n try {\n return JSON.parse(\n new TextDecoder().decode(decodeBase64urlIgnorePadding(value)),\n );\n } catch {\n return {};\n }\n}\n\n/** @internal */\nexport function encodeEnterpriseSamlRelayState(\n value: EnterpriseSamlRelayState,\n) {\n return encodeBase64urlNoPadding(\n new TextEncoder().encode(\n JSON.stringify({\n source: `${value.source.kind}:${value.source.id}`,\n signature: value.signature,\n requestId: value.requestId,\n state: value.state,\n redirectTo: value.redirectTo,\n }),\n ),\n );\n}\n\n/** @internal */\nexport function decodeEnterpriseSamlRelayStateOrThrow(\n value: string | null,\n): EnterpriseSamlRelayState {\n if (!value) {\n throw new Error(\"Missing SAML RelayState.\");\n }\n const decoded = decodeRelayState(value);\n if (\n typeof decoded.source !== \"string\" ||\n typeof decoded.signature !== \"string\" ||\n typeof decoded.requestId !== \"string\" ||\n typeof decoded.state !== \"string\"\n ) {\n throw new Error(\"Invalid SAML RelayState.\");\n }\n const [kind, ...rest] = decoded.source.split(\":\");\n const id = rest.join(\":\");\n if (kind !== \"enterprise\" || id.length === 0) {\n throw new Error(\"Invalid enterprise SAML source.\");\n }\n return {\n source: { kind, id } as EnterpriseSamlSource,\n signature: decoded.signature,\n requestId: decoded.requestId,\n state: decoded.state,\n redirectTo:\n typeof decoded.redirectTo === \"string\" ? decoded.redirectTo : undefined,\n };\n}\n\n/** @internal */\nexport async function readRequestBody(\n request: Request,\n): Promise<Record<string, string>> {\n const contentType = request.headers.get(\"Content-Type\") ?? \"\";\n if (\n contentType.includes(\"application/x-www-form-urlencoded\") ||\n contentType.includes(\"multipart/form-data\")\n ) {\n const form = await request.formData();\n const body: Record<string, string> = {};\n form.forEach((value, key) => {\n body[key] = typeof value === \"string\" ? value : value.name;\n });\n return body;\n }\n return {};\n}\n\n/** @internal */\nexport async function readEnterpriseSamlHttpRequest(\n request: Request,\n): Promise<EnterpriseSamlHttpRequest> {\n const url = new URL(request.url);\n const body = await readRequestBody(request);\n const query = Object.fromEntries(url.searchParams);\n const binding =\n request.method === \"GET\"\n ? \"redirect\"\n : body.SAMLResponse || body.SAMLRequest\n ? \"post\"\n : \"redirect\";\n return {\n url,\n body,\n query,\n binding,\n relayState:\n body.RelayState ?? url.searchParams.get(\"RelayState\") ?? undefined,\n hasSamlRequest: Boolean(\n body.SAMLRequest ?? url.searchParams.get(\"SAMLRequest\"),\n ),\n hasSamlResponse: Boolean(\n body.SAMLResponse ?? url.searchParams.get(\"SAMLResponse\"),\n ),\n };\n}\n\n/** @internal */\nexport function parseSamlIdpMetadata(metadata: string): ParsedSamlMetadata {\n const idp = IdentityProvider({ metadata });\n const entityMeta = idp.entityMeta;\n\n const normalizeService = (value: unknown): string | undefined => {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n };\n\n return {\n issuer: entityMeta.getEntityID(),\n sso: {\n redirect: normalizeService(entityMeta.getSingleSignOnService(\"redirect\")),\n post: normalizeService(entityMeta.getSingleSignOnService(\"post\")),\n },\n slo: {\n redirect: normalizeService(entityMeta.getSingleLogoutService(\"redirect\")),\n post: normalizeService(entityMeta.getSingleLogoutService(\"post\")),\n },\n signingCert: entityMeta.getX509Certificate(\"signing\"),\n encryptionCert: entityMeta.getX509Certificate(\"encrypt\"),\n nameIdFormats: (() => {\n const nameIdFormat = entityMeta.getNameIDFormat();\n return Array.isArray(nameIdFormat) ? nameIdFormat : [];\n })(),\n wantsSignedAuthnRequests: entityMeta.isWantAuthnRequestsSigned(),\n };\n}\n\n/** @internal */\nexport function createServiceProviderMetadata(opts: {\n entityId: string;\n acsUrl: string;\n sloUrl?: string;\n authnRequestsSigned?: boolean;\n signingCert?: string | string[];\n encryptCert?: string | string[];\n privateKey?: string;\n privateKeyPass?: string;\n encPrivateKey?: string;\n encPrivateKeyPass?: string;\n}) {\n const binding = Constants.namespace.binding;\n const sp = ServiceProvider({\n entityID: opts.entityId,\n authnRequestsSigned: opts.authnRequestsSigned ?? false,\n privateKey: opts.privateKey,\n privateKeyPass: opts.privateKeyPass,\n signingCert: opts.signingCert,\n encryptCert: opts.encryptCert,\n encPrivateKey: opts.encPrivateKey,\n encPrivateKeyPass: opts.encPrivateKeyPass,\n assertionConsumerService: [\n {\n Binding: binding.post,\n Location: opts.acsUrl,\n },\n ],\n singleLogoutService: opts.sloUrl\n ? [\n {\n Binding: binding.redirect,\n Location: opts.sloUrl,\n },\n {\n Binding: binding.post,\n Location: opts.sloUrl,\n },\n ]\n : undefined,\n });\n return sp.getMetadata();\n}\n\n/** @internal */\nexport function createEnterpriseSamlMetadataXml(opts: {\n rootUrl: string;\n source: EnterpriseSamlSource;\n config: unknown;\n}) {\n return createServiceProviderMetadata(\n getSamlServiceProviderOptions({\n rootUrl: opts.rootUrl,\n source: opts.source,\n config: opts.config,\n }),\n );\n}\n\n/** @internal */\nexport function getSamlServiceProviderOptions(opts: {\n rootUrl: string;\n source: EnterpriseSamlSource;\n config: unknown;\n overrides?: {\n entityId?: string;\n acsUrl?: string;\n sloUrl?: string;\n };\n relayState?: string;\n}) {\n const saml = getSamlConfig(opts.config);\n const sp = asRecord(saml.sp) ?? {};\n const urls = getEnterpriseSamlUrls({\n rootUrl: opts.rootUrl,\n source: opts.source,\n });\n return {\n entityId: opts.overrides?.entityId ?? sp.entityId ?? urls.metadataUrl,\n acsUrl: opts.overrides?.acsUrl ?? sp.acsUrl ?? urls.acsUrl,\n sloUrl: opts.overrides?.sloUrl ?? sp.sloUrl ?? urls.sloUrl,\n relayState: opts.relayState,\n authnRequestsSigned: saml.signAuthnRequests,\n signingCert: sp.signingCert,\n encryptCert: sp.encryptCert,\n privateKey: sp.privateKey,\n privateKeyPass: sp.privateKeyPass,\n encPrivateKey: sp.encPrivateKey,\n encPrivateKeyPass: sp.encPrivateKeyPass,\n };\n}\n\n/** @internal */\nexport function createSamlServiceProvider(opts: {\n entityId: string;\n acsUrl: string;\n sloUrl?: string;\n relayState?: string;\n authnRequestsSigned?: boolean;\n signingCert?: string | string[];\n encryptCert?: string | string[];\n privateKey?: string;\n privateKeyPass?: string;\n encPrivateKey?: string;\n encPrivateKeyPass?: string;\n}) {\n const binding = Constants.namespace.binding;\n return ServiceProvider({\n entityID: opts.entityId,\n relayState: opts.relayState ?? \"\",\n authnRequestsSigned: opts.authnRequestsSigned ?? false,\n privateKey: opts.privateKey,\n privateKeyPass: opts.privateKeyPass,\n signingCert: opts.signingCert,\n encryptCert: opts.encryptCert,\n encPrivateKey: opts.encPrivateKey,\n encPrivateKeyPass: opts.encPrivateKeyPass,\n assertionConsumerService: [\n {\n Binding: binding.post,\n Location: opts.acsUrl,\n },\n ],\n singleLogoutService: opts.sloUrl\n ? [\n { Binding: binding.redirect, Location: opts.sloUrl },\n { Binding: binding.post, Location: opts.sloUrl },\n ]\n : undefined,\n });\n}\n\n/** @internal */\nexport function createEnterpriseSamlRuntime(opts: {\n rootUrl: string;\n source: EnterpriseSamlSource;\n config: unknown;\n relayState?: string;\n overrides?: {\n entityId?: string;\n acsUrl?: string;\n sloUrl?: string;\n };\n}) {\n const saml = getSamlConfig(opts.config);\n const spOptions = getSamlServiceProviderOptions({\n rootUrl: opts.rootUrl,\n source: opts.source,\n config: opts.config,\n relayState: opts.relayState,\n overrides: opts.overrides,\n });\n if (typeof saml.idp?.metadataXml !== \"string\") {\n throw new Error(\"SAML IdP metadata is missing.\");\n }\n return {\n saml,\n sp: createSamlServiceProvider(spOptions),\n idp: IdentityProvider({ metadata: saml.idp.metadataXml }),\n urls: getEnterpriseSamlUrls({ rootUrl: opts.rootUrl, source: opts.source }),\n };\n}\n\n/** @internal */\nexport function createEnterpriseSamlSignInRequest(opts: {\n rootUrl: string;\n source: EnterpriseSamlSource;\n config: unknown;\n state: string;\n signature: string;\n redirectTo?: string;\n}) {\n const runtime = createEnterpriseSamlRuntime({\n rootUrl: opts.rootUrl,\n source: opts.source,\n config: opts.config,\n });\n const binding = runtime.saml.idp.sso?.redirect ? \"redirect\" : \"post\";\n const loginRequest = runtime.sp.createLoginRequest(\n runtime.idp,\n binding as any,\n ) as any;\n const relayState = encodeEnterpriseSamlRelayState({\n source: opts.source,\n signature: opts.signature,\n requestId: loginRequest.id,\n state: opts.state,\n redirectTo: opts.redirectTo,\n });\n return {\n requestId: loginRequest.id as string,\n binding,\n relayState,\n redirectUrl:\n binding === \"redirect\"\n ? (() => {\n const redirectUrl = new URL(loginRequest.context);\n redirectUrl.searchParams.set(\"RelayState\", relayState);\n return redirectUrl.toString();\n })()\n : undefined,\n post:\n binding === \"post\"\n ? {\n endpoint: loginRequest.entityEndpoint as string,\n value: loginRequest.context as string,\n }\n : undefined,\n };\n}\n\n/** @internal */\nexport async function parseEnterpriseSamlLoginResponse(opts: {\n request: Request;\n rootUrl: string;\n source: EnterpriseSamlSource;\n config: unknown;\n}) {\n ensureSamlifyValidator();\n const httpRequest = await readEnterpriseSamlHttpRequest(opts.request);\n const runtime = createEnterpriseSamlRuntime({\n rootUrl: opts.rootUrl,\n source: opts.source,\n config: opts.config,\n });\n const parsed = (await runtime.sp.parseLoginResponse(\n runtime.idp as any,\n httpRequest.binding as any,\n {\n query: httpRequest.query,\n body: httpRequest.body,\n },\n )) as any;\n // Check for weak SAML algorithms and warn.\n warnWeakSamlAlgorithms(parsed);\n\n return {\n ...httpRequest,\n runtime,\n parsed,\n relayState: decodeEnterpriseSamlRelayStateOrThrow(\n httpRequest.relayState ?? null,\n ),\n };\n}\n\nconst WEAK_SAML_ALGORITHMS = new Set([\n // Signature algorithms\n \"http://www.w3.org/2000/09/xmldsig#rsa-sha1\",\n \"http://www.w3.org/2000/09/xmldsig#dsa-sha1\",\n // Digest algorithms\n \"http://www.w3.org/2000/09/xmldsig#sha1\",\n // Key encryption\n \"http://www.w3.org/2001/04/xmlenc#rsa-1_5\",\n // Data encryption\n \"http://www.w3.org/2001/04/xmlenc#tripledes-cbc\",\n]);\n\n/**\n * Warn when the SAML response uses weak cryptographic algorithms\n * such as SHA-1, RSA 1.5, or 3DES.\n */\nfunction warnWeakSamlAlgorithms(parsed: any) {\n try {\n const sigAlg =\n parsed?.extract?.signature?.signatureAlgorithm ??\n parsed?.extract?.response?.signatureAlgorithm;\n const digestAlg = parsed?.extract?.signature?.digestAlgorithm;\n\n if (sigAlg && WEAK_SAML_ALGORITHMS.has(sigAlg)) {\n console.warn(\n `[convex-auth] SAML response uses weak signature algorithm: ${sigAlg}. ` +\n `Consider upgrading your IdP to use RSA-SHA256 or stronger.`,\n );\n }\n if (digestAlg && WEAK_SAML_ALGORITHMS.has(digestAlg)) {\n console.warn(\n `[convex-auth] SAML response uses weak digest algorithm: ${digestAlg}. ` +\n `Consider upgrading your IdP to use SHA-256 or stronger.`,\n );\n }\n } catch {\n // Non-critical — don't break auth flow for algorithm check failures\n }\n}\n\n/** @internal */\nexport function validateEnterpriseSamlLoginRelayState(opts: {\n relayState: EnterpriseSamlRelayState;\n source: EnterpriseSamlSource;\n inResponseTo?: string;\n}) {\n if (\n opts.relayState.source.kind !== opts.source.kind ||\n opts.relayState.source.id !== opts.source.id ||\n opts.relayState.requestId !== opts.inResponseTo\n ) {\n throw new Error(\"SAML RelayState did not match the pending login request.\");\n }\n}\n\n/** @internal */\nexport async function parseEnterpriseSamlLogoutMessage(opts: {\n request: Request;\n rootUrl: string;\n source: EnterpriseSamlSource;\n config: unknown;\n}) {\n ensureSamlifyValidator();\n const httpRequest = await readEnterpriseSamlHttpRequest(opts.request);\n const runtime = createEnterpriseSamlRuntime({\n rootUrl: opts.rootUrl,\n source: opts.source,\n config: opts.config,\n relayState: httpRequest.relayState,\n });\n const parsedRequest = httpRequest.hasSamlRequest\n ? ((await runtime.sp.parseLogoutRequest(\n runtime.idp as any,\n httpRequest.binding as any,\n {\n query: httpRequest.query,\n body: httpRequest.body,\n },\n )) as any)\n : undefined;\n return {\n ...httpRequest,\n runtime,\n parsedRequest,\n };\n}\n\n/** @internal */\nexport function profileFromSamlExtract(\n extract: any,\n mapping?: SAMLAttributeMapping,\n) {\n const attributes =\n typeof extract?.attributes === \"object\" && extract.attributes !== null\n ? (extract.attributes as Record<string, unknown>)\n : {};\n const resolveFirst = (...keys: Array<string | undefined>) => {\n for (const key of keys) {\n if (!key) {\n continue;\n }\n const attribute = attributes[key];\n const value = Array.isArray(attribute) ? attribute[0] : attribute;\n if (value !== undefined) {\n return value;\n }\n }\n return undefined;\n };\n const fieldResolvers = {\n email: () => resolveFirst(mapping?.email),\n name: () =>\n resolveFirst(mapping?.name) ??\n ([resolveFirst(mapping?.firstName), resolveFirst(mapping?.lastName)]\n .filter(Boolean)\n .join(\" \") ||\n undefined),\n subject: () =>\n resolveFirst(mapping?.subject) ?? (extract?.nameID as string | undefined),\n } as const;\n const subject = fieldResolvers.subject() as string | undefined;\n if (subject === undefined) {\n throw new Error(\n \"SAML profile is missing a subject. Configure `attributeMapping.subject` or ensure the assertion includes a NameID.\",\n );\n }\n const email = fieldResolvers.email() as string | undefined;\n const name = fieldResolvers.name() as string | undefined;\n return {\n id: subject,\n email,\n emailVerified: typeof email === \"string\" ? true : undefined,\n name,\n samlAttributes: attributes,\n samlSessionIndex: extract?.sessionIndex?.SessionIndex as string | undefined,\n };\n}\n"],"mappings":"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"}
|