@holo-js/auth-clerk 0.1.5 → 0.1.7

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 (2) hide show
  1. package/dist/index.mjs +32 -55
  2. package/package.json +4 -4
package/dist/index.mjs CHANGED
@@ -231,19 +231,29 @@ async function verifyClerkSessionToken(token, config, authorizedParties = []) {
231
231
  throw new Error("[@holo-js/auth-clerk] Clerk token signature verification failed.");
232
232
  }
233
233
  const exp = typeof parsed.payload.exp === "number" ? parsed.payload.exp : void 0;
234
- if (typeof exp === "number" && exp * 1e3 <= Date.now()) {
234
+ if (typeof exp !== "number") {
235
+ throw new Error("[@holo-js/auth-clerk] Clerk token did not include an expiration.");
236
+ }
237
+ if (exp * 1e3 <= Date.now()) {
235
238
  throw new Error("[@holo-js/auth-clerk] Clerk token has expired.");
236
239
  }
240
+ if (typeof parsed.payload.sub !== "string" || !parsed.payload.sub.trim()) {
241
+ throw new Error("[@holo-js/auth-clerk] Clerk token did not include a subject.");
242
+ }
243
+ if ((typeof parsed.payload.sid !== "string" || !parsed.payload.sid.trim()) && (typeof parsed.payload.session_id !== "string" || !parsed.payload.session_id.trim())) {
244
+ throw new Error("[@holo-js/auth-clerk] Clerk token did not include a session id.");
245
+ }
237
246
  const nbf = typeof parsed.payload.nbf === "number" ? parsed.payload.nbf : void 0;
238
247
  if (typeof nbf === "number" && nbf * 1e3 > Date.now()) {
239
248
  throw new Error("[@holo-js/auth-clerk] Clerk token is not valid yet.");
240
249
  }
241
250
  const azp = typeof parsed.payload.azp === "string" ? parsed.payload.azp.trim() : "";
242
- if (azp) {
243
- const allowedAuthorizedParties = authorizedParties.map((value) => value.trim()).filter(Boolean);
244
- if (allowedAuthorizedParties.length > 0 && !allowedAuthorizedParties.includes(azp)) {
245
- throw new Error(`[@holo-js/auth-clerk] Clerk token authorized party "${azp}" is not allowed.`);
246
- }
251
+ const allowedAuthorizedParties = authorizedParties.map((value) => value.trim()).filter(Boolean);
252
+ if (allowedAuthorizedParties.length > 0 && !azp) {
253
+ throw new Error("[@holo-js/auth-clerk] Clerk token did not include an authorized party.");
254
+ }
255
+ if (azp && allowedAuthorizedParties.length > 0 && !allowedAuthorizedParties.includes(azp)) {
256
+ throw new Error(`[@holo-js/auth-clerk] Clerk token authorized party "${azp}" is not allowed.`);
247
257
  }
248
258
  return parsed.payload;
249
259
  }
@@ -670,21 +680,6 @@ async function ensureNoUnexpectedEmailCollision(adapter, providerName, profile,
670
680
  });
671
681
  }
672
682
  }
673
- async function assertUserLinkAvailable(providerName, authProvider, adapter, user, clerkUserId) {
674
- const existing = await getBindings().identityStore.findByUserId(
675
- providerName,
676
- authProvider,
677
- requireUserId(adapter, user, "[@holo-js/auth-clerk] Linked users must expose a serializable id.")
678
- );
679
- if (existing && existing.providerUserId !== clerkUserId) {
680
- throw new ClerkAuthConflictError({
681
- provider: providerName,
682
- clerkUserId,
683
- email: existing.email,
684
- message: `[@holo-js/auth-clerk] Local user is already linked to Clerk identity "${existing.providerUserId}".`
685
- });
686
- }
687
- }
688
683
  function isEmailVerificationRequired() {
689
684
  return authRuntimeInternals.getRuntimeBindings().config.emailVerification.required === true;
690
685
  }
