@effect-auth/core 0.1.0-alpha.1 → 0.1.0-alpha.13

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.
Files changed (255) hide show
  1. package/README.md +790 -73
  2. package/dist/ApiKey.d.ts +207 -0
  3. package/dist/ApiKey.d.ts.map +1 -0
  4. package/dist/ApiKey.js +275 -0
  5. package/dist/ApiKey.js.map +1 -0
  6. package/dist/AuditLog.d.ts +335 -1
  7. package/dist/AuditLog.d.ts.map +1 -1
  8. package/dist/AuditLog.js +318 -1
  9. package/dist/AuditLog.js.map +1 -1
  10. package/dist/AuthConfig.d.ts +42 -0
  11. package/dist/AuthConfig.d.ts.map +1 -0
  12. package/dist/AuthConfig.js +43 -0
  13. package/dist/AuthConfig.js.map +1 -0
  14. package/dist/AuthFlow.d.ts +462 -36
  15. package/dist/AuthFlow.d.ts.map +1 -1
  16. package/dist/AuthFlow.js +657 -5
  17. package/dist/AuthFlow.js.map +1 -1
  18. package/dist/AuthKernel.d.ts +3 -0
  19. package/dist/AuthKernel.d.ts.map +1 -0
  20. package/dist/AuthKernel.js +9 -0
  21. package/dist/AuthKernel.js.map +1 -0
  22. package/dist/Challenge.d.ts +24 -4
  23. package/dist/Challenge.d.ts.map +1 -1
  24. package/dist/Challenge.js +167 -1
  25. package/dist/Challenge.js.map +1 -1
  26. package/dist/Client.d.ts +449 -0
  27. package/dist/Client.d.ts.map +1 -0
  28. package/dist/Client.js +985 -0
  29. package/dist/Client.js.map +1 -0
  30. package/dist/Crypto.d.ts +6 -1
  31. package/dist/Crypto.d.ts.map +1 -1
  32. package/dist/Crypto.js +62 -1
  33. package/dist/Crypto.js.map +1 -1
  34. package/dist/DomainVerification.d.ts +200 -0
  35. package/dist/DomainVerification.d.ts.map +1 -0
  36. package/dist/DomainVerification.js +304 -0
  37. package/dist/DomainVerification.js.map +1 -0
  38. package/dist/EffectQbSqliteStorage.d.ts +985 -0
  39. package/dist/EffectQbSqliteStorage.d.ts.map +1 -0
  40. package/dist/EffectQbSqliteStorage.js +2824 -0
  41. package/dist/EffectQbSqliteStorage.js.map +1 -0
  42. package/dist/EmailOtp.d.ts +120 -0
  43. package/dist/EmailOtp.d.ts.map +1 -0
  44. package/dist/EmailOtp.js +286 -0
  45. package/dist/EmailOtp.js.map +1 -0
  46. package/dist/EmailVerification.d.ts +121 -0
  47. package/dist/EmailVerification.d.ts.map +1 -0
  48. package/dist/EmailVerification.js +200 -0
  49. package/dist/EmailVerification.js.map +1 -0
  50. package/dist/HttpApi/Api.d.ts +2410 -0
  51. package/dist/HttpApi/Api.d.ts.map +1 -0
  52. package/dist/HttpApi/Api.js +3026 -0
  53. package/dist/HttpApi/Api.js.map +1 -0
  54. package/dist/HttpApi/Endpoints.d.ts +1073 -0
  55. package/dist/HttpApi/Endpoints.d.ts.map +1 -0
  56. package/dist/HttpApi/Endpoints.js +428 -0
  57. package/dist/HttpApi/Endpoints.js.map +1 -0
  58. package/dist/HttpApi/Errors.d.ts +114 -0
  59. package/dist/HttpApi/Errors.d.ts.map +1 -0
  60. package/dist/HttpApi/Errors.js +230 -0
  61. package/dist/HttpApi/Errors.js.map +1 -0
  62. package/dist/HttpApi/Schemas.d.ts +1254 -0
  63. package/dist/HttpApi/Schemas.d.ts.map +1 -0
  64. package/dist/HttpApi/Schemas.js +862 -0
  65. package/dist/HttpApi/Schemas.js.map +1 -0
  66. package/dist/HttpApi/Security.d.ts +159 -0
  67. package/dist/HttpApi/Security.d.ts.map +1 -0
  68. package/dist/HttpApi/Security.js +530 -0
  69. package/dist/HttpApi/Security.js.map +1 -0
  70. package/dist/HttpApi/Transport.d.ts +65 -0
  71. package/dist/HttpApi/Transport.d.ts.map +1 -0
  72. package/dist/HttpApi/Transport.js +311 -0
  73. package/dist/HttpApi/Transport.js.map +1 -0
  74. package/dist/HttpApi/index.d.ts +8 -0
  75. package/dist/HttpApi/index.d.ts.map +1 -0
  76. package/dist/HttpApi/index.js +7 -0
  77. package/dist/HttpApi/index.js.map +1 -0
  78. package/dist/HttpApi.d.ts +2 -0
  79. package/dist/HttpApi.d.ts.map +1 -0
  80. package/dist/HttpApi.js +2 -0
  81. package/dist/HttpApi.js.map +1 -0
  82. package/dist/Identifiers.d.ts +3 -0
  83. package/dist/Identifiers.d.ts.map +1 -1
  84. package/dist/Identifiers.js +2 -0
  85. package/dist/Identifiers.js.map +1 -1
  86. package/dist/IncidentAction.d.ts +80 -0
  87. package/dist/IncidentAction.d.ts.map +1 -0
  88. package/dist/IncidentAction.js +158 -0
  89. package/dist/IncidentAction.js.map +1 -0
  90. package/dist/Internal.d.ts +7 -0
  91. package/dist/Internal.d.ts.map +1 -0
  92. package/dist/Internal.js +12 -0
  93. package/dist/Internal.js.map +1 -0
  94. package/dist/Jwt.d.ts +281 -0
  95. package/dist/Jwt.d.ts.map +1 -0
  96. package/dist/Jwt.js +721 -0
  97. package/dist/Jwt.js.map +1 -0
  98. package/dist/LoginApproval.d.ts +314 -0
  99. package/dist/LoginApproval.d.ts.map +1 -0
  100. package/dist/LoginApproval.js +551 -0
  101. package/dist/LoginApproval.js.map +1 -0
  102. package/dist/LoginNotification.d.ts +183 -0
  103. package/dist/LoginNotification.d.ts.map +1 -0
  104. package/dist/LoginNotification.js +329 -0
  105. package/dist/LoginNotification.js.map +1 -0
  106. package/dist/LoginRisk.d.ts +344 -0
  107. package/dist/LoginRisk.d.ts.map +1 -0
  108. package/dist/LoginRisk.js +484 -0
  109. package/dist/LoginRisk.js.map +1 -0
  110. package/dist/MachineAuth.d.ts +73 -0
  111. package/dist/MachineAuth.d.ts.map +1 -0
  112. package/dist/MachineAuth.js +147 -0
  113. package/dist/MachineAuth.js.map +1 -0
  114. package/dist/MagicLink.d.ts +85 -0
  115. package/dist/MagicLink.d.ts.map +1 -0
  116. package/dist/MagicLink.js +206 -0
  117. package/dist/MagicLink.js.map +1 -0
  118. package/dist/Mailer.d.ts +147 -0
  119. package/dist/Mailer.d.ts.map +1 -0
  120. package/dist/Mailer.js +208 -0
  121. package/dist/Mailer.js.map +1 -0
  122. package/dist/OAuth.d.ts +1890 -0
  123. package/dist/OAuth.d.ts.map +1 -0
  124. package/dist/OAuth.js +3063 -0
  125. package/dist/OAuth.js.map +1 -0
  126. package/dist/Passkey.d.ts +334 -0
  127. package/dist/Passkey.d.ts.map +1 -0
  128. package/dist/Passkey.js +422 -0
  129. package/dist/Passkey.js.map +1 -0
  130. package/dist/PasskeySimpleWebAuthn.d.ts +11 -0
  131. package/dist/PasskeySimpleWebAuthn.d.ts.map +1 -0
  132. package/dist/PasskeySimpleWebAuthn.js +181 -0
  133. package/dist/PasskeySimpleWebAuthn.js.map +1 -0
  134. package/dist/Password.d.ts +237 -0
  135. package/dist/Password.d.ts.map +1 -0
  136. package/dist/Password.js +641 -0
  137. package/dist/Password.js.map +1 -0
  138. package/dist/Policy.d.ts +7 -4
  139. package/dist/Policy.d.ts.map +1 -1
  140. package/dist/Policy.js +28 -5
  141. package/dist/Policy.js.map +1 -1
  142. package/dist/Privacy.d.ts +15 -0
  143. package/dist/Privacy.d.ts.map +1 -1
  144. package/dist/Privacy.js +58 -1
  145. package/dist/Privacy.js.map +1 -1
  146. package/dist/RateLimiter.d.ts +104 -0
  147. package/dist/RateLimiter.d.ts.map +1 -0
  148. package/dist/RateLimiter.js +118 -0
  149. package/dist/RateLimiter.js.map +1 -0
  150. package/dist/RecoveryCode.d.ts +169 -0
  151. package/dist/RecoveryCode.d.ts.map +1 -0
  152. package/dist/RecoveryCode.js +299 -0
  153. package/dist/RecoveryCode.js.map +1 -0
  154. package/dist/RefreshToken.d.ts +222 -0
  155. package/dist/RefreshToken.d.ts.map +1 -0
  156. package/dist/RefreshToken.js +342 -0
  157. package/dist/RefreshToken.js.map +1 -0
  158. package/dist/Retention.d.ts +98 -0
  159. package/dist/Retention.d.ts.map +1 -0
  160. package/dist/Retention.js +204 -0
  161. package/dist/Retention.js.map +1 -0
  162. package/dist/SecurityTimeline.d.ts +78 -0
  163. package/dist/SecurityTimeline.d.ts.map +1 -0
  164. package/dist/SecurityTimeline.js +461 -0
  165. package/dist/SecurityTimeline.js.map +1 -0
  166. package/dist/Sessions.d.ts +123 -11
  167. package/dist/Sessions.d.ts.map +1 -1
  168. package/dist/Sessions.js +534 -1
  169. package/dist/Sessions.js.map +1 -1
  170. package/dist/StepUp.d.ts +44 -0
  171. package/dist/StepUp.d.ts.map +1 -0
  172. package/dist/StepUp.js +82 -0
  173. package/dist/StepUp.js.map +1 -0
  174. package/dist/Storage.d.ts +73 -5
  175. package/dist/Storage.d.ts.map +1 -1
  176. package/dist/Storage.js +11 -1
  177. package/dist/Storage.js.map +1 -1
  178. package/dist/StorageMigrations.d.ts +23 -1
  179. package/dist/StorageMigrations.d.ts.map +1 -1
  180. package/dist/StorageMigrations.js +462 -2
  181. package/dist/StorageMigrations.js.map +1 -1
  182. package/dist/Testing.d.ts +9 -1
  183. package/dist/Testing.d.ts.map +1 -1
  184. package/dist/Testing.js +30 -2
  185. package/dist/Testing.js.map +1 -1
  186. package/dist/Totp.d.ts +220 -0
  187. package/dist/Totp.d.ts.map +1 -0
  188. package/dist/Totp.js +477 -0
  189. package/dist/Totp.js.map +1 -0
  190. package/dist/TrustedDevice.d.ts +127 -0
  191. package/dist/TrustedDevice.d.ts.map +1 -0
  192. package/dist/TrustedDevice.js +252 -0
  193. package/dist/TrustedDevice.js.map +1 -0
  194. package/dist/WaitUntil.d.ts.map +1 -1
  195. package/dist/WaitUntil.js +1 -1
  196. package/dist/WaitUntil.js.map +1 -1
  197. package/dist/Webhook.d.ts +380 -0
  198. package/dist/Webhook.d.ts.map +1 -0
  199. package/dist/Webhook.js +592 -0
  200. package/dist/Webhook.js.map +1 -0
  201. package/dist/alchemy/cloudflare/Email.d.ts +25 -0
  202. package/dist/alchemy/cloudflare/Email.d.ts.map +1 -0
  203. package/dist/alchemy/cloudflare/Email.js +117 -0
  204. package/dist/alchemy/cloudflare/Email.js.map +1 -0
  205. package/dist/alchemy/cloudflare/RateLimitDurableObject.d.ts +34 -0
  206. package/dist/alchemy/cloudflare/RateLimitDurableObject.d.ts.map +1 -0
  207. package/dist/alchemy/cloudflare/RateLimitDurableObject.js +30 -0
  208. package/dist/alchemy/cloudflare/RateLimitDurableObject.js.map +1 -0
  209. package/dist/cloudflare/Email.d.ts +25 -0
  210. package/dist/cloudflare/Email.d.ts.map +1 -0
  211. package/dist/cloudflare/Email.js +153 -0
  212. package/dist/cloudflare/Email.js.map +1 -0
  213. package/dist/cloudflare/RateLimitDurableObject.d.ts +50 -0
  214. package/dist/cloudflare/RateLimitDurableObject.d.ts.map +1 -0
  215. package/dist/cloudflare/RateLimitDurableObject.js +51 -0
  216. package/dist/cloudflare/RateLimitDurableObject.js.map +1 -0
  217. package/dist/index.d.ts +25 -0
  218. package/dist/index.d.ts.map +1 -1
  219. package/dist/index.js +25 -0
  220. package/dist/index.js.map +1 -1
  221. package/dist/internal/RateLimitDurableObject.d.ts +32 -0
  222. package/dist/internal/RateLimitDurableObject.d.ts.map +1 -0
  223. package/dist/internal/RateLimitDurableObject.js +80 -0
  224. package/dist/internal/RateLimitDurableObject.js.map +1 -0
  225. package/migrations/0002_auth_password.sql +25 -0
  226. package/migrations/0003_auth_login_approval_review.sql +22 -0
  227. package/migrations/0004_auth_trusted_device.sql +12 -0
  228. package/migrations/0005_auth_passkey.sql +17 -0
  229. package/migrations/0006_auth_totp_factor.sql +17 -0
  230. package/migrations/0007_auth_recovery_code.sql +13 -0
  231. package/migrations/0008_auth_api_key.sql +17 -0
  232. package/migrations/0009_auth_refresh_token.sql +21 -0
  233. package/migrations/0010_auth_jwt_revocation.sql +8 -0
  234. package/migrations/0011_auth_oauth_account.sql +16 -0
  235. package/migrations/0012_auth_oauth_provider_token_vault.sql +20 -0
  236. package/migrations/0013_auth_security_timeline.sql +16 -0
  237. package/migrations/0014_auth_webhook_outbox.sql +16 -0
  238. package/migrations/0015_auth_webhook_replay.sql +7 -0
  239. package/migrations/0016_auth_login_risk_history.sql +23 -0
  240. package/migrations/0017_auth_audit_log.sql +17 -0
  241. package/migrations/0018_auth_domain_verification.sql +18 -0
  242. package/migrations/0019_auth_oauth_authorization_code.sql +17 -0
  243. package/migrations/0020_auth_oauth_provider_mode_token.sql +24 -0
  244. package/migrations/0021_auth_oauth_client_secret.sql +14 -0
  245. package/migrations/0022_auth_oauth_client.sql +15 -0
  246. package/migrations/0023_auth_oauth_consent.sql +15 -0
  247. package/package.json +162 -26
  248. package/dist/D1Kysely.d.ts +0 -40
  249. package/dist/D1Kysely.d.ts.map +0 -1
  250. package/dist/D1Kysely.js +0 -75
  251. package/dist/D1Kysely.js.map +0 -1
  252. package/dist/KyselyStorage.d.ts +0 -41
  253. package/dist/KyselyStorage.d.ts.map +0 -1
  254. package/dist/KyselyStorage.js +0 -176
  255. package/dist/KyselyStorage.js.map +0 -1
