@passlock/client 0.9.32 → 2.0.0-beta.2

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 (180) hide show
  1. package/README.md +14 -86
  2. package/README.template.md +16 -88
  3. package/dist/index.d.ts +4 -206
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +2 -158
  6. package/dist/index.js.map +1 -1
  7. package/dist/logger/index.d.ts +24 -0
  8. package/dist/logger/index.d.ts.map +1 -0
  9. package/dist/logger/index.js +47 -0
  10. package/dist/logger/index.js.map +1 -0
  11. package/dist/network.d.ts +39 -0
  12. package/dist/network.d.ts.map +1 -0
  13. package/dist/network.js +83 -0
  14. package/dist/network.js.map +1 -0
  15. package/dist/passkey/authentication/index.d.ts +21 -0
  16. package/dist/passkey/authentication/index.d.ts.map +1 -0
  17. package/dist/passkey/authentication/index.js +22 -0
  18. package/dist/passkey/authentication/index.js.map +1 -0
  19. package/dist/passkey/authentication/micro.d.ts +71 -0
  20. package/dist/passkey/authentication/micro.d.ts.map +1 -0
  21. package/dist/passkey/authentication/micro.js +107 -0
  22. package/dist/passkey/authentication/micro.js.map +1 -0
  23. package/dist/passkey/index.d.ts +7 -0
  24. package/dist/passkey/index.d.ts.map +1 -0
  25. package/dist/passkey/index.js +5 -0
  26. package/dist/passkey/index.js.map +1 -0
  27. package/dist/passkey/registration/index.d.ts +19 -0
  28. package/dist/passkey/registration/index.d.ts.map +1 -0
  29. package/dist/passkey/registration/index.js +20 -0
  30. package/dist/passkey/registration/index.js.map +1 -0
  31. package/dist/passkey/registration/micro.d.ts +101 -0
  32. package/dist/passkey/registration/micro.d.ts.map +1 -0
  33. package/dist/passkey/registration/micro.js +126 -0
  34. package/dist/passkey/registration/micro.js.map +1 -0
  35. package/dist/passkey/shared.d.ts +24 -0
  36. package/dist/passkey/shared.d.ts.map +1 -0
  37. package/dist/passkey/shared.js +10 -0
  38. package/dist/passkey/shared.js.map +1 -0
  39. package/dist/passkey/support.d.ts +3 -0
  40. package/dist/passkey/support.d.ts.map +1 -0
  41. package/dist/passkey/support.js +4 -0
  42. package/dist/passkey/support.js.map +1 -0
  43. package/dist/passkey/types.d.ts +26 -0
  44. package/dist/passkey/types.d.ts.map +1 -0
  45. package/dist/passkey/types.js +2 -0
  46. package/dist/passkey/types.js.map +1 -0
  47. package/dist/promise.d.ts +15 -0
  48. package/dist/promise.d.ts.map +1 -0
  49. package/dist/promise.js +46 -0
  50. package/dist/promise.js.map +1 -0
  51. package/dist/shared.d.ts +15 -0
  52. package/dist/shared.d.ts.map +1 -0
  53. package/dist/shared.js +2 -0
  54. package/dist/shared.js.map +1 -0
  55. package/dist/tenancy.d.ts +8 -0
  56. package/dist/tenancy.d.ts.map +1 -0
  57. package/dist/tenancy.js +4 -0
  58. package/dist/tenancy.js.map +1 -0
  59. package/package.json +52 -58
  60. package/LICENSE +0 -21
  61. package/dist/authentication/authenticate.d.ts +0 -23
  62. package/dist/authentication/authenticate.fixture.d.ts +0 -52
  63. package/dist/authentication/authenticate.fixture.js +0 -50
  64. package/dist/authentication/authenticate.fixture.js.map +0 -1
  65. package/dist/authentication/authenticate.js +0 -72
  66. package/dist/authentication/authenticate.js.map +0 -1
  67. package/dist/capabilities/capabilities.d.ts +0 -19
  68. package/dist/capabilities/capabilities.js +0 -37
  69. package/dist/capabilities/capabilities.js.map +0 -1
  70. package/dist/connection/connection.d.ts +0 -15
  71. package/dist/connection/connection.fixture.d.ts +0 -10
  72. package/dist/connection/connection.fixture.js +0 -13
  73. package/dist/connection/connection.fixture.js.map +0 -1
  74. package/dist/connection/connection.js +0 -23
  75. package/dist/connection/connection.js.map +0 -1
  76. package/dist/effect.d.ts +0 -26
  77. package/dist/effect.js +0 -78
  78. package/dist/effect.js.map +0 -1
  79. package/dist/email/email.d.ts +0 -70
  80. package/dist/email/email.fixture.d.ts +0 -46
  81. package/dist/email/email.fixture.js +0 -25
  82. package/dist/email/email.fixture.js.map +0 -1
  83. package/dist/email/email.js +0 -83
  84. package/dist/email/email.js.map +0 -1
  85. package/dist/event/event.d.ts +0 -8
  86. package/dist/event/event.js +0 -23
  87. package/dist/event/event.js.map +0 -1
  88. package/dist/logging/eventLogger.d.ts +0 -17
  89. package/dist/logging/eventLogger.js +0 -38
  90. package/dist/logging/eventLogger.js.map +0 -1
  91. package/dist/registration/register.d.ts +0 -25
  92. package/dist/registration/register.fixture.d.ts +0 -53
  93. package/dist/registration/register.fixture.js +0 -66
  94. package/dist/registration/register.fixture.js.map +0 -1
  95. package/dist/registration/register.js +0 -77
  96. package/dist/registration/register.js.map +0 -1
  97. package/dist/rpc/client.d.ts +0 -30
  98. package/dist/rpc/client.js +0 -101
  99. package/dist/rpc/client.js.map +0 -1
  100. package/dist/rpc/config.d.ts +0 -15
  101. package/dist/rpc/config.js +0 -6
  102. package/dist/rpc/config.js.map +0 -1
  103. package/dist/rpc/connection.d.ts +0 -8
  104. package/dist/rpc/connection.js +0 -16
  105. package/dist/rpc/connection.js.map +0 -1
  106. package/dist/rpc/passkey/authentication.d.ts +0 -8
  107. package/dist/rpc/passkey/authentication.js +0 -17
  108. package/dist/rpc/passkey/authentication.js.map +0 -1
  109. package/dist/rpc/passkey/registration.d.ts +0 -8
  110. package/dist/rpc/passkey/registration.js +0 -17
  111. package/dist/rpc/passkey/registration.js.map +0 -1
  112. package/dist/rpc/social.d.ts +0 -10
  113. package/dist/rpc/social.js +0 -19
  114. package/dist/rpc/social.js.map +0 -1
  115. package/dist/rpc/user.d.ts +0 -8
  116. package/dist/rpc/user.js +0 -20
  117. package/dist/rpc/user.js.map +0 -1
  118. package/dist/social/social.d.ts +0 -23
  119. package/dist/social/social.fixture.d.ts +0 -46
  120. package/dist/social/social.fixture.js +0 -31
  121. package/dist/social/social.fixture.js.map +0 -1
  122. package/dist/social/social.js +0 -38
  123. package/dist/social/social.js.map +0 -1
  124. package/dist/storage/storage.d.ts +0 -56
  125. package/dist/storage/storage.fixture.d.ts +0 -4
  126. package/dist/storage/storage.fixture.js +0 -10
  127. package/dist/storage/storage.fixture.js.map +0 -1
  128. package/dist/storage/storage.js +0 -111
  129. package/dist/storage/storage.js.map +0 -1
  130. package/dist/test/fixtures.d.ts +0 -15
  131. package/dist/test/fixtures.js +0 -56
  132. package/dist/test/fixtures.js.map +0 -1
  133. package/dist/tsconfig.tsbuildinfo +0 -1
  134. package/dist/user/user.d.ts +0 -25
  135. package/dist/user/user.fixture.d.ts +0 -12
  136. package/dist/user/user.fixture.js +0 -20
  137. package/dist/user/user.fixture.js.map +0 -1
  138. package/dist/user/user.js +0 -37
  139. package/dist/user/user.js.map +0 -1
  140. package/dist/version.d.ts +0 -1
  141. package/dist/version.js +0 -2
  142. package/dist/version.js.map +0 -1
  143. package/src/authentication/authenticate.fixture.ts +0 -73
  144. package/src/authentication/authenticate.test.ts +0 -249
  145. package/src/authentication/authenticate.ts +0 -143
  146. package/src/capabilities/capabilities.ts +0 -83
  147. package/src/connection/connection.fixture.ts +0 -20
  148. package/src/connection/connection.test.ts +0 -60
  149. package/src/connection/connection.ts +0 -51
  150. package/src/effect.ts +0 -280
  151. package/src/email/email.fixture.ts +0 -44
  152. package/src/email/email.test.ts +0 -186
  153. package/src/email/email.ts +0 -148
  154. package/src/event/event.node.test.ts +0 -21
  155. package/src/event/event.test.ts +0 -37
  156. package/src/event/event.ts +0 -25
  157. package/src/index.ts +0 -407
  158. package/src/logging/eventLogger.test.ts +0 -104
  159. package/src/logging/eventLogger.ts +0 -41
  160. package/src/registration/register.fixture.ts +0 -96
  161. package/src/registration/register.test.ts +0 -216
  162. package/src/registration/register.ts +0 -156
  163. package/src/rpc/client.ts +0 -174
  164. package/src/rpc/config.ts +0 -18
  165. package/src/rpc/connection.ts +0 -32
  166. package/src/rpc/passkey/authentication.ts +0 -52
  167. package/src/rpc/passkey/registration.ts +0 -52
  168. package/src/rpc/social.ts +0 -55
  169. package/src/rpc/user.ts +0 -68
  170. package/src/social/social.fixture.ts +0 -44
  171. package/src/social/social.test.ts +0 -179
  172. package/src/social/social.ts +0 -79
  173. package/src/storage/storage.fixture.ts +0 -16
  174. package/src/storage/storage.test.ts +0 -206
  175. package/src/storage/storage.ts +0 -168
  176. package/src/test/fixtures.ts +0 -70
  177. package/src/user/user.fixture.ts +0 -33
  178. package/src/user/user.test.ts +0 -84
  179. package/src/user/user.ts +0 -71
  180. package/src/version.ts +0 -1
