@unchainedshop/core-users 4.3.5 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -2
- package/lib/db/UsersCollection.d.ts +8 -5
- package/lib/db/UsersCollection.js +0 -1
- package/lib/db/WebAuthnCredentialsCreationRequestsCollection.d.ts +1 -2
- package/lib/db/WebAuthnCredentialsCreationRequestsCollection.js +0 -1
- package/lib/migrations/20241218092300-convert-locale.d.ts +2 -0
- package/lib/migrations/20241218092300-convert-locale.js +36 -0
- package/lib/module/configureUsersModule.d.ts +53 -23
- package/lib/module/configureUsersModule.js +127 -18
- package/lib/module/configureUsersWebAuthnModule.d.ts +78 -20
- package/lib/module/configureUsersWebAuthnModule.js +126 -112
- package/lib/module/pbkdf2.d.ts +0 -1
- package/lib/module/pbkdf2.js +3 -7
- package/lib/users-index.d.ts +5 -6
- package/lib/users-index.js +5 -6
- package/lib/users-settings.d.ts +11 -11
- package/lib/users-settings.js +7 -10
- package/lib/utils/web3-verification.d.ts +1 -0
- package/lib/utils/web3-verification.js +81 -0
- package/package.json +26 -16
- package/lib/db/UsersCollection.d.ts.map +0 -1
- package/lib/db/UsersCollection.js.map +0 -1
- package/lib/db/WebAuthnCredentialsCreationRequestsCollection.d.ts.map +0 -1
- package/lib/db/WebAuthnCredentialsCreationRequestsCollection.js.map +0 -1
- package/lib/module/configureUsersModule.d.ts.map +0 -1
- package/lib/module/configureUsersModule.js.map +0 -1
- package/lib/module/configureUsersWebAuthnModule.d.ts.map +0 -1
- package/lib/module/configureUsersWebAuthnModule.js.map +0 -1
- package/lib/module/pbkdf2.d.ts.map +0 -1
- package/lib/module/pbkdf2.js.map +0 -1
- package/lib/users-index.d.ts.map +0 -1
- package/lib/users-index.js.map +0 -1
- package/lib/users-settings.d.ts.map +0 -1
- package/lib/users-settings.js.map +0 -1
- package/src/db/UsersCollection.ts +0 -174
- package/src/db/WebAuthnCredentialsCreationRequestsCollection.ts +0 -26
- package/src/module/buildFindSelector.test.ts +0 -34
- package/src/module/configureUsersModule.ts +0 -857
- package/src/module/configureUsersWebAuthnModule.ts +0 -234
- package/src/module/pbkdf2.ts +0 -46
- package/src/module/removeConfidentialServiceHashes.test.ts +0 -12
- package/src/users-index.ts +0 -5
- package/src/users-settings.ts +0 -99
- package/tests/mock/user-mock.ts +0 -72
- package/tsconfig.json +0 -10
|
@@ -1,42 +1,48 @@
|
|
|
1
1
|
import { createLogger } from '@unchainedshop/logger';
|
|
2
|
-
import
|
|
2
|
+
import pMemoize from 'p-memoize';
|
|
3
|
+
import ExpiryMap from 'expiry-map';
|
|
4
|
+
import { server as webauthnServer } from '@passwordless-id/webauthn';
|
|
5
|
+
import { WebAuthnCredentialsCreationRequestsCollection } from "../db/WebAuthnCredentialsCreationRequestsCollection.js";
|
|
3
6
|
const logger = createLogger('unchained:core-users');
|
|
7
|
+
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
|
|
4
8
|
const { ROOT_URL = 'http://localhost:4010', EMAIL_WEBSITE_NAME = 'Unchained' } = process.env;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const fido2LibPackage = await import('fido2-lib');
|
|
8
|
-
Fido2Lib = fido2LibPackage.Fido2Lib;
|
|
9
|
-
}
|
|
10
|
-
catch {
|
|
11
|
-
logger.warn(`optional peer npm package 'fido2-lib' not installed, WebAuthn will not work`);
|
|
12
|
-
}
|
|
13
|
-
let setupMDSPromise;
|
|
14
|
-
const setupMDSCollection = async () => {
|
|
9
|
+
async function fetchMDSEntriesImpl() {
|
|
10
|
+
const cache = new Map();
|
|
15
11
|
try {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
12
|
+
const response = await fetch('https://mds.fidoalliance.org/');
|
|
13
|
+
if (!response.ok) {
|
|
14
|
+
logger.warn('Failed to fetch FIDO MDS', { status: response.status });
|
|
15
|
+
return cache;
|
|
16
|
+
}
|
|
17
|
+
const jwtBlob = await response.text();
|
|
18
|
+
const parts = jwtBlob.split('.');
|
|
19
|
+
if (parts.length !== 3) {
|
|
20
|
+
logger.warn('Invalid MDS JWT format');
|
|
21
|
+
return cache;
|
|
22
|
+
}
|
|
23
|
+
const payload = parts[1].replace(/-/g, '+').replace(/_/g, '/');
|
|
24
|
+
const decoded = Buffer.from(payload, 'base64').toString('utf-8');
|
|
25
|
+
const mdsData = JSON.parse(decoded);
|
|
26
|
+
if (Array.isArray(mdsData.entries)) {
|
|
27
|
+
for (const entry of mdsData.entries) {
|
|
28
|
+
if (entry.aaguid) {
|
|
29
|
+
cache.set(entry.aaguid.toLowerCase(), entry);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
logger.debug(`Loaded ${cache.size} MDS entries`);
|
|
23
34
|
}
|
|
24
|
-
catch (
|
|
25
|
-
logger.error
|
|
26
|
-
return [];
|
|
35
|
+
catch (error) {
|
|
36
|
+
logger.warn('Error fetching MDS', { error: error.message });
|
|
27
37
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
setupMDSPromise = setupMDSCollection();
|
|
33
|
-
return setupMDSPromise;
|
|
34
|
-
};
|
|
38
|
+
return cache;
|
|
39
|
+
}
|
|
40
|
+
const mdsCache = new ExpiryMap(ONE_DAY_MS);
|
|
41
|
+
const fetchMDSEntries = pMemoize(fetchMDSEntriesImpl, { cache: mdsCache });
|
|
35
42
|
export function toArrayBuffer(buffer) {
|
|
36
43
|
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
37
44
|
}
|
|
38
45
|
export function buf2hex(buffer) {
|
|
39
|
-
// buffer is an ArrayBuffer
|
|
40
46
|
return Array.prototype.map
|
|
41
47
|
.call(new Uint8Array(buffer), (x) => `00${x.toString(16)}`.slice(-2))
|
|
42
48
|
.join('');
|
|
@@ -44,128 +50,137 @@ export function buf2hex(buffer) {
|
|
|
44
50
|
export const configureUsersWebAuthnModule = async ({ db }) => {
|
|
45
51
|
const WebAuthnCredentialsCreationRequests = await WebAuthnCredentialsCreationRequestsCollection(db);
|
|
46
52
|
const thisDomain = new URL(ROOT_URL).hostname;
|
|
47
|
-
const
|
|
48
|
-
new Fido2Lib({
|
|
49
|
-
rpId: thisDomain,
|
|
50
|
-
rpName: EMAIL_WEBSITE_NAME,
|
|
51
|
-
rpIcon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAARCSURBVHgB7Ve9UxNbFL8fm7yA4ktegHnlMk98dMbOMnR2D6pnGTqtCH+BWFoBpZXQaaelFbGzEztHHF26DKizzijDx+Zef+fu3vXuJgsxztjonQnZOZw993d+5zOM/epHslFO1a/KS/UbuvTnETsKQ/YDh3+XNi72yuVlzVgbL1YhCaOTk2ssDAI24hHDKsrpfxZkufwCj6t0OUAEBMkrlR6wHzjDMVCd872yemeete7gczeKoh2wQTICsyi0DrTWVc55eHqwu8OGPEMCMNSby5hS89H7Nx0Se9NXVvF1J69O7MDwJsKzgfCcmSP9SQhvxcV6S5cnummCHYVH4kJ9DE9NfHx1+HGLxKo0sSOkvIXHSnyz7mjOySufdLmUN3Vp4slZiSoyXk7NrhHVQui1fGzhzTq+QsZ5U07NtowQ3oH2FavDhXjS2389w7W+lrDgI2+2yfaZAEpT/y5LopjztnEkf1F6GXsc38TvWKO9g91NfO3EBGgjpxzooTosCISvXQjAm7zc1Fyvm7IChRHQM+uVcxGBAbstI84bVcqyUE3lAMyVWkrky0UsuGUYRqeni4zQk1cAk15ELxMYy07OqElKqo5ieVWWymsDAbhKGa9Qatag8P5omcQiUEot9nmb1c9cFkm5FJPJWqWp2UYegKkCMf7XHjRaeGwgs+9T1iPTA8ibkM/h5ev4XwVJthEd7D7kF+ozANRI9B9RlpO+lUO/IcZqz0jGPr8PUUFU7k185mwFZUIwBAuGUqWUob8nxCqLQ0H6qbeOnNmQGftOBVHO9QEw+ozZRKLE8y0wxDxFLISIE6n7KsDfjUS8kBoludZbCYBvl8XNaCMPLAOASsde5vYAlFPbeqWV+q/Pq5xR6HRS6zkWzPzIlXdmGKWXFaM/V06zwAGQaVppSJ3yzk7DAqpcb7UQD/q8cuRoxb75dtlxm5Zb3mzALEj7O7I/zWRUBRurHcO7G9Sw5MXJT+rLh+dmRlSqe6iOm1aOC/5nBELr2yTDOw3YO4Z+x3icq7iB01BMXm4j4dbIO+rtVi6nr7xLBg0tIjN20mGGbBPdVs+8J07mvcjzkbnbGf14tNNeYcb4wJVMH358jpo2zSf1lgCM1V4m6CsFXiUG9Iref9txe4kQXgVT9jqXejNZaEKAvFu4D5ikStBjus3bJcPxdjALNE8OduetHep+yIsXGQcZf9wTxyusGwSFS2mCvmaMcn6Lj9d9OV77BGN7iOuCYQFeqcMPT43+peln2IraFH/EdsvuALDTTTthvE0tIRnvsc/x/8/diIq2HnsSFoKEhXUAWM6zYA5VwoDtaLiV7O85XypFy+hVnbRlhCXoo9zZHWkpGWY3/L613D25PZFzeVVxvZqs6ywSYKZ7/ro+2g8TOu6eSBXAGfWIio2z2n871GY8OgN06BcSfitQuZr1CxuQ3Zh/6qkk0/P3GeV8BeBCYUHc/WHIAAAAAElFTkSuQmCC',
|
|
52
|
-
challengeSize: 128,
|
|
53
|
-
attestation: 'none',
|
|
54
|
-
});
|
|
53
|
+
const thisOrigin = new URL(ROOT_URL).origin;
|
|
55
54
|
return {
|
|
56
55
|
findMDSMetadataForAAGUID: async (aaguid) => {
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
});
|
|
61
|
-
return foundEntry?.metadataStatement;
|
|
56
|
+
const mdsEntries = await fetchMDSEntries();
|
|
57
|
+
const entry = mdsEntries.get(aaguid.toLowerCase());
|
|
58
|
+
return entry?.metadataStatement || null;
|
|
62
59
|
},
|
|
63
60
|
createCredentialCreationOptions: async (origin, username, extensionOptions) => {
|
|
64
|
-
|
|
65
|
-
return null;
|
|
66
|
-
const registrationOptions = await f2l.attestationOptions(extensionOptions);
|
|
67
|
-
// Convert challenge to base64 without using Buffer
|
|
68
|
-
const challenge = btoa(String.fromCharCode(...new Uint8Array(registrationOptions.challenge)));
|
|
61
|
+
const challenge = webauthnServer.randomChallenge();
|
|
69
62
|
const { insertedId } = await WebAuthnCredentialsCreationRequests.insertOne({
|
|
70
63
|
_id: new Date().getTime(),
|
|
71
64
|
challenge,
|
|
72
65
|
origin,
|
|
73
|
-
factor:
|
|
66
|
+
factor: 'either',
|
|
74
67
|
username,
|
|
75
68
|
});
|
|
76
69
|
return {
|
|
77
|
-
...registrationOptions,
|
|
78
70
|
challenge,
|
|
79
71
|
requestId: insertedId,
|
|
72
|
+
rp: {
|
|
73
|
+
id: thisDomain,
|
|
74
|
+
name: EMAIL_WEBSITE_NAME,
|
|
75
|
+
},
|
|
76
|
+
user: {
|
|
77
|
+
id: username,
|
|
78
|
+
name: username,
|
|
79
|
+
displayName: username,
|
|
80
|
+
},
|
|
81
|
+
pubKeyCredParams: [
|
|
82
|
+
{ type: 'public-key', alg: -7 },
|
|
83
|
+
{ type: 'public-key', alg: -257 },
|
|
84
|
+
],
|
|
85
|
+
timeout: extensionOptions?.timeout || 60000,
|
|
86
|
+
attestation: 'none',
|
|
87
|
+
authenticatorSelection: extensionOptions?.authenticatorSelection || {
|
|
88
|
+
userVerification: 'preferred',
|
|
89
|
+
},
|
|
80
90
|
};
|
|
81
91
|
},
|
|
82
92
|
createCredentialRequestOptions: async (origin, username, extensionOptions) => {
|
|
83
|
-
|
|
84
|
-
return null;
|
|
85
|
-
const loginOptions = await f2l.assertionOptions(extensionOptions);
|
|
86
|
-
// Convert challenge to base64 without using Buffer
|
|
87
|
-
const challenge = btoa(String.fromCharCode(...new Uint8Array(loginOptions.challenge)));
|
|
93
|
+
const challenge = webauthnServer.randomChallenge();
|
|
88
94
|
const { insertedId } = await WebAuthnCredentialsCreationRequests.insertOne({
|
|
89
95
|
_id: new Date().getTime(),
|
|
90
96
|
challenge,
|
|
91
97
|
origin,
|
|
92
|
-
factor:
|
|
98
|
+
factor: 'either',
|
|
93
99
|
username,
|
|
94
100
|
});
|
|
95
101
|
return {
|
|
96
|
-
...loginOptions,
|
|
97
102
|
challenge,
|
|
98
103
|
requestId: insertedId,
|
|
104
|
+
rpId: thisDomain,
|
|
105
|
+
timeout: extensionOptions?.timeout || 60000,
|
|
106
|
+
userVerification: extensionOptions?.userVerification || 'preferred',
|
|
107
|
+
allowCredentials: extensionOptions?.allowCredentials,
|
|
99
108
|
};
|
|
100
109
|
},
|
|
101
110
|
verifyCredentialCreation: async (username, credentials) => {
|
|
102
|
-
if (!f2l)
|
|
103
|
-
return null;
|
|
104
111
|
const request = await WebAuthnCredentialsCreationRequests.findOne({
|
|
105
112
|
username,
|
|
106
113
|
}, { sort: { _id: -1 } });
|
|
107
|
-
if (!request)
|
|
114
|
+
if (!request) {
|
|
115
|
+
logger.error('WebAuthn: No credential creation request found for username', { username });
|
|
108
116
|
return null;
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
117
|
+
}
|
|
118
|
+
const expectedOrigin = request.origin || thisOrigin;
|
|
119
|
+
logger.info('WebAuthn: Verifying credential creation', {
|
|
120
|
+
username,
|
|
121
|
+
expectedOrigin,
|
|
122
|
+
expectedChallenge: request.challenge,
|
|
123
|
+
credentialId: credentials.id,
|
|
124
|
+
});
|
|
125
|
+
try {
|
|
126
|
+
const registrationInfo = await webauthnServer.verifyRegistration(credentials, {
|
|
127
|
+
challenge: request.challenge,
|
|
128
|
+
origin: expectedOrigin,
|
|
129
|
+
});
|
|
130
|
+
logger.info('WebAuthn: Credential creation verified successfully', {
|
|
131
|
+
username,
|
|
132
|
+
credentialId: registrationInfo.credential.id,
|
|
133
|
+
});
|
|
134
|
+
return {
|
|
135
|
+
id: registrationInfo.credential.id,
|
|
136
|
+
publicKey: registrationInfo.credential.publicKey,
|
|
137
|
+
algorithm: registrationInfo.credential.algorithm,
|
|
138
|
+
aaguid: registrationInfo.authenticator.aaguid,
|
|
139
|
+
counter: registrationInfo.authenticator.counter,
|
|
140
|
+
created: new Date(),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
logger.error('WebAuthn credential creation verification failed', {
|
|
145
|
+
error: error.message,
|
|
146
|
+
username,
|
|
147
|
+
expectedOrigin,
|
|
148
|
+
expectedChallenge: request.challenge,
|
|
149
|
+
});
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
131
152
|
},
|
|
132
153
|
verifyCredentialRequest: async (userPublicKeys, username, credentials) => {
|
|
133
|
-
if (!f2l)
|
|
134
|
-
return null;
|
|
135
154
|
const request = await WebAuthnCredentialsCreationRequests.findOne({
|
|
136
155
|
_id: credentials.requestId,
|
|
137
156
|
}, { sort: { _id: -1 } });
|
|
138
157
|
if (!request)
|
|
139
158
|
return null;
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
const signature = Buffer.from(credentials.response.signature, 'base64');
|
|
143
|
-
const userHandle = Buffer.from(credentials.response.userHandle, 'base64');
|
|
144
|
-
const clientDataJSON = Buffer.from(credentials.response.clientDataJSON, 'base64');
|
|
145
|
-
const { publicKey, counter } = userPublicKeys.find((publicCredentials) => {
|
|
146
|
-
return credentials.id === publicCredentials.id;
|
|
147
|
-
}) || {};
|
|
148
|
-
if (!publicKey)
|
|
159
|
+
const matchingKey = userPublicKeys.find((key) => key.id === credentials.id);
|
|
160
|
+
if (!matchingKey)
|
|
149
161
|
return null;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
userHandle:
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
162
|
+
try {
|
|
163
|
+
const credentialKey = {
|
|
164
|
+
id: matchingKey.id,
|
|
165
|
+
publicKey: matchingKey.publicKey,
|
|
166
|
+
algorithm: matchingKey.algorithm || 'ES256',
|
|
167
|
+
transports: matchingKey.transports || [],
|
|
168
|
+
};
|
|
169
|
+
const authenticationInfo = await webauthnServer.verifyAuthentication(credentials, credentialKey, {
|
|
170
|
+
challenge: request.challenge,
|
|
171
|
+
origin: request.origin || thisOrigin,
|
|
172
|
+
userVerified: false,
|
|
173
|
+
counter: matchingKey.counter,
|
|
174
|
+
});
|
|
175
|
+
return {
|
|
176
|
+
userHandle: credentials.response.userHandle || username,
|
|
177
|
+
counter: authenticationInfo.counter,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
logger.debug('WebAuthn credential request verification failed', { error: error.message });
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
169
184
|
},
|
|
170
185
|
deleteUserWebAuthnCredentials: async (username) => {
|
|
171
186
|
const { deletedCount } = await WebAuthnCredentialsCreationRequests.deleteMany({
|
|
@@ -175,4 +190,3 @@ export const configureUsersWebAuthnModule = async ({ db }) => {
|
|
|
175
190
|
},
|
|
176
191
|
};
|
|
177
192
|
};
|
|
178
|
-
//# sourceMappingURL=configureUsersWebAuthnModule.js.map
|
package/lib/module/pbkdf2.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
export declare function generateSalt(saltLength?: number): string;
|
|
2
2
|
export declare function getDerivedKey(salt: string, password: string, iterations?: number, keyLength?: number): Promise<string>;
|
|
3
3
|
export declare function compare(password: string, hash: string, salt: string): Promise<boolean>;
|
|
4
|
-
//# sourceMappingURL=pbkdf2.d.ts.map
|
package/lib/module/pbkdf2.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const PBKDF2_SALT_LENGTH = 16; // Bytes
|
|
1
|
+
const PBKDF2_ITERATIONS = 300000;
|
|
2
|
+
const PBKDF2_KEY_LENGTH = 256;
|
|
3
|
+
const PBKDF2_SALT_LENGTH = 16;
|
|
5
4
|
export function generateSalt(saltLength = PBKDF2_SALT_LENGTH) {
|
|
6
5
|
const array = new Uint8Array(saltLength);
|
|
7
6
|
crypto.getRandomValues(array);
|
|
8
|
-
// Convert to hex string without using Buffer
|
|
9
7
|
return Array.from(array)
|
|
10
8
|
.map((b) => b.toString(16).padStart(2, '0'))
|
|
11
9
|
.join('');
|
|
@@ -22,7 +20,6 @@ export async function getDerivedKey(salt, password, iterations = PBKDF2_ITERATIO
|
|
|
22
20
|
salt: textEncoder.encode(salt),
|
|
23
21
|
iterations,
|
|
24
22
|
}, importedKey, keyLength);
|
|
25
|
-
// Convert ArrayBuffer to hex string without using Buffer
|
|
26
23
|
return Array.from(new Uint8Array(bits))
|
|
27
24
|
.map((b) => b.toString(16).padStart(2, '0'))
|
|
28
25
|
.join('');
|
|
@@ -31,4 +28,3 @@ export async function compare(password, hash, salt) {
|
|
|
31
28
|
const comparableHash = await getDerivedKey(salt, password);
|
|
32
29
|
return comparableHash === hash;
|
|
33
30
|
}
|
|
34
|
-
//# sourceMappingURL=pbkdf2.js.map
|
package/lib/users-index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
export * from './db/UsersCollection.
|
|
2
|
-
export * from './db/WebAuthnCredentialsCreationRequestsCollection.
|
|
3
|
-
export * from './module/configureUsersModule.
|
|
4
|
-
export * from './module/configureUsersWebAuthnModule.
|
|
5
|
-
export * from './users-settings.
|
|
6
|
-
//# sourceMappingURL=users-index.d.ts.map
|
|
1
|
+
export * from './db/UsersCollection.ts';
|
|
2
|
+
export * from './db/WebAuthnCredentialsCreationRequestsCollection.ts';
|
|
3
|
+
export * from './module/configureUsersModule.ts';
|
|
4
|
+
export * from './module/configureUsersWebAuthnModule.ts';
|
|
5
|
+
export * from './users-settings.ts';
|
package/lib/users-index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
6
|
-
//# sourceMappingURL=users-index.js.map
|
|
1
|
+
export * from "./db/UsersCollection.js";
|
|
2
|
+
export * from "./db/WebAuthnCredentialsCreationRequestsCollection.js";
|
|
3
|
+
export * from "./module/configureUsersModule.js";
|
|
4
|
+
export * from "./module/configureUsersWebAuthnModule.js";
|
|
5
|
+
export * from "./users-settings.js";
|
package/lib/users-settings.d.ts
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import { mongodb } from '@unchainedshop/mongodb';
|
|
2
|
-
import { User } from './db/UsersCollection.
|
|
1
|
+
import { type mongodb } from '@unchainedshop/mongodb';
|
|
2
|
+
import type { User } from './db/UsersCollection.ts';
|
|
3
3
|
export interface UserRegistrationData extends Partial<User> {
|
|
4
4
|
email?: string;
|
|
5
5
|
password: string | null;
|
|
6
6
|
webAuthnPublicKeyCredentials?: any;
|
|
7
7
|
}
|
|
8
|
-
export declare
|
|
9
|
-
RESET_PASSWORD
|
|
10
|
-
VERIFY_EMAIL
|
|
11
|
-
ENROLL_ACCOUNT
|
|
12
|
-
PASSWORD_RESETTED
|
|
13
|
-
EMAIL_VERIFIED
|
|
14
|
-
}
|
|
8
|
+
export declare const UserAccountAction: {
|
|
9
|
+
readonly RESET_PASSWORD: "reset-password";
|
|
10
|
+
readonly VERIFY_EMAIL: "verify-email";
|
|
11
|
+
readonly ENROLL_ACCOUNT: "enroll-account";
|
|
12
|
+
readonly PASSWORD_RESETTED: "password-resetted";
|
|
13
|
+
readonly EMAIL_VERIFIED: "email-verified";
|
|
14
|
+
};
|
|
15
|
+
export type UserAccountAction = (typeof UserAccountAction)[keyof typeof UserAccountAction];
|
|
15
16
|
export interface UserSettings {
|
|
16
17
|
mergeUserCartsOnLogin: boolean;
|
|
17
18
|
autoMessagingAfterUserCreation: boolean;
|
|
18
|
-
earliestValidTokenDate: (type: UserAccountAction.VERIFY_EMAIL | UserAccountAction.RESET_PASSWORD) => Date;
|
|
19
|
+
earliestValidTokenDate: (type: typeof UserAccountAction.VERIFY_EMAIL | typeof UserAccountAction.RESET_PASSWORD) => Date;
|
|
19
20
|
validateEmail: (email: string) => Promise<boolean>;
|
|
20
21
|
validateUsername: (username: string) => Promise<boolean>;
|
|
21
22
|
validateNewUser: (user: UserRegistrationData) => Promise<UserRegistrationData>;
|
|
@@ -24,4 +25,3 @@ export interface UserSettings {
|
|
|
24
25
|
}
|
|
25
26
|
export type UserSettingsOptions = Omit<Partial<UserSettings>, 'configureSettings'>;
|
|
26
27
|
export declare const userSettings: UserSettings;
|
|
27
|
-
//# sourceMappingURL=users-settings.d.ts.map
|
package/lib/users-settings.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { insensitiveTrimmedRegexOperator } from '@unchainedshop/mongodb';
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
})(UserAccountAction || (UserAccountAction = {}));
|
|
2
|
+
export const UserAccountAction = {
|
|
3
|
+
RESET_PASSWORD: 'reset-password',
|
|
4
|
+
VERIFY_EMAIL: 'verify-email',
|
|
5
|
+
ENROLL_ACCOUNT: 'enroll-account',
|
|
6
|
+
PASSWORD_RESETTED: 'password-resetted',
|
|
7
|
+
EMAIL_VERIFIED: 'email-verified',
|
|
8
|
+
};
|
|
10
9
|
const defaultAutoMessagingAfterUserCreation = true;
|
|
11
10
|
const defaultMergeUserCartsOnLogin = true;
|
|
12
11
|
const defaultEarliestValidTokenDate = () => {
|
|
13
|
-
// 1 hour ago
|
|
14
12
|
return new Date(new Date().getTime() - 1000 * 60 * 60);
|
|
15
13
|
};
|
|
16
14
|
const defaultValidateNewUser = async (user) => {
|
|
@@ -63,4 +61,3 @@ export const userSettings = {
|
|
|
63
61
|
userSettings.validatePassword = validatePassword || defaultValidatePassword;
|
|
64
62
|
},
|
|
65
63
|
};
|
|
66
|
-
//# sourceMappingURL=users-settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function verifyWeb3Signature(nonce: string, signature: `0x${string}`, expectedAddress: string): Promise<boolean>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { createLogger } from '@unchainedshop/logger';
|
|
2
|
+
const logger = createLogger('unchained:core-users');
|
|
3
|
+
let secp256k1;
|
|
4
|
+
let keccak_256;
|
|
5
|
+
let bytesToHex;
|
|
6
|
+
let hexToBytes;
|
|
7
|
+
async function loadNoblePackages() {
|
|
8
|
+
try {
|
|
9
|
+
const curves = await import('@noble/curves/secp256k1.js');
|
|
10
|
+
const hashes = await import('@noble/hashes/sha3.js');
|
|
11
|
+
const utils = await import('@noble/hashes/utils.js');
|
|
12
|
+
if (!curves || !hashes || !utils) {
|
|
13
|
+
throw new Error('Missing required @noble packages for Web3 signature verification');
|
|
14
|
+
}
|
|
15
|
+
secp256k1 = curves.secp256k1;
|
|
16
|
+
keccak_256 = hashes.keccak_256;
|
|
17
|
+
bytesToHex = utils.bytesToHex;
|
|
18
|
+
hexToBytes = utils.hexToBytes;
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
logger.warn('Failed to load @noble packages for Web3 verification', { error: error.message });
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function fromRPCSig(sig) {
|
|
27
|
+
const bytes = hexToBytes(sig.startsWith('0x') ? sig.slice(2) : sig);
|
|
28
|
+
if (bytes.length !== 65)
|
|
29
|
+
throw new Error('Invalid signature length');
|
|
30
|
+
const r = bytes.slice(0, 32);
|
|
31
|
+
const s = bytes.slice(32, 64);
|
|
32
|
+
let v = BigInt(bytes[64]);
|
|
33
|
+
if (v >= 35n) {
|
|
34
|
+
v = v - 35n - 2n * 1n;
|
|
35
|
+
}
|
|
36
|
+
else if (v >= 27n) {
|
|
37
|
+
v = v - 27n;
|
|
38
|
+
}
|
|
39
|
+
return { v, r, s };
|
|
40
|
+
}
|
|
41
|
+
function hashPersonalMessage(message) {
|
|
42
|
+
const prefix = new TextEncoder().encode('\x19Ethereum Signed Message:\n');
|
|
43
|
+
const lengthBytes = new TextEncoder().encode(message.length.toString());
|
|
44
|
+
const combined = new Uint8Array(prefix.length + lengthBytes.length + message.length);
|
|
45
|
+
combined.set(prefix, 0);
|
|
46
|
+
combined.set(lengthBytes, prefix.length);
|
|
47
|
+
combined.set(message, prefix.length + lengthBytes.length);
|
|
48
|
+
return keccak_256(combined);
|
|
49
|
+
}
|
|
50
|
+
function ecrecover(msgHash, v, r, s) {
|
|
51
|
+
const recovery = Number(v);
|
|
52
|
+
const signature = new Uint8Array(64);
|
|
53
|
+
signature.set(r, 0);
|
|
54
|
+
signature.set(s, 32);
|
|
55
|
+
const publicKey = secp256k1.Signature.fromBytes(signature)
|
|
56
|
+
.addRecoveryBit(recovery)
|
|
57
|
+
.recoverPublicKey(msgHash);
|
|
58
|
+
return publicKey.toBytes(false).slice(1);
|
|
59
|
+
}
|
|
60
|
+
function publicToAddress(publicKey) {
|
|
61
|
+
const hash = keccak_256(publicKey);
|
|
62
|
+
return hash.slice(-20);
|
|
63
|
+
}
|
|
64
|
+
export async function verifyWeb3Signature(nonce, signature, expectedAddress) {
|
|
65
|
+
const packagesLoaded = await loadNoblePackages();
|
|
66
|
+
if (!packagesLoaded) {
|
|
67
|
+
throw new Error('Web3 signature verification is not available. Please install the required @noble packages: @noble/curves, @noble/hashes');
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
const messageHash = hashPersonalMessage(hexToBytes(Buffer.from(nonce, 'utf8').toString('hex')));
|
|
71
|
+
const sigParams = fromRPCSig(signature);
|
|
72
|
+
const publicKey = ecrecover(messageHash, sigParams.v, sigParams.r, sigParams.s);
|
|
73
|
+
const sender = publicToAddress(publicKey);
|
|
74
|
+
const recoveredAddr = `0x${bytesToHex(sender)}`;
|
|
75
|
+
return recoveredAddr.toLowerCase() === expectedAddress.toLowerCase();
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
logger.debug('Web3 signature verification failed', { error: error.message });
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
package/package.json
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unchainedshop/core-users",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.0",
|
|
4
4
|
"main": "lib/users-index.js",
|
|
5
5
|
"types": "lib/users-index.d.ts",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
7
8
|
"scripts": {
|
|
8
9
|
"clean": "tsc -b --clean",
|
|
9
10
|
"build": "tsc -b",
|
|
10
11
|
"prepublishOnly": "npm run clean && npm run build",
|
|
11
12
|
"watch": "tsc -w",
|
|
12
|
-
"test": "
|
|
13
|
-
"test:watch": "
|
|
13
|
+
"test": "node --test",
|
|
14
|
+
"test:watch": "node --test --watch"
|
|
14
15
|
},
|
|
15
16
|
"repository": {
|
|
16
17
|
"type": "git",
|
|
@@ -22,8 +23,10 @@
|
|
|
22
23
|
"core"
|
|
23
24
|
],
|
|
24
25
|
"authors": [
|
|
25
|
-
"
|
|
26
|
-
"
|
|
26
|
+
"Pascal Kaufmann",
|
|
27
|
+
"Mikael Araya",
|
|
28
|
+
"Vedran Rudelj",
|
|
29
|
+
"Joël Meiller"
|
|
27
30
|
],
|
|
28
31
|
"license": "EUPL-1.2",
|
|
29
32
|
"bugs": {
|
|
@@ -31,26 +34,33 @@
|
|
|
31
34
|
},
|
|
32
35
|
"homepage": "https://github.com/unchainedshop/unchained#readme",
|
|
33
36
|
"dependencies": {
|
|
37
|
+
"@passwordless-id/webauthn": "^2.3.1",
|
|
38
|
+
"@unchainedshop/events": "^4.5.0",
|
|
39
|
+
"@unchainedshop/file-upload": "^4.5.0",
|
|
40
|
+
"@unchainedshop/logger": "^4.5.0",
|
|
41
|
+
"@unchainedshop/mongodb": "^4.5.0",
|
|
42
|
+
"@unchainedshop/roles": "^4.5.0",
|
|
43
|
+
"@unchainedshop/utils": "^4.5.0",
|
|
34
44
|
"bcryptjs": "^3.0.2",
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"@unchainedshop/logger": "^4.3.0",
|
|
38
|
-
"@unchainedshop/mongodb": "^4.3.0",
|
|
39
|
-
"@unchainedshop/roles": "^4.3.0",
|
|
40
|
-
"@unchainedshop/utils": "^4.3.0"
|
|
45
|
+
"expiry-map": "^2.0.0",
|
|
46
|
+
"p-memoize": "^8.0.0"
|
|
41
47
|
},
|
|
42
48
|
"peerDependencies": {
|
|
43
|
-
"
|
|
49
|
+
"@noble/curves": "^2.0.0",
|
|
50
|
+
"@noble/hashes": "^2.0.0"
|
|
44
51
|
},
|
|
45
52
|
"peerDependenciesMeta": {
|
|
46
|
-
"
|
|
53
|
+
"@noble/curves": {
|
|
54
|
+
"optional": true
|
|
55
|
+
},
|
|
56
|
+
"@noble/hashes": {
|
|
47
57
|
"optional": true
|
|
48
58
|
}
|
|
49
59
|
},
|
|
50
60
|
"devDependencies": {
|
|
51
|
-
"@
|
|
52
|
-
"
|
|
53
|
-
"
|
|
61
|
+
"@noble/curves": "^2.0.0",
|
|
62
|
+
"@noble/hashes": "^2.0.0",
|
|
63
|
+
"@types/node": "^25.0.0",
|
|
54
64
|
"typescript": "^5.8.3"
|
|
55
65
|
}
|
|
56
66
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"UsersCollection.d.ts","sourceRoot":"","sources":["../../src/db/UsersCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,OAAO,EACP,OAAO,EACP,OAAO,EAGR,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AACD,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,IAAI,GAAG;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,eAAe,EAAE,OAAO,CAAC;IACzB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,GAAG,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,iBAAiB,EAAE,sBAAsB,EAAE,CAAC;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ,GAAG,eAAe,CAAC;AAEpB,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG;IAC7C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,eAAe,GAAU,IAAI,OAAO,CAAC,EAAE,sCAyGnD,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"UsersCollection.js","sourceRoot":"","sources":["../../src/db/UsersCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,cAAc,EACd,6BAA6B,GAC9B,MAAM,wBAAwB,CAAC;AA6DhC,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,EAAc,EAAE,EAAE;IACtD,MAAM,KAAK,GAAG,EAAE,CAAC,UAAU,CAAO,OAAO,CAAC,CAAC;IAE3C,IAAI,CAAC,6BAA6B,EAAE,EAAE,CAAC;QACrC,MAAM,cAAc,CAAO,KAAK,EAAE;YAChC;gBACE,KAAK,EAAE;oBACL,GAAG,EAAE,MAAM;oBACX,QAAQ,EAAE,MAAM;oBAChB,gBAAgB,EAAE,MAAM;oBACxB,qBAAqB,EAAE,MAAM;oBAC7B,8BAA8B,EAAE,MAAM;oBACtC,6BAA6B,EAAE,MAAM;oBACrC,4BAA4B,EAAE,MAAM;oBACpC,gCAAgC,EAAE,MAAM;oBACxC,iCAAiC,EAAE,MAAM;iBACnC;gBACR,OAAO,EAAE;oBACP,OAAO,EAAE;wBACP,GAAG,EAAE,CAAC;wBACN,gBAAgB,EAAE,CAAC;wBACnB,qBAAqB,EAAE,CAAC;wBACxB,8BAA8B,EAAE,CAAC;wBACjC,6BAA6B,EAAE,CAAC;wBAChC,4BAA4B,EAAE,CAAC;wBAC/B,gCAAgC,EAAE,CAAC;wBACnC,iCAAiC,EAAE,CAAC;qBACrC;oBACD,IAAI,EAAE,sBAAsB;iBAC7B;aACF;SACF,CAAC,CAAC;IACL,CAAC;IAED,MAAM,cAAc,CAAO,KAAK,EAAE;QAChC;YACE,KAAK,EAAE;gBACL,OAAO,EAAE,CAAC;gBACV,OAAO,EAAE,CAAC;gBACV,KAAK,EAAE,CAAC;aACT;YACD,OAAO,EAAE,EAAE;SACZ;QACD;YACE,KAAK,EAAE;gBACL,KAAK,EAAE,CAAC;aACT;YACD,OAAO,EAAE;gBACP,MAAM,EAAE,IAAI;aACb;SACF;QACD;YACE,KAAK,EAAE;gBACL,OAAO,EAAE,CAAC;aACX;YACD,OAAO,EAAE,EAAE;SACZ;QACD;YACE,KAAK,EAAE;gBACL,QAAQ,EAAE,CAAC;aACZ;YACD,OAAO,EAAE;gBACP,MAAM,EAAE,IAAI;gBACZ,MAAM,EAAE,IAAI;aACb;SACF;QACD;YACE,KAAK,EAAE;gBACL,gBAAgB,EAAE,CAAC;aACb;YACR,OAAO,EAAE;gBACP,MAAM,EAAE,IAAI;gBACZ,MAAM,EAAE,IAAI;aACb;SACF;QAED;YACE,KAAK,EAAE;gBACL,yCAAyC,EAAE,CAAC;aACtC;YACR,OAAO,EAAE;gBACP,MAAM,EAAE,IAAI;aACb;SACF;QAED;YACE,KAAK,EAAE;gBACL,+BAA+B,EAAE,CAAC;aAC5B;YACR,OAAO,EAAE;gBACP,MAAM,EAAE,IAAI;aACb;SACF;QAED;YACE,KAAK,EAAE;gBACL,uBAAuB,EAAE,CAAC;aAC3B;YACD,OAAO,EAAE;gBACP,MAAM,EAAE,IAAI;aACb;SACF;KACF,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"WebAuthnCredentialsCreationRequestsCollection.d.ts","sourceRoot":"","sources":["../../src/db/WebAuthnCredentialsCreationRequestsCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAkB,MAAM,wBAAwB,CAAC;AAEjE,MAAM,WAAW,kCAAkC;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;CACvC;AAED,KAAK,UAAU,GAAG,kCAAkC,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE,eAAO,MAAM,6CAA6C,GAAU,IAAI,OAAO,CAAC,EAAE,4CAcjF,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"WebAuthnCredentialsCreationRequestsCollection.js","sourceRoot":"","sources":["../../src/db/WebAuthnCredentialsCreationRequestsCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAWjE,MAAM,CAAC,MAAM,6CAA6C,GAAG,KAAK,EAAE,EAAc,EAAE,EAAE;IACpF,MAAM,mCAAmC,GAAG,EAAE,CAAC,UAAU,CACvD,iDAAiD,CAClD,CAAC;IAEF,MAAM,cAAc,CAAa,mCAAmC,EAAE;QACpE;YACE,KAAK,EAAE;gBACL,QAAQ,EAAE,CAAC;aACZ;SACF;KACF,CAAC,CAAC;IAEH,OAAO,mCAAmC,CAAC;AAC7C,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"configureUsersModule.d.ts","sourceRoot":"","sources":["../../src/module/configureUsersModule.ts"],"names":[],"mappings":"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"}
|