@passlock/client 2.0.0-beta.2 → 2.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/{network.d.ts → internal/network.d.ts} +5 -3
- package/dist/internal/network.d.ts.map +1 -0
- package/dist/{network.js → internal/network.js} +29 -10
- package/dist/internal/network.js.map +1 -0
- package/dist/internal/promise.d.ts.map +1 -0
- package/dist/internal/promise.js.map +1 -0
- package/dist/internal/tenancy.d.ts.map +1 -0
- package/dist/internal/tenancy.js.map +1 -0
- package/dist/logger/index.d.ts +3 -1
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js +8 -3
- package/dist/logger/index.js.map +1 -1
- package/dist/passkey/authentication/authentication.d.ts +118 -0
- package/dist/passkey/authentication/authentication.d.ts.map +1 -0
- package/dist/passkey/authentication/{micro.js → authentication.js} +98 -33
- package/dist/passkey/authentication/authentication.js.map +1 -0
- package/dist/passkey/authentication/authentication.test.d.ts +2 -0
- package/dist/passkey/authentication/authentication.test.d.ts.map +1 -0
- package/dist/passkey/authentication/authentication.test.js +157 -0
- package/dist/passkey/authentication/authentication.test.js.map +1 -0
- package/dist/passkey/authentication/index.d.ts +3 -3
- package/dist/passkey/authentication/index.d.ts.map +1 -1
- package/dist/passkey/authentication/index.js +5 -5
- package/dist/passkey/authentication/index.js.map +1 -1
- package/dist/passkey/{shared.d.ts → errors.d.ts} +5 -4
- package/dist/passkey/errors.d.ts.map +1 -0
- package/dist/passkey/{shared.js → errors.js} +4 -4
- package/dist/passkey/errors.js.map +1 -0
- package/dist/passkey/index.d.ts +5 -6
- package/dist/passkey/index.d.ts.map +1 -1
- package/dist/passkey/index.js +5 -4
- package/dist/passkey/index.js.map +1 -1
- package/dist/passkey/registration/index.d.ts +3 -3
- package/dist/passkey/registration/index.d.ts.map +1 -1
- package/dist/passkey/registration/index.js +5 -5
- package/dist/passkey/registration/index.js.map +1 -1
- package/dist/passkey/registration/{micro.d.ts → registration.d.ts} +45 -10
- package/dist/passkey/registration/registration.d.ts.map +1 -0
- package/dist/passkey/registration/{micro.js → registration.js} +63 -42
- package/dist/passkey/registration/registration.js.map +1 -0
- package/dist/passkey/registration/registration.test.d.ts +2 -0
- package/dist/passkey/registration/registration.test.d.ts.map +1 -0
- package/dist/passkey/registration/registration.test.js +161 -0
- package/dist/passkey/registration/registration.test.js.map +1 -0
- package/dist/passkey/signals/index.d.ts +9 -0
- package/dist/passkey/signals/index.d.ts.map +1 -0
- package/dist/passkey/signals/index.js +19 -0
- package/dist/passkey/signals/index.js.map +1 -0
- package/dist/passkey/signals/signals.d.ts +45 -0
- package/dist/passkey/signals/signals.d.ts.map +1 -0
- package/dist/passkey/signals/signals.js +156 -0
- package/dist/passkey/signals/signals.js.map +1 -0
- package/dist/passkey/support.d.ts.map +1 -1
- package/dist/passkey/support.js +1 -1
- package/dist/passkey/support.js.map +1 -1
- package/dist/passkey/types.d.ts.map +1 -1
- package/dist/shared.d.ts.map +1 -1
- package/package.json +22 -25
- package/dist/network.d.ts.map +0 -1
- package/dist/network.js.map +0 -1
- package/dist/passkey/authentication/micro.d.ts +0 -71
- package/dist/passkey/authentication/micro.d.ts.map +0 -1
- package/dist/passkey/authentication/micro.js.map +0 -1
- package/dist/passkey/registration/micro.d.ts.map +0 -1
- package/dist/passkey/registration/micro.js.map +0 -1
- package/dist/passkey/shared.d.ts.map +0 -1
- package/dist/passkey/shared.js.map +0 -1
- package/dist/promise.d.ts.map +0 -1
- package/dist/promise.js.map +0 -1
- package/dist/tenancy.d.ts.map +0 -1
- package/dist/tenancy.js.map +0 -1
- /package/dist/{promise.d.ts → internal/promise.d.ts} +0 -0
- /package/dist/{promise.js → internal/promise.js} +0 -0
- /package/dist/{tenancy.d.ts → internal/tenancy.d.ts} +0 -0
- /package/dist/{tenancy.js → internal/tenancy.js} +0 -0
|
@@ -1,18 +1,24 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { buildEndpoint, Endpoint, makeRequest
|
|
5
|
-
import {
|
|
6
|
-
import {} from "../../shared";
|
|
1
|
+
import * as Helper from "@simplewebauthn/browser";
|
|
2
|
+
import { WebAuthnError, } from "@simplewebauthn/browser";
|
|
3
|
+
import { Context, Micro, pipe } from "effect";
|
|
4
|
+
import { buildEndpoint, Endpoint, makeRequest } from "../../internal/network";
|
|
5
|
+
import { TenancyId } from "../../internal/tenancy";
|
|
7
6
|
import { Logger } from "../../logger";
|
|
8
|
-
|
|
7
|
+
import { OtherPasskeyError, PasskeysUnsupportedError } from "../errors";
|
|
8
|
+
export class RegistrationHelper extends Context.Tag("RegistrationHelper")() {
|
|
9
|
+
static Default = {
|
|
10
|
+
browserSupportsWebAuthn: Helper.browserSupportsWebAuthn,
|
|
11
|
+
startRegistration: Helper.startRegistration,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export const isDuplicatePasskey = (err) => err instanceof DuplicatePasskeyError;
|
|
9
15
|
/**
|
|
10
16
|
* Raised if excludeCredentials or userId was provided and the
|
|
11
17
|
* device recognises one of the passkey ids i.e. the user currently
|
|
12
18
|
* has a passkey registered on the current device for a given userId.
|
|
13
19
|
*/
|
|
14
|
-
export class DuplicatePasskeyError extends Micro.TaggedError("@error/
|
|
15
|
-
static
|
|
20
|
+
export class DuplicatePasskeyError extends Micro.TaggedError("@error/DuplicatePasskey") {
|
|
21
|
+
static isDuplicatePasskey = isDuplicatePasskey;
|
|
16
22
|
}
|
|
17
23
|
const isOptionsResponse = (payload) => {
|
|
18
24
|
if (typeof payload !== "object")
|
|
@@ -31,24 +37,28 @@ const isOptionsResponse = (payload) => {
|
|
|
31
37
|
return false;
|
|
32
38
|
return true;
|
|
33
39
|
};
|
|
34
|
-
const
|
|
40
|
+
export const registrationEvent = ["optionsRequest", "createCredential", "saveCredential"];
|
|
41
|
+
export const fetchOptions = (options) => Micro.gen(function* () {
|
|
35
42
|
const logger = yield* Micro.service(Logger);
|
|
36
43
|
const { endpoint } = yield* Micro.service(Endpoint);
|
|
37
44
|
const { tenancyId } = yield* Micro.service(TenancyId);
|
|
45
|
+
const { username, userDisplayName, userId, excludeCredentials, userVerification, timeout, onEvent, } = options;
|
|
38
46
|
const url = new URL(`${tenancyId}/passkey/registration/options`, endpoint);
|
|
47
|
+
onEvent?.("optionsRequest");
|
|
39
48
|
yield* logger.logInfo("Fetching passkey registration options from Passlock");
|
|
49
|
+
const payload = {
|
|
50
|
+
excludeCredentials,
|
|
51
|
+
timeout,
|
|
52
|
+
userDisplayName,
|
|
53
|
+
userId,
|
|
54
|
+
username,
|
|
55
|
+
userVerification,
|
|
56
|
+
};
|
|
40
57
|
return yield* makeRequest({
|
|
41
|
-
url,
|
|
42
|
-
payload: {
|
|
43
|
-
username,
|
|
44
|
-
userDisplayName,
|
|
45
|
-
userId,
|
|
46
|
-
excludeCredentials,
|
|
47
|
-
userVerification,
|
|
48
|
-
timeout,
|
|
49
|
-
},
|
|
50
|
-
responsePredicate: isOptionsResponse,
|
|
51
58
|
label: "registration options",
|
|
59
|
+
payload,
|
|
60
|
+
responsePredicate: isOptionsResponse,
|
|
61
|
+
url,
|
|
52
62
|
});
|
|
53
63
|
});
|
|
54
64
|
const RegistrationSuccessTag = "RegistrationSuccess";
|
|
@@ -65,31 +75,17 @@ export const isRegistrationSuccess = (payload) => {
|
|
|
65
75
|
return false;
|
|
66
76
|
return true;
|
|
67
77
|
};
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
const { endpoint } = yield* Micro.service(Endpoint);
|
|
71
|
-
const { tenancyId } = yield* Micro.service(TenancyId);
|
|
72
|
-
const url = new URL(`${tenancyId}/passkey/registration/verification`, endpoint);
|
|
73
|
-
yield* logger.logInfo("Registering passkey in Passlock vault");
|
|
74
|
-
const registrationResponse = yield* makeRequest({
|
|
75
|
-
url,
|
|
76
|
-
payload: { sessionToken, response },
|
|
77
|
-
responsePredicate: isRegistrationSuccess,
|
|
78
|
-
label: "registration verification",
|
|
79
|
-
});
|
|
80
|
-
yield* logger.logInfo(`Passkey registered with id ${registrationResponse.principal.authenticatorId}`);
|
|
81
|
-
return registrationResponse;
|
|
82
|
-
});
|
|
83
|
-
const startRegistration = (optionsJSON) => Micro.gen(function* () {
|
|
78
|
+
export const startRegistration = (optionsJSON, { onEvent }) => Micro.gen(function* () {
|
|
79
|
+
onEvent?.("createCredential");
|
|
84
80
|
const logger = yield* Micro.service(Logger);
|
|
85
81
|
yield* logger.logInfo("Registering passkey on device");
|
|
86
|
-
const
|
|
82
|
+
const helper = yield* Micro.service(RegistrationHelper);
|
|
83
|
+
const isSupport = helper.browserSupportsWebAuthn();
|
|
87
84
|
if (!isSupport)
|
|
88
85
|
yield* new PasskeysUnsupportedError({
|
|
89
86
|
message: "Device does not support passkeys",
|
|
90
87
|
});
|
|
91
88
|
return yield* Micro.tryPromise({
|
|
92
|
-
try: () => simpleRegistration({ optionsJSON }),
|
|
93
89
|
catch: (error) => {
|
|
94
90
|
if (error instanceof WebAuthnError &&
|
|
95
91
|
error.code === "ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED") {
|
|
@@ -97,16 +93,37 @@ const startRegistration = (optionsJSON) => Micro.gen(function* () {
|
|
|
97
93
|
}
|
|
98
94
|
else if (error instanceof WebAuthnError) {
|
|
99
95
|
return new OtherPasskeyError({
|
|
96
|
+
code: error.code,
|
|
100
97
|
error: error.cause,
|
|
101
98
|
message: error.message,
|
|
102
|
-
code: error.code,
|
|
103
99
|
});
|
|
104
100
|
}
|
|
105
101
|
else {
|
|
106
102
|
return new OtherPasskeyError({ error, message: "Unexpected error" });
|
|
107
103
|
}
|
|
108
104
|
},
|
|
105
|
+
try: () => helper.startRegistration({ optionsJSON }),
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
export const verifyCredential = (sessionToken, response, { onEvent }) => Micro.gen(function* () {
|
|
109
|
+
const logger = yield* Micro.service(Logger);
|
|
110
|
+
const { endpoint } = yield* Micro.service(Endpoint);
|
|
111
|
+
const { tenancyId } = yield* Micro.service(TenancyId);
|
|
112
|
+
const url = new URL(`${tenancyId}/passkey/registration/verification`, endpoint);
|
|
113
|
+
onEvent?.("saveCredential");
|
|
114
|
+
yield* logger.logInfo("Registering passkey in Passlock vault");
|
|
115
|
+
const payload = {
|
|
116
|
+
response,
|
|
117
|
+
sessionToken,
|
|
118
|
+
};
|
|
119
|
+
const registrationResponse = yield* makeRequest({
|
|
120
|
+
label: "registration verification",
|
|
121
|
+
payload,
|
|
122
|
+
responsePredicate: isRegistrationSuccess,
|
|
123
|
+
url,
|
|
109
124
|
});
|
|
125
|
+
yield* logger.logInfo(`Passkey registered with id ${registrationResponse.principal.authenticatorId}`);
|
|
126
|
+
return registrationResponse;
|
|
110
127
|
});
|
|
111
128
|
/**
|
|
112
129
|
* Register a passkey on the local device and store the
|
|
@@ -118,9 +135,13 @@ export const registerPasskey = (options) => {
|
|
|
118
135
|
const endpoint = buildEndpoint(options);
|
|
119
136
|
const effect = Micro.gen(function* () {
|
|
120
137
|
const { sessionToken, optionsJSON } = yield* fetchOptions(options);
|
|
121
|
-
const response = yield* startRegistration(optionsJSON
|
|
122
|
-
|
|
138
|
+
const response = yield* startRegistration(optionsJSON, {
|
|
139
|
+
onEvent: options.onEvent,
|
|
140
|
+
});
|
|
141
|
+
return yield* verifyCredential(sessionToken, response, {
|
|
142
|
+
onEvent: options.onEvent,
|
|
143
|
+
});
|
|
123
144
|
});
|
|
124
145
|
return pipe(effect, Micro.provideService(TenancyId, options), Micro.provideService(Endpoint, endpoint));
|
|
125
146
|
};
|
|
126
|
-
//# sourceMappingURL=
|
|
147
|
+
//# sourceMappingURL=registration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registration.js","sourceRoot":"","sources":["../../../src/passkey/registration/registration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registration.test.d.ts","sourceRoot":"","sources":["../../../src/passkey/registration/registration.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import fetchMock from "@fetch-mock/vitest";
|
|
2
|
+
import { Context, Micro, pipe } from "effect";
|
|
3
|
+
import { afterAll, describe, expect, it, vi } from "vitest";
|
|
4
|
+
import { Endpoint } from "../../internal/network";
|
|
5
|
+
import { TenancyId } from "../../internal/tenancy";
|
|
6
|
+
import { Logger } from "../../logger";
|
|
7
|
+
import { PasskeysUnsupportedError } from "../errors";
|
|
8
|
+
import { fetchOptions, RegistrationHelper, registerPasskey, startRegistration, verifyCredential, } from "./registration";
|
|
9
|
+
const loggerTest = {
|
|
10
|
+
logDebug: () => Micro.void,
|
|
11
|
+
logError: () => Micro.void,
|
|
12
|
+
logInfo: () => Micro.void,
|
|
13
|
+
logWarn: () => Micro.void,
|
|
14
|
+
};
|
|
15
|
+
describe(fetchOptions.name, () => {
|
|
16
|
+
const endpoint = "https://api.passlock.dev";
|
|
17
|
+
const tenancyId = "dummyTenancyId";
|
|
18
|
+
const username = "dummyUsername";
|
|
19
|
+
const userDisplayName = "dummyDisplayName";
|
|
20
|
+
const userId = "dummyUserId";
|
|
21
|
+
const ctx = pipe(Context.make(Endpoint, { endpoint }), Context.add(Logger, loggerTest), Context.add(TenancyId, { tenancyId }));
|
|
22
|
+
const expectedRoute = `${endpoint}/${tenancyId}/passkey/registration/options`;
|
|
23
|
+
const mockResponse = {
|
|
24
|
+
optionsJSON: {},
|
|
25
|
+
sessionToken: "dummySessionToken",
|
|
26
|
+
};
|
|
27
|
+
describe("given an empty set of options", () => {
|
|
28
|
+
it("should fetch some PublicKeyCredentialCreationOptions", async () => {
|
|
29
|
+
fetchMock.mockGlobal().postOnce(expectedRoute, mockResponse);
|
|
30
|
+
const result = await pipe(fetchOptions({ username }), Micro.provideContext(ctx), Micro.runPromise);
|
|
31
|
+
expect(result.sessionToken).toBeTruthy();
|
|
32
|
+
expect(result.optionsJSON).toBeTruthy();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
describe("given a username", () => {
|
|
36
|
+
it("should send it to the backend", async () => {
|
|
37
|
+
fetchMock.mockGlobal().postOnce(expectedRoute, mockResponse);
|
|
38
|
+
await pipe(fetchOptions({ username }), Micro.provideContext(ctx), Micro.runPromise);
|
|
39
|
+
expect(fetchMock).toHavePosted(expectedRoute, { body: { username } });
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
describe("given a userDisplayName", () => {
|
|
43
|
+
it("should send it to the backend", async () => {
|
|
44
|
+
fetchMock.mockGlobal().postOnce(expectedRoute, mockResponse);
|
|
45
|
+
await pipe(fetchOptions({ userDisplayName, username }), Micro.provideContext(ctx), Micro.runPromise);
|
|
46
|
+
expect(fetchMock).toHavePosted(expectedRoute, {
|
|
47
|
+
body: { userDisplayName, username },
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe("given a userId", () => {
|
|
52
|
+
it("should send it to the backend", async () => {
|
|
53
|
+
fetchMock.mockGlobal().postOnce(expectedRoute, mockResponse);
|
|
54
|
+
await pipe(fetchOptions({ userId, username }), Micro.provideContext(ctx), Micro.runPromise);
|
|
55
|
+
expect(fetchMock).toHavePosted(expectedRoute, {
|
|
56
|
+
body: { userId, username },
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe("given a list of excludeCredentials", () => {
|
|
61
|
+
const excludeCredentials = ["dummyCredential"];
|
|
62
|
+
it("should send them to the backend", async () => {
|
|
63
|
+
fetchMock.mockGlobal().postOnce(expectedRoute, mockResponse);
|
|
64
|
+
await pipe(fetchOptions({ excludeCredentials, username }), Micro.provideContext(ctx), Micro.runPromise);
|
|
65
|
+
expect(fetchMock).toHavePosted(expectedRoute, {
|
|
66
|
+
body: { excludeCredentials, username },
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
describe("given a userVerification", () => {
|
|
71
|
+
const userVerification = "required";
|
|
72
|
+
it("should send it to the backend", async () => {
|
|
73
|
+
fetchMock.mockGlobal().postOnce(expectedRoute, mockResponse);
|
|
74
|
+
await pipe(fetchOptions({ username, userVerification }), Micro.provideContext(ctx), Micro.runPromise);
|
|
75
|
+
expect(fetchMock).toHavePosted(expectedRoute, {
|
|
76
|
+
body: { username, userVerification },
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
it("should invoke the onEvent handler", async () => {
|
|
81
|
+
fetchMock.mockGlobal().postOnce(expectedRoute, mockResponse);
|
|
82
|
+
const onEvent = vi.fn();
|
|
83
|
+
await pipe(fetchOptions({ onEvent, username }), Micro.provideContext(ctx), Micro.runPromise);
|
|
84
|
+
expect(onEvent).toHaveBeenCalledWith("optionsRequest");
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
describe(startRegistration.name, () => {
|
|
88
|
+
describe("given valid options", () => {
|
|
89
|
+
const registrationHelperTest = {
|
|
90
|
+
browserSupportsWebAuthn: () => true,
|
|
91
|
+
startRegistration: () => Promise.resolve({}),
|
|
92
|
+
};
|
|
93
|
+
it("should invoke the underlying startRegistration function", async () => {
|
|
94
|
+
await pipe(startRegistration({}, {}), Micro.provideService(Logger, loggerTest), Micro.provideService(RegistrationHelper, registrationHelperTest), Micro.runPromise);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
describe("if the device does not support passkeys", () => {
|
|
98
|
+
const registrationHelperTest = {
|
|
99
|
+
browserSupportsWebAuthn: () => false,
|
|
100
|
+
startRegistration: () => Promise.resolve({}),
|
|
101
|
+
};
|
|
102
|
+
it("should return an error", async () => {
|
|
103
|
+
const result = await pipe(startRegistration({}, {}), Micro.flip, Micro.provideService(Logger, loggerTest), Micro.provideService(RegistrationHelper, registrationHelperTest), Micro.runPromise);
|
|
104
|
+
expect(result).toBeInstanceOf(PasskeysUnsupportedError);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
describe(verifyCredential.name, () => {
|
|
109
|
+
const endpoint = "https://api.passlock.dev";
|
|
110
|
+
const tenancyId = "dummyTenancyId";
|
|
111
|
+
const ctx = pipe(Context.make(Endpoint, { endpoint }), Context.add(Logger, loggerTest), Context.add(TenancyId, { tenancyId }));
|
|
112
|
+
const expectedRoute = `${endpoint}/${tenancyId}/passkey/registration/verification`;
|
|
113
|
+
describe("when the passkey exists", () => {
|
|
114
|
+
const mockResponse = {
|
|
115
|
+
_tag: "RegistrationSuccess",
|
|
116
|
+
code: "dummyCode",
|
|
117
|
+
id_token: "dummyIdToken",
|
|
118
|
+
principal: {
|
|
119
|
+
authenticatorId: "dummyPasskeyId",
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
it("should return a successful response", async () => {
|
|
123
|
+
fetchMock.mockGlobal().postOnce(expectedRoute, mockResponse);
|
|
124
|
+
const result = await pipe(verifyCredential("dummySessionToken", {}, {}), Micro.provideContext(ctx), Micro.runPromise);
|
|
125
|
+
expect(result).toStrictEqual(mockResponse);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
describe(registerPasskey.name, () => {
|
|
130
|
+
const endpoint = "https://api.passlock.dev";
|
|
131
|
+
const tenancyId = "dummyTenancyId";
|
|
132
|
+
const username = "dummyUsername";
|
|
133
|
+
const registrationHelperTest = {
|
|
134
|
+
browserSupportsWebAuthn: () => true,
|
|
135
|
+
startRegistration: () => Promise.resolve({}),
|
|
136
|
+
};
|
|
137
|
+
const ctx = pipe(Context.make(Endpoint, { endpoint }), Context.add(Logger, loggerTest), Context.add(TenancyId, { tenancyId }), Context.add(RegistrationHelper, registrationHelperTest));
|
|
138
|
+
const optionsRoute = `${endpoint}/${tenancyId}/passkey/registration/options`;
|
|
139
|
+
const optionsResponse = {
|
|
140
|
+
optionsJSON: {},
|
|
141
|
+
sessionToken: "dummySessionToken",
|
|
142
|
+
};
|
|
143
|
+
const verificationRoute = `${endpoint}/${tenancyId}/passkey/registration/verification`;
|
|
144
|
+
const verificationResponse = {
|
|
145
|
+
_tag: "RegistrationSuccess",
|
|
146
|
+
code: "dummyCode",
|
|
147
|
+
id_token: "dummyIdToken",
|
|
148
|
+
principal: {
|
|
149
|
+
authenticatorId: "dummyPasskeyId",
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
it("should fetch the options and kick off the registration", async () => {
|
|
153
|
+
fetchMock.mockGlobal().postOnce(optionsRoute, optionsResponse);
|
|
154
|
+
fetchMock.mockGlobal().postOnce(verificationRoute, verificationResponse);
|
|
155
|
+
pipe(registerPasskey({ tenancyId, username }), Micro.provideContext(ctx), Micro.runPromise);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
afterAll(() => {
|
|
159
|
+
fetchMock.unmockGlobal();
|
|
160
|
+
});
|
|
161
|
+
//# sourceMappingURL=registration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registration.test.js","sourceRoot":"","sources":["../../../src/passkey/registration/registration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PasslockOptions } from "../../shared";
|
|
2
|
+
import { Logger } from "../../logger";
|
|
3
|
+
import { type CredentialMapping, type DeletionError, isDeletionError } from "./signals";
|
|
4
|
+
export declare const isPasskeyDeletionSupport: () => boolean;
|
|
5
|
+
export declare const deletePasskey: (identifiers: string | CredentialMapping, options: PasslockOptions, logger?: typeof Logger.Service) => Promise<boolean | DeletionError>;
|
|
6
|
+
export declare const deletePasskeyUnsafe: (passkeyId: string, options: PasslockOptions, logger?: typeof Logger.Service) => Promise<boolean>;
|
|
7
|
+
export { isDeletionError };
|
|
8
|
+
export type { DeletionError, CredentialMapping };
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/passkey/signals/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAGnD,OAAO,EAAe,MAAM,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAElB,eAAe,EAGhB,MAAM,WAAW,CAAA;AAElB,eAAO,MAAM,wBAAwB,eAAuD,CAAA;AAE5F,eAAO,MAAM,aAAa,GACxB,aAAa,MAAM,GAAG,iBAAiB,EACvC,SAAS,eAAe,EACxB,SAAQ,OAAO,MAAM,CAAC,OAAqB,KAC1C,OAAO,CAAC,OAAO,GAAG,aAAa,CAOjC,CAAA;AAED,eAAO,MAAM,mBAAmB,GAC9B,WAAW,MAAM,EACjB,SAAS,eAAe,EACxB,SAAQ,OAAO,MAAM,CAAC,OAAqB,KAC1C,OAAO,CAAC,OAAO,CAOjB,CAAA;AAED,OAAO,EAAE,eAAe,EAAE,CAAA;AAC1B,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Micro, pipe } from "effect";
|
|
2
|
+
import { runToPromise, runToPromiseUnsafe } from "../../internal/promise";
|
|
3
|
+
import { EventLogger, Logger } from "../../logger";
|
|
4
|
+
import { deletePasskey as deletePasskeyM, isDeletionError, isPasskeyDeletionSupport as isPasskeyDeletionSupportM, signalCredentialRemoval, } from "./signals";
|
|
5
|
+
export const isPasskeyDeletionSupport = () => pipe(isPasskeyDeletionSupportM, Micro.runSync);
|
|
6
|
+
export const deletePasskey = (identifiers, options, logger = EventLogger) => {
|
|
7
|
+
const micro = typeof identifiers === "string"
|
|
8
|
+
? deletePasskeyM(identifiers, options)
|
|
9
|
+
: signalCredentialRemoval(identifiers);
|
|
10
|
+
return pipe(micro, Micro.provideService(Logger, logger), runToPromise);
|
|
11
|
+
};
|
|
12
|
+
export const deletePasskeyUnsafe = (passkeyId, options, logger = EventLogger) => {
|
|
13
|
+
const micro = typeof passkeyId === "string"
|
|
14
|
+
? deletePasskeyM(passkeyId, options)
|
|
15
|
+
: signalCredentialRemoval(passkeyId);
|
|
16
|
+
return pipe(micro, Micro.provideService(Logger, logger), runToPromiseUnsafe);
|
|
17
|
+
};
|
|
18
|
+
export { isDeletionError };
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/passkey/signals/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACpC,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,EAGL,aAAa,IAAI,cAAc,EAC/B,eAAe,EACf,wBAAwB,IAAI,yBAAyB,EACrD,uBAAuB,GACxB,MAAM,WAAW,CAAA;AAElB,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,yBAAyB,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;AAE5F,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,WAAuC,EACvC,OAAwB,EACxB,SAAgC,WAAW,EACT,EAAE;IACpC,MAAM,KAAK,GACT,OAAO,WAAW,KAAK,QAAQ;QAC7B,CAAC,CAAC,cAAc,CAAC,WAAW,EAAE,OAAO,CAAC;QACtC,CAAC,CAAC,uBAAuB,CAAC,WAAW,CAAC,CAAA;IAE1C,OAAO,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,CAAC,CAAA;AACxE,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,SAAiB,EACjB,OAAwB,EACxB,SAAgC,WAAW,EACzB,EAAE;IACpB,MAAM,KAAK,GACT,OAAO,SAAS,KAAK,QAAQ;QAC3B,CAAC,CAAC,cAAc,CAAC,SAAS,EAAE,OAAO,CAAC;QACpC,CAAC,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAA;IAExC,OAAO,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,kBAAkB,CAAC,CAAA;AAC9E,CAAC,CAAA;AAED,OAAO,EAAE,eAAe,EAAE,CAAA"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { PasslockOptions } from "../../shared";
|
|
2
|
+
import { Micro } from "effect";
|
|
3
|
+
import { Logger } from "../../logger";
|
|
4
|
+
export declare const isPasskeyDeletionSupport: Micro.Micro<boolean, never, never>;
|
|
5
|
+
export declare const isAcceptedCredentialsSupport: Micro.Micro<boolean, never, never>;
|
|
6
|
+
export declare const isDeletionError: (err: unknown) => err is DeletionError;
|
|
7
|
+
declare const DeletionError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => Micro.YieldableError & {
|
|
8
|
+
readonly _tag: "@error/DeletionError";
|
|
9
|
+
} & Readonly<A>;
|
|
10
|
+
export declare class DeletionError extends DeletionError_base<{
|
|
11
|
+
readonly message: string;
|
|
12
|
+
readonly code: "PASSKEY_DELETION_UNSUPPORTED" | "PASSKEY_NOT_FOUND" | "OTHER_ERROR";
|
|
13
|
+
}> {
|
|
14
|
+
static isDeletionError: (err: unknown) => err is DeletionError;
|
|
15
|
+
}
|
|
16
|
+
export declare const isSyncError: (err: unknown) => err is SyncError;
|
|
17
|
+
declare const SyncError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => Micro.YieldableError & {
|
|
18
|
+
readonly _tag: "@error/SyncError";
|
|
19
|
+
} & Readonly<A>;
|
|
20
|
+
export declare class SyncError extends SyncError_base<{
|
|
21
|
+
readonly message: string;
|
|
22
|
+
readonly code: "PASSKEY_SYNC_UNSUPPORTED" | "OTHER_ERROR";
|
|
23
|
+
}> {
|
|
24
|
+
static isSyncError: (err: unknown) => err is SyncError;
|
|
25
|
+
}
|
|
26
|
+
export interface CredentialMapping {
|
|
27
|
+
credentialId: string;
|
|
28
|
+
rpId: string;
|
|
29
|
+
}
|
|
30
|
+
export declare const deletePasskey: (passkeyId: string, options: PasslockOptions) => Micro.Micro<boolean, DeletionError, Logger>;
|
|
31
|
+
/**
|
|
32
|
+
* Tell the client device to remove a given credential
|
|
33
|
+
* @param error
|
|
34
|
+
* @returns
|
|
35
|
+
*/
|
|
36
|
+
export declare const signalCredentialRemoval: (signal: CredentialMapping) => Micro.Micro<boolean, DeletionError, Logger>;
|
|
37
|
+
export interface CredentialMappings {
|
|
38
|
+
rpId: string;
|
|
39
|
+
userId: string;
|
|
40
|
+
allAcceptedCredentialIds: string[];
|
|
41
|
+
}
|
|
42
|
+
export declare const syncPasskeys: (passkeyIds: Array<string>, options: PasslockOptions) => Micro.Micro<boolean, SyncError, Logger>;
|
|
43
|
+
export declare const signalAcceptedCredentials: (signal: CredentialMappings) => Micro.Micro<boolean, SyncError, Logger>;
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=signals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signals.d.ts","sourceRoot":"","sources":["../../../src/passkey/signals/signals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EAAE,KAAK,EAAQ,MAAM,QAAQ,CAAA;AAGpC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAErC,eAAO,MAAM,wBAAwB,oCAKnC,CAAA;AAEF,eAAO,MAAM,4BAA4B,oCAKvC,CAAA;AAIF,eAAO,MAAM,eAAe,GAAI,KAAK,OAAO,yBAAiC,CAAA;;;;AAE7E,qBAAa,aAAc,SAAQ,mBAA0C;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,8BAA8B,GAAG,mBAAmB,GAAG,aAAa,CAAA;CACpF,CAAC;IACA,MAAM,CAAC,eAAe,QANa,OAAO,0BAMF;CACzC;AAID,eAAO,MAAM,WAAW,GAAI,KAAK,OAAO,qBAA6B,CAAA;;;;AAErE,qBAAa,SAAU,SAAQ,eAAsC;IACnE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,0BAA0B,GAAG,aAAa,CAAA;CAC1D,CAAC;IACA,MAAM,CAAC,WAAW,QANa,OAAO,sBAMN;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;CACb;AAeD,eAAO,MAAM,aAAa,GAAI,WAAW,MAAM,EAAE,SAAS,eAAe,gDA+BrE,CAAA;AAEJ;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAClC,QAAQ,iBAAiB,KACxB,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,CAiCzC,CAAA;AAEJ,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,wBAAwB,EAAE,MAAM,EAAE,CAAA;CACnC;AAkBD,eAAO,MAAM,YAAY,GAAI,YAAY,KAAK,CAAC,MAAM,CAAC,EAAE,SAAS,eAAe,4CAgC5E,CAAA;AAEJ,eAAO,MAAM,yBAAyB,GACpC,QAAQ,kBAAkB,KACzB,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAgCrC,CAAA"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { Micro, pipe } from "effect";
|
|
2
|
+
import { encodeUriComponent } from "effect/Encoding";
|
|
3
|
+
import { buildEndpoint } from "../../internal/network";
|
|
4
|
+
import { Logger } from "../../logger";
|
|
5
|
+
export const isPasskeyDeletionSupport = Micro.sync(() => {
|
|
6
|
+
return (PublicKeyCredential?.signalUnknownCredential &&
|
|
7
|
+
typeof PublicKeyCredential.signalUnknownCredential === "function");
|
|
8
|
+
});
|
|
9
|
+
export const isAcceptedCredentialsSupport = Micro.sync(() => {
|
|
10
|
+
return (PublicKeyCredential?.signalAllAcceptedCredentials &&
|
|
11
|
+
typeof PublicKeyCredential.signalAllAcceptedCredentials === "function");
|
|
12
|
+
});
|
|
13
|
+
/* Deletion error */
|
|
14
|
+
export const isDeletionError = (err) => err instanceof DeletionError;
|
|
15
|
+
export class DeletionError extends Micro.TaggedError("@error/DeletionError") {
|
|
16
|
+
static isDeletionError = isDeletionError;
|
|
17
|
+
}
|
|
18
|
+
/* Sync error */
|
|
19
|
+
export const isSyncError = (err) => err instanceof SyncError;
|
|
20
|
+
export class SyncError extends Micro.TaggedError("@error/SyncError") {
|
|
21
|
+
static isSyncError = isSyncError;
|
|
22
|
+
}
|
|
23
|
+
const isCredentialMapping = (payload) => {
|
|
24
|
+
if (typeof payload !== "object")
|
|
25
|
+
return false;
|
|
26
|
+
if (payload === null)
|
|
27
|
+
return false;
|
|
28
|
+
if (!("credentialId" in payload))
|
|
29
|
+
return false;
|
|
30
|
+
if (typeof payload.credentialId !== "string")
|
|
31
|
+
return false;
|
|
32
|
+
if (!("rpId" in payload))
|
|
33
|
+
return false;
|
|
34
|
+
if (typeof payload.rpId !== "string")
|
|
35
|
+
return false;
|
|
36
|
+
return true;
|
|
37
|
+
};
|
|
38
|
+
export const deletePasskey = (passkeyId, options) => Micro.gen(function* () {
|
|
39
|
+
const { tenancyId } = options;
|
|
40
|
+
const logger = yield* Micro.service(Logger);
|
|
41
|
+
const { endpoint } = buildEndpoint(options);
|
|
42
|
+
yield* logger.logInfo("Testing for local passkey removal support");
|
|
43
|
+
const canDelete = yield* isPasskeyDeletionSupport;
|
|
44
|
+
if (!canDelete)
|
|
45
|
+
return yield* new DeletionError({
|
|
46
|
+
code: "PASSKEY_DELETION_UNSUPPORTED",
|
|
47
|
+
message: "Passkey deletion not supported on this device",
|
|
48
|
+
});
|
|
49
|
+
yield* logger.logInfo("Fetching passkey credential and rp id");
|
|
50
|
+
const url = new URL(`${tenancyId}/credential/${passkeyId}`, endpoint);
|
|
51
|
+
const response = yield* Micro.promise(() => fetch(url));
|
|
52
|
+
if (response.status === 404)
|
|
53
|
+
return yield* new DeletionError({
|
|
54
|
+
code: "OTHER_ERROR",
|
|
55
|
+
message: "Unable to find the metadata associated with this passkey",
|
|
56
|
+
});
|
|
57
|
+
const credential = yield* Micro.promise(() => response.json());
|
|
58
|
+
if (!isCredentialMapping(credential))
|
|
59
|
+
return yield* new DeletionError({
|
|
60
|
+
code: "OTHER_ERROR",
|
|
61
|
+
message: "Invalid metadata associated with this passkey",
|
|
62
|
+
});
|
|
63
|
+
return yield* signalCredentialRemoval(credential);
|
|
64
|
+
});
|
|
65
|
+
/**
|
|
66
|
+
* Tell the client device to remove a given credential
|
|
67
|
+
* @param error
|
|
68
|
+
* @returns
|
|
69
|
+
*/
|
|
70
|
+
export const signalCredentialRemoval = (signal) => Micro.gen(function* () {
|
|
71
|
+
const logger = yield* Micro.service(Logger);
|
|
72
|
+
yield* logger.logInfo("Testing for local passkey removal support");
|
|
73
|
+
const canDelete = yield* isPasskeyDeletionSupport;
|
|
74
|
+
if (!canDelete)
|
|
75
|
+
return yield* new DeletionError({
|
|
76
|
+
code: "PASSKEY_DELETION_UNSUPPORTED",
|
|
77
|
+
message: "Passkey deletion not supported on this device",
|
|
78
|
+
});
|
|
79
|
+
// might not be defined in older browsers
|
|
80
|
+
yield* logger.logInfo("Signalling browser to remove passkey");
|
|
81
|
+
yield* pipe(Micro.tryPromise({
|
|
82
|
+
try: () => PublicKeyCredential.signalUnknownCredential(signal),
|
|
83
|
+
catch: (err) => err instanceof Error ? err : new Error("Unable to signal credential removal"),
|
|
84
|
+
}), Micro.catchAllDefect((err) => err instanceof Error
|
|
85
|
+
? logger.logWarn(err.message)
|
|
86
|
+
: logger.logWarn("Unable to signal credential removal")), Micro.catchAll((err) => logger.logWarn(err.message)), Micro.forkDaemon);
|
|
87
|
+
yield* logger.logInfo("Passkey removed");
|
|
88
|
+
return true;
|
|
89
|
+
});
|
|
90
|
+
const isCredentialMappings = (payload) => {
|
|
91
|
+
if (typeof payload !== "object")
|
|
92
|
+
return false;
|
|
93
|
+
if (payload === null)
|
|
94
|
+
return false;
|
|
95
|
+
if (!("rpId" in payload))
|
|
96
|
+
return false;
|
|
97
|
+
if (typeof payload.rpId !== "string")
|
|
98
|
+
return false;
|
|
99
|
+
if (!("userId" in payload))
|
|
100
|
+
return false;
|
|
101
|
+
if (typeof payload.userId !== "string")
|
|
102
|
+
return false;
|
|
103
|
+
if (!("allAcceptedCredentialIds" in payload))
|
|
104
|
+
return false;
|
|
105
|
+
if (Array.isArray(payload.allAcceptedCredentialIds))
|
|
106
|
+
return false;
|
|
107
|
+
return true;
|
|
108
|
+
};
|
|
109
|
+
export const syncPasskeys = (passkeyIds, options) => Micro.gen(function* () {
|
|
110
|
+
const { tenancyId } = options;
|
|
111
|
+
const logger = yield* Micro.service(Logger);
|
|
112
|
+
const { endpoint } = buildEndpoint(options);
|
|
113
|
+
yield* logger.logInfo("Testing for local passkey sync support");
|
|
114
|
+
const canSync = yield* isAcceptedCredentialsSupport;
|
|
115
|
+
if (!canSync)
|
|
116
|
+
return yield* new SyncError({
|
|
117
|
+
code: "PASSKEY_SYNC_UNSUPPORTED",
|
|
118
|
+
message: "Passkey deletion not supported on this device",
|
|
119
|
+
});
|
|
120
|
+
yield* logger.logInfo("Fetching passkey credentials and rp id");
|
|
121
|
+
const encodedPasskeyIds = encodeUriComponent(passkeyIds.join(","));
|
|
122
|
+
const url = new URL(`${tenancyId}/credentials/${encodedPasskeyIds}`, endpoint);
|
|
123
|
+
const response = yield* Micro.promise(() => fetch(url));
|
|
124
|
+
if (response.status === 404)
|
|
125
|
+
return yield* new SyncError({
|
|
126
|
+
code: "OTHER_ERROR",
|
|
127
|
+
message: "Unable to find the metadata associated with these passkeys",
|
|
128
|
+
});
|
|
129
|
+
const credentials = yield* Micro.promise(() => response.json());
|
|
130
|
+
if (!isCredentialMappings(credentials))
|
|
131
|
+
return yield* new SyncError({
|
|
132
|
+
code: "OTHER_ERROR",
|
|
133
|
+
message: "Invalid metadata associated with one or more passkeys",
|
|
134
|
+
});
|
|
135
|
+
return yield* signalAcceptedCredentials(credentials);
|
|
136
|
+
});
|
|
137
|
+
export const signalAcceptedCredentials = (signal) => Micro.gen(function* () {
|
|
138
|
+
const logger = yield* Micro.service(Logger);
|
|
139
|
+
yield* logger.logInfo("Testing for accepted credential signalling support");
|
|
140
|
+
const canSync = yield* isAcceptedCredentialsSupport;
|
|
141
|
+
if (!canSync)
|
|
142
|
+
return yield* new SyncError({
|
|
143
|
+
code: "PASSKEY_SYNC_UNSUPPORTED",
|
|
144
|
+
message: "Passkey sync not supported on this device",
|
|
145
|
+
});
|
|
146
|
+
yield* logger.logInfo("Signalling browser of accepted credentials");
|
|
147
|
+
yield* pipe(Micro.tryPromise({
|
|
148
|
+
try: () => PublicKeyCredential.signalAllAcceptedCredentials(signal),
|
|
149
|
+
catch: (err) => err instanceof Error ? err : new Error("Unable to signal accepted credentials"),
|
|
150
|
+
}), Micro.timeout(1000), Micro.catchAllDefect((err) => err instanceof Error
|
|
151
|
+
? logger.logWarn(err.message)
|
|
152
|
+
: logger.logWarn("Unable to signal accepted credentials")), Micro.catchAll((err) => logger.logWarn(err.message)));
|
|
153
|
+
yield* logger.logInfo("Accepted credentials signalled");
|
|
154
|
+
return true;
|
|
155
|
+
});
|
|
156
|
+
//# sourceMappingURL=signals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signals.js","sourceRoot":"","sources":["../../../src/passkey/signals/signals.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAErC,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;IACtD,OAAO,CACL,mBAAmB,EAAE,uBAAuB;QAC5C,OAAO,mBAAmB,CAAC,uBAAuB,KAAK,UAAU,CAClE,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,4BAA4B,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;IAC1D,OAAO,CACL,mBAAmB,EAAE,4BAA4B;QACjD,OAAO,mBAAmB,CAAC,4BAA4B,KAAK,UAAU,CACvE,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,oBAAoB;AAEpB,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAY,EAAE,EAAE,CAAC,GAAG,YAAY,aAAa,CAAA;AAE7E,MAAM,OAAO,aAAc,SAAQ,KAAK,CAAC,WAAW,CAAC,sBAAsB,CAGzE;IACA,MAAM,CAAC,eAAe,GAAG,eAAe,CAAA;;AAG1C,gBAAgB;AAEhB,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAY,EAAE,EAAE,CAAC,GAAG,YAAY,SAAS,CAAA;AAErE,MAAM,OAAO,SAAU,SAAQ,KAAK,CAAC,WAAW,CAAC,kBAAkB,CAGjE;IACA,MAAM,CAAC,WAAW,GAAG,WAAW,CAAA;;AAQlC,MAAM,mBAAmB,GAAG,CAAC,OAAgB,EAAgC,EAAE;IAC7E,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC7C,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,KAAK,CAAA;IAElC,IAAI,CAAC,CAAC,cAAc,IAAI,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IAC9C,IAAI,OAAO,OAAO,CAAC,YAAY,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAE1D,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IACtC,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAElD,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,SAAiB,EAAE,OAAwB,EAAE,EAAE,CAC3E,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;IACjB,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAA;IAC7B,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAC3C,MAAM,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;IAE3C,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAA;IAClE,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,wBAAwB,CAAA;IACjD,IAAI,CAAC,SAAS;QACZ,OAAO,KAAK,CAAC,CAAC,IAAI,aAAa,CAAC;YAC9B,IAAI,EAAE,8BAA8B;YACpC,OAAO,EAAE,+CAA+C;SACzD,CAAC,CAAA;IAEJ,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,uCAAuC,CAAC,CAAA;IAC9D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,SAAS,eAAe,SAAS,EAAE,EAAE,QAAQ,CAAC,CAAA;IACrE,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAA;IACvD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;QACzB,OAAO,KAAK,CAAC,CAAC,IAAI,aAAa,CAAC;YAC9B,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,0DAA0D;SACpE,CAAC,CAAA;IAEJ,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;IAC9D,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC;QAClC,OAAO,KAAK,CAAC,CAAC,IAAI,aAAa,CAAC;YAC9B,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,+CAA+C;SACzD,CAAC,CAAA;IAEJ,OAAO,KAAK,CAAC,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAA;AACnD,CAAC,CAAC,CAAA;AAEJ;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,MAAyB,EACoB,EAAE,CAC/C,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;IACjB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAE3C,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAA;IAClE,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,wBAAwB,CAAA;IACjD,IAAI,CAAC,SAAS;QACZ,OAAO,KAAK,CAAC,CAAC,IAAI,aAAa,CAAC;YAC9B,IAAI,EAAE,8BAA8B;YACpC,OAAO,EAAE,+CAA+C;SACzD,CAAC,CAAA;IAEJ,yCAAyC;IACzC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,sCAAsC,CAAC,CAAA;IAE7D,KAAK,CAAC,CAAC,IAAI,CACT,KAAK,CAAC,UAAU,CAAC;QACf,GAAG,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,uBAAuB,CAAC,MAAM,CAAC;QAC9D,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CACb,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,qCAAqC,CAAC;KAChF,CAAC,EACF,KAAK,CAAC,cAAc,CAAC,CAAC,GAAG,EAAE,EAAE,CAC3B,GAAG,YAAY,KAAK;QAClB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;QAC7B,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAC1D,EACD,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,EACpD,KAAK,CAAC,UAAU,CACjB,CAAA;IAED,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAA;IAExC,OAAO,IAAI,CAAA;AACb,CAAC,CAAC,CAAA;AAQJ,MAAM,oBAAoB,GAAG,CAAC,OAAgB,EAAiC,EAAE;IAC/E,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC7C,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,KAAK,CAAA;IAElC,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IACtC,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAElD,IAAI,CAAC,CAAC,QAAQ,IAAI,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IACxC,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAEpD,IAAI,CAAC,CAAC,0BAA0B,IAAI,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IAC1D,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,wBAAwB,CAAC;QAAE,OAAO,KAAK,CAAA;IAEjE,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,UAAyB,EAAE,OAAwB,EAAE,EAAE,CAClF,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;IACjB,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAA;IAC7B,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAC3C,MAAM,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;IAE3C,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAA;IAC/D,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,4BAA4B,CAAA;IACnD,IAAI,CAAC,OAAO;QACV,OAAO,KAAK,CAAC,CAAC,IAAI,SAAS,CAAC;YAC1B,IAAI,EAAE,0BAA0B;YAChC,OAAO,EAAE,+CAA+C;SACzD,CAAC,CAAA;IAEJ,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAA;IAC/D,MAAM,iBAAiB,GAAG,kBAAkB,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IAClE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,SAAS,gBAAgB,iBAAiB,EAAE,EAAE,QAAQ,CAAC,CAAA;IAC9E,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAA;IACvD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;QACzB,OAAO,KAAK,CAAC,CAAC,IAAI,SAAS,CAAC;YAC1B,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,4DAA4D;SACtE,CAAC,CAAA;IAEJ,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;IAC/D,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC;QACpC,OAAO,KAAK,CAAC,CAAC,IAAI,SAAS,CAAC;YAC1B,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,uDAAuD;SACjE,CAAC,CAAA;IAEJ,OAAO,KAAK,CAAC,CAAC,yBAAyB,CAAC,WAAW,CAAC,CAAA;AACtD,CAAC,CAAC,CAAA;AAEJ,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,MAA0B,EACe,EAAE,CAC3C,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;IACjB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAE3C,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,oDAAoD,CAAC,CAAA;IAC3E,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,4BAA4B,CAAA;IACnD,IAAI,CAAC,OAAO;QACV,OAAO,KAAK,CAAC,CAAC,IAAI,SAAS,CAAC;YAC1B,IAAI,EAAE,0BAA0B;YAChC,OAAO,EAAE,2CAA2C;SACrD,CAAC,CAAA;IAEJ,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,4CAA4C,CAAC,CAAA;IAEnE,KAAK,CAAC,CAAC,IAAI,CACT,KAAK,CAAC,UAAU,CAAC;QACf,GAAG,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,4BAA4B,CAAC,MAAM,CAAC;QACnE,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CACb,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,uCAAuC,CAAC;KAClF,CAAC,EACF,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EACnB,KAAK,CAAC,cAAc,CAAC,CAAC,GAAG,EAAE,EAAE,CAC3B,GAAG,YAAY,KAAK;QAClB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;QAC7B,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,uCAAuC,CAAC,CAC5D,EACD,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CACrD,CAAA;IAED,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAA;IAEvD,OAAO,IAAI,CAAA;AACb,CAAC,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"support.d.ts","sourceRoot":"","sources":["../../src/passkey/support.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"support.d.ts","sourceRoot":"","sources":["../../src/passkey/support.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gBAAgB,QAAO,OAAoC,CAAA;AAExE,eAAO,MAAM,iBAAiB,QAAO,OAAO,CAAC,OAAO,CAAsC,CAAA"}
|
package/dist/passkey/support.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { browserSupportsWebAuthn, browserSupportsWebAuthnAutofill
|
|
1
|
+
import { browserSupportsWebAuthn, browserSupportsWebAuthnAutofill } from "@simplewebauthn/browser";
|
|
2
2
|
export const isPasskeySupport = () => browserSupportsWebAuthn();
|
|
3
3
|
export const isAutofillSupport = () => browserSupportsWebAuthnAutofill();
|
|
4
4
|
//# sourceMappingURL=support.js.map
|