@@ -0,0 +1,422 @@
1
+ import { Brand, Context, Data, Duration, Effect, Layer, Option, Redacted } from "effect";
2
+ import { Challenge } from "./Challenge.js";
3
+ import { Crypto } from "./Crypto.js";
4
+ import { CredentialId } from "./Identifiers.js";
5
+ import { currentUnixMillis } from "./Internal.js";
6
+ export const PasskeyCredentialId = Brand.nominal();
7
+ export const passkeyRegistrationChallengeType = "passkey-registration";
8
+ export const passkeyAuthenticationChallengeType = "passkey-authentication";
9
+ export const defaultPasskeyChallengeBytes = 32;
10
+ export const defaultPasskeyChallengeTtl = Duration.minutes(5);
11
+ export class PasskeyCredentialStoreError extends Data.TaggedError("PasskeyCredentialStoreError") {
12
+ }
13
+ export class PasskeyCredentialStore extends Context.Service()("auth/PasskeyCredentialStore") {
14
+ }
15
+ (function (PasskeyCredentialStore) {
16
+ PasskeyCredentialStore.make = (service) => PasskeyCredentialStore.of(service);
17
+ })(PasskeyCredentialStore || (PasskeyCredentialStore = {}));
18
+ const cloneCredential = (record) => structuredClone(record);
19
+ export const makePasskeyCredentialStoreMemory = () => {
20
+ const credentials = new Map();
21
+ return PasskeyCredentialStore.make({
22
+ insert: (row) => Effect.sync(() => {
23
+ credentials.set(row.credentialId, cloneCredential(row));
24
+ }),
25
+ findByCredentialId: (credentialId) => Effect.sync(() => {
26
+ const row = credentials.get(credentialId);
27
+ return row === undefined ? Option.none() : Option.some(cloneCredential(row));
28
+ }),
29
+ listByUser: (input) => Effect.sync(() => [...credentials.values()]
30
+ .filter((row) => row.userId === input.userId &&
31
+ (input.includeRevoked === true || row.revokedAt === undefined))
32
+ .map(cloneCredential)),
33
+ updateSignCount: (input) => Effect.sync(() => {
34
+ const row = credentials.get(input.credentialId);
35
+ if (row === undefined || row.revokedAt !== undefined) {
36
+ return Option.none();
37
+ }
38
+ const updated = {
39
+ ...row,
40
+ signCount: input.signCount,
41
+ lastUsedAt: input.lastUsedAt,
42
+ metadata: input.metadata ?? row.metadata,
43
+ };
44
+ credentials.set(input.credentialId, updated);
45
+ return Option.some(cloneCredential(updated));
46
+ }),
47
+ revoke: (input) => Effect.sync(() => {
48
+ const row = credentials.get(input.credentialId);
49
+ if (row !== undefined) {
50
+ credentials.set(input.credentialId, {
51
+ ...row,
52
+ revokedAt: input.revokedAt,
53
+ metadata: input.reason === undefined
54
+ ? row.metadata
55
+ : { ...row.metadata, revokeReason: input.reason },
56
+ });
57
+ }
58
+ }),
59
+ });
60
+ };
61
+ export const PasskeyCredentialStoreMemoryLive = Layer.sync(PasskeyCredentialStore)(makePasskeyCredentialStoreMemory);
62
+ export class PasskeyCredentialManagementError extends Data.TaggedError("PasskeyCredentialManagementError") {
63
+ }
64
+ export class PasskeyCredentialManagement extends Context.Service()("auth/PasskeyCredentialManagement") {
65
+ }
66
+ (function (PasskeyCredentialManagement) {
67
+ PasskeyCredentialManagement.make = (service) => PasskeyCredentialManagement.of(service);
68
+ })(PasskeyCredentialManagement || (PasskeyCredentialManagement = {}));
69
+ const credentialInfo = (credential) => ({
70
+ credentialId: credential.credentialId,
71
+ ...(credential.transports === undefined
72
+ ? {}
73
+ : { transports: credential.transports }),
74
+ ...(credential.backedUp === undefined ? {} : { backedUp: credential.backedUp }),
75
+ createdAt: credential.createdAt,
76
+ ...(credential.lastUsedAt === undefined
77
+ ? {}
78
+ : { lastUsedAt: credential.lastUsedAt }),
79
+ ...(credential.revokedAt === undefined
80
+ ? {}
81
+ : { revokedAt: credential.revokedAt }),
82
+ ...(credential.metadata === undefined ? {} : { metadata: credential.metadata }),
83
+ });
84
+ const passkeyCredentialManagementError = (operation, message, cause) => new PasskeyCredentialManagementError({
85
+ operation,
86
+ message,
87
+ ...(cause === undefined ? {} : { cause }),
88
+ });
89
+ export const makePasskeyCredentialManagement = (dependencies) => PasskeyCredentialManagement.make({
90
+ listForUser: Effect.fn("auth.passkey.credential_management.list")(function* (input) {
91
+ const credentials = yield* dependencies.credentialStore
92
+ .listByUser({
93
+ userId: input.userId,
94
+ ...(input.includeRevoked === undefined
95
+ ? {}
96
+ : { includeRevoked: input.includeRevoked }),
97
+ })
98
+ .pipe(Effect.mapError((cause) => passkeyCredentialManagementError("list", "Failed to list passkey credentials", cause)));
99
+ return credentials.map(credentialInfo);
100
+ }),
101
+ revokeForUser: Effect.fn("auth.passkey.credential_management.revoke")(function* (input) {
102
+ const credential = yield* dependencies.credentialStore
103
+ .findByCredentialId(input.credentialId)
104
+ .pipe(Effect.mapError((cause) => passkeyCredentialManagementError("revoke", "Failed to load passkey credential", cause)));
105
+ if (Option.isNone(credential) || credential.value.userId !== input.userId) {
106
+ return yield* passkeyCredentialManagementError("revoke", "Passkey credential not found");
107
+ }
108
+ if (credential.value.revokedAt !== undefined) {
109
+ return;
110
+ }
111
+ const revokedAt = input.revokedAt ?? (yield* currentUnixMillis);
112
+ yield* dependencies.credentialStore
113
+ .revoke({
114
+ credentialId: input.credentialId,
115
+ revokedAt,
116
+ ...(input.reason === undefined ? {} : { reason: input.reason }),
117
+ })
118
+ .pipe(Effect.mapError((cause) => passkeyCredentialManagementError("revoke", "Failed to revoke passkey credential", cause)));
119
+ }),
120
+ });
121
+ export const PasskeyCredentialManagementLive = Layer.effect(PasskeyCredentialManagement)(Effect.gen(function* () {
122
+ const credentialStore = yield* PasskeyCredentialStore;
123
+ return makePasskeyCredentialManagement({ credentialStore });
124
+ }));
125
+ export class PasskeyVerifierError extends Data.TaggedError("PasskeyVerifierError") {
126
+ }
127
+ export class PasskeyVerifier extends Context.Service()("auth/PasskeyVerifier") {
128
+ }
129
+ (function (PasskeyVerifier) {
130
+ PasskeyVerifier.make = (service) => PasskeyVerifier.of(service);
131
+ })(PasskeyVerifier || (PasskeyVerifier = {}));
132
+ export class PasskeyVerificationError extends Data.TaggedError("PasskeyVerificationError") {
133
+ }
134
+ export class PasskeyVerification extends Context.Service()("auth/PasskeyVerification") {
135
+ }
136
+ (function (PasskeyVerification) {
137
+ PasskeyVerification.make = (service) => PasskeyVerification.of(service);
138
+ })(PasskeyVerification || (PasskeyVerification = {}));
139
+ export class PasskeyOptionsError extends Data.TaggedError("PasskeyOptionsError") {
140
+ }
141
+ export class PasskeyOptions extends Context.Service()("auth/PasskeyOptions") {
142
+ }
143
+ (function (PasskeyOptions) {
144
+ PasskeyOptions.make = (service) => PasskeyOptions.of(service);
145
+ })(PasskeyOptions || (PasskeyOptions = {}));
146
+ const defaultPubKeyCredParams = [
147
+ { type: "public-key", alg: -7 },
148
+ { type: "public-key", alg: -257 },
149
+ ];
150
+ const credentialDescriptor = (credential) => ({
151
+ type: "public-key",
152
+ id: credential.credentialId,
153
+ ...(credential.transports === undefined
154
+ ? {}
155
+ : { transports: credential.transports }),
156
+ });
157
+ const issuePasskeyChallenge = (dependencies, input) => Effect.gen(function* () {
158
+ const secret = Redacted.make(yield* dependencies.crypto.randomToken(input.challengeBytes ?? defaultPasskeyChallengeBytes));
159
+ const issued = yield* dependencies.challenge.issue({
160
+ type: input.type,
161
+ subject: input.subject,
162
+ ttl: input.ttl ?? defaultPasskeyChallengeTtl,
163
+ secret,
164
+ metadata: input.metadata,
165
+ });
166
+ return {
167
+ challengeId: issued.id,
168
+ challenge: Redacted.value(secret),
169
+ expiresAt: issued.expiresAt,
170
+ };
171
+ }).pipe(Effect.mapError((cause) => new PasskeyOptionsError({
172
+ message: "Failed to issue passkey challenge",
173
+ cause,
174
+ })));
175
+ const userCredentials = (credentialStore, userId) => credentialStore === undefined
176
+ ? Effect.succeed([])
177
+ : credentialStore.listByUser({ userId }).pipe(Effect.mapError((cause) => new PasskeyOptionsError({
178
+ message: "Failed to load passkey credentials",
179
+ cause,
180
+ })));
181
+ const nonEmptyDescriptors = (descriptors) => descriptors.length === 0 ? undefined : descriptors;
182
+ const passkeyVerificationError = (operation, message, cause) => new PasskeyVerificationError({
183
+ operation,
184
+ message,
185
+ ...(cause === undefined ? {} : { cause }),
186
+ });
187
+ const mergeMetadata = (...values) => {
188
+ let merged;
189
+ for (const value of values) {
190
+ if (value === undefined) {
191
+ continue;
192
+ }
193
+ merged ??= {};
194
+ Object.assign(merged, value);
195
+ }
196
+ return merged;
197
+ };
198
+ const validateSignCount = (operation, signCount) => Number.isInteger(signCount) && signCount >= 0
199
+ ? Effect.succeed(signCount)
200
+ : Effect.fail(passkeyVerificationError(operation, "Invalid passkey sign count"));
201
+ const makeCredentialRecordId = (dependencies, operation) => dependencies.crypto
202
+ .randomToken(dependencies.credentialRecordIdBytes ?? 16)
203
+ .pipe(Effect.map(CredentialId), Effect.mapError((cause) => passkeyVerificationError(operation, "Failed to generate passkey credential record id", cause)));
204
+ const verifyStoredPasskeyChallenge = (dependencies, operation, input) => dependencies.challenge
205
+ .verify({
206
+ challengeId: input.challengeId,
207
+ type: input.type,
208
+ secret: Redacted.make(input.challenge),
209
+ })
210
+ .pipe(Effect.mapError((cause) => passkeyVerificationError(operation, "Invalid passkey challenge", cause)));
211
+ export const makePasskeyVerification = (dependencies) => PasskeyVerification.make({
212
+ finishRegistration: Effect.fn("auth.passkey.finish_registration")(function* (input) {
213
+ const operation = "finish-registration";
214
+ const verified = yield* dependencies.verifier
215
+ .verifyRegistration({
216
+ response: input.response,
217
+ relyingPartyId: input.relyingPartyId,
218
+ expectedOrigin: input.expectedOrigin,
219
+ userId: input.userId,
220
+ ...(input.requireUserVerification === undefined
221
+ ? {}
222
+ : { requireUserVerification: input.requireUserVerification }),
223
+ ...(input.metadata === undefined ? {} : { metadata: input.metadata }),
224
+ })
225
+ .pipe(Effect.mapError((cause) => passkeyVerificationError(operation, "Failed to verify passkey registration response", cause)));
226
+ const signCount = yield* validateSignCount(operation, verified.signCount);
227
+ const existingCredential = yield* dependencies.credentialStore
228
+ .findByCredentialId(verified.credentialId)
229
+ .pipe(Effect.mapError((cause) => passkeyVerificationError(operation, "Failed to load passkey credential", cause)));
230
+ if (Option.isSome(existingCredential)) {
231
+ return yield* passkeyVerificationError(operation, "Passkey credential already exists");
232
+ }
233
+ const challenge = yield* verifyStoredPasskeyChallenge(dependencies, operation, {
234
+ challengeId: input.challengeId,
235
+ type: passkeyRegistrationChallengeType,
236
+ challenge: verified.challenge,
237
+ });
238
+ if (challenge.subject !== input.userId) {
239
+ return yield* passkeyVerificationError(operation, "Passkey registration subject mismatch");
240
+ }
241
+ const now = input.now ?? (yield* currentUnixMillis);
242
+ const credentialMetadata = mergeMetadata(input.metadata, verified.metadata);
243
+ const credential = {
244
+ id: input.recordId ??
245
+ (yield* makeCredentialRecordId(dependencies, operation)),
246
+ userId: input.userId,
247
+ credentialId: verified.credentialId,
248
+ publicKey: verified.publicKey,
249
+ signCount,
250
+ ...(verified.transports === undefined
251
+ ? {}
252
+ : { transports: verified.transports }),
253
+ ...(verified.backedUp === undefined ? {} : { backedUp: verified.backedUp }),
254
+ createdAt: now,
255
+ ...(credentialMetadata === undefined
256
+ ? {}
257
+ : { metadata: credentialMetadata }),
258
+ };
259
+ yield* dependencies.credentialStore.insert(credential).pipe(Effect.mapError((cause) => passkeyVerificationError(operation, "Failed to store passkey credential", cause)));
260
+ return {
261
+ challengeId: challenge.id,
262
+ userId: input.userId,
263
+ credential,
264
+ };
265
+ }),
266
+ finishAuthentication: Effect.fn("auth.passkey.finish_authentication")(function* (input) {
267
+ const operation = "finish-authentication";
268
+ const credentialId = yield* dependencies.verifier
269
+ .readAuthenticationCredentialId({ response: input.response })
270
+ .pipe(Effect.mapError((cause) => passkeyVerificationError(operation, "Failed to read passkey credential id", cause)));
271
+ const credentialOption = yield* dependencies.credentialStore
272
+ .findByCredentialId(credentialId)
273
+ .pipe(Effect.mapError((cause) => passkeyVerificationError(operation, "Failed to load passkey credential", cause)));
274
+ if (Option.isNone(credentialOption)) {
275
+ return yield* passkeyVerificationError(operation, "Passkey credential not found");
276
+ }
277
+ const credential = credentialOption.value;
278
+ if (credential.revokedAt !== undefined) {
279
+ return yield* passkeyVerificationError(operation, "Passkey credential revoked");
280
+ }
281
+ if (input.userId !== undefined && credential.userId !== input.userId) {
282
+ return yield* passkeyVerificationError(operation, "Passkey credential user mismatch");
283
+ }
284
+ const verified = yield* dependencies.verifier
285
+ .verifyAuthentication({
286
+ response: input.response,
287
+ credential,
288
+ relyingPartyId: input.relyingPartyId,
289
+ expectedOrigin: input.expectedOrigin,
290
+ ...(input.requireUserVerification === undefined
291
+ ? {}
292
+ : { requireUserVerification: input.requireUserVerification }),
293
+ ...(input.metadata === undefined ? {} : { metadata: input.metadata }),
294
+ })
295
+ .pipe(Effect.mapError((cause) => passkeyVerificationError(operation, "Failed to verify passkey authentication response", cause)));
296
+ const signCount = yield* validateSignCount(operation, verified.newSignCount);
297
+ if (verified.credentialId !== credential.credentialId) {
298
+ return yield* passkeyVerificationError(operation, "Passkey authentication credential mismatch");
299
+ }
300
+ const challenge = yield* verifyStoredPasskeyChallenge(dependencies, operation, {
301
+ challengeId: input.challengeId,
302
+ type: passkeyAuthenticationChallengeType,
303
+ challenge: verified.challenge,
304
+ });
305
+ if (input.userId !== undefined
306
+ ? challenge.subject !== input.userId
307
+ : challenge.subject !== credential.userId &&
308
+ challenge.subject !== input.relyingPartyId) {
309
+ return yield* passkeyVerificationError(operation, "Passkey authentication subject mismatch");
310
+ }
311
+ const now = input.now ?? (yield* currentUnixMillis);
312
+ const credentialMetadata = mergeMetadata(credential.metadata, input.metadata, verified.metadata);
313
+ const updatedCredential = yield* dependencies.credentialStore
314
+ .updateSignCount({
315
+ credentialId: credential.credentialId,
316
+ signCount,
317
+ lastUsedAt: now,
318
+ ...(credentialMetadata === undefined
319
+ ? {}
320
+ : { metadata: credentialMetadata }),
321
+ })
322
+ .pipe(Effect.mapError((cause) => passkeyVerificationError(operation, "Failed to update passkey credential", cause)));
323
+ if (Option.isNone(updatedCredential)) {
324
+ return yield* passkeyVerificationError(operation, "Passkey credential unavailable");
325
+ }
326
+ return {
327
+ challengeId: challenge.id,
328
+ userId: updatedCredential.value.userId,
329
+ credential: updatedCredential.value,
330
+ };
331
+ }),
332
+ });
333
+ export const makePasskeyOptions = (dependencies) => PasskeyOptions.make({
334
+ startRegistration: Effect.fn("auth.passkey.start_registration")(function* (input) {
335
+ const credentials = yield* userCredentials(dependencies.credentialStore, input.userId);
336
+ const issued = yield* issuePasskeyChallenge(dependencies, {
337
+ type: passkeyRegistrationChallengeType,
338
+ subject: input.userId,
339
+ ttl: input.ttl,
340
+ challengeBytes: input.challengeBytes,
341
+ metadata: input.metadata,
342
+ });
343
+ const excludeCredentials = input.excludeCredentials ?? credentials.map(credentialDescriptor);
344
+ return {
345
+ challengeId: issued.challengeId,
346
+ expiresAt: issued.expiresAt,
347
+ publicKey: {
348
+ challenge: issued.challenge,
349
+ rp: input.relyingParty,
350
+ user: {
351
+ id: input.userId,
352
+ name: input.userName,
353
+ displayName: input.userDisplayName,
354
+ },
355
+ pubKeyCredParams: input.pubKeyCredParams ?? defaultPubKeyCredParams,
356
+ ...(input.timeout === undefined ? {} : { timeout: input.timeout }),
357
+ ...(nonEmptyDescriptors(excludeCredentials) === undefined
358
+ ? {}
359
+ : { excludeCredentials }),
360
+ ...(input.authenticatorSelection === undefined
361
+ ? {}
362
+ : { authenticatorSelection: input.authenticatorSelection }),
363
+ ...(input.attestation === undefined ? {} : { attestation: input.attestation }),
364
+ },
365
+ };
366
+ }),
367
+ startAuthentication: Effect.fn("auth.passkey.start_authentication")(function* (input) {
368
+ const credentials = input.allowCredentials ??
369
+ (input.userId === undefined
370
+ ? []
371
+ : (yield* userCredentials(dependencies.credentialStore, input.userId)).map(credentialDescriptor));
372
+ const issued = yield* issuePasskeyChallenge(dependencies, {
373
+ type: passkeyAuthenticationChallengeType,
374
+ subject: input.userId ?? input.relyingPartyId,
375
+ ttl: input.ttl,
376
+ challengeBytes: input.challengeBytes,
377
+ metadata: input.metadata,
378
+ });
379
+ return {
380
+ challengeId: issued.challengeId,
381
+ expiresAt: issued.expiresAt,
382
+ publicKey: {
383
+ challenge: issued.challenge,
384
+ rpId: input.relyingPartyId,
385
+ ...(input.timeout === undefined ? {} : { timeout: input.timeout }),
386
+ ...(nonEmptyDescriptors(credentials) === undefined
387
+ ? {}
388
+ : { allowCredentials: credentials }),
389
+ ...(input.userVerification === undefined
390
+ ? {}
391
+ : { userVerification: input.userVerification }),
392
+ },
393
+ };
394
+ }),
395
+ });
396
+ export const PasskeyOptionsLive = Layer.effect(PasskeyOptions)(Effect.gen(function* () {
397
+ const challenge = yield* Challenge;
398
+ const crypto = yield* Crypto;
399
+ const credentialStore = yield* Effect.serviceOption(PasskeyCredentialStore);
400
+ return makePasskeyOptions({
401
+ challenge,
402
+ crypto,
403
+ ...(Option.isSome(credentialStore)
404
+ ? { credentialStore: credentialStore.value }
405
+ : {}),
406
+ });
407
+ }));
408
+ export const PasskeyVerificationLive = (options) => Layer.effect(PasskeyVerification)(Effect.gen(function* () {
409
+ const challenge = yield* Challenge;
410
+ const crypto = yield* Crypto;
411
+ const credentialStore = yield* PasskeyCredentialStore;
412
+ const verifier = yield* PasskeyVerifier;
413
+ return makePasskeyVerification({
414
+ ...options,
415
+ challenge,
416
+ crypto,
417
+ credentialStore,
418
+ verifier,
419
+ });
420
+ }));
421
+ export const PasskeyFeatureLive = PasskeyOptionsLive;
422
+ //# sourceMappingURL=Passkey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Passkey.js","sourceRoot":"","sources":["../src/Passkey.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { verifyAuthenticationResponse as simpleWebAuthnVerifyAuthenticationResponse, verifyRegistrationResponse as simpleWebAuthnVerifyRegistrationResponse } from "@simplewebauthn/server";
2
+ import { Layer } from "effect";
3
+ import { PasskeyVerifier } from "./Passkey.js";
4
+ import type { PasskeyVerifierService } from "./Passkey.js";
5
+ export interface SimpleWebAuthnPasskeyVerifierOptions {
6
+ readonly verifyRegistrationResponse?: typeof simpleWebAuthnVerifyRegistrationResponse;
7
+ readonly verifyAuthenticationResponse?: typeof simpleWebAuthnVerifyAuthenticationResponse;
8
+ }
9
+ export declare const makeSimpleWebAuthnPasskeyVerifier: (options?: SimpleWebAuthnPasskeyVerifierOptions) => PasskeyVerifierService;
10
+ export declare const SimpleWebAuthnPasskeyVerifierLive: Layer.Layer<PasskeyVerifier, never, never>;
11
+ //# sourceMappingURL=PasskeySimpleWebAuthn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PasskeySimpleWebAuthn.d.ts","sourceRoot":"","sources":["../src/PasskeySimpleWebAuthn.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,IAAI,0CAA0C,EAC1E,0BAA0B,IAAI,wCAAwC,EACvE,MAAM,wBAAwB,CAAC;AAMhC,OAAO,EAAoB,KAAK,EAAU,MAAM,QAAQ,CAAC;AAEzD,OAAO,EAEL,eAAe,EAEhB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAIV,sBAAsB,EACvB,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,oCAAoC;IACnD,QAAQ,CAAC,0BAA0B,CAAC,EAAE,OAAO,wCAAwC,CAAC;IACtF,QAAQ,CAAC,4BAA4B,CAAC,EAAE,OAAO,0CAA0C,CAAC;CAC3F;AAkMD,eAAO,MAAM,iCAAiC,GAC5C,UAAS,oCAAyC,KACjD,sBAgHF,CAAC;AAEF,eAAO,MAAM,iCAAiC,4CAG7C,CAAC"}
@@ -0,0 +1,181 @@
1
+ import { verifyAuthenticationResponse as simpleWebAuthnVerifyAuthenticationResponse, verifyRegistrationResponse as simpleWebAuthnVerifyRegistrationResponse, } from "@simplewebauthn/server";
2
+ import { Effect, Encoding, Layer, Result } from "effect";
3
+ import { PasskeyCredentialId, PasskeyVerifier, PasskeyVerifierError, } from "./Passkey.js";
4
+ const textDecoder = new TextDecoder();
5
+ const verifierError = (operation, message, cause) => new PasskeyVerifierError({
6
+ operation,
7
+ message,
8
+ ...(cause === undefined ? {} : { cause }),
9
+ });
10
+ const responseString = (credential, key, operation) => {
11
+ const value = credential.response[key];
12
+ return typeof value === "string"
13
+ ? Effect.succeed(value)
14
+ : Effect.fail(verifierError(operation, `Missing ${key}`));
15
+ };
16
+ const optionalResponseString = (credential, key, operation) => {
17
+ const value = credential.response[key];
18
+ return value === undefined
19
+ ? Effect.succeed(undefined)
20
+ : typeof value === "string"
21
+ ? Effect.succeed(value)
22
+ : Effect.fail(verifierError(operation, `Invalid ${key}`));
23
+ };
24
+ const decodeBase64UrlBytes = (value, operation) => Result.match(Encoding.decodeBase64Url(value), {
25
+ onSuccess: Effect.succeed,
26
+ onFailure: (cause) => Effect.fail(verifierError(operation, "Invalid base64url value", cause)),
27
+ });
28
+ const clientDataChallenge = (clientDataJSON, operation) => decodeBase64UrlBytes(clientDataJSON, operation).pipe(Effect.flatMap((bytes) => Effect.try({
29
+ try: () => JSON.parse(textDecoder.decode(bytes)),
30
+ catch: (cause) => verifierError(operation, "Invalid clientDataJSON", cause),
31
+ })), Effect.flatMap((clientData) => typeof clientData.challenge === "string"
32
+ ? Effect.succeed(clientData.challenge)
33
+ : Effect.fail(verifierError(operation, "Missing clientData challenge"))));
34
+ const expectedOrigin = (origin) => typeof origin === "string" ? origin : [...origin];
35
+ const passkeyAuthenticatorAttachment = (credential, operation) => {
36
+ const attachment = credential.authenticatorAttachment;
37
+ return attachment === undefined
38
+ ? Effect.succeed(undefined)
39
+ : attachment === "cross-platform" || attachment === "platform"
40
+ ? Effect.succeed(attachment)
41
+ : Effect.fail(verifierError(operation, "Invalid authenticatorAttachment"));
42
+ };
43
+ const stringArrayResponse = (credential, key, operation) => {
44
+ const value = credential.response[key];
45
+ return value === undefined
46
+ ? Effect.succeed(undefined)
47
+ : Array.isArray(value) && value.every((item) => typeof item === "string")
48
+ ? Effect.succeed(value)
49
+ : Effect.fail(verifierError(operation, `Invalid ${key}`));
50
+ };
51
+ const registrationResponseForSimpleWebAuthn = (credential) => Effect.gen(function* () {
52
+ const operation = "verify-registration";
53
+ const clientDataJSON = yield* responseString(credential, "clientDataJSON", operation);
54
+ const attestationObject = yield* responseString(credential, "attestationObject", operation);
55
+ const attachment = yield* passkeyAuthenticatorAttachment(credential, operation);
56
+ const transports = yield* stringArrayResponse(credential, "transports", operation);
57
+ return {
58
+ id: credential.id,
59
+ rawId: credential.rawId ?? credential.id,
60
+ type: credential.type,
61
+ response: {
62
+ clientDataJSON,
63
+ attestationObject,
64
+ ...(transports === undefined
65
+ ? {}
66
+ : {
67
+ transports: transports,
68
+ }),
69
+ },
70
+ ...(attachment === undefined ? {} : { authenticatorAttachment: attachment }),
71
+ clientExtensionResults: credential.clientExtensionResults ?? {},
72
+ };
73
+ });
74
+ const authenticationResponseForSimpleWebAuthn = (credential) => Effect.gen(function* () {
75
+ const operation = "verify-authentication";
76
+ const clientDataJSON = yield* responseString(credential, "clientDataJSON", operation);
77
+ const authenticatorData = yield* responseString(credential, "authenticatorData", operation);
78
+ const signature = yield* responseString(credential, "signature", operation);
79
+ const userHandle = yield* optionalResponseString(credential, "userHandle", operation);
80
+ const attachment = yield* passkeyAuthenticatorAttachment(credential, operation);
81
+ return {
82
+ id: credential.id,
83
+ rawId: credential.rawId ?? credential.id,
84
+ type: credential.type,
85
+ response: {
86
+ clientDataJSON,
87
+ authenticatorData,
88
+ signature,
89
+ ...(userHandle === undefined ? {} : { userHandle }),
90
+ },
91
+ ...(attachment === undefined ? {} : { authenticatorAttachment: attachment }),
92
+ clientExtensionResults: credential.clientExtensionResults ?? {},
93
+ };
94
+ });
95
+ const credentialForSimpleWebAuthn = (credential) => decodeBase64UrlBytes(credential.publicKey, "verify-authentication").pipe(Effect.map((publicKey) => ({
96
+ id: credential.credentialId,
97
+ publicKey: new Uint8Array(publicKey),
98
+ counter: credential.signCount,
99
+ ...(credential.transports === undefined
100
+ ? {}
101
+ : {
102
+ transports: credential.transports,
103
+ }),
104
+ })));
105
+ export const makeSimpleWebAuthnPasskeyVerifier = (options = {}) => {
106
+ const verifyRegistrationResponse = options.verifyRegistrationResponse ?? simpleWebAuthnVerifyRegistrationResponse;
107
+ const verifyAuthenticationResponse = options.verifyAuthenticationResponse ?? simpleWebAuthnVerifyAuthenticationResponse;
108
+ return PasskeyVerifier.make({
109
+ readAuthenticationCredentialId: ({ response }) => Effect.succeed(PasskeyCredentialId(response.id)),
110
+ verifyRegistration: (input) => Effect.gen(function* () {
111
+ const response = yield* registrationResponseForSimpleWebAuthn(input.response);
112
+ const challenge = yield* clientDataChallenge(response.response.clientDataJSON, "verify-registration");
113
+ const result = yield* Effect.tryPromise({
114
+ try: () => verifyRegistrationResponse({
115
+ response,
116
+ expectedChallenge: challenge,
117
+ expectedOrigin: expectedOrigin(input.expectedOrigin),
118
+ expectedRPID: input.relyingPartyId,
119
+ ...(input.requireUserVerification === undefined
120
+ ? {}
121
+ : { requireUserVerification: input.requireUserVerification }),
122
+ }),
123
+ catch: (cause) => verifierError("verify-registration", "Failed to verify registration response", cause),
124
+ });
125
+ const info = result.registrationInfo;
126
+ if (!result.verified || info === undefined) {
127
+ return yield* verifierError("verify-registration", "Passkey registration was not verified");
128
+ }
129
+ return {
130
+ challenge,
131
+ credentialId: PasskeyCredentialId(info.credential.id),
132
+ publicKey: Encoding.encodeBase64Url(info.credential.publicKey),
133
+ signCount: info.credential.counter,
134
+ ...(info.credential.transports === undefined
135
+ ? {}
136
+ : { transports: info.credential.transports }),
137
+ backedUp: info.credentialBackedUp,
138
+ metadata: {
139
+ credentialDeviceType: info.credentialDeviceType,
140
+ origin: info.origin,
141
+ ...(info.rpID === undefined ? {} : { rpId: info.rpID }),
142
+ },
143
+ };
144
+ }),
145
+ verifyAuthentication: (input) => Effect.gen(function* () {
146
+ const response = yield* authenticationResponseForSimpleWebAuthn(input.response);
147
+ const challenge = yield* clientDataChallenge(response.response.clientDataJSON, "verify-authentication");
148
+ const credential = yield* credentialForSimpleWebAuthn(input.credential);
149
+ const result = yield* Effect.tryPromise({
150
+ try: () => verifyAuthenticationResponse({
151
+ response,
152
+ expectedChallenge: challenge,
153
+ expectedOrigin: expectedOrigin(input.expectedOrigin),
154
+ expectedRPID: input.relyingPartyId,
155
+ credential,
156
+ ...(input.requireUserVerification === undefined
157
+ ? {}
158
+ : { requireUserVerification: input.requireUserVerification }),
159
+ }),
160
+ catch: (cause) => verifierError("verify-authentication", "Failed to verify authentication response", cause),
161
+ });
162
+ const info = result.authenticationInfo;
163
+ if (!result.verified) {
164
+ return yield* verifierError("verify-authentication", "Passkey authentication was not verified");
165
+ }
166
+ return {
167
+ challenge,
168
+ credentialId: PasskeyCredentialId(info.credentialID),
169
+ newSignCount: info.newCounter,
170
+ userVerified: info.userVerified,
171
+ metadata: {
172
+ credentialDeviceType: info.credentialDeviceType,
173
+ origin: info.origin,
174
+ rpId: info.rpID,
175
+ },
176
+ };
177
+ }),
178
+ });
179
+ };
180
+ export const SimpleWebAuthnPasskeyVerifierLive = Layer.succeed(PasskeyVerifier, makeSimpleWebAuthnPasskeyVerifier());
181
+ //# sourceMappingURL=PasskeySimpleWebAuthn.js.map