@delmaredigital/payload-better-auth 0.6.1 → 0.6.4
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/adapter/index.js
CHANGED
|
@@ -262,8 +262,15 @@
|
|
|
262
262
|
}
|
|
263
263
|
// Get Payload collection slug from model name
|
|
264
264
|
// Uses factory's getModelName which respects BetterAuthOptions.modelName config
|
|
265
|
+
// Fix: Better Auth's getModelName blindly appends 's' even when name already ends in 's'
|
|
266
|
+
// (e.g., 'jwks' becomes 'jwkss'). We normalize to prevent double-s slugs.
|
|
265
267
|
const getCollection = (model)=>{
|
|
266
|
-
|
|
268
|
+
const name = getModelName(model);
|
|
269
|
+
// Fix double-s from naive pluralization (e.g., jwkss → jwks)
|
|
270
|
+
if (name.endsWith('ss') && !model.endsWith('ss')) {
|
|
271
|
+
return name.slice(0, -1);
|
|
272
|
+
}
|
|
273
|
+
return name;
|
|
267
274
|
};
|
|
268
275
|
// The CustomAdapter interface uses generics (T) for return types.
|
|
269
276
|
// Payload returns concrete types (JsonObject & TypeWithID).
|
package/dist/plugin/index.js
CHANGED
|
@@ -481,6 +481,12 @@ let apiKeyPermissionsConfig = undefined;
|
|
|
481
481
|
console.error('[better-auth] Failed to create auth:', error);
|
|
482
482
|
throw error;
|
|
483
483
|
}
|
|
484
|
+
// Warn if nextCookies() plugin is detected — it's incompatible with Payload CMS.
|
|
485
|
+
// Check via betterAuthOptions (if provided) or the auth instance's options.
|
|
486
|
+
const pluginsToCheck = options.admin?.betterAuthOptions?.plugins ?? authInstance.options?.plugins;
|
|
487
|
+
if (pluginsToCheck?.some((p)=>p.id === 'next-cookies')) {
|
|
488
|
+
console.warn('\n⚠️ [payload-better-auth] The nextCookies() plugin was detected in your Better Auth config.\n' + ' This plugin is INCOMPATIBLE with Payload CMS and will cause infinite form-state\n' + ' submissions and input resets in the admin panel.\n\n' + ' The nextCookies() plugin is designed for Server Actions, but payload-better-auth\n' + ' handles cookie passthrough automatically via its endpoint proxy.\n\n' + ' → Remove nextCookies() from your Better Auth plugins to fix this issue.\n' + ' → See: https://github.com/delmaredigital/payload-better-auth/issues/15\n');
|
|
489
|
+
}
|
|
484
490
|
}
|
|
485
491
|
// Attach to payload for global access
|
|
486
492
|
Object.defineProperty(payload, 'betterAuth', {
|
|
@@ -546,6 +552,90 @@ let apiKeyPermissionsConfig = undefined;
|
|
|
546
552
|
headers
|
|
547
553
|
});
|
|
548
554
|
if (!sessionData?.user?.id) {
|
|
555
|
+
// No session found — check for OAuth JWT Bearer token
|
|
556
|
+
const authHeader = headers.get('authorization');
|
|
557
|
+
if (authHeader?.startsWith('Bearer ')) {
|
|
558
|
+
const token = authHeader.slice(7);
|
|
559
|
+
// Try OAuth JWT verification via the oauth-provider's verifyAccessToken
|
|
560
|
+
try {
|
|
561
|
+
const { verifyAccessToken } = await import('better-auth/oauth2');
|
|
562
|
+
const baseURL = auth.options?.baseURL;
|
|
563
|
+
if (!baseURL) throw new Error('baseURL not configured');
|
|
564
|
+
const jwtPayload = await verifyAccessToken(token, {
|
|
565
|
+
jwksUrl: `${baseURL}/api/auth/jwks`,
|
|
566
|
+
verifyOptions: {
|
|
567
|
+
issuer: baseURL,
|
|
568
|
+
audience: baseURL
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
if (jwtPayload?.sub) {
|
|
572
|
+
const users = await payload.find({
|
|
573
|
+
collection: usersCollection,
|
|
574
|
+
where: {
|
|
575
|
+
id: {
|
|
576
|
+
equals: jwtPayload.sub
|
|
577
|
+
}
|
|
578
|
+
},
|
|
579
|
+
limit: 1,
|
|
580
|
+
depth: 0
|
|
581
|
+
});
|
|
582
|
+
if (users.docs.length > 0) {
|
|
583
|
+
// Extract org context and scopes from JWT claims
|
|
584
|
+
const oauthOrgId = jwtPayload.organizationId;
|
|
585
|
+
const oauthScopes = typeof jwtPayload.scope === 'string' ? jwtPayload.scope.split(' ') : Array.isArray(jwtPayload.scope) ? jwtPayload.scope : [];
|
|
586
|
+
// Look up org role if orgId is present
|
|
587
|
+
let orgRole;
|
|
588
|
+
if (oauthOrgId) {
|
|
589
|
+
try {
|
|
590
|
+
const memberships = await payload.find({
|
|
591
|
+
collection: membersCollection,
|
|
592
|
+
where: {
|
|
593
|
+
and: [
|
|
594
|
+
{
|
|
595
|
+
user: {
|
|
596
|
+
equals: jwtPayload.sub
|
|
597
|
+
}
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
organization: {
|
|
601
|
+
equals: oauthOrgId
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
]
|
|
605
|
+
},
|
|
606
|
+
limit: 1,
|
|
607
|
+
depth: 0
|
|
608
|
+
});
|
|
609
|
+
if (memberships.docs.length > 0) {
|
|
610
|
+
orgRole = memberships.docs[0].role;
|
|
611
|
+
}
|
|
612
|
+
} catch {
|
|
613
|
+
// Members collection might not exist
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
const userDoc = users.docs[0];
|
|
617
|
+
const oauthUser = {
|
|
618
|
+
...userDoc,
|
|
619
|
+
id: userDoc.id,
|
|
620
|
+
oauthScopes,
|
|
621
|
+
collection: usersCollection,
|
|
622
|
+
_strategy: 'better-auth',
|
|
623
|
+
...oauthOrgId ? {
|
|
624
|
+
activeOrganizationId: oauthOrgId
|
|
625
|
+
} : {},
|
|
626
|
+
...orgRole ? {
|
|
627
|
+
organizationRole: orgRole
|
|
628
|
+
} : {}
|
|
629
|
+
};
|
|
630
|
+
return {
|
|
631
|
+
user: oauthUser
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
} catch {
|
|
636
|
+
// JWT verification failed — not a valid OAuth token, continue to return null
|
|
637
|
+
}
|
|
638
|
+
}
|
|
549
639
|
return {
|
|
550
640
|
user: null
|
|
551
641
|
};
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
hasPasskey: false,
|
|
16
16
|
hasMagicLink: false,
|
|
17
17
|
hasMultiSession: false,
|
|
18
|
-
hasOrganization: false
|
|
18
|
+
hasOrganization: false,
|
|
19
|
+
hasNextCookies: false
|
|
19
20
|
};
|
|
20
21
|
for (const plugin of plugins){
|
|
21
22
|
// Better Auth plugins have an id property
|
|
@@ -42,6 +43,9 @@
|
|
|
42
43
|
case 'organization':
|
|
43
44
|
result.hasOrganization = true;
|
|
44
45
|
break;
|
|
46
|
+
case 'next-cookies':
|
|
47
|
+
result.hasNextCookies = true;
|
|
48
|
+
break;
|
|
45
49
|
}
|
|
46
50
|
}
|
|
47
51
|
return result;
|