@effect-auth/core 0.1.0-alpha.15 → 0.1.0-alpha.18
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/LICENSE +21 -0
- package/README.md +332 -131
- package/dist/AbuseProtection.d.ts +100 -0
- package/dist/AbuseProtection.d.ts.map +1 -0
- package/dist/AbuseProtection.js +71 -0
- package/dist/AbuseProtection.js.map +1 -0
- package/dist/AccessGrant.d.ts +344 -0
- package/dist/AccessGrant.d.ts.map +1 -0
- package/dist/AccessGrant.js +687 -0
- package/dist/AccessGrant.js.map +1 -0
- package/dist/ApiKey.d.ts +2 -14
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +36 -27
- package/dist/ApiKey.js.map +1 -1
- package/dist/Assurance.d.ts +415 -0
- package/dist/Assurance.d.ts.map +1 -0
- package/dist/Assurance.js +764 -0
- package/dist/Assurance.js.map +1 -0
- package/dist/AtomicPlanExecutor.d.ts +28 -0
- package/dist/AtomicPlanExecutor.d.ts.map +1 -0
- package/dist/AtomicPlanExecutor.js +5 -0
- package/dist/AtomicPlanExecutor.js.map +1 -0
- package/dist/AuditLog.d.ts +2314 -52
- package/dist/AuditLog.d.ts.map +1 -1
- package/dist/AuditLog.js +511 -33
- package/dist/AuditLog.js.map +1 -1
- package/dist/AuthConfig.d.ts.map +1 -1
- package/dist/AuthConfig.js.map +1 -1
- package/dist/AuthFlow.d.ts +326 -220
- package/dist/AuthFlow.d.ts.map +1 -1
- package/dist/AuthFlow.js +611 -263
- package/dist/AuthFlow.js.map +1 -1
- package/dist/AuthKernel.d.ts +1 -1
- package/dist/AuthRateLimit.d.ts +96 -0
- package/dist/AuthRateLimit.d.ts.map +1 -0
- package/dist/AuthRateLimit.js +212 -0
- package/dist/AuthRateLimit.js.map +1 -0
- package/dist/Challenge.d.ts +0 -3
- package/dist/Challenge.d.ts.map +1 -1
- package/dist/Challenge.js +1 -4
- package/dist/Challenge.js.map +1 -1
- package/dist/Client.d.ts +205 -10
- package/dist/Client.d.ts.map +1 -1
- package/dist/Client.js +397 -16
- package/dist/Client.js.map +1 -1
- package/dist/CloudflareTurnstile.d.ts +28 -0
- package/dist/CloudflareTurnstile.d.ts.map +1 -0
- package/dist/CloudflareTurnstile.js +205 -0
- package/dist/CloudflareTurnstile.js.map +1 -0
- package/dist/Crypto.d.ts +0 -3
- package/dist/Crypto.d.ts.map +1 -1
- package/dist/Crypto.js +5 -7
- package/dist/Crypto.js.map +1 -1
- package/dist/DelegatedAccessStorageMigrations.d.ts +7 -0
- package/dist/DelegatedAccessStorageMigrations.d.ts.map +1 -0
- package/dist/DelegatedAccessStorageMigrations.js +159 -0
- package/dist/DelegatedAccessStorageMigrations.js.map +1 -0
- package/dist/DisposableEmailDomains.d.ts +19 -0
- package/dist/DisposableEmailDomains.d.ts.map +1 -0
- package/dist/DisposableEmailDomains.js +85 -0
- package/dist/DisposableEmailDomains.js.map +1 -0
- package/dist/DomainVerification.d.ts +0 -9
- package/dist/DomainVerification.d.ts.map +1 -1
- package/dist/DomainVerification.js +36 -22
- package/dist/DomainVerification.js.map +1 -1
- package/dist/DrizzleBunSqliteStorage.d.ts +18 -0
- package/dist/DrizzleBunSqliteStorage.d.ts.map +1 -0
- package/dist/DrizzleBunSqliteStorage.js +11 -0
- package/dist/DrizzleBunSqliteStorage.js.map +1 -0
- package/dist/DrizzleD1SqliteStorage.d.ts +28 -0
- package/dist/DrizzleD1SqliteStorage.d.ts.map +1 -0
- package/dist/DrizzleD1SqliteStorage.js +10 -0
- package/dist/DrizzleD1SqliteStorage.js.map +1 -0
- package/dist/DrizzleDurableObjectSqliteStorage.d.ts +19 -0
- package/dist/DrizzleDurableObjectSqliteStorage.d.ts.map +1 -0
- package/dist/DrizzleDurableObjectSqliteStorage.js +14 -0
- package/dist/DrizzleDurableObjectSqliteStorage.js.map +1 -0
- package/dist/DrizzleEffectSqliteStorage.d.ts +31 -0
- package/dist/DrizzleEffectSqliteStorage.d.ts.map +1 -0
- package/dist/DrizzleEffectSqliteStorage.js +108 -0
- package/dist/DrizzleEffectSqliteStorage.js.map +1 -0
- package/dist/DrizzleNodeSqliteStorage.d.ts +18 -0
- package/dist/DrizzleNodeSqliteStorage.d.ts.map +1 -0
- package/dist/DrizzleNodeSqliteStorage.js +11 -0
- package/dist/DrizzleNodeSqliteStorage.js.map +1 -0
- package/dist/DrizzleWasmSqliteStorage.d.ts +23 -0
- package/dist/DrizzleWasmSqliteStorage.d.ts.map +1 -0
- package/dist/DrizzleWasmSqliteStorage.js +15 -0
- package/dist/DrizzleWasmSqliteStorage.js.map +1 -0
- package/dist/EffectQbPostgresDelegatedAccessStorage.d.ts +34 -0
- package/dist/EffectQbPostgresDelegatedAccessStorage.d.ts.map +1 -0
- package/dist/EffectQbPostgresDelegatedAccessStorage.js +499 -0
- package/dist/EffectQbPostgresDelegatedAccessStorage.js.map +1 -0
- package/dist/EffectQbPostgresStorage.d.ts +171 -0
- package/dist/EffectQbPostgresStorage.d.ts.map +1 -0
- package/dist/EffectQbPostgresStorage.js +4280 -0
- package/dist/EffectQbPostgresStorage.js.map +1 -0
- package/dist/EffectQbSqliteDelegatedAccessStorage.d.ts +112 -0
- package/dist/EffectQbSqliteDelegatedAccessStorage.d.ts.map +1 -0
- package/dist/EffectQbSqliteDelegatedAccessStorage.js +602 -0
- package/dist/EffectQbSqliteDelegatedAccessStorage.js.map +1 -0
- package/dist/EffectQbSqliteStorage.d.ts +184 -27
- package/dist/EffectQbSqliteStorage.d.ts.map +1 -1
- package/dist/EffectQbSqliteStorage.js +1729 -135
- package/dist/EffectQbSqliteStorage.js.map +1 -1
- package/dist/EmailAuth.d.ts +65 -0
- package/dist/EmailAuth.d.ts.map +1 -0
- package/dist/EmailAuth.js +171 -0
- package/dist/EmailAuth.js.map +1 -0
- package/dist/EmailIdentityAuth.d.ts +30 -0
- package/dist/EmailIdentityAuth.d.ts.map +1 -0
- package/dist/EmailIdentityAuth.js +142 -0
- package/dist/EmailIdentityAuth.js.map +1 -0
- package/dist/EmailOtp.d.ts +10 -11
- package/dist/EmailOtp.d.ts.map +1 -1
- package/dist/EmailOtp.js +44 -81
- package/dist/EmailOtp.js.map +1 -1
- package/dist/EmailRisk.d.ts +48 -0
- package/dist/EmailRisk.d.ts.map +1 -0
- package/dist/EmailRisk.js +33 -0
- package/dist/EmailRisk.js.map +1 -0
- package/dist/EmailVerification.d.ts +10 -16
- package/dist/EmailVerification.d.ts.map +1 -1
- package/dist/EmailVerification.js +85 -42
- package/dist/EmailVerification.js.map +1 -1
- package/dist/Guard.d.ts +11 -0
- package/dist/Guard.d.ts.map +1 -0
- package/dist/Guard.js +11 -0
- package/dist/Guard.js.map +1 -0
- package/dist/HibpPwnedPasswords.d.ts +56 -0
- package/dist/HibpPwnedPasswords.d.ts.map +1 -0
- package/dist/HibpPwnedPasswords.js +232 -0
- package/dist/HibpPwnedPasswords.js.map +1 -0
- package/dist/HttpApi/AdminPermissionDefinition.d.ts +4 -0
- package/dist/HttpApi/AdminPermissionDefinition.d.ts.map +1 -0
- package/dist/HttpApi/AdminPermissionDefinition.js +4 -0
- package/dist/HttpApi/AdminPermissionDefinition.js.map +1 -0
- package/dist/HttpApi/AdminSecurityTimeline.d.ts +4 -0
- package/dist/HttpApi/AdminSecurityTimeline.d.ts.map +1 -0
- package/dist/HttpApi/AdminSecurityTimeline.js +4 -0
- package/dist/HttpApi/AdminSecurityTimeline.js.map +1 -0
- package/dist/HttpApi/AdminSession.d.ts +4 -0
- package/dist/HttpApi/AdminSession.d.ts.map +1 -0
- package/dist/HttpApi/AdminSession.js +4 -0
- package/dist/HttpApi/AdminSession.js.map +1 -0
- package/dist/HttpApi/AdminTrustedDevice.d.ts +4 -0
- package/dist/HttpApi/AdminTrustedDevice.d.ts.map +1 -0
- package/dist/HttpApi/AdminTrustedDevice.js +4 -0
- package/dist/HttpApi/AdminTrustedDevice.js.map +1 -0
- package/dist/HttpApi/Api.d.ts +1172 -1172
- package/dist/HttpApi/Api.d.ts.map +1 -1
- package/dist/HttpApi/Api.js +2160 -896
- package/dist/HttpApi/Api.js.map +1 -1
- package/dist/HttpApi/ApiKey.d.ts +4 -0
- package/dist/HttpApi/ApiKey.d.ts.map +1 -0
- package/dist/HttpApi/ApiKey.js +4 -0
- package/dist/HttpApi/ApiKey.js.map +1 -0
- package/dist/HttpApi/Audit.d.ts +6 -0
- package/dist/HttpApi/Audit.d.ts.map +1 -0
- package/dist/HttpApi/Audit.js +10 -0
- package/dist/HttpApi/Audit.js.map +1 -0
- package/dist/HttpApi/ClientApi.d.ts +917 -0
- package/dist/HttpApi/ClientApi.d.ts.map +1 -0
- package/dist/HttpApi/ClientApi.js +101 -0
- package/dist/HttpApi/ClientApi.js.map +1 -0
- package/dist/HttpApi/EmailAuth.d.ts +6 -0
- package/dist/HttpApi/EmailAuth.d.ts.map +1 -0
- package/dist/HttpApi/EmailAuth.js +6 -0
- package/dist/HttpApi/EmailAuth.js.map +1 -0
- package/dist/HttpApi/EmailGuards.d.ts +115 -0
- package/dist/HttpApi/EmailGuards.d.ts.map +1 -0
- package/dist/HttpApi/EmailGuards.js +191 -0
- package/dist/HttpApi/EmailGuards.js.map +1 -0
- package/dist/HttpApi/EmailOtp.d.ts +6 -0
- package/dist/HttpApi/EmailOtp.d.ts.map +1 -0
- package/dist/HttpApi/EmailOtp.js +6 -0
- package/dist/HttpApi/EmailOtp.js.map +1 -0
- package/dist/HttpApi/EmailVerification.d.ts +6 -0
- package/dist/HttpApi/EmailVerification.d.ts.map +1 -0
- package/dist/HttpApi/EmailVerification.js +6 -0
- package/dist/HttpApi/EmailVerification.js.map +1 -0
- package/dist/HttpApi/Endpoints.d.ts +629 -301
- package/dist/HttpApi/Endpoints.d.ts.map +1 -1
- package/dist/HttpApi/Endpoints.js +178 -120
- package/dist/HttpApi/Endpoints.js.map +1 -1
- package/dist/HttpApi/Errors.d.ts +26 -7
- package/dist/HttpApi/Errors.d.ts.map +1 -1
- package/dist/HttpApi/Errors.js +26 -4
- package/dist/HttpApi/Errors.js.map +1 -1
- package/dist/HttpApi/Identity.d.ts +6 -0
- package/dist/HttpApi/Identity.d.ts.map +1 -0
- package/dist/HttpApi/Identity.js +6 -0
- package/dist/HttpApi/Identity.js.map +1 -0
- package/dist/HttpApi/IdentityGuards.d.ts +31 -0
- package/dist/HttpApi/IdentityGuards.d.ts.map +1 -0
- package/dist/HttpApi/IdentityGuards.js +33 -0
- package/dist/HttpApi/IdentityGuards.js.map +1 -0
- package/dist/HttpApi/Jwt.d.ts +4 -0
- package/dist/HttpApi/Jwt.d.ts.map +1 -0
- package/dist/HttpApi/Jwt.js +4 -0
- package/dist/HttpApi/Jwt.js.map +1 -0
- package/dist/HttpApi/JwtDiscovery.d.ts +4 -0
- package/dist/HttpApi/JwtDiscovery.d.ts.map +1 -0
- package/dist/HttpApi/JwtDiscovery.js +4 -0
- package/dist/HttpApi/JwtDiscovery.js.map +1 -0
- package/dist/HttpApi/LoginApproval.d.ts +5 -0
- package/dist/HttpApi/LoginApproval.d.ts.map +1 -0
- package/dist/HttpApi/LoginApproval.js +5 -0
- package/dist/HttpApi/LoginApproval.js.map +1 -0
- package/dist/HttpApi/LoginNotification.d.ts +5 -0
- package/dist/HttpApi/LoginNotification.d.ts.map +1 -0
- package/dist/HttpApi/LoginNotification.js +5 -0
- package/dist/HttpApi/LoginNotification.js.map +1 -0
- package/dist/HttpApi/MagicLink.d.ts +6 -0
- package/dist/HttpApi/MagicLink.d.ts.map +1 -0
- package/dist/HttpApi/MagicLink.js +6 -0
- package/dist/HttpApi/MagicLink.js.map +1 -0
- package/dist/HttpApi/Mfa.d.ts +5 -0
- package/dist/HttpApi/Mfa.d.ts.map +1 -0
- package/dist/HttpApi/Mfa.js +5 -0
- package/dist/HttpApi/Mfa.js.map +1 -0
- package/dist/HttpApi/Middleware.d.ts +14 -0
- package/dist/HttpApi/Middleware.d.ts.map +1 -0
- package/dist/HttpApi/Middleware.js +5 -0
- package/dist/HttpApi/Middleware.js.map +1 -0
- package/dist/HttpApi/OAuth.d.ts +4 -0
- package/dist/HttpApi/OAuth.d.ts.map +1 -0
- package/dist/HttpApi/OAuth.js +4 -0
- package/dist/HttpApi/OAuth.js.map +1 -0
- package/dist/HttpApi/OAuthProviderAuthorization.d.ts +4 -0
- package/dist/HttpApi/OAuthProviderAuthorization.d.ts.map +1 -0
- package/dist/HttpApi/OAuthProviderAuthorization.js +4 -0
- package/dist/HttpApi/OAuthProviderAuthorization.js.map +1 -0
- package/dist/HttpApi/OAuthToken.d.ts +4 -0
- package/dist/HttpApi/OAuthToken.d.ts.map +1 -0
- package/dist/HttpApi/OAuthToken.js +4 -0
- package/dist/HttpApi/OAuthToken.js.map +1 -0
- package/dist/HttpApi/OidcDiscovery.d.ts +4 -0
- package/dist/HttpApi/OidcDiscovery.d.ts.map +1 -0
- package/dist/HttpApi/OidcDiscovery.js +4 -0
- package/dist/HttpApi/OidcDiscovery.js.map +1 -0
- package/dist/HttpApi/Operations/AdminPermissionDefinition.d.ts +28 -0
- package/dist/HttpApi/Operations/AdminPermissionDefinition.d.ts.map +1 -0
- package/dist/HttpApi/Operations/AdminPermissionDefinition.js +5 -0
- package/dist/HttpApi/Operations/AdminPermissionDefinition.js.map +1 -0
- package/dist/HttpApi/Operations/AdminSession.d.ts +16 -0
- package/dist/HttpApi/Operations/AdminSession.d.ts.map +1 -0
- package/dist/HttpApi/Operations/AdminSession.js +5 -0
- package/dist/HttpApi/Operations/AdminSession.js.map +1 -0
- package/dist/HttpApi/Operations/ApiKey.d.ts +16 -0
- package/dist/HttpApi/Operations/ApiKey.d.ts.map +1 -0
- package/dist/HttpApi/Operations/ApiKey.js +5 -0
- package/dist/HttpApi/Operations/ApiKey.js.map +1 -0
- package/dist/HttpApi/Operations/Discovery.d.ts +19 -0
- package/dist/HttpApi/Operations/Discovery.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Discovery.js +7 -0
- package/dist/HttpApi/Operations/Discovery.js.map +1 -0
- package/dist/HttpApi/Operations/EmailAuth.d.ts +12 -0
- package/dist/HttpApi/Operations/EmailAuth.d.ts.map +1 -0
- package/dist/HttpApi/Operations/EmailAuth.js +5 -0
- package/dist/HttpApi/Operations/EmailAuth.js.map +1 -0
- package/dist/HttpApi/Operations/EmailOtp.d.ts +14 -0
- package/dist/HttpApi/Operations/EmailOtp.d.ts.map +1 -0
- package/dist/HttpApi/Operations/EmailOtp.js +5 -0
- package/dist/HttpApi/Operations/EmailOtp.js.map +1 -0
- package/dist/HttpApi/Operations/EmailVerification.d.ts +14 -0
- package/dist/HttpApi/Operations/EmailVerification.d.ts.map +1 -0
- package/dist/HttpApi/Operations/EmailVerification.js +5 -0
- package/dist/HttpApi/Operations/EmailVerification.js.map +1 -0
- package/dist/HttpApi/Operations/HttpOperation.d.ts +4 -0
- package/dist/HttpApi/Operations/HttpOperation.d.ts.map +1 -0
- package/dist/HttpApi/Operations/HttpOperation.js +2 -0
- package/dist/HttpApi/Operations/HttpOperation.js.map +1 -0
- package/dist/HttpApi/Operations/Identity.d.ts +22 -0
- package/dist/HttpApi/Operations/Identity.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Identity.js +5 -0
- package/dist/HttpApi/Operations/Identity.js.map +1 -0
- package/dist/HttpApi/Operations/Jwt.d.ts +14 -0
- package/dist/HttpApi/Operations/Jwt.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Jwt.js +5 -0
- package/dist/HttpApi/Operations/Jwt.js.map +1 -0
- package/dist/HttpApi/Operations/LoginApproval.d.ts +16 -0
- package/dist/HttpApi/Operations/LoginApproval.d.ts.map +1 -0
- package/dist/HttpApi/Operations/LoginApproval.js +5 -0
- package/dist/HttpApi/Operations/LoginApproval.js.map +1 -0
- package/dist/HttpApi/Operations/MagicLink.d.ts +14 -0
- package/dist/HttpApi/Operations/MagicLink.d.ts.map +1 -0
- package/dist/HttpApi/Operations/MagicLink.js +5 -0
- package/dist/HttpApi/Operations/MagicLink.js.map +1 -0
- package/dist/HttpApi/Operations/Mfa.d.ts +24 -0
- package/dist/HttpApi/Operations/Mfa.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Mfa.js +5 -0
- package/dist/HttpApi/Operations/Mfa.js.map +1 -0
- package/dist/HttpApi/Operations/OAuth.d.ts +20 -0
- package/dist/HttpApi/Operations/OAuth.d.ts.map +1 -0
- package/dist/HttpApi/Operations/OAuth.js +5 -0
- package/dist/HttpApi/Operations/OAuth.js.map +1 -0
- package/dist/HttpApi/Operations/OAuthProviderAuthorization.d.ts +12 -0
- package/dist/HttpApi/Operations/OAuthProviderAuthorization.d.ts.map +1 -0
- package/dist/HttpApi/Operations/OAuthProviderAuthorization.js +5 -0
- package/dist/HttpApi/Operations/OAuthProviderAuthorization.js.map +1 -0
- package/dist/HttpApi/Operations/OAuthToken.d.ts +16 -0
- package/dist/HttpApi/Operations/OAuthToken.d.ts.map +1 -0
- package/dist/HttpApi/Operations/OAuthToken.js +5 -0
- package/dist/HttpApi/Operations/OAuthToken.js.map +1 -0
- package/dist/HttpApi/Operations/Passkey.d.ts +22 -0
- package/dist/HttpApi/Operations/Passkey.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Passkey.js +5 -0
- package/dist/HttpApi/Operations/Passkey.js.map +1 -0
- package/dist/HttpApi/Operations/Password.d.ts +22 -0
- package/dist/HttpApi/Operations/Password.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Password.js +5 -0
- package/dist/HttpApi/Operations/Password.js.map +1 -0
- package/dist/HttpApi/Operations/RecoveryCodes.d.ts +20 -0
- package/dist/HttpApi/Operations/RecoveryCodes.d.ts.map +1 -0
- package/dist/HttpApi/Operations/RecoveryCodes.js +5 -0
- package/dist/HttpApi/Operations/RecoveryCodes.js.map +1 -0
- package/dist/HttpApi/Operations/RefreshToken.d.ts +12 -0
- package/dist/HttpApi/Operations/RefreshToken.d.ts.map +1 -0
- package/dist/HttpApi/Operations/RefreshToken.js +5 -0
- package/dist/HttpApi/Operations/RefreshToken.js.map +1 -0
- package/dist/HttpApi/Operations/Security.d.ts +12 -0
- package/dist/HttpApi/Operations/Security.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Security.js +5 -0
- package/dist/HttpApi/Operations/Security.js.map +1 -0
- package/dist/HttpApi/Operations/SecurityTimeline.d.ts +19 -0
- package/dist/HttpApi/Operations/SecurityTimeline.d.ts.map +1 -0
- package/dist/HttpApi/Operations/SecurityTimeline.js +7 -0
- package/dist/HttpApi/Operations/SecurityTimeline.js.map +1 -0
- package/dist/HttpApi/Operations/Session.d.ts +22 -0
- package/dist/HttpApi/Operations/Session.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Session.js +5 -0
- package/dist/HttpApi/Operations/Session.js.map +1 -0
- package/dist/HttpApi/Operations/StepUp.d.ts +22 -0
- package/dist/HttpApi/Operations/StepUp.d.ts.map +1 -0
- package/dist/HttpApi/Operations/StepUp.js +5 -0
- package/dist/HttpApi/Operations/StepUp.js.map +1 -0
- package/dist/HttpApi/Operations/Totp.d.ts +20 -0
- package/dist/HttpApi/Operations/Totp.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Totp.js +5 -0
- package/dist/HttpApi/Operations/Totp.js.map +1 -0
- package/dist/HttpApi/Operations/TrustedDevice.d.ts +23 -0
- package/dist/HttpApi/Operations/TrustedDevice.d.ts.map +1 -0
- package/dist/HttpApi/Operations/TrustedDevice.js +7 -0
- package/dist/HttpApi/Operations/TrustedDevice.js.map +1 -0
- package/dist/HttpApi/Operations/index.d.ts +27 -0
- package/dist/HttpApi/Operations/index.d.ts.map +1 -0
- package/dist/HttpApi/Operations/index.js +27 -0
- package/dist/HttpApi/Operations/index.js.map +1 -0
- package/dist/HttpApi/Passkey.d.ts +5 -0
- package/dist/HttpApi/Passkey.d.ts.map +1 -0
- package/dist/HttpApi/Passkey.js +5 -0
- package/dist/HttpApi/Passkey.js.map +1 -0
- package/dist/HttpApi/Password.d.ts +220 -0
- package/dist/HttpApi/Password.d.ts.map +1 -0
- package/dist/HttpApi/Password.js +237 -0
- package/dist/HttpApi/Password.js.map +1 -0
- package/dist/HttpApi/PasswordContract.d.ts +307 -0
- package/dist/HttpApi/PasswordContract.d.ts.map +1 -0
- package/dist/HttpApi/PasswordContract.js +63 -0
- package/dist/HttpApi/PasswordContract.js.map +1 -0
- package/dist/HttpApi/PasswordGuards.d.ts +82 -0
- package/dist/HttpApi/PasswordGuards.d.ts.map +1 -0
- package/dist/HttpApi/PasswordGuards.js +179 -0
- package/dist/HttpApi/PasswordGuards.js.map +1 -0
- package/dist/HttpApi/RecoveryCodes.d.ts +5 -0
- package/dist/HttpApi/RecoveryCodes.d.ts.map +1 -0
- package/dist/HttpApi/RecoveryCodes.js +5 -0
- package/dist/HttpApi/RecoveryCodes.js.map +1 -0
- package/dist/HttpApi/RefreshToken.d.ts +4 -0
- package/dist/HttpApi/RefreshToken.d.ts.map +1 -0
- package/dist/HttpApi/RefreshToken.js +4 -0
- package/dist/HttpApi/RefreshToken.js.map +1 -0
- package/dist/HttpApi/RequestGuards.d.ts +42 -0
- package/dist/HttpApi/RequestGuards.d.ts.map +1 -0
- package/dist/HttpApi/RequestGuards.js +194 -0
- package/dist/HttpApi/RequestGuards.js.map +1 -0
- package/dist/HttpApi/Schemas.d.ts +361 -84
- package/dist/HttpApi/Schemas.d.ts.map +1 -1
- package/dist/HttpApi/Schemas.js +190 -27
- package/dist/HttpApi/Schemas.js.map +1 -1
- package/dist/HttpApi/Security.d.ts +12 -93
- package/dist/HttpApi/Security.d.ts.map +1 -1
- package/dist/HttpApi/Security.js +65 -356
- package/dist/HttpApi/Security.js.map +1 -1
- package/dist/HttpApi/SecurityTimeline.d.ts +4 -0
- package/dist/HttpApi/SecurityTimeline.d.ts.map +1 -0
- package/dist/HttpApi/SecurityTimeline.js +4 -0
- package/dist/HttpApi/SecurityTimeline.js.map +1 -0
- package/dist/HttpApi/Session.d.ts +5 -0
- package/dist/HttpApi/Session.d.ts.map +1 -0
- package/dist/HttpApi/Session.js +5 -0
- package/dist/HttpApi/Session.js.map +1 -0
- package/dist/HttpApi/SessionGuards.d.ts +15 -0
- package/dist/HttpApi/SessionGuards.d.ts.map +1 -0
- package/dist/HttpApi/SessionGuards.js +37 -0
- package/dist/HttpApi/SessionGuards.js.map +1 -0
- package/dist/HttpApi/StepUp.d.ts +5 -0
- package/dist/HttpApi/StepUp.d.ts.map +1 -0
- package/dist/HttpApi/StepUp.js +5 -0
- package/dist/HttpApi/StepUp.js.map +1 -0
- package/dist/HttpApi/Totp.d.ts +5 -0
- package/dist/HttpApi/Totp.d.ts.map +1 -0
- package/dist/HttpApi/Totp.js +5 -0
- package/dist/HttpApi/Totp.js.map +1 -0
- package/dist/HttpApi/Transport.d.ts +4 -6
- package/dist/HttpApi/Transport.d.ts.map +1 -1
- package/dist/HttpApi/Transport.js +62 -36
- package/dist/HttpApi/Transport.js.map +1 -1
- package/dist/HttpApi/TrustedDevice.d.ts +4 -0
- package/dist/HttpApi/TrustedDevice.d.ts.map +1 -0
- package/dist/HttpApi/TrustedDevice.js +4 -0
- package/dist/HttpApi/TrustedDevice.js.map +1 -0
- package/dist/HttpApi/index.d.ts +9 -3
- package/dist/HttpApi/index.d.ts.map +1 -1
- package/dist/HttpApi/index.js +8 -2
- package/dist/HttpApi/index.js.map +1 -1
- package/dist/Identity.d.ts +138 -0
- package/dist/Identity.d.ts.map +1 -0
- package/dist/Identity.js +105 -0
- package/dist/Identity.js.map +1 -0
- package/dist/IdentityManagement.d.ts +189 -0
- package/dist/IdentityManagement.d.ts.map +1 -0
- package/dist/IdentityManagement.js +317 -0
- package/dist/IdentityManagement.js.map +1 -0
- package/dist/IncidentAction.d.ts +1 -4
- package/dist/IncidentAction.d.ts.map +1 -1
- package/dist/IncidentAction.js +15 -9
- package/dist/IncidentAction.js.map +1 -1
- package/dist/Internal.d.ts +2 -0
- package/dist/Internal.d.ts.map +1 -1
- package/dist/Internal.js +30 -0
- package/dist/Internal.js.map +1 -1
- package/dist/Invitation.d.ts +362 -0
- package/dist/Invitation.d.ts.map +1 -0
- package/dist/Invitation.js +633 -0
- package/dist/Invitation.js.map +1 -0
- package/dist/IpQualityScore.d.ts +38 -0
- package/dist/IpQualityScore.d.ts.map +1 -0
- package/dist/IpQualityScore.js +215 -0
- package/dist/IpQualityScore.js.map +1 -0
- package/dist/Jwt.d.ts +9 -30
- package/dist/Jwt.d.ts.map +1 -1
- package/dist/Jwt.js +72 -60
- package/dist/Jwt.js.map +1 -1
- package/dist/LoginApproval.d.ts +16 -31
- package/dist/LoginApproval.d.ts.map +1 -1
- package/dist/LoginApproval.js +47 -41
- package/dist/LoginApproval.js.map +1 -1
- package/dist/LoginNotification.d.ts +8 -12
- package/dist/LoginNotification.d.ts.map +1 -1
- package/dist/LoginNotification.js +30 -17
- package/dist/LoginNotification.js.map +1 -1
- package/dist/LoginRisk.d.ts +11 -13
- package/dist/LoginRisk.d.ts.map +1 -1
- package/dist/LoginRisk.js +66 -26
- package/dist/LoginRisk.js.map +1 -1
- package/dist/LoginRiskEnrichment.d.ts +145 -0
- package/dist/LoginRiskEnrichment.d.ts.map +1 -0
- package/dist/LoginRiskEnrichment.js +220 -0
- package/dist/LoginRiskEnrichment.js.map +1 -0
- package/dist/MachineAuth.d.ts.map +1 -1
- package/dist/MachineAuth.js.map +1 -1
- package/dist/MagicLink.d.ts +9 -8
- package/dist/MagicLink.d.ts.map +1 -1
- package/dist/MagicLink.js +40 -73
- package/dist/MagicLink.js.map +1 -1
- package/dist/Mailer.d.ts +20 -13
- package/dist/Mailer.d.ts.map +1 -1
- package/dist/Mailer.js +10 -12
- package/dist/Mailer.js.map +1 -1
- package/dist/OAuth.d.ts +100 -103
- package/dist/OAuth.d.ts.map +1 -1
- package/dist/OAuth.js +404 -217
- package/dist/OAuth.js.map +1 -1
- package/dist/Passkey.d.ts +17 -19
- package/dist/Passkey.d.ts.map +1 -1
- package/dist/Passkey.js +86 -39
- package/dist/Passkey.js.map +1 -1
- package/dist/PasskeyBrowser.d.ts +39 -0
- package/dist/PasskeyBrowser.d.ts.map +1 -0
- package/dist/PasskeyBrowser.js +206 -0
- package/dist/PasskeyBrowser.js.map +1 -0
- package/dist/PasskeySimpleWebAuthn.d.ts.map +1 -1
- package/dist/PasskeySimpleWebAuthn.js +19 -7
- package/dist/PasskeySimpleWebAuthn.js.map +1 -1
- package/dist/Password.d.ts +71 -37
- package/dist/Password.d.ts.map +1 -1
- package/dist/Password.js +296 -82
- package/dist/Password.js.map +1 -1
- package/dist/PasswordRisk.d.ts +63 -0
- package/dist/PasswordRisk.d.ts.map +1 -0
- package/dist/PasswordRisk.js +37 -0
- package/dist/PasswordRisk.js.map +1 -0
- package/dist/Permission.d.ts +308 -0
- package/dist/Permission.d.ts.map +1 -0
- package/dist/Permission.js +827 -0
- package/dist/Permission.js.map +1 -0
- package/dist/Policy.d.ts +31 -18
- package/dist/Policy.d.ts.map +1 -1
- package/dist/Policy.js +58 -14
- package/dist/Policy.js.map +1 -1
- package/dist/PostgresDelegatedAccessStorageMigrations.d.ts +7 -0
- package/dist/PostgresDelegatedAccessStorageMigrations.d.ts.map +1 -0
- package/dist/PostgresDelegatedAccessStorageMigrations.js +119 -0
- package/dist/PostgresDelegatedAccessStorageMigrations.js.map +1 -0
- package/dist/PostgresStorageMigrations.d.ts +15 -0
- package/dist/PostgresStorageMigrations.d.ts.map +1 -0
- package/dist/PostgresStorageMigrations.js +620 -0
- package/dist/PostgresStorageMigrations.js.map +1 -0
- package/dist/Privacy.d.ts +0 -3
- package/dist/Privacy.d.ts.map +1 -1
- package/dist/Privacy.js +2 -5
- package/dist/Privacy.js.map +1 -1
- package/dist/RateLimiter.d.ts +0 -3
- package/dist/RateLimiter.d.ts.map +1 -1
- package/dist/RateLimiter.js +1 -4
- package/dist/RateLimiter.js.map +1 -1
- package/dist/RecoveryCode.d.ts +84 -12
- package/dist/RecoveryCode.d.ts.map +1 -1
- package/dist/RecoveryCode.js +273 -75
- package/dist/RecoveryCode.js.map +1 -1
- package/dist/RecoveryPolicy.d.ts +81 -0
- package/dist/RecoveryPolicy.d.ts.map +1 -0
- package/dist/RecoveryPolicy.js +119 -0
- package/dist/RecoveryPolicy.js.map +1 -0
- package/dist/RefreshToken.d.ts +1 -10
- package/dist/RefreshToken.d.ts.map +1 -1
- package/dist/RefreshToken.js +31 -22
- package/dist/RefreshToken.js.map +1 -1
- package/dist/Retention.d.ts.map +1 -1
- package/dist/Retention.js.map +1 -1
- package/dist/SecurityTimeline.d.ts +1 -4
- package/dist/SecurityTimeline.d.ts.map +1 -1
- package/dist/SecurityTimeline.js +110 -17
- package/dist/SecurityTimeline.js.map +1 -1
- package/dist/Sessions.d.ts +124 -29
- package/dist/Sessions.d.ts.map +1 -1
- package/dist/Sessions.js +626 -94
- package/dist/Sessions.js.map +1 -1
- package/dist/StepUp.d.ts +132 -11
- package/dist/StepUp.d.ts.map +1 -1
- package/dist/StepUp.js +387 -19
- package/dist/StepUp.js.map +1 -1
- package/dist/Storage.d.ts +89 -23
- package/dist/Storage.d.ts.map +1 -1
- package/dist/Storage.js +10 -12
- package/dist/Storage.js.map +1 -1
- package/dist/StorageMigrations.d.ts +6 -1
- package/dist/StorageMigrations.d.ts.map +1 -1
- package/dist/StorageMigrations.js +224 -0
- package/dist/StorageMigrations.js.map +1 -1
- package/dist/StorageSchemaGenerator.d.ts +486 -0
- package/dist/StorageSchemaGenerator.d.ts.map +1 -0
- package/dist/StorageSchemaGenerator.js +1022 -0
- package/dist/StorageSchemaGenerator.js.map +1 -0
- package/dist/StrongFactor.d.ts +64 -0
- package/dist/StrongFactor.d.ts.map +1 -0
- package/dist/StrongFactor.js +100 -0
- package/dist/StrongFactor.js.map +1 -0
- package/dist/Testing.d.ts +1 -1
- package/dist/Testing.js +2 -2
- package/dist/Testing.js.map +1 -1
- package/dist/Totp.d.ts +88 -13
- package/dist/Totp.d.ts.map +1 -1
- package/dist/Totp.js +194 -36
- package/dist/Totp.js.map +1 -1
- package/dist/TrustedDevice.d.ts +0 -9
- package/dist/TrustedDevice.d.ts.map +1 -1
- package/dist/TrustedDevice.js +15 -17
- package/dist/TrustedDevice.js.map +1 -1
- package/dist/WaitUntil.d.ts +0 -3
- package/dist/WaitUntil.d.ts.map +1 -1
- package/dist/WaitUntil.js +1 -4
- package/dist/WaitUntil.js.map +1 -1
- package/dist/Webhook.d.ts +42 -12
- package/dist/Webhook.d.ts.map +1 -1
- package/dist/Webhook.js +165 -26
- package/dist/Webhook.js.map +1 -1
- package/dist/alchemy/cloudflare/Email.d.ts +4 -4
- package/dist/alchemy/cloudflare/Email.d.ts.map +1 -1
- package/dist/alchemy/cloudflare/Email.js +10 -5
- package/dist/alchemy/cloudflare/Email.js.map +1 -1
- package/dist/alchemy/cloudflare/RateLimitDurableObject.d.ts +4 -4
- package/dist/alchemy/cloudflare/RateLimitDurableObject.d.ts.map +1 -1
- package/dist/alchemy/cloudflare/RateLimitDurableObject.js +5 -4
- package/dist/alchemy/cloudflare/RateLimitDurableObject.js.map +1 -1
- package/dist/cloudflare/Email.d.ts.map +1 -1
- package/dist/cloudflare/Email.js +1 -1
- package/dist/cloudflare/Email.js.map +1 -1
- package/dist/cloudflare/RateLimitDurableObject.d.ts +6 -5
- package/dist/cloudflare/RateLimitDurableObject.d.ts.map +1 -1
- package/dist/cloudflare/RateLimitDurableObject.js.map +1 -1
- package/dist/cloudflare/RequestMetadata.d.ts +49 -0
- package/dist/cloudflare/RequestMetadata.d.ts.map +1 -0
- package/dist/cloudflare/RequestMetadata.js +71 -0
- package/dist/cloudflare/RequestMetadata.js.map +1 -0
- package/dist/index.d.ts +0 -35
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -35
- package/dist/index.js.map +1 -1
- package/dist/internal/AuthFlowFinalizer.d.ts +31 -0
- package/dist/internal/AuthFlowFinalizer.d.ts.map +1 -0
- package/dist/internal/AuthFlowFinalizer.js +182 -0
- package/dist/internal/AuthFlowFinalizer.js.map +1 -0
- package/dist/internal/RateLimitDurableObject.d.ts.map +1 -1
- package/dist/internal/RateLimitDurableObject.js +3 -0
- package/dist/internal/RateLimitDurableObject.js.map +1 -1
- package/migrations/0001_auth_storage.sql +1 -0
- package/migrations/0006_auth_totp_factor.sql +1 -0
- package/migrations/0024_auth_permission.sql +39 -0
- package/migrations/0025_auth_permission_definition.sql +19 -0
- package/migrations/0026_auth_user_identity.sql +59 -0
- package/migrations/0027_auth_audit_log_storage_order.sql +46 -0
- package/migrations/0028_auth_oauth_client_secret_key.sql +39 -0
- package/migrations/delegated-access/0001_auth_delegated_access.sql +152 -0
- package/migrations/postgres/0001_auth_core.sql +77 -0
- package/migrations/postgres/0002_auth_security_oauth.sql +65 -0
- package/migrations/postgres/0003_auth_credentials_tokens.sql +43 -0
- package/migrations/postgres/0004_auth_security_history.sql +103 -0
- package/migrations/postgres/0005_auth_webhooks.sql +29 -0
- package/migrations/postgres/0006_auth_domain_timeline.sql +50 -0
- package/migrations/postgres/0007_auth_oauth_clients.sql +85 -0
- package/migrations/postgres/0008_auth_oauth_tokens.sql +63 -0
- package/migrations/postgres/0009_auth_permissions.sql +66 -0
- package/migrations/postgres/delegated-access/0001_auth_delegated_access.sql +112 -0
- package/package.json +309 -2
|
@@ -0,0 +1,764 @@
|
|
|
1
|
+
import { Context, Data, Effect, Layer, Result, Schema } from "effect";
|
|
2
|
+
import { CredentialIdSchema, OAuthProviderIdSchema, UnixMillisSchema, } from "./Identifiers.js";
|
|
3
|
+
export const assuranceLevels = ["aal1", "aal2", "aal3"];
|
|
4
|
+
const assuranceRank = {
|
|
5
|
+
aal1: 1,
|
|
6
|
+
aal2: 2,
|
|
7
|
+
aal3: 3,
|
|
8
|
+
};
|
|
9
|
+
export const rankAssurance = (level) => assuranceRank[level];
|
|
10
|
+
export const assuranceAtLeast = (actual, required) => rankAssurance(actual) >= rankAssurance(required);
|
|
11
|
+
export const strongerAssurance = (left, right) => (assuranceAtLeast(left, right) ? left : right);
|
|
12
|
+
export const canonicalAuthMethodReferences = [
|
|
13
|
+
"pwd",
|
|
14
|
+
"email_otp",
|
|
15
|
+
"magic_link",
|
|
16
|
+
"oauth",
|
|
17
|
+
"totp",
|
|
18
|
+
"passkey",
|
|
19
|
+
"recovery_code",
|
|
20
|
+
];
|
|
21
|
+
export class AuthenticationEvidenceTimeError extends Data.TaggedError("AuthenticationEvidenceTimeError") {
|
|
22
|
+
}
|
|
23
|
+
/** Maximum time authentication evidence may lead the server clock by default. */
|
|
24
|
+
export const defaultAuthenticationEvidenceFutureSkewMillis = 60_000;
|
|
25
|
+
export const validateAuthenticationEvidenceTimestamps = (events, serverNow, maximumFutureSkewMillis = defaultAuthenticationEvidenceFutureSkewMillis) => {
|
|
26
|
+
const latestAccepted = Number(serverNow) + maximumFutureSkewMillis;
|
|
27
|
+
for (const event of events) {
|
|
28
|
+
if (Number(event.verifiedAt) > latestAccepted) {
|
|
29
|
+
return Result.fail(new AuthenticationEvidenceTimeError({
|
|
30
|
+
eventType: event.type,
|
|
31
|
+
verifiedAt: event.verifiedAt,
|
|
32
|
+
serverNow,
|
|
33
|
+
maximumFutureSkewMillis,
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return Result.void;
|
|
38
|
+
};
|
|
39
|
+
const NonEmptyString = Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(256));
|
|
40
|
+
export const maximumCustomEvidenceProperties = 32;
|
|
41
|
+
export const maximumCustomEvidencePropertyKeyLength = 128;
|
|
42
|
+
export const maximumCustomEvidenceStringPropertyLength = 2048;
|
|
43
|
+
export const maximumCustomAuthMethodReferenceLength = 128;
|
|
44
|
+
const CustomEvidenceStringProperty = Schema.String.check(Schema.isMaxLength(maximumCustomEvidenceStringPropertyLength));
|
|
45
|
+
const CustomEvidencePropertiesSchema = Schema.Record(Schema.String, Schema.Union([Schema.Boolean, Schema.Finite, CustomEvidenceStringProperty])).check(Schema.makeFilter((properties) => {
|
|
46
|
+
const keys = Object.keys(properties);
|
|
47
|
+
if (keys.length > maximumCustomEvidenceProperties) {
|
|
48
|
+
return `Expected at most ${maximumCustomEvidenceProperties} custom evidence properties`;
|
|
49
|
+
}
|
|
50
|
+
return keys.every((key) => key.length >= 1 && key.length <= maximumCustomEvidencePropertyKeyLength)
|
|
51
|
+
? undefined
|
|
52
|
+
: `Expected custom evidence property keys to contain 1..${maximumCustomEvidencePropertyKeyLength} characters`;
|
|
53
|
+
}));
|
|
54
|
+
const NonNegativeInteger = Schema.Number.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(0));
|
|
55
|
+
const VerifiedAt = UnixMillisSchema.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(0));
|
|
56
|
+
const Base = { version: Schema.Literal(1), verifiedAt: VerifiedAt };
|
|
57
|
+
export const AuthenticationEvent = Schema.Union([
|
|
58
|
+
Schema.Struct({
|
|
59
|
+
...Base,
|
|
60
|
+
type: Schema.Literal("password"),
|
|
61
|
+
credentialId: CredentialIdSchema,
|
|
62
|
+
}),
|
|
63
|
+
Schema.Struct({
|
|
64
|
+
...Base,
|
|
65
|
+
type: Schema.Literal("email_otp"),
|
|
66
|
+
identityId: NonEmptyString,
|
|
67
|
+
}),
|
|
68
|
+
Schema.Struct({
|
|
69
|
+
...Base,
|
|
70
|
+
type: Schema.Literal("magic_link"),
|
|
71
|
+
identityId: NonEmptyString,
|
|
72
|
+
}),
|
|
73
|
+
Schema.Struct({
|
|
74
|
+
...Base,
|
|
75
|
+
type: Schema.Literal("oauth"),
|
|
76
|
+
providerId: OAuthProviderIdSchema,
|
|
77
|
+
providerAccountId: NonEmptyString,
|
|
78
|
+
}),
|
|
79
|
+
Schema.Struct({
|
|
80
|
+
...Base,
|
|
81
|
+
type: Schema.Literal("totp"),
|
|
82
|
+
factorId: CredentialIdSchema,
|
|
83
|
+
acceptedCounter: NonNegativeInteger,
|
|
84
|
+
}),
|
|
85
|
+
Schema.Struct({
|
|
86
|
+
...Base,
|
|
87
|
+
type: Schema.Literal("passkey"),
|
|
88
|
+
credentialId: CredentialIdSchema,
|
|
89
|
+
userVerification: Schema.Literals(["verified", "not-verified", "unknown"]),
|
|
90
|
+
authenticatorAttachment: Schema.optional(Schema.Literals(["platform", "cross-platform"])),
|
|
91
|
+
backedUp: Schema.optional(Schema.Boolean),
|
|
92
|
+
backupEligible: Schema.optional(Schema.Boolean),
|
|
93
|
+
signCount: Schema.optional(NonNegativeInteger),
|
|
94
|
+
aaguid: Schema.optional(NonEmptyString),
|
|
95
|
+
}),
|
|
96
|
+
Schema.Struct({
|
|
97
|
+
...Base,
|
|
98
|
+
type: Schema.Literal("recovery_code"),
|
|
99
|
+
codeId: CredentialIdSchema,
|
|
100
|
+
}),
|
|
101
|
+
Schema.Struct({
|
|
102
|
+
...Base,
|
|
103
|
+
type: Schema.Literal("custom"),
|
|
104
|
+
policyId: NonEmptyString,
|
|
105
|
+
policyVersion: NonNegativeInteger.check(Schema.isGreaterThan(0)),
|
|
106
|
+
kind: NonEmptyString,
|
|
107
|
+
properties: CustomEvidencePropertiesSchema,
|
|
108
|
+
}),
|
|
109
|
+
]);
|
|
110
|
+
export const maximumSessionAuthenticationEvents = 32;
|
|
111
|
+
export const AuthenticationEvents = Schema.Array(AuthenticationEvent).check(Schema.isMaxLength(maximumSessionAuthenticationEvents));
|
|
112
|
+
export const parseAuthenticationEvent = Schema.decodeUnknownSync(AuthenticationEvent);
|
|
113
|
+
export const parseAuthenticationEvents = Schema.decodeUnknownSync(AuthenticationEvents);
|
|
114
|
+
const immutable = (evidence) => Object.freeze(evidence);
|
|
115
|
+
export const passwordEvidence = (evidence) => immutable({ version: 1, type: "password", ...evidence });
|
|
116
|
+
export const emailOtpEvidence = (evidence) => immutable({ version: 1, type: "email_otp", ...evidence });
|
|
117
|
+
export const magicLinkEvidence = (evidence) => immutable({ version: 1, type: "magic_link", ...evidence });
|
|
118
|
+
export const oauthEvidence = (evidence) => immutable({ version: 1, type: "oauth", ...evidence });
|
|
119
|
+
export const totpEvidence = (evidence) => immutable({ version: 1, type: "totp", ...evidence });
|
|
120
|
+
export const passkeyEvidence = (evidence) => immutable({ version: 1, type: "passkey", ...evidence });
|
|
121
|
+
export const recoveryCodeEvidence = (evidence) => immutable({ version: 1, type: "recovery_code", ...evidence });
|
|
122
|
+
const parseCustomEvidence = Schema.decodeUnknownSync(AuthenticationEvent, {
|
|
123
|
+
onExcessProperty: "error",
|
|
124
|
+
});
|
|
125
|
+
export const customEvidence = (evidence) => {
|
|
126
|
+
const parsed = parseCustomEvidence({
|
|
127
|
+
version: 1,
|
|
128
|
+
type: "custom",
|
|
129
|
+
...evidence,
|
|
130
|
+
});
|
|
131
|
+
if (parsed.type !== "custom") {
|
|
132
|
+
throw new TypeError("Expected custom authentication evidence");
|
|
133
|
+
}
|
|
134
|
+
return immutable({
|
|
135
|
+
...parsed,
|
|
136
|
+
properties: Object.freeze({ ...parsed.properties }),
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
export class CustomEvidencePolicyError extends Data.TaggedError("CustomEvidencePolicyError") {
|
|
140
|
+
}
|
|
141
|
+
export class CustomEvidencePolicyConfigurationError extends Data.TaggedError("CustomEvidencePolicyConfigurationError") {
|
|
142
|
+
}
|
|
143
|
+
const CustomEvidencePolicyTypeId = Symbol.for("@effect-auth/core/Assurance/CustomEvidencePolicy");
|
|
144
|
+
const configurationError = (reason, policyId, policyVersion, cause) => new CustomEvidencePolicyConfigurationError({
|
|
145
|
+
reason,
|
|
146
|
+
policyId: typeof policyId === "string" ? policyId : "<invalid>",
|
|
147
|
+
policyVersion: typeof policyVersion === "number" ? policyVersion : Number.NaN,
|
|
148
|
+
...(cause === undefined ? {} : { cause }),
|
|
149
|
+
});
|
|
150
|
+
const policyError = (reason, evidence, cause) => new CustomEvidencePolicyError({
|
|
151
|
+
reason,
|
|
152
|
+
policyId: evidence.policyId,
|
|
153
|
+
policyVersion: evidence.policyVersion,
|
|
154
|
+
...(cause === undefined ? {} : { cause }),
|
|
155
|
+
});
|
|
156
|
+
const isFlatPropertyAst = (ast) => {
|
|
157
|
+
if (ast.encoding !== undefined ||
|
|
158
|
+
ast.context?.isOptional === true ||
|
|
159
|
+
ast.context?.isMutable === true ||
|
|
160
|
+
ast.context?.defaultValue !== undefined) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
switch (ast._tag) {
|
|
164
|
+
case "Boolean":
|
|
165
|
+
case "String":
|
|
166
|
+
case "Number": {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
case "Literal": {
|
|
170
|
+
return (typeof ast.literal === "boolean" ||
|
|
171
|
+
typeof ast.literal === "string" ||
|
|
172
|
+
(typeof ast.literal === "number" && Number.isFinite(ast.literal)));
|
|
173
|
+
}
|
|
174
|
+
case "Enum": {
|
|
175
|
+
return ast.enums.every(([, value]) => typeof value === "string" ||
|
|
176
|
+
(typeof value === "number" && Number.isFinite(value)));
|
|
177
|
+
}
|
|
178
|
+
case "TemplateLiteral": {
|
|
179
|
+
return ast.parts.every(isFlatPropertyAst);
|
|
180
|
+
}
|
|
181
|
+
case "Union": {
|
|
182
|
+
return ast.types.length > 0 && ast.types.every(isFlatPropertyAst);
|
|
183
|
+
}
|
|
184
|
+
default: {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
const isValidCustomEvidencePropertiesSchema = (properties) => {
|
|
190
|
+
if (typeof properties !== "object" ||
|
|
191
|
+
properties === null ||
|
|
192
|
+
!("fields" in properties) ||
|
|
193
|
+
!("ast" in properties)) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
const schema = properties;
|
|
197
|
+
const fieldKeys = Reflect.ownKeys(schema.fields);
|
|
198
|
+
return (schema.ast._tag === "Objects" &&
|
|
199
|
+
schema.ast.encoding === undefined &&
|
|
200
|
+
schema.ast.indexSignatures.length === 0 &&
|
|
201
|
+
schema.ast.propertySignatures.length === fieldKeys.length &&
|
|
202
|
+
fieldKeys.length <= maximumCustomEvidenceProperties &&
|
|
203
|
+
schema.ast.propertySignatures.every((field) => typeof field.name === "string" &&
|
|
204
|
+
field.name.length >= 1 &&
|
|
205
|
+
field.name.length <= maximumCustomEvidencePropertyKeyLength &&
|
|
206
|
+
isFlatPropertyAst(field.type)));
|
|
207
|
+
};
|
|
208
|
+
const validateDefinitionMetadata = (definition) => {
|
|
209
|
+
if (typeof definition.policyId !== "string" ||
|
|
210
|
+
definition.policyId.length === 0 ||
|
|
211
|
+
definition.policyId.length > 256) {
|
|
212
|
+
return Result.fail(configurationError("invalid_policy_id", definition.policyId, definition.policyVersion));
|
|
213
|
+
}
|
|
214
|
+
if (typeof definition.policyVersion !== "number" ||
|
|
215
|
+
!Number.isSafeInteger(definition.policyVersion) ||
|
|
216
|
+
definition.policyVersion <= 0) {
|
|
217
|
+
return Result.fail(configurationError("invalid_policy_version", definition.policyId, definition.policyVersion));
|
|
218
|
+
}
|
|
219
|
+
if (typeof definition.kind !== "string" ||
|
|
220
|
+
definition.kind.length === 0 ||
|
|
221
|
+
definition.kind.length > 256) {
|
|
222
|
+
return Result.fail(configurationError("invalid_policy_kind", definition.policyId, definition.policyVersion));
|
|
223
|
+
}
|
|
224
|
+
if (!isValidCustomEvidencePropertiesSchema(definition.properties) ||
|
|
225
|
+
typeof definition.evaluate !== "function") {
|
|
226
|
+
return Result.fail(configurationError("invalid_policy_metadata", definition.policyId, definition.policyVersion, new TypeError("Custom evidence policies require at most 32 flat, required, transformation-free property fields and an evaluator")));
|
|
227
|
+
}
|
|
228
|
+
return Result.void;
|
|
229
|
+
};
|
|
230
|
+
const decodeBoundedCustomEvidenceProperties = Schema.decodeUnknownResult(CustomEvidencePropertiesSchema, { errors: "all", onExcessProperty: "error" });
|
|
231
|
+
const safeDecodeProperties = (decode, input) => {
|
|
232
|
+
const attempted = Result.try(() => decode(input));
|
|
233
|
+
return Result.isFailure(attempted)
|
|
234
|
+
? Result.fail(attempted.failure)
|
|
235
|
+
: attempted.success;
|
|
236
|
+
};
|
|
237
|
+
export const defineCustomEvidence = (definition) => {
|
|
238
|
+
Result.getOrThrow(validateDefinitionMetadata(definition));
|
|
239
|
+
const typedPropertiesSchema = Schema.toType(definition.properties);
|
|
240
|
+
const decodeTypedProperties = Schema.decodeUnknownResult(typedPropertiesSchema, { errors: "all", onExcessProperty: "error" });
|
|
241
|
+
const internals = {
|
|
242
|
+
validateProperties: (properties) => {
|
|
243
|
+
const bounded = safeDecodeProperties(decodeBoundedCustomEvidenceProperties, properties);
|
|
244
|
+
if (Result.isFailure(bounded)) {
|
|
245
|
+
return bounded;
|
|
246
|
+
}
|
|
247
|
+
const decoded = safeDecodeProperties(decodeTypedProperties, bounded.success);
|
|
248
|
+
return Result.isFailure(decoded)
|
|
249
|
+
? decoded
|
|
250
|
+
: Result.succeed(Object.freeze({ ...decoded.success }));
|
|
251
|
+
},
|
|
252
|
+
evaluate: (properties) => definition.evaluate(properties),
|
|
253
|
+
};
|
|
254
|
+
const policy = Object.freeze({
|
|
255
|
+
policyId: definition.policyId,
|
|
256
|
+
policyVersion: definition.policyVersion,
|
|
257
|
+
kind: definition.kind,
|
|
258
|
+
[CustomEvidencePolicyTypeId]: Object.freeze(internals),
|
|
259
|
+
});
|
|
260
|
+
const make = (input) => {
|
|
261
|
+
const properties = Result.getOrThrow(internals.validateProperties(input.properties));
|
|
262
|
+
return customEvidence({
|
|
263
|
+
verifiedAt: input.verifiedAt,
|
|
264
|
+
policyId: definition.policyId,
|
|
265
|
+
policyVersion: definition.policyVersion,
|
|
266
|
+
kind: definition.kind,
|
|
267
|
+
properties,
|
|
268
|
+
});
|
|
269
|
+
};
|
|
270
|
+
return Object.freeze({ policy, make });
|
|
271
|
+
};
|
|
272
|
+
export class CustomEvidencePolicies extends Context.Service()("auth/CustomEvidencePolicies") {
|
|
273
|
+
}
|
|
274
|
+
export const emptyCustomEvidencePolicyRegistry = Object.freeze({ resolve: () => undefined });
|
|
275
|
+
const isCustomEvidencePolicy = (policy) => {
|
|
276
|
+
if (typeof policy !== "object" ||
|
|
277
|
+
policy === null ||
|
|
278
|
+
!(CustomEvidencePolicyTypeId in policy)) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
const internals = policy[CustomEvidencePolicyTypeId];
|
|
282
|
+
return (typeof internals === "object" &&
|
|
283
|
+
internals !== null &&
|
|
284
|
+
"validateProperties" in internals &&
|
|
285
|
+
typeof internals.validateProperties === "function" &&
|
|
286
|
+
"evaluate" in internals &&
|
|
287
|
+
typeof internals.evaluate === "function");
|
|
288
|
+
};
|
|
289
|
+
export const makeCustomEvidencePolicyRegistryResult = (policies) => {
|
|
290
|
+
const registered = new Map();
|
|
291
|
+
for (const policy of policies) {
|
|
292
|
+
const metadata = Result.try(() => ({
|
|
293
|
+
policyId: policy.policyId,
|
|
294
|
+
policyVersion: policy.policyVersion,
|
|
295
|
+
kind: policy.kind,
|
|
296
|
+
valid: isCustomEvidencePolicy(policy),
|
|
297
|
+
}));
|
|
298
|
+
if (Result.isFailure(metadata)) {
|
|
299
|
+
return Result.fail(configurationError("invalid_policy_metadata", "<invalid>", Number.NaN, metadata.failure));
|
|
300
|
+
}
|
|
301
|
+
const { kind, policyId, policyVersion, valid } = metadata.success;
|
|
302
|
+
if (typeof policyId !== "string" ||
|
|
303
|
+
policyId.length === 0 ||
|
|
304
|
+
policyId.length > 256) {
|
|
305
|
+
return Result.fail(configurationError("invalid_policy_id", policyId, policyVersion));
|
|
306
|
+
}
|
|
307
|
+
if (!Number.isSafeInteger(policyVersion) || policyVersion <= 0) {
|
|
308
|
+
return Result.fail(configurationError("invalid_policy_version", policyId, policyVersion));
|
|
309
|
+
}
|
|
310
|
+
if (typeof kind !== "string" || kind.length === 0 || kind.length > 256) {
|
|
311
|
+
return Result.fail(configurationError("invalid_policy_kind", policyId, policyVersion));
|
|
312
|
+
}
|
|
313
|
+
if (!valid) {
|
|
314
|
+
return Result.fail(configurationError("invalid_policy_metadata", policyId, policyVersion));
|
|
315
|
+
}
|
|
316
|
+
const key = `${policyId}\u0000${policyVersion}`;
|
|
317
|
+
if (registered.has(key)) {
|
|
318
|
+
return Result.fail(configurationError("duplicate_policy", policyId, policyVersion));
|
|
319
|
+
}
|
|
320
|
+
registered.set(key, policy);
|
|
321
|
+
}
|
|
322
|
+
return Result.succeed(Object.freeze({
|
|
323
|
+
resolve: (policyId, policyVersion) => registered.get(`${policyId}\u0000${policyVersion}`),
|
|
324
|
+
}));
|
|
325
|
+
};
|
|
326
|
+
/**
|
|
327
|
+
* Compatibility constructor for existing synchronous call sites. New code should
|
|
328
|
+
* use makeCustomEvidencePolicyRegistryResult with defineCustomEvidence policies.
|
|
329
|
+
*/
|
|
330
|
+
export const makeCustomEvidencePolicyRegistry = (policies) => Result.getOrThrow(makeCustomEvidencePolicyRegistryResult(policies));
|
|
331
|
+
(function (CustomEvidencePolicies) {
|
|
332
|
+
CustomEvidencePolicies.make = (policies) => Effect.fromResult(makeCustomEvidencePolicyRegistryResult(policies)).pipe(Effect.map(CustomEvidencePolicies.of));
|
|
333
|
+
})(CustomEvidencePolicies || (CustomEvidencePolicies = {}));
|
|
334
|
+
export const CustomEvidencePoliciesLive = (policies) => Layer.effect(CustomEvidencePolicies)(CustomEvidencePolicies.make(policies));
|
|
335
|
+
const CustomEvidencePolicyResultSchema = Schema.Union([
|
|
336
|
+
Schema.Struct({
|
|
337
|
+
role: Schema.Literal("primary"),
|
|
338
|
+
level: Schema.Literal("aal1"),
|
|
339
|
+
amr: Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(maximumCustomAuthMethodReferenceLength)),
|
|
340
|
+
}),
|
|
341
|
+
Schema.Struct({
|
|
342
|
+
role: Schema.Literal("independent-second-factor"),
|
|
343
|
+
level: Schema.Literal("aal1"),
|
|
344
|
+
amr: Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(maximumCustomAuthMethodReferenceLength)),
|
|
345
|
+
}),
|
|
346
|
+
Schema.Struct({
|
|
347
|
+
role: Schema.Literal("multi-factor"),
|
|
348
|
+
level: Schema.Literals(["aal2", "aal3"]),
|
|
349
|
+
amr: Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(maximumCustomAuthMethodReferenceLength)),
|
|
350
|
+
}),
|
|
351
|
+
]);
|
|
352
|
+
const decodeCustomEvidencePolicyResult = Schema.decodeUnknownResult(CustomEvidencePolicyResultSchema, { errors: "all", onExcessProperty: "error" });
|
|
353
|
+
const reservedCustomAuthMethodReferences = new Set(canonicalAuthMethodReferences);
|
|
354
|
+
const evaluateCustomEvidenceResult = (evidence, registry) => {
|
|
355
|
+
const resolved = Result.try(() => registry.resolve(evidence.policyId, evidence.policyVersion));
|
|
356
|
+
if (Result.isFailure(resolved)) {
|
|
357
|
+
return Result.fail(policyError("unregistered_policy", evidence, resolved.failure));
|
|
358
|
+
}
|
|
359
|
+
const policy = resolved.success;
|
|
360
|
+
if (policy === undefined) {
|
|
361
|
+
return Result.fail(policyError("unregistered_policy", evidence));
|
|
362
|
+
}
|
|
363
|
+
if (!isCustomEvidencePolicy(policy)) {
|
|
364
|
+
return Result.fail(policyError("unregistered_policy", evidence));
|
|
365
|
+
}
|
|
366
|
+
const internals = policy[CustomEvidencePolicyTypeId];
|
|
367
|
+
if (evidence.kind !== policy.kind) {
|
|
368
|
+
return Result.fail(policyError("kind_mismatch", evidence, {
|
|
369
|
+
expected: policy.kind,
|
|
370
|
+
actual: evidence.kind,
|
|
371
|
+
}));
|
|
372
|
+
}
|
|
373
|
+
const properties = internals.validateProperties(evidence.properties);
|
|
374
|
+
if (Result.isFailure(properties)) {
|
|
375
|
+
return Result.fail(policyError("invalid_properties", evidence, properties.failure));
|
|
376
|
+
}
|
|
377
|
+
const evaluated = Result.try({
|
|
378
|
+
try: () => internals.evaluate(properties.success),
|
|
379
|
+
catch: (cause) => policyError("invalid_result", evidence, cause),
|
|
380
|
+
});
|
|
381
|
+
if (Result.isFailure(evaluated)) {
|
|
382
|
+
return Result.fail(evaluated.failure);
|
|
383
|
+
}
|
|
384
|
+
const decodedAttempt = Result.try(() => decodeCustomEvidencePolicyResult(evaluated.success));
|
|
385
|
+
if (Result.isFailure(decodedAttempt)) {
|
|
386
|
+
return Result.fail(policyError("invalid_result", evidence, decodedAttempt.failure));
|
|
387
|
+
}
|
|
388
|
+
const decoded = decodedAttempt.success;
|
|
389
|
+
if (Result.isFailure(decoded)) {
|
|
390
|
+
return Result.fail(policyError("invalid_result", evidence, decoded.failure));
|
|
391
|
+
}
|
|
392
|
+
if (reservedCustomAuthMethodReferences.has(decoded.success.amr)) {
|
|
393
|
+
return Result.fail(policyError("reserved_amr", evidence));
|
|
394
|
+
}
|
|
395
|
+
return Result.succeed(Object.freeze(decoded.success));
|
|
396
|
+
};
|
|
397
|
+
const evidenceAssuranceSemanticsResult = (evidence, registry) => {
|
|
398
|
+
if (evidence.type === "custom") {
|
|
399
|
+
const evaluated = evaluateCustomEvidenceResult(evidence, registry);
|
|
400
|
+
if (Result.isFailure(evaluated)) {
|
|
401
|
+
return Result.fail(evaluated.failure);
|
|
402
|
+
}
|
|
403
|
+
const result = evaluated.success;
|
|
404
|
+
return Result.succeed({
|
|
405
|
+
amr: result.amr,
|
|
406
|
+
level: result.level,
|
|
407
|
+
primaryEstablished: result.role === "primary" || result.role === "multi-factor",
|
|
408
|
+
independentSecondFactor: result.role === "independent-second-factor" ||
|
|
409
|
+
result.role === "multi-factor",
|
|
410
|
+
multiFactor: result.role === "multi-factor",
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
if (evidence.type === "passkey") {
|
|
414
|
+
const multiFactor = evidence.userVerification === "verified";
|
|
415
|
+
return Result.succeed({
|
|
416
|
+
amr: "passkey",
|
|
417
|
+
level: multiFactor ? "aal2" : "aal1",
|
|
418
|
+
primaryEstablished: true,
|
|
419
|
+
independentSecondFactor: multiFactor,
|
|
420
|
+
multiFactor,
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
if (evidence.type === "totp") {
|
|
424
|
+
return Result.succeed({
|
|
425
|
+
amr: "totp",
|
|
426
|
+
level: "aal1",
|
|
427
|
+
primaryEstablished: false,
|
|
428
|
+
independentSecondFactor: true,
|
|
429
|
+
multiFactor: false,
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
if (evidence.type === "recovery_code") {
|
|
433
|
+
return Result.succeed({
|
|
434
|
+
amr: "recovery_code",
|
|
435
|
+
level: "aal1",
|
|
436
|
+
primaryEstablished: false,
|
|
437
|
+
independentSecondFactor: false,
|
|
438
|
+
multiFactor: false,
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
return Result.succeed({
|
|
442
|
+
amr: evidence.type === "password" ? "pwd" : evidence.type,
|
|
443
|
+
level: "aal1",
|
|
444
|
+
primaryEstablished: true,
|
|
445
|
+
independentSecondFactor: false,
|
|
446
|
+
multiFactor: false,
|
|
447
|
+
});
|
|
448
|
+
};
|
|
449
|
+
export const authenticationMethodForResult = (evidence, customEvidencePolicies) => {
|
|
450
|
+
const semantics = evidenceAssuranceSemanticsResult(evidence, customEvidencePolicies);
|
|
451
|
+
return Result.isFailure(semantics)
|
|
452
|
+
? Result.fail(semantics.failure)
|
|
453
|
+
: Result.succeed(semantics.success.amr);
|
|
454
|
+
};
|
|
455
|
+
export const authenticationMethodFor = (evidence, customEvidencePolicies = emptyCustomEvidencePolicyRegistry) => Result.getOrThrow(authenticationMethodForResult(evidence, customEvidencePolicies));
|
|
456
|
+
export const authenticationFactorId = (evidence) => {
|
|
457
|
+
switch (evidence.type) {
|
|
458
|
+
case "password":
|
|
459
|
+
case "passkey": {
|
|
460
|
+
return evidence.credentialId;
|
|
461
|
+
}
|
|
462
|
+
case "totp": {
|
|
463
|
+
return evidence.factorId;
|
|
464
|
+
}
|
|
465
|
+
case "recovery_code": {
|
|
466
|
+
return evidence.codeId;
|
|
467
|
+
}
|
|
468
|
+
default: {
|
|
469
|
+
return undefined;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
export const authenticationEventMatchesMethodResult = (evidence, method, customEvidencePolicies) => {
|
|
474
|
+
const actual = authenticationMethodForResult(evidence, customEvidencePolicies);
|
|
475
|
+
return Result.isFailure(actual)
|
|
476
|
+
? Result.fail(actual.failure)
|
|
477
|
+
: Result.succeed(actual.success === method);
|
|
478
|
+
};
|
|
479
|
+
export const authenticationEventMatchesMethod = (evidence, method, customEvidencePolicies = emptyCustomEvidencePolicyRegistry) => Result.getOrThrow(authenticationEventMatchesMethodResult(evidence, method, customEvidencePolicies));
|
|
480
|
+
export const latestAuthenticationEvent = (events, predicate) => {
|
|
481
|
+
let latest;
|
|
482
|
+
for (const event of events) {
|
|
483
|
+
if (predicate(event) &&
|
|
484
|
+
(latest === undefined || event.verifiedAt > latest.verifiedAt)) {
|
|
485
|
+
latest = event;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
return latest;
|
|
489
|
+
};
|
|
490
|
+
export const latestMethodAuthenticationEventResult = (events, method, customEvidencePolicies) => {
|
|
491
|
+
let latest;
|
|
492
|
+
for (const event of events) {
|
|
493
|
+
const matches = authenticationEventMatchesMethodResult(event, method, customEvidencePolicies);
|
|
494
|
+
if (Result.isFailure(matches)) {
|
|
495
|
+
return Result.fail(matches.failure);
|
|
496
|
+
}
|
|
497
|
+
if (matches.success &&
|
|
498
|
+
(latest === undefined || event.verifiedAt > latest.verifiedAt)) {
|
|
499
|
+
latest = event;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
return Result.succeed(latest);
|
|
503
|
+
};
|
|
504
|
+
export const latestMethodAuthenticationEvent = (events, method, customEvidencePolicies = emptyCustomEvidencePolicyRegistry) => Result.getOrThrow(latestMethodAuthenticationEventResult(events, method, customEvidencePolicies));
|
|
505
|
+
export const latestFactorAuthenticationEventResult = (events, method, factorId, customEvidencePolicies) => {
|
|
506
|
+
let latest;
|
|
507
|
+
for (const event of events) {
|
|
508
|
+
const matches = authenticationEventMatchesMethodResult(event, method, customEvidencePolicies);
|
|
509
|
+
if (Result.isFailure(matches)) {
|
|
510
|
+
return Result.fail(matches.failure);
|
|
511
|
+
}
|
|
512
|
+
if (matches.success &&
|
|
513
|
+
authenticationFactorId(event) === factorId &&
|
|
514
|
+
(latest === undefined || event.verifiedAt > latest.verifiedAt)) {
|
|
515
|
+
latest = event;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
return Result.succeed(latest);
|
|
519
|
+
};
|
|
520
|
+
export const latestFactorAuthenticationEvent = (events, method, factorId, customEvidencePolicies = emptyCustomEvidencePolicyRegistry) => Result.getOrThrow(latestFactorAuthenticationEventResult(events, method, factorId, customEvidencePolicies));
|
|
521
|
+
const collectEventSemanticsResult = (events, registry) => {
|
|
522
|
+
const collected = [];
|
|
523
|
+
for (const event of events) {
|
|
524
|
+
const semantics = evidenceAssuranceSemanticsResult(event, registry);
|
|
525
|
+
if (Result.isFailure(semantics)) {
|
|
526
|
+
return Result.fail(semantics.failure);
|
|
527
|
+
}
|
|
528
|
+
collected.push({ event, semantics: semantics.success });
|
|
529
|
+
}
|
|
530
|
+
return Result.succeed(collected);
|
|
531
|
+
};
|
|
532
|
+
const laterEvent = (left, right) => left === undefined
|
|
533
|
+
? right
|
|
534
|
+
: right === undefined || left.event.verifiedAt >= right.event.verifiedAt
|
|
535
|
+
? left
|
|
536
|
+
: right;
|
|
537
|
+
const latestSemanticEvent = (events, predicate) => {
|
|
538
|
+
let latest;
|
|
539
|
+
for (const entry of events) {
|
|
540
|
+
if (predicate(entry) &&
|
|
541
|
+
(latest === undefined || entry.event.verifiedAt > latest.event.verifiedAt)) {
|
|
542
|
+
latest = entry;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
return latest;
|
|
546
|
+
};
|
|
547
|
+
export const latestAssuranceAuthenticationEventResult = (events, required, customEvidencePolicies) => {
|
|
548
|
+
const collected = collectEventSemanticsResult(events, customEvidencePolicies);
|
|
549
|
+
if (Result.isFailure(collected)) {
|
|
550
|
+
return Result.fail(collected.failure);
|
|
551
|
+
}
|
|
552
|
+
const entries = collected.success;
|
|
553
|
+
if (required !== "aal1" &&
|
|
554
|
+
entries.some(({ event }) => event.type === "recovery_code")) {
|
|
555
|
+
return Result.succeed(undefined);
|
|
556
|
+
}
|
|
557
|
+
if (required === "aal1") {
|
|
558
|
+
return Result.succeed(latestSemanticEvent(entries, ({ semantics }) => semantics.primaryEstablished)?.event);
|
|
559
|
+
}
|
|
560
|
+
const multiFactor = latestSemanticEvent(entries, ({ semantics }) => semantics.multiFactor && assuranceAtLeast(semantics.level, required));
|
|
561
|
+
if (required === "aal3") {
|
|
562
|
+
return Result.succeed(multiFactor?.event);
|
|
563
|
+
}
|
|
564
|
+
const primary = latestSemanticEvent(entries, ({ semantics }) => semantics.primaryEstablished && !semantics.multiFactor);
|
|
565
|
+
const independent = latestSemanticEvent(entries, ({ semantics }) => semantics.independentSecondFactor && !semantics.multiFactor);
|
|
566
|
+
const composed = primary === undefined || independent === undefined
|
|
567
|
+
? undefined
|
|
568
|
+
: laterEvent(primary, independent);
|
|
569
|
+
return Result.succeed(laterEvent(multiFactor, composed)?.event);
|
|
570
|
+
};
|
|
571
|
+
export const latestAssuranceAuthenticationEvent = (events, required, customEvidencePolicies = emptyCustomEvidencePolicyRegistry) => Result.getOrThrow(latestAssuranceAuthenticationEventResult(events, required, customEvidencePolicies));
|
|
572
|
+
export const deriveAssuranceResult = (events, options = {}) => {
|
|
573
|
+
const registry = options.customEvidencePolicies ?? emptyCustomEvidencePolicyRegistry;
|
|
574
|
+
const collected = collectEventSemanticsResult(events, registry);
|
|
575
|
+
if (Result.isFailure(collected)) {
|
|
576
|
+
return Result.fail(collected.failure);
|
|
577
|
+
}
|
|
578
|
+
let level = "aal1";
|
|
579
|
+
let primaryEstablished = false;
|
|
580
|
+
let hasIndependentSecondFactor = false;
|
|
581
|
+
let recoveryRemediation = false;
|
|
582
|
+
let authenticatedAt;
|
|
583
|
+
const methods = new Set();
|
|
584
|
+
for (const { event, semantics } of collected.success) {
|
|
585
|
+
methods.add(semantics.amr);
|
|
586
|
+
authenticatedAt =
|
|
587
|
+
authenticatedAt === undefined || event.verifiedAt > authenticatedAt
|
|
588
|
+
? event.verifiedAt
|
|
589
|
+
: authenticatedAt;
|
|
590
|
+
level = strongerAssurance(level, semantics.level);
|
|
591
|
+
primaryEstablished ||= semantics.primaryEstablished;
|
|
592
|
+
hasIndependentSecondFactor ||= semantics.independentSecondFactor;
|
|
593
|
+
if (event.type === "recovery_code") {
|
|
594
|
+
recoveryRemediation = true;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
if (primaryEstablished && hasIndependentSecondFactor) {
|
|
598
|
+
level = strongerAssurance(level, "aal2");
|
|
599
|
+
}
|
|
600
|
+
if (recoveryRemediation && assuranceAtLeast(level, "aal2")) {
|
|
601
|
+
level = "aal1";
|
|
602
|
+
}
|
|
603
|
+
const builtIns = canonicalAuthMethodReferences.filter((method) => methods.delete(method));
|
|
604
|
+
// ES2022 does not provide toSorted; both arrays are fresh local copies.
|
|
605
|
+
// oxlint-disable-next-line unicorn/no-array-sort
|
|
606
|
+
const custom = [...methods].sort();
|
|
607
|
+
return Result.succeed(Object.freeze({
|
|
608
|
+
level,
|
|
609
|
+
amr: Object.freeze([...builtIns, ...custom]),
|
|
610
|
+
...(authenticatedAt === undefined ? {} : { authenticatedAt }),
|
|
611
|
+
primaryEstablished,
|
|
612
|
+
recoveryRemediation,
|
|
613
|
+
}));
|
|
614
|
+
};
|
|
615
|
+
export const deriveAssurance = (events, options = {}) => Result.getOrThrow(deriveAssuranceResult(events, options));
|
|
616
|
+
const compareStrings = (left, right) => left < right ? -1 : left > right ? 1 : 0;
|
|
617
|
+
const stableEventKey = (event, semantics) => {
|
|
618
|
+
const properties = event.type === "custom"
|
|
619
|
+
? Object.keys(event.properties)
|
|
620
|
+
// ES2022 does not provide toSorted; this is a fresh local array.
|
|
621
|
+
// oxlint-disable-next-line unicorn/no-array-sort
|
|
622
|
+
.sort(compareStrings)
|
|
623
|
+
.map((key) => [key, event.properties[key]])
|
|
624
|
+
: undefined;
|
|
625
|
+
return JSON.stringify([
|
|
626
|
+
event.type,
|
|
627
|
+
semantics.amr,
|
|
628
|
+
event.verifiedAt,
|
|
629
|
+
event.type === "password" || event.type === "passkey"
|
|
630
|
+
? event.credentialId
|
|
631
|
+
: event.type === "totp"
|
|
632
|
+
? event.factorId
|
|
633
|
+
: event.type === "recovery_code"
|
|
634
|
+
? event.codeId
|
|
635
|
+
: event.type === "email_otp" || event.type === "magic_link"
|
|
636
|
+
? event.identityId
|
|
637
|
+
: event.type === "oauth"
|
|
638
|
+
? [event.providerId, event.providerAccountId]
|
|
639
|
+
: [
|
|
640
|
+
event.policyId,
|
|
641
|
+
event.policyVersion,
|
|
642
|
+
event.kind,
|
|
643
|
+
semantics.level,
|
|
644
|
+
semantics.primaryEstablished,
|
|
645
|
+
semantics.independentSecondFactor,
|
|
646
|
+
properties,
|
|
647
|
+
],
|
|
648
|
+
]);
|
|
649
|
+
};
|
|
650
|
+
const compactionKey = ({ event, semantics }) => {
|
|
651
|
+
const factor = authenticationFactorId(event);
|
|
652
|
+
if (factor !== undefined) {
|
|
653
|
+
return `factor:${event.type}:${factor}`;
|
|
654
|
+
}
|
|
655
|
+
return event.type === "custom"
|
|
656
|
+
? `custom:${event.policyId}:${event.policyVersion}:${event.kind}:${semantics.amr}:${semantics.level}:${semantics.primaryEstablished}:${semantics.independentSecondFactor}`
|
|
657
|
+
: `method:${event.type}`;
|
|
658
|
+
};
|
|
659
|
+
const compactionImportance = ({ event, semantics, }) => event.type === "recovery_code"
|
|
660
|
+
? 500
|
|
661
|
+
: semantics.multiFactor
|
|
662
|
+
? semantics.level === "aal3"
|
|
663
|
+
? 400
|
|
664
|
+
: 350
|
|
665
|
+
: semantics.independentSecondFactor
|
|
666
|
+
? 250
|
|
667
|
+
: semantics.primaryEstablished
|
|
668
|
+
? 200
|
|
669
|
+
: 100;
|
|
670
|
+
export const compactAuthenticationEventsResult = (events, maximumEvents, customEvidencePolicies) => {
|
|
671
|
+
if (!Number.isSafeInteger(maximumEvents) || maximumEvents < 0) {
|
|
672
|
+
throw new RangeError("maximumEvents must be a non-negative safe integer");
|
|
673
|
+
}
|
|
674
|
+
const collected = collectEventSemanticsResult(events, customEvidencePolicies);
|
|
675
|
+
if (Result.isFailure(collected)) {
|
|
676
|
+
return Result.fail(collected.failure);
|
|
677
|
+
}
|
|
678
|
+
if (maximumEvents === 0) {
|
|
679
|
+
return Result.succeed(Object.freeze([]));
|
|
680
|
+
}
|
|
681
|
+
const sorted = [...collected.success];
|
|
682
|
+
// ES2022 does not provide toSorted; this array is a fresh local copy.
|
|
683
|
+
// oxlint-disable-next-line unicorn/no-array-sort
|
|
684
|
+
sorted.sort((left, right) => left.event.verifiedAt === right.event.verifiedAt
|
|
685
|
+
? compareStrings(stableEventKey(left.event, left.semantics), stableEventKey(right.event, right.semantics))
|
|
686
|
+
: left.event.verifiedAt < right.event.verifiedAt
|
|
687
|
+
? -1
|
|
688
|
+
: 1);
|
|
689
|
+
if (sorted.length <= maximumEvents) {
|
|
690
|
+
return Result.succeed(Object.freeze(sorted.map(({ event }) => event)));
|
|
691
|
+
}
|
|
692
|
+
// Retain the latest event for each stable method/factor. If cardinality exceeds
|
|
693
|
+
// the bound, older factor-specific evidence is deliberately absent so a
|
|
694
|
+
// factor freshness check fails rather than falling back to another factor.
|
|
695
|
+
const latestByKey = new Map();
|
|
696
|
+
for (const entry of sorted) {
|
|
697
|
+
latestByKey.set(compactionKey(entry), entry);
|
|
698
|
+
}
|
|
699
|
+
const retained = [...latestByKey.values()];
|
|
700
|
+
// oxlint-disable-next-line unicorn/no-array-sort
|
|
701
|
+
retained.sort((left, right) => compactionImportance(right) - compactionImportance(left) ||
|
|
702
|
+
(left.event.verifiedAt === right.event.verifiedAt
|
|
703
|
+
? compareStrings(stableEventKey(left.event, left.semantics), stableEventKey(right.event, right.semantics))
|
|
704
|
+
: left.event.verifiedAt > right.event.verifiedAt
|
|
705
|
+
? -1
|
|
706
|
+
: 1));
|
|
707
|
+
const selected = retained.slice(0, maximumEvents);
|
|
708
|
+
// oxlint-disable-next-line unicorn/no-array-sort
|
|
709
|
+
selected.sort((left, right) => left.event.verifiedAt === right.event.verifiedAt
|
|
710
|
+
? compareStrings(stableEventKey(left.event, left.semantics), stableEventKey(right.event, right.semantics))
|
|
711
|
+
: left.event.verifiedAt < right.event.verifiedAt
|
|
712
|
+
? -1
|
|
713
|
+
: 1);
|
|
714
|
+
return Result.succeed(Object.freeze(selected.map(({ event }) => event)));
|
|
715
|
+
};
|
|
716
|
+
const compatibilityCompactionKey = (event) => event.type === "custom"
|
|
717
|
+
? JSON.stringify([
|
|
718
|
+
event.type,
|
|
719
|
+
event.policyId,
|
|
720
|
+
event.policyVersion,
|
|
721
|
+
event.kind,
|
|
722
|
+
Object.keys(event.properties)
|
|
723
|
+
// ES2022 does not provide toSorted; this is a fresh local array.
|
|
724
|
+
// oxlint-disable-next-line unicorn/no-array-sort
|
|
725
|
+
.sort(compareStrings)
|
|
726
|
+
.map((key) => [key, event.properties[key]]),
|
|
727
|
+
])
|
|
728
|
+
: event.type;
|
|
729
|
+
export const compactAuthenticationEvents = (events, maximumEvents = 32, customEvidencePolicies) => {
|
|
730
|
+
if (!Number.isSafeInteger(maximumEvents) || maximumEvents < 0) {
|
|
731
|
+
throw new RangeError("maximumEvents must be a non-negative safe integer");
|
|
732
|
+
}
|
|
733
|
+
if (customEvidencePolicies === undefined &&
|
|
734
|
+
events.length <= maximumEvents &&
|
|
735
|
+
events.some((event) => event.type === "custom")) {
|
|
736
|
+
const sorted = [...events];
|
|
737
|
+
// Compatibility for callers that compact before using their captured
|
|
738
|
+
// registry to derive assurance. No policy decision is needed without truncation.
|
|
739
|
+
// oxlint-disable-next-line unicorn/no-array-sort
|
|
740
|
+
sorted.sort((left, right) => left.verifiedAt === right.verifiedAt
|
|
741
|
+
? compareStrings(compatibilityCompactionKey(left), compatibilityCompactionKey(right))
|
|
742
|
+
: left.verifiedAt < right.verifiedAt
|
|
743
|
+
? -1
|
|
744
|
+
: 1);
|
|
745
|
+
return Result.getOrThrow(Result.succeed(Object.freeze(sorted)));
|
|
746
|
+
}
|
|
747
|
+
return Result.getOrThrow(compactAuthenticationEventsResult(events, maximumEvents, customEvidencePolicies ?? emptyCustomEvidencePolicyRegistry));
|
|
748
|
+
};
|
|
749
|
+
export const deriveMfaVerifiedAtResult = (events, customEvidencePolicies) => {
|
|
750
|
+
const collected = collectEventSemanticsResult(events, customEvidencePolicies);
|
|
751
|
+
if (Result.isFailure(collected)) {
|
|
752
|
+
return Result.fail(collected.failure);
|
|
753
|
+
}
|
|
754
|
+
const entries = collected.success;
|
|
755
|
+
const multiFactor = latestSemanticEvent(entries, ({ semantics }) => semantics.multiFactor);
|
|
756
|
+
const primary = latestSemanticEvent(entries, ({ semantics }) => semantics.primaryEstablished && !semantics.multiFactor);
|
|
757
|
+
const independent = latestSemanticEvent(entries, ({ semantics }) => semantics.independentSecondFactor && !semantics.multiFactor);
|
|
758
|
+
const composed = primary === undefined || independent === undefined
|
|
759
|
+
? undefined
|
|
760
|
+
: laterEvent(primary, independent);
|
|
761
|
+
return Result.succeed(laterEvent(multiFactor, composed)?.event.verifiedAt);
|
|
762
|
+
};
|
|
763
|
+
export const deriveMfaVerifiedAt = (events, customEvidencePolicies = emptyCustomEvidencePolicyRegistry) => Result.getOrThrow(deriveMfaVerifiedAtResult(events, customEvidencePolicies));
|
|
764
|
+
//# sourceMappingURL=Assurance.js.map
|