@holo-js/auth-clerk 0.2.6 → 0.3.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/dist/index.d.ts +1 -2
- package/dist/index.mjs +25 -50
- package/package.json +3 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { AuthResult, AuthenticatedAuthUser, AuthEstablishedSession, AuthFieldErrors, AuthLogoutResult, authRuntimeInternals } from '@holo-js/auth';
|
|
2
|
-
import { AuthClerkProviderConfig, NormalizedAuthClerkProviderConfig } from '@holo-js/config';
|
|
1
|
+
import { AuthClerkProviderConfig, AuthResult, AuthenticatedAuthUser, AuthEstablishedSession, AuthFieldErrors, AuthLogoutResult, NormalizedAuthClerkProviderConfig, authRuntimeInternals } from '@holo-js/auth';
|
|
3
2
|
|
|
4
3
|
interface ClerkEmailAddress {
|
|
5
4
|
readonly id?: string;
|
package/dist/index.mjs
CHANGED
|
@@ -114,6 +114,7 @@ async function verifyClerkSessionToken(token, config, authorizedParties = []) {
|
|
|
114
114
|
if ((typeof parsed.payload.sid !== "string" || !parsed.payload.sid.trim()) && (typeof parsed.payload.session_id !== "string" || !parsed.payload.session_id.trim())) {
|
|
115
115
|
throw new Error("[@holo-js/auth-clerk] Clerk token did not include a session id.");
|
|
116
116
|
}
|
|
117
|
+
const sessionId = typeof parsed.payload.sid === "string" && parsed.payload.sid.trim() ? parsed.payload.sid.trim() : parsed.payload.session_id.trim();
|
|
117
118
|
const nbf = typeof parsed.payload.nbf === "number" ? parsed.payload.nbf : void 0;
|
|
118
119
|
if (typeof nbf === "number" && nbf * 1e3 > Date.now()) {
|
|
119
120
|
throw new Error("[@holo-js/auth-clerk] Clerk token is not valid yet.");
|
|
@@ -126,7 +127,12 @@ async function verifyClerkSessionToken(token, config, authorizedParties = []) {
|
|
|
126
127
|
if (azp && allowedAuthorizedParties.length > 0 && !allowedAuthorizedParties.includes(azp)) {
|
|
127
128
|
throw new Error(`[@holo-js/auth-clerk] Clerk token authorized party "${azp}" is not allowed.`);
|
|
128
129
|
}
|
|
129
|
-
return
|
|
130
|
+
return Object.freeze({
|
|
131
|
+
...parsed.payload,
|
|
132
|
+
exp,
|
|
133
|
+
sessionId,
|
|
134
|
+
sub: parsed.payload.sub.trim()
|
|
135
|
+
});
|
|
130
136
|
}
|
|
131
137
|
function normalizeClerkEmailAddress(value) {
|
|
132
138
|
const verification = value.verification && typeof value.verification === "object" ? value.verification : void 0;
|
|
@@ -181,7 +187,7 @@ function createDefaultProviderRuntime(providerName, config) {
|
|
|
181
187
|
config.apiUrl ?? "",
|
|
182
188
|
config.frontendApi ?? "",
|
|
183
189
|
config.secretKey ?? "",
|
|
184
|
-
[...config.authorizedParties
|
|
190
|
+
[...config.authorizedParties].sort()
|
|
185
191
|
]);
|
|
186
192
|
const existing = clerkDefaultProviderRuntimeCache.get(cacheKey);
|
|
187
193
|
if (existing) {
|
|
@@ -190,14 +196,9 @@ function createDefaultProviderRuntime(providerName, config) {
|
|
|
190
196
|
const runtime = Object.freeze({
|
|
191
197
|
async verifySession({ token }) {
|
|
192
198
|
const claims = await verifyClerkSessionToken(token, config, config.authorizedParties);
|
|
193
|
-
const
|
|
194
|
-
if (!userId) {
|
|
195
|
-
throw new Error("[@holo-js/auth-clerk] Clerk token did not include a subject.");
|
|
196
|
-
}
|
|
197
|
-
const profile = await fetchClerkUserProfile(userId, config);
|
|
198
|
-
const sessionId = typeof claims.sid === "string" ? claims.sid : typeof claims.session_id === "string" ? claims.session_id : token;
|
|
199
|
+
const profile = await fetchClerkUserProfile(claims.sub, config);
|
|
199
200
|
return Object.freeze({
|
|
200
|
-
sessionId,
|
|
201
|
+
sessionId: claims.sessionId,
|
|
201
202
|
user: profile,
|
|
202
203
|
accessToken: token,
|
|
203
204
|
raw: Object.freeze({
|
|
@@ -219,7 +220,7 @@ function resolveConfiguredProviderName(provider) {
|
|
|
219
220
|
if (configuredDefaultProvider) {
|
|
220
221
|
return configuredDefaultProvider;
|
|
221
222
|
}
|
|
222
|
-
const configuredProviders = Object.entries(bindings.config.clerk).flatMap(([name
|
|
223
|
+
const configuredProviders = Object.entries(bindings.config.clerk).flatMap(([name]) => name !== "provider" && name !== "identityStore" ? [name] : []);
|
|
223
224
|
if (configuredProviders.length === 0) {
|
|
224
225
|
return "default";
|
|
225
226
|
}
|
|
@@ -249,7 +250,7 @@ function getConfiguredProviderConfig(provider) {
|
|
|
249
250
|
frontendApi: configured.frontendApi,
|
|
250
251
|
redirectUri: configured.redirectUri,
|
|
251
252
|
sessionCookie: configured.sessionCookie,
|
|
252
|
-
authorizedParties: configured.authorizedParties
|
|
253
|
+
authorizedParties: configured.authorizedParties,
|
|
253
254
|
guard: configured.guard,
|
|
254
255
|
mapToProvider: configured.mapToProvider
|
|
255
256
|
};
|
|
@@ -322,7 +323,7 @@ function createClerkErrorResponse(error, code) {
|
|
|
322
323
|
code,
|
|
323
324
|
message: getErrorMessage(error)
|
|
324
325
|
}, {
|
|
325
|
-
status:
|
|
326
|
+
status: 422
|
|
326
327
|
});
|
|
327
328
|
}
|
|
328
329
|
function resolveGuardAndProvider(provider) {
|
|
@@ -330,9 +331,6 @@ function resolveGuardAndProvider(provider) {
|
|
|
330
331
|
const providerConfig = getConfiguredProviderConfig(provider);
|
|
331
332
|
const guardName = providerConfig.guard ?? authBindings.config.defaults.guard;
|
|
332
333
|
const guard = authBindings.config.guards[guardName];
|
|
333
|
-
if (!guard) {
|
|
334
|
-
throw new Error(`[@holo-js/auth-clerk] Guard "${guardName}" is not configured for Clerk provider "${providerConfig.name}".`);
|
|
335
|
-
}
|
|
336
334
|
if (guard.driver !== "session") {
|
|
337
335
|
throw new Error(`[@holo-js/auth-clerk] Clerk sign-in requires auth guard "${guardName}" to use the session driver.`);
|
|
338
336
|
}
|
|
@@ -348,9 +346,6 @@ function resolveGuardAndProvider(provider) {
|
|
|
348
346
|
};
|
|
349
347
|
}
|
|
350
348
|
function requireUserId(adapter, user, message) {
|
|
351
|
-
if (!user || typeof user !== "object") {
|
|
352
|
-
throw new Error(message);
|
|
353
|
-
}
|
|
354
349
|
const userId = adapter.getId(user);
|
|
355
350
|
if (typeof userId !== "string" && typeof userId !== "number") {
|
|
356
351
|
throw new Error(message);
|
|
@@ -363,17 +358,8 @@ function requireUserRecord(user, message) {
|
|
|
363
358
|
}
|
|
364
359
|
return user;
|
|
365
360
|
}
|
|
366
|
-
function requireSerializedUser(user, message) {
|
|
367
|
-
if (typeof user.id === "string" || typeof user.id === "number") {
|
|
368
|
-
return user;
|
|
369
|
-
}
|
|
370
|
-
throw new Error(message);
|
|
371
|
-
}
|
|
372
361
|
function createClerkSessionPayload(authenticated, session) {
|
|
373
|
-
const user =
|
|
374
|
-
authenticated.user,
|
|
375
|
-
"[@holo-js/auth-clerk] Clerk-authenticated local users must expose a serializable id."
|
|
376
|
-
);
|
|
362
|
+
const user = authenticated.user;
|
|
377
363
|
return Object.freeze({
|
|
378
364
|
guard: authenticated.guard,
|
|
379
365
|
provider: authenticated.authProvider,
|
|
@@ -416,7 +402,7 @@ function serializeLocalUser(adapter, user, providerName) {
|
|
|
416
402
|
configurable: true
|
|
417
403
|
});
|
|
418
404
|
Object.defineProperty(result, "can", {
|
|
419
|
-
value: () => false,
|
|
405
|
+
value: async () => false,
|
|
420
406
|
enumerable: false,
|
|
421
407
|
configurable: true
|
|
422
408
|
});
|
|
@@ -499,9 +485,6 @@ function normalizeHostedProfile(profile) {
|
|
|
499
485
|
});
|
|
500
486
|
}
|
|
501
487
|
async function findUserByEmail(adapter, email) {
|
|
502
|
-
if (!email?.trim()) {
|
|
503
|
-
return null;
|
|
504
|
-
}
|
|
505
488
|
const user = await adapter.findByCredentials({ email: email.trim() });
|
|
506
489
|
return user ? requireUserRecord(user, "[@holo-js/auth-clerk] Auth provider lookups must return object users.") : null;
|
|
507
490
|
}
|
|
@@ -572,11 +555,11 @@ function createIdentityRecord(input) {
|
|
|
572
555
|
}
|
|
573
556
|
async function withIdentitySyncLock(key, callback) {
|
|
574
557
|
const previous = clerkIdentitySyncLocks.get(key) ?? Promise.resolve();
|
|
575
|
-
let release
|
|
576
|
-
|
|
577
|
-
const current = previous.then(() => new Promise((resolve) => {
|
|
558
|
+
let release;
|
|
559
|
+
const gate = new Promise((resolve) => {
|
|
578
560
|
release = resolve;
|
|
579
|
-
})
|
|
561
|
+
});
|
|
562
|
+
const current = previous.then(() => gate);
|
|
580
563
|
clerkIdentitySyncLocks.set(key, current);
|
|
581
564
|
await previous;
|
|
582
565
|
try {
|
|
@@ -606,7 +589,7 @@ async function resolveClaimedIdentityUser(adapter, identity, fallback) {
|
|
|
606
589
|
await adapter.findById(identity.userId),
|
|
607
590
|
"[@holo-js/auth-clerk] Claimed Clerk identities must reference an existing local user."
|
|
608
591
|
);
|
|
609
|
-
if (
|
|
592
|
+
if (adapter.delete) {
|
|
610
593
|
await adapter.delete(fallback.userId);
|
|
611
594
|
}
|
|
612
595
|
return claimedUser;
|
|
@@ -640,13 +623,9 @@ function isConfiguredClerkRedirectRequest(request, config) {
|
|
|
640
623
|
if (!redirectUri) {
|
|
641
624
|
return hasClerkCallbackState(request);
|
|
642
625
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
return requestUrl.origin === configuredUrl.origin && requestUrl.pathname === configuredUrl.pathname;
|
|
647
|
-
} catch {
|
|
648
|
-
return false;
|
|
649
|
-
}
|
|
626
|
+
const requestUrl = new URL(request.url);
|
|
627
|
+
const configuredUrl = new URL(redirectUri, requestUrl.origin);
|
|
628
|
+
return requestUrl.origin === configuredUrl.origin && requestUrl.pathname === configuredUrl.pathname;
|
|
650
629
|
}
|
|
651
630
|
function splitSetCookieHeader(value) {
|
|
652
631
|
return value.split(/,(?=\s*[^;,=\s]+=)/g).map((cookie) => cookie.trim()).filter(Boolean);
|
|
@@ -721,7 +700,7 @@ async function verifySession(token, provider) {
|
|
|
721
700
|
function resolveRequestAuthorizedParties(config, request) {
|
|
722
701
|
return Object.freeze([
|
|
723
702
|
.../* @__PURE__ */ new Set([
|
|
724
|
-
...config.authorizedParties
|
|
703
|
+
...config.authorizedParties,
|
|
725
704
|
new URL(request.url).origin
|
|
726
705
|
])
|
|
727
706
|
]);
|
|
@@ -732,9 +711,6 @@ async function verifyDefaultSessionToken(token, providerConfig, authorizedPartie
|
|
|
732
711
|
authorizedParties
|
|
733
712
|
};
|
|
734
713
|
const defaultRuntime = createDefaultProviderRuntime(providerConfig.name, config);
|
|
735
|
-
if (!defaultRuntime.verifySession) {
|
|
736
|
-
throw new Error(`[@holo-js/auth-clerk] Clerk provider runtime "${providerConfig.name}" does not implement verifySession().`);
|
|
737
|
-
}
|
|
738
714
|
return defaultRuntime.verifySession({
|
|
739
715
|
provider: providerConfig.name,
|
|
740
716
|
token,
|
|
@@ -932,8 +908,7 @@ async function syncIdentity(session, provider, options = {}) {
|
|
|
932
908
|
const claimedIdentity = await claimNewIdentity(identityStore, identity);
|
|
933
909
|
const claimedUser = await resolveClaimedIdentityUser(adapter, claimedIdentity, {
|
|
934
910
|
user: localUser,
|
|
935
|
-
userId: identity.userId
|
|
936
|
-
deleteOnMismatch: true
|
|
911
|
+
userId: identity.userId
|
|
937
912
|
});
|
|
938
913
|
const claimedStatus = sameUserId(claimedIdentity.userId, identity.userId) ? "created" : "linked";
|
|
939
914
|
return Object.freeze({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holo-js/auth-clerk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Holo-JS Framework - Clerk auth integration contracts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,9 +24,8 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@clerk/backend": "^3.4.7",
|
|
27
|
-
"@holo-js/auth": "^0.
|
|
28
|
-
"@holo-js/
|
|
29
|
-
"@holo-js/session": "^0.2.6"
|
|
27
|
+
"@holo-js/auth": "^0.3.0",
|
|
28
|
+
"@holo-js/session": "^0.3.0"
|
|
30
29
|
},
|
|
31
30
|
"devDependencies": {
|
|
32
31
|
"@types/node": "^22.10.2",
|