@@ -1,25 +0,0 @@
1
- /**
2
- * Check for an existing user
3
- */
4
- import { Context, Effect as E, Layer } from 'effect';
5
- import type { BadRequest, Disabled, NotFound } from '@passlock/shared/dist/error/error.js';
6
- import type { VerifyEmail } from '@passlock/shared/dist/schema/email.js';
7
- import * as RPC from '../rpc/user.js';
8
- export type Email = {
9
- email: string;
10
- };
11
- export type ResendEmail = VerifyEmail & {
12
- userId: string;
13
- };
14
- export type ResendEmailErrors = BadRequest | NotFound | Disabled;
15
- declare const UserService_base: Context.TagClass<UserService, "@services/UserService", {
16
- isExistingUser: (request: Email) => E.Effect<boolean, BadRequest>;
17
- resendVerificationEmail: (request: ResendEmail) => E.Effect<void, ResendEmailErrors>;
18
- }>;
19
- export declare class UserService extends UserService_base {
20
- }
21
- type Dependencies = RPC.UserClient;
22
- export declare const isExistingUser: (request: Email) => E.Effect<boolean, BadRequest, Dependencies>;
23
- export declare const resendVerificationEmail: (request: ResendEmail) => E.Effect<void, ResendEmailErrors, Dependencies>;
24
- export declare const UserServiceLive: Layer.Layer<UserService, never, RPC.UserClient>;
25
- export {};
@@ -1,12 +0,0 @@
1
- import { Layer as L } from 'effect';
2
- import { IsExistingUserRequest, IsExistingUserResponse, ResendEmailRequest, ResendEmailResponse, VerifyEmailResponse } from '@passlock/shared/dist/rpc/user.js';
3
- import { UserClient } from '../rpc/user.js';
4
- import type { ResendEmail } from './user.js';
5
- export declare const email = "jdoe@gmail.com";
6
- export declare const isRegisteredReq: IsExistingUserRequest;
7
- export declare const isRegisteredRes: IsExistingUserResponse;
8
- export declare const verifyEmailRes: VerifyEmailResponse;
9
- export declare const resendEmailReq: ResendEmail;
10
- export declare const rpcResendEmailReq: ResendEmailRequest;
11
- export declare const rpcResendEmailRes: ResendEmailResponse;
12
- export declare const rpcClientTest: L.Layer<UserClient, never, never>;
@@ -1,20 +0,0 @@
1
- import { Effect as E, Layer as L, Option as O } from 'effect';
2
- import { IsExistingUserRequest, IsExistingUserResponse, ResendEmailRequest, ResendEmailResponse, VerifyEmailResponse, } from '@passlock/shared/dist/rpc/user.js';
3
- import * as Fixtures from '../test/fixtures.js';
4
- import { UserClient } from '../rpc/user.js';
5
- export const email = 'jdoe@gmail.com';
6
- export const isRegisteredReq = new IsExistingUserRequest({ email });
7
- export const isRegisteredRes = new IsExistingUserResponse({ existingUser: false, detail: O.none() });
8
- export const verifyEmailRes = new VerifyEmailResponse({ principal: Fixtures.principal });
9
- export const resendEmailReq = { userId: '123', method: 'code' };
10
- export const rpcResendEmailReq = new ResendEmailRequest({
11
- userId: '123',
12
- verifyEmail: { method: 'code' },
13
- });
14
- export const rpcResendEmailRes = new ResendEmailResponse({});
15
- export const rpcClientTest = L.succeed(UserClient, UserClient.of({
16
- isExistingUser: () => E.succeed({ existingUser: true, detail: O.none() }),
17
- verifyEmail: () => E.succeed(verifyEmailRes),
18
- resendVerificationEmail: () => E.fail(Fixtures.notImplemented),
19
- }));
20
- //# sourceMappingURL=user.fixture.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"user.fixture.js","sourceRoot":"","sources":["../../src/user/user.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAE7D,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,mCAAmC,CAAA;AAE1C,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAG3C,MAAM,CAAC,MAAM,KAAK,GAAG,gBAAgB,CAAA;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,qBAAqB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;AACnE,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,sBAAsB,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;AACpG,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,mBAAmB,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAA;AACxF,MAAM,CAAC,MAAM,cAAc,GAAgB,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAA;AAC5E,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,kBAAkB,CAAC;IACtD,MAAM,EAAE,KAAK;IACb,WAAW,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;CAChC,CAAC,CAAA;AACF,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,mBAAmB,CAAC,EAAE,CAAC,CAAA;AAE5D,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,OAAO,CACpC,UAAU,EACV,UAAU,CAAC,EAAE,CAAC;IACZ,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;IACzE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC;IAC5C,uBAAuB,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC;CAC/D,CAAC,CACH,CAAA"}
package/dist/user/user.js DELETED
@@ -1,37 +0,0 @@
1
- /**
2
- * Check for an existing user
3
- */
4
- import { Context, Effect as E, Layer, flow } from 'effect';
5
- import * as RPC from '../rpc/user.js';
6
- /* Service */
7
- export class UserService extends Context.Tag('@services/UserService')() {
8
- }
9
- export const isExistingUser = (request) => {
10
- return E.gen(function* (_) {
11
- yield* _(E.logInfo('Checking registration status'));
12
- const rpcClient = yield* _(RPC.UserClient);
13
- yield* _(E.logDebug('Making RPC request'));
14
- const { existingUser } = yield* _(rpcClient.isExistingUser(new RPC.IsExistingUserRequest(request)));
15
- return existingUser;
16
- });
17
- };
18
- export const resendVerificationEmail = (request) => {
19
- return E.gen(function* (_) {
20
- yield* _(E.logInfo('Resending verification email'));
21
- const rpcClient = yield* _(RPC.UserClient);
22
- yield* _(E.logDebug('Making RPC request'));
23
- const { userId, ...verifyEmail } = request;
24
- yield* _(rpcClient.resendVerificationEmail(new RPC.ResendEmailRequest({ userId, verifyEmail })));
25
- });
26
- };
27
- /* Live */
28
- /* v8 ignore start */
29
- export const UserServiceLive = Layer.effect(UserService, E.gen(function* (_) {
30
- const context = yield* _(E.context());
31
- return UserService.of({
32
- isExistingUser: flow(isExistingUser, E.provide(context)),
33
- resendVerificationEmail: flow(resendVerificationEmail, E.provide(context)),
34
- });
35
- }));
36
- /* v8 ignore stop */
37
- //# sourceMappingURL=user.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"user.js","sourceRoot":"","sources":["../../src/user/user.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAI1D,OAAO,KAAK,GAAG,MAAM,gBAAgB,CAAA;AAWrC,aAAa;AAEb,MAAM,OAAO,WAAY,SAAQ,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,EAMlE;CAAG;AAMN,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,OAAc,EAA+C,EAAE;IAC5F,OAAO,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC,CAAA;QACnD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QAE1C,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAA;QAC1C,MAAM,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QAEnG,OAAO,YAAY,CAAA;IACrB,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,OAAoB,EAC6B,EAAE;IACnD,OAAO,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC,CAAA;QACnD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QAE1C,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAA;QAC1C,MAAM,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,GAAG,OAAO,CAAA;QAC1C,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,IAAI,GAAG,CAAC,kBAAkB,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,CAAA;IAClG,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AAED,UAAU;AAEV,qBAAqB;AACrB,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,CACzC,WAAW,EACX,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;IAChB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAkB,CAAC,CAAA;IACrD,OAAO,WAAW,CAAC,EAAE,CAAC;QACpB,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACxD,uBAAuB,EAAE,IAAI,CAAC,uBAAuB,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;KAC3E,CAAC,CAAA;AACJ,CAAC,CAAC,CACH,CAAA;AACD,oBAAoB"}
package/dist/version.d.ts DELETED
@@ -1 +0,0 @@
1
- export declare const PASSLOCK_CLIENT_VERSION = "0.9.32";
package/dist/version.js DELETED
@@ -1,2 +0,0 @@
1
- export const PASSLOCK_CLIENT_VERSION = '0.9.32';
2
- //# sourceMappingURL=version.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,uBAAuB,GAAG,YAAY,CAAA"}
@@ -1,73 +0,0 @@
1
- import { Effect as E, Layer as L, Option as O } from 'effect'
2
-
3
- import {
4
- OptionsResponse,
5
- VerificationRequest,
6
- VerificationResponse,
7
- } from '@passlock/shared/dist/rpc/passkey/authentication.js'
8
- import { IsExistingUserResponse, VerifyEmailResponse } from '@passlock/shared/dist/rpc/user.js'
9
- import type { AuthenticationCredential } from '@passlock/shared/dist/schema/passkey.js'
10
-
11
- import * as Fixtures from '../test/fixtures.js'
12
- import { AuthenticationClient } from '../rpc/passkey/authentication.js'
13
- import { type AuthenticationRequest, GetCredential } from './authenticate.js'
14
-
15
- export const session = 'session'
16
- export const token = 'token'
17
- export const code = 'code'
18
- export const authType = 'passkey'
19
- export const expireAt = Date.now() + 10000
20
-
21
- export const request: AuthenticationRequest = {
22
- userVerification: O.some('preferred'),
23
- email: O.none(),
24
- }
25
-
26
- export const rpcOptionsRes = new OptionsResponse({
27
- session,
28
- publicKey: {
29
- rpId: 'passlock.dev',
30
- challenge: 'FKZSl_saKu5OXjLLwoq8eK3wlD8XgpGiS10SszW5RiE',
31
- timeout: 60000,
32
- userVerification: 'preferred',
33
- },
34
- })
35
-
36
- export const credential: AuthenticationCredential = {
37
- id: '1',
38
- type: 'public-key',
39
- rawId: 'id',
40
- response: {
41
- clientDataJSON: '',
42
- authenticatorData: '',
43
- signature: '',
44
- userHandle: null,
45
- },
46
- clientExtensionResults: {},
47
- authenticatorAttachment: null,
48
- }
49
-
50
- export const rpcVerificationReq = new VerificationRequest({ session, credential })
51
-
52
- export const rpcVerificationRes = new VerificationResponse({ principal: Fixtures.principal })
53
-
54
- export const rpcIsExistingUserRes = new IsExistingUserResponse({ existingUser: true, detail: O.none() })
55
-
56
- export const rpcVerifyEmailRes = new VerifyEmailResponse({ principal: Fixtures.principal })
57
-
58
- export const getCredentialTest = L.succeed(
59
- GetCredential,
60
- GetCredential.of({ getCredential: () => E.succeed(credential) }),
61
- )
62
-
63
- export const rpcClientTest = L.succeed(
64
- AuthenticationClient,
65
- AuthenticationClient.of({
66
- getAuthenticationOptions: () => E.succeed(rpcOptionsRes),
67
- verifyAuthenticationCredential: () => E.succeed(rpcVerificationRes),
68
- }),
69
- )
70
-
71
- export const principal = Fixtures.principal
72
- export const capabilitiesTest = Fixtures.capabilitiesTest
73
- export const storageServiceTest = Fixtures.storageServiceTest
@@ -1,249 +0,0 @@
1
- import { Effect as E, Layer as L, Layer, LogLevel, Logger, Option as O, pipe } from 'effect'
2
- import { describe, expect, test, vi } from 'vitest'
3
- import { mock } from 'vitest-mock-extended'
4
-
5
- import * as Fixture from './authenticate.fixture.js'
6
- import { AuthenticationClient } from '../rpc/passkey/authentication.js'
7
- import { StorageService } from '../storage/storage.js'
8
- import { AuthenticateServiceLive, AuthenticationService, GetCredential } from './authenticate.js'
9
-
10
- describe('authenticate should', () => {
11
- test('return a valid principal', async () => {
12
- const assertions = E.gen(function* (_) {
13
- const service = yield* _(AuthenticationService)
14
-
15
- const result = yield* _(
16
- service.authenticatePasskey({
17
- email: O.none(),
18
- userVerification: O.some('preferred'),
19
- }),
20
- )
21
-
22
- expect(result).toEqual(Fixture.principal)
23
- })
24
-
25
- const service = pipe(
26
- AuthenticateServiceLive,
27
- L.provide(Fixture.getCredentialTest),
28
- L.provide(Fixture.capabilitiesTest),
29
- L.provide(Fixture.storageServiceTest),
30
- L.provide(Fixture.rpcClientTest),
31
- )
32
-
33
- const effect = pipe(E.provide(assertions, service), Logger.withMinimumLogLevel(LogLevel.None))
34
-
35
- return E.runPromise(effect)
36
- })
37
-
38
- test('pass the authentication request to the backend', async () => {
39
- const assertions = E.gen(function* (_) {
40
- const service = yield* _(AuthenticationService)
41
-
42
- yield* _(
43
- service.authenticatePasskey({
44
- email: O.none(),
45
- userVerification: O.some('preferred'),
46
- }),
47
- )
48
-
49
- const rpcClient = yield* _(AuthenticationClient)
50
- expect(rpcClient.getAuthenticationOptions).toHaveBeenCalledOnce()
51
- expect(rpcClient.verifyAuthenticationCredential).toHaveBeenCalledOnce()
52
- })
53
-
54
- const rpcClientTest = L.effect(
55
- AuthenticationClient,
56
- E.sync(() => {
57
- const rpcMock = mock<AuthenticationClient['Type']>()
58
-
59
- rpcMock.getAuthenticationOptions.mockReturnValue(E.succeed(Fixture.rpcOptionsRes))
60
- rpcMock.verifyAuthenticationCredential.mockReturnValue(
61
- E.succeed(Fixture.rpcVerificationRes),
62
- )
63
-
64
- return rpcMock
65
- }),
66
- )
67
-
68
- const service = pipe(
69
- AuthenticateServiceLive,
70
- L.provide(Fixture.getCredentialTest),
71
- L.provide(Fixture.capabilitiesTest),
72
- L.provide(Fixture.storageServiceTest),
73
- L.provide(rpcClientTest),
74
- )
75
-
76
- const layers = Layer.merge(service, rpcClientTest)
77
- const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None))
78
-
79
- return E.runPromise(effect)
80
- })
81
-
82
- test('send the credential to the backend', async () => {
83
- const assertions = E.gen(function* (_) {
84
- const service = yield* _(AuthenticationService)
85
-
86
- yield* _(
87
- service.authenticatePasskey({
88
- email: O.none(),
89
- userVerification: O.some('preferred'),
90
- }),
91
- )
92
-
93
- const rpcClient = yield* _(AuthenticationClient)
94
- expect(rpcClient.getAuthenticationOptions).toHaveBeenCalledOnce()
95
- expect(rpcClient.verifyAuthenticationCredential).toHaveBeenCalledWith(
96
- Fixture.rpcVerificationReq,
97
- )
98
- })
99
-
100
- const rpcClientTest = L.effect(
101
- AuthenticationClient,
102
- E.sync(() => {
103
- const rpcMock = mock<AuthenticationClient['Type']>()
104
-
105
- rpcMock.getAuthenticationOptions.mockReturnValue(E.succeed(Fixture.rpcOptionsRes))
106
- rpcMock.verifyAuthenticationCredential.mockReturnValue(
107
- E.succeed(Fixture.rpcVerificationRes),
108
- )
109
-
110
- return rpcMock
111
- }),
112
- )
113
-
114
- const service = pipe(
115
- AuthenticateServiceLive,
116
- L.provide(Fixture.getCredentialTest),
117
- L.provide(Fixture.capabilitiesTest),
118
- L.provide(Fixture.storageServiceTest),
119
- L.provide(rpcClientTest),
120
- )
121
-
122
- const layers = Layer.merge(service, rpcClientTest)
123
- const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None))
124
-
125
- return E.runPromise(effect)
126
- })
127
-
128
- test('store the credential in local storage', async () => {
129
- const assertions = E.gen(function* (_) {
130
- const service = yield* _(AuthenticationService)
131
-
132
- yield* _(
133
- service.authenticatePasskey({
134
- email: O.none(),
135
- userVerification: O.some('preferred'),
136
- }),
137
- )
138
-
139
- const storageService = yield* _(StorageService)
140
- expect(storageService.storeToken).toHaveBeenCalledWith(Fixture.principal)
141
- })
142
-
143
- const storageServiceTest = L.effect(
144
- StorageService,
145
- E.sync(() => {
146
- const storageMock = mock<StorageService['Type']>()
147
-
148
- storageMock.storeToken.mockReturnValue(E.void)
149
- storageMock.clearExpiredToken.mockReturnValue(E.void)
150
-
151
- return storageMock
152
- }),
153
- )
154
-
155
- const service = pipe(
156
- AuthenticateServiceLive,
157
- L.provide(Fixture.getCredentialTest),
158
- L.provide(Fixture.capabilitiesTest),
159
- L.provide(Fixture.rpcClientTest),
160
- L.provide(storageServiceTest),
161
- )
162
-
163
- const layers = Layer.merge(service, storageServiceTest)
164
- const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None))
165
-
166
- return E.runPromise(effect)
167
- })
168
-
169
- test('schedule deletion of the local token', async () => {
170
- const assertions = E.gen(function* (_) {
171
- const service = yield* _(AuthenticationService)
172
-
173
- yield* _(
174
- service.authenticatePasskey({
175
- email: O.none(),
176
- userVerification: O.some('preferred'),
177
- }),
178
- )
179
-
180
- const storageService = yield* _(StorageService)
181
- expect(storageService.clearExpiredToken).toHaveBeenCalledWith('passkey')
182
- })
183
-
184
- const storageServiceTest = L.effect(
185
- StorageService,
186
- E.sync(() => {
187
- const storageMock = mock<StorageService['Type']>()
188
-
189
- storageMock.storeToken.mockReturnValue(E.void)
190
- storageMock.clearExpiredToken.mockReturnValue(E.void)
191
-
192
- return storageMock
193
- }),
194
- )
195
-
196
- const service = pipe(
197
- AuthenticateServiceLive,
198
- L.provide(Fixture.getCredentialTest),
199
- L.provide(Fixture.capabilitiesTest),
200
- L.provide(Fixture.rpcClientTest),
201
- L.provide(storageServiceTest),
202
- )
203
-
204
- const layers = Layer.merge(service, storageServiceTest)
205
- const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None))
206
-
207
- return E.runPromise(effect)
208
- })
209
-
210
- test("return an error if the browser can't create a credential", async () => {
211
- const assertions = E.gen(function* (_) {
212
- const service = yield* _(AuthenticationService)
213
-
214
- yield* _(
215
- service.authenticatePasskey({
216
- email: O.none(),
217
- userVerification: O.some('preferred'),
218
- }),
219
- )
220
-
221
- const { getCredential } = yield* _(GetCredential)
222
- expect(getCredential).toHaveBeenCalledOnce()
223
- })
224
-
225
- const getCredentialTest = L.effect(
226
- GetCredential,
227
- E.sync(() => {
228
- const getCredential = vi.fn()
229
-
230
- getCredential.mockReturnValue(E.succeed(Fixture.credential))
231
-
232
- return { getCredential }
233
- }),
234
- )
235
-
236
- const service = pipe(
237
- AuthenticateServiceLive,
238
- L.provide(Fixture.storageServiceTest),
239
- L.provide(Fixture.capabilitiesTest),
240
- L.provide(Fixture.rpcClientTest),
241
- L.provide(getCredentialTest),
242
- )
243
-
244
- const layers = Layer.merge(service, getCredentialTest)
245
- const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None))
246
-
247
- return E.runPromise(effect)
248
- })
249
- })
@@ -1,143 +0,0 @@
1
- /**
2
- * Passkey authentication effects
3
- */
4
- import {
5
- type CredentialRequestOptionsJSON,
6
- parseRequestOptionsFromJSON,
7
- } from '@github/webauthn-json/browser-ponyfill'
8
- import { Context, Effect as E, Layer, flow, pipe } from 'effect'
9
-
10
- import { InternalBrowserError, type NotSupported } from '@passlock/shared/dist/error/error.js'
11
- import * as RPC from '../rpc/passkey/authentication.js'
12
- import type { AuthenticationCredential } from '@passlock/shared/dist/schema/passkey.js'
13
- import type { Principal } from '@passlock/shared/dist/schema/principal.js'
14
-
15
- import { Capabilities } from '../capabilities/capabilities.js'
16
- import { StorageService } from '../storage/storage.js'
17
-
18
- /* Requests */
19
-
20
- export type AuthenticationRequest = RPC.OptionsRequest
21
- /* Errors */
22
-
23
- export type AuthenticationErrors = NotSupported | RPC.OptionsErrors | RPC.VerificationErrors
24
-
25
- /* Dependencies */
26
-
27
- export class GetCredential extends Context.Tag('@services/GetCredential')<
28
- GetCredential,
29
- {
30
- getCredential: (
31
- request: CredentialRequestOptions,
32
- ) => E.Effect<AuthenticationCredential, InternalBrowserError>
33
- }
34
- >() {}
35
-
36
- /* Service */
37
-
38
- export class AuthenticationService extends Context.Tag('@services/AuthenticationService')<
39
- AuthenticationService,
40
- {
41
- authenticatePasskey: (
42
- request: AuthenticationRequest,
43
- ) => E.Effect<Principal, AuthenticationErrors>
44
- }
45
- >() {}
46
-
47
- /* Utilities */
48
-
49
- const fetchOptions = (request: RPC.OptionsRequest) => {
50
- return E.gen(function* (_) {
51
- yield* _(E.logDebug('Making request'))
52
-
53
- const rpcClient = yield* _(RPC.AuthenticationClient)
54
- const { publicKey, session } = yield* _(rpcClient.getAuthenticationOptions(request))
55
-
56
- yield* _(E.logDebug('Converting Passlock options to CredentialRequestOptions'))
57
- const options = yield* _(toRequestOptions({ publicKey }))
58
-
59
- return { options, session }
60
- })
61
- }
62
-
63
- const toRequestOptions = (request: CredentialRequestOptionsJSON) => {
64
- return pipe(
65
- E.try(() => parseRequestOptionsFromJSON(request)),
66
- E.mapError(
67
- error =>
68
- new InternalBrowserError({
69
- message: 'Browser was unable to create credential request options',
70
- detail: String(error.error),
71
- }),
72
- ),
73
- )
74
- }
75
-
76
- const verifyCredential = (request: RPC.VerificationRequest) => {
77
- return E.gen(function* (_) {
78
- yield* _(E.logDebug('Making request'))
79
-
80
- const rpcClient = yield* _(RPC.AuthenticationClient)
81
- const { principal } = yield* _(rpcClient.verifyAuthenticationCredential(request))
82
-
83
- return principal
84
- })
85
- }
86
-
87
- /* Effects */
88
-
89
- type Dependencies = GetCredential | Capabilities | StorageService | RPC.AuthenticationClient
90
-
91
- export const authenticatePasskey = (
92
- request: AuthenticationRequest,
93
- ): E.Effect<Principal, AuthenticationErrors, Dependencies> => {
94
- const effect = E.gen(function* (_) {
95
- yield* _(E.logInfo('Checking if browser supports Passkeys'))
96
- const capabilities = yield* _(Capabilities)
97
- yield* _(capabilities.passkeySupport)
98
-
99
- yield* _(E.logInfo('Fetching authentication options from Passlock'))
100
-
101
- const { options, session } = yield* _(fetchOptions(request))
102
-
103
- yield* _(E.logInfo('Looking up credential'))
104
- const { getCredential } = yield* _(GetCredential)
105
- const credential = yield* _(getCredential(options))
106
-
107
- yield* _(E.logInfo('Verifying credential with Passlock'))
108
- const principal = yield* _(verifyCredential(new RPC.VerificationRequest({ credential, session })))
109
-
110
- const storageService = yield* _(StorageService)
111
- yield* _(storageService.storeToken(principal))
112
- yield* _(E.logDebug('Stored token in local storage'))
113
-
114
- yield* _(E.logDebug('Defering local token deletion'))
115
- const delayedClearTokenE = pipe(
116
- storageService.clearExpiredToken('passkey'),
117
- E.delay('6 minutes'),
118
- E.fork,
119
- )
120
- yield* _(delayedClearTokenE)
121
-
122
- return principal
123
- })
124
-
125
- return E.catchTag(effect, 'InternalBrowserError', e => E.die(e))
126
- }
127
-
128
- /* Live */
129
-
130
- /* v8 ignore start */
131
- export const AuthenticateServiceLive = Layer.effect(
132
- AuthenticationService,
133
- E.gen(function* (_) {
134
- const context = yield* _(
135
- E.context<GetCredential | RPC.AuthenticationClient | Capabilities | StorageService>(),
136
- )
137
-
138
- return AuthenticationService.of({
139
- authenticatePasskey: flow(authenticatePasskey, E.provide(context)),
140
- })
141
- }),
142
- )
143
- /* v8 ignore stop */
@@ -1,83 +0,0 @@
1
- /**
2
- * Test if the browser supports passkeys, conditional UI etc
3
- */
4
- import { Context, Effect as E, Layer, identity, pipe } from 'effect'
5
-
6
- import { NotSupported } from '@passlock/shared/dist/error/error.js'
7
-
8
- /* Service */
9
-
10
- export class Capabilities extends Context.Tag('@services/Capabilities')<
11
- Capabilities,
12
- {
13
- passkeySupport: E.Effect<void, NotSupported>
14
- isPasskeySupport: E.Effect<boolean>
15
- autofillSupport: E.Effect<void, NotSupported>
16
- isAutofillSupport: E.Effect<boolean>
17
- }
18
- >() {}
19
-
20
- /* Effects */
21
-
22
- const hasWebAuthn = E.suspend(() =>
23
- typeof window.PublicKeyCredential === 'function'
24
- ? E.void
25
- : new NotSupported({ message: 'WebAuthn API is not supported on this device' }),
26
- )
27
-
28
- const hasPlatformAuth = pipe(
29
- E.tryPromise(() => window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()),
30
- E.filterOrFail(
31
- identity,
32
- () => new NotSupported({ message: 'No platform authenticator available on this device' }),
33
- ),
34
- E.asVoid,
35
- )
36
-
37
- const hasConditionalUi = pipe(
38
- E.tryPromise({
39
- try: () => window.PublicKeyCredential.isConditionalMediationAvailable(),
40
- catch: () =>
41
- new NotSupported({ message: 'Conditional mediation not available on this device' }),
42
- }),
43
- E.filterOrFail(
44
- identity,
45
- () => new NotSupported({ message: 'Conditional mediation not available on this device' }),
46
- ),
47
- E.asVoid,
48
- )
49
-
50
- export const passkeySupport = pipe(
51
- hasWebAuthn,
52
- E.andThen(hasPlatformAuth),
53
- E.catchTag('UnknownException', e => E.die(e)),
54
- )
55
-
56
- export const isPasskeySupport = pipe(
57
- passkeySupport,
58
- E.match({
59
- onFailure: () => false,
60
- onSuccess: () => true,
61
- }),
62
- )
63
-
64
- export const autofillSupport = pipe(passkeySupport, E.andThen(hasConditionalUi))
65
-
66
- export const isAutofillSupport = pipe(
67
- autofillSupport,
68
- E.match({
69
- onFailure: () => false,
70
- onSuccess: () => true,
71
- }),
72
- )
73
-
74
- /* Live */
75
-
76
- /* v8 ignore start */
77
- export const capabilitiesLive = Layer.succeed(Capabilities, {
78
- passkeySupport,
79
- isPasskeySupport,
80
- autofillSupport,
81
- isAutofillSupport,
82
- })
83
- /* v8 ignore stop */
@@ -1,20 +0,0 @@
1
- import { Effect as E, Layer as L } from 'effect'
2
-
3
- import { ConnectResponse } from '@passlock/shared/dist/rpc/connection.js'
4
-
5
- import { ConnectionClient } from '../rpc/connection.js'
6
-
7
- export const preConnectRes = new ConnectResponse({ warmed: true })
8
-
9
- export const rpcClientTest = L.succeed(
10
- ConnectionClient,
11
- ConnectionClient.of({
12
- preConnect: () => E.succeed(preConnectRes),
13
- }),
14
- )
15
-
16
- export const rpcConfig = {
17
- endpoint: 'https://example.com',
18
- tenancyId: 'tenancyId',
19
- clientId: 'clientId',
20
- }