@@ -967,16 +962,19 @@ async function syncIdentity(session, provider, options = {}) {
967
962
  const existingLinkedUser = await adapter.findById(existingIdentity.userId);
968
963
  let linkedUser = existingLinkedUser ? requireUserRecord(existingLinkedUser, "[@holo-js/auth-clerk] Auth provider lookups must return object users.") : null;
969
964
  if (!linkedUser) {
970
- linkedUser = verifiedEmail ? await findUserByEmail(adapter, verifiedEmail) : null;
971
- if (linkedUser) {
972
- await assertUserLinkAvailable(providerName, authProvider, adapter, linkedUser, profile.id);
973
- }
974
- if (!linkedUser) {
975
- linkedUser = requireUserRecord(
976
- await adapter.create(resolveCreateUserInput(profile, options.user)),
977
- "[@holo-js/auth-clerk] Auth provider create() must return an object user."
978
- );
965
+ const emailMatchedUser = verifiedEmail ? await findUserByEmail(adapter, verifiedEmail) : null;
966
+ if (emailMatchedUser) {
967
+ throw new ClerkAuthConflictError({
968
+ provider: providerName,
969
+ clerkUserId: profile.id,
970
+ email: verifiedEmail,
971
+ message: `[@holo-js/auth-clerk] Clerk email "${verifiedEmail}" matches an existing local user and must be linked explicitly.`
972
+ });
979
973
  }
974
+ linkedUser = requireUserRecord(
975
+ await adapter.create(resolveCreateUserInput(profile, options.user)),
976
+ "[@holo-js/auth-clerk] Auth provider create() must return an object user."
977
+ );
980
978
  const relinked = await updateLocalUser(adapter, linkedUser, resolveUpdateUserInput(profile, options.user));
981
979
  const relinkedUser = relinked.user;
982
980
  const identity3 = createIdentityRecord({
@@ -1038,32 +1036,11 @@ async function syncIdentity(session, provider, options = {}) {
1038
1036
  }
1039
1037
  let localUser = verifiedEmail ? await findUserByEmail(adapter, verifiedEmail) : null;
1040
1038
  if (localUser) {
1041
- await assertUserLinkAvailable(providerName, authProvider, adapter, localUser, profile.id);
1042
- const linked = await updateLocalUser(adapter, localUser, resolveUpdateUserInput(profile, options.user));
1043
- const identity2 = createIdentityRecord({
1044
- provider: providerName,
1045
- guard,
1046
- authProvider,
1047
- userId: requireUserId(
1048
- adapter,
1049
- linked.user,
1050
- "[@holo-js/auth-clerk] Linked local users must expose a serializable id."
1051
- ),
1052
- profile
1053
- });
1054
- const claimedIdentity2 = await claimNewIdentity(identityStore, identity2);
1055
- const claimedUser2 = await resolveClaimedIdentityUser(adapter, claimedIdentity2, {
1056
- user: linked.user,
1057
- userId: identity2.userId
1058
- });
1059
- return Object.freeze({
1039
+ throw new ClerkAuthConflictError({
1060
1040
  provider: providerName,
1061
- guard,
1062
- authProvider,
1063
- status: "linked",
1064
- user: serializeLocalUser(adapter, claimedUser2, authProvider),
1065
- identity: claimedIdentity2,
1066
- session
1041
+ clerkUserId: profile.id,
1042
+ email: verifiedEmail,
1043
+ message: `[@holo-js/auth-clerk] Clerk email "${verifiedEmail}" matches an existing local user and must be linked explicitly.`
1067
1044
  });
1068
1045
  }
1069
1046
  localUser = requireUserRecord(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holo-js/auth-clerk",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Holo-JS Framework - Clerk auth integration contracts",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -24,9 +24,9 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "@clerk/backend": "^3.4.7",
27
- "@holo-js/auth": "^0.1.5",
28
- "@holo-js/config": "^0.1.5",
29
- "@holo-js/session": "^0.1.5"
27
+ "@holo-js/auth": "^0.1.7",
28
+ "@holo-js/config": "^0.1.7",
29
+ "@holo-js/session": "^0.1.7"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^22.10.2",