@payloadcms/figma 0.0.1-alpha.4 → 0.0.1-alpha.41

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 (269) hide show
  1. package/dist/api/control-plane.d.ts +22 -1
  2. package/dist/api/control-plane.d.ts.map +1 -1
  3. package/dist/api/control-plane.js +55 -22
  4. package/dist/api/control-plane.js.map +1 -1
  5. package/dist/api/figma-api.d.ts.map +1 -1
  6. package/dist/api/figma-api.js +45 -26
  7. package/dist/api/figma-api.js.map +1 -1
  8. package/dist/auth/callback-server.d.ts.map +1 -1
  9. package/dist/auth/callback-server.js +2 -1
  10. package/dist/auth/callback-server.js.map +1 -1
  11. package/dist/auth/crypto-utils.d.ts.map +1 -1
  12. package/dist/auth/crypto-utils.js +5 -5
  13. package/dist/auth/crypto-utils.js.map +1 -1
  14. package/dist/auth/jwt-validator.d.ts +2 -1
  15. package/dist/auth/jwt-validator.d.ts.map +1 -1
  16. package/dist/auth/jwt-validator.js +2 -2
  17. package/dist/auth/jwt-validator.js.map +1 -1
  18. package/dist/auth/oauth-flow.d.ts +1 -1
  19. package/dist/auth/oauth-flow.d.ts.map +1 -1
  20. package/dist/auth/oauth-flow.js +9 -8
  21. package/dist/auth/oauth-flow.js.map +1 -1
  22. package/dist/auth/project-token.d.ts.map +1 -1
  23. package/dist/auth/project-token.js +9 -4
  24. package/dist/auth/project-token.js.map +1 -1
  25. package/dist/auth/refresh.d.ts.map +1 -1
  26. package/dist/auth/refresh.js +14 -9
  27. package/dist/auth/refresh.js.map +1 -1
  28. package/dist/auth/token-store.d.ts +10 -0
  29. package/dist/auth/token-store.d.ts.map +1 -1
  30. package/dist/auth/token-store.js +20 -0
  31. package/dist/auth/token-store.js.map +1 -1
  32. package/dist/cli.d.ts.map +1 -1
  33. package/dist/cli.js +31 -0
  34. package/dist/cli.js.map +1 -1
  35. package/dist/commands/build-lambda-zip.d.ts +5 -0
  36. package/dist/commands/build-lambda-zip.d.ts.map +1 -0
  37. package/dist/commands/build-lambda-zip.js +19 -0
  38. package/dist/commands/build-lambda-zip.js.map +1 -0
  39. package/dist/commands/deploy.d.ts +4 -0
  40. package/dist/commands/deploy.d.ts.map +1 -1
  41. package/dist/commands/deploy.js +71 -129
  42. package/dist/commands/deploy.js.map +1 -1
  43. package/dist/commands/init.d.ts +1 -5
  44. package/dist/commands/init.d.ts.map +1 -1
  45. package/dist/commands/init.js +94 -85
  46. package/dist/commands/init.js.map +1 -1
  47. package/dist/commands/list-tokens.d.ts.map +1 -1
  48. package/dist/commands/list-tokens.js +6 -3
  49. package/dist/commands/list-tokens.js.map +1 -1
  50. package/dist/commands/login.d.ts +8 -1
  51. package/dist/commands/login.d.ts.map +1 -1
  52. package/dist/commands/login.js +21 -11
  53. package/dist/commands/login.js.map +1 -1
  54. package/dist/commands/logout.js +2 -2
  55. package/dist/commands/logout.js.map +1 -1
  56. package/dist/config/oauth.d.ts +4 -14
  57. package/dist/config/oauth.d.ts.map +1 -1
  58. package/dist/config/oauth.js +19 -40
  59. package/dist/config/oauth.js.map +1 -1
  60. package/dist/constants.d.ts +26 -18
  61. package/dist/constants.d.ts.map +1 -1
  62. package/dist/constants.js +34 -20
  63. package/dist/constants.js.map +1 -1
  64. package/dist/db-content-api/README.md +98 -0
  65. package/dist/db-content-api/generated/content-api-types.d.ts +3854 -0
  66. package/dist/db-content-api/generated/content-api-types.d.ts.map +1 -0
  67. package/dist/db-content-api/generated/content-api-types.js +7 -0
  68. package/dist/db-content-api/generated/content-api-types.js.map +1 -0
  69. package/dist/db-content-api/index.d.ts +18 -0
  70. package/dist/db-content-api/index.d.ts.map +1 -0
  71. package/dist/db-content-api/index.js +578 -0
  72. package/dist/db-content-api/index.js.map +1 -0
  73. package/dist/db-content-api/temp-utilities/pagination.d.ts +13 -0
  74. package/dist/db-content-api/temp-utilities/pagination.d.ts.map +1 -0
  75. package/dist/db-content-api/temp-utilities/pagination.js +45 -0
  76. package/dist/db-content-api/temp-utilities/pagination.js.map +1 -0
  77. package/dist/db-content-api/temp-utilities/slug.d.ts +2 -0
  78. package/dist/db-content-api/temp-utilities/slug.d.ts.map +1 -0
  79. package/dist/db-content-api/temp-utilities/slug.js +3 -0
  80. package/dist/db-content-api/temp-utilities/slug.js.map +1 -0
  81. package/dist/db-content-api/temp-utilities/sorting.d.ts +3 -0
  82. package/dist/db-content-api/temp-utilities/sorting.d.ts.map +1 -0
  83. package/dist/db-content-api/temp-utilities/sorting.js +32 -0
  84. package/dist/db-content-api/temp-utilities/sorting.js.map +1 -0
  85. package/dist/db-content-api/temp-utilities/unwrapDocument.d.ts +4 -0
  86. package/dist/db-content-api/temp-utilities/unwrapDocument.d.ts.map +1 -0
  87. package/dist/db-content-api/temp-utilities/unwrapDocument.js +53 -0
  88. package/dist/db-content-api/temp-utilities/unwrapDocument.js.map +1 -0
  89. package/dist/db-content-api/utilities/auth.d.ts +30 -0
  90. package/dist/db-content-api/utilities/auth.d.ts.map +1 -0
  91. package/dist/db-content-api/utilities/auth.js +81 -0
  92. package/dist/db-content-api/utilities/auth.js.map +1 -0
  93. package/dist/db-content-api/utilities/data/applyDefaults.d.ts +7 -0
  94. package/dist/db-content-api/utilities/data/applyDefaults.d.ts.map +1 -0
  95. package/dist/db-content-api/utilities/data/applyDefaults.js +59 -0
  96. package/dist/db-content-api/utilities/data/applyDefaults.js.map +1 -0
  97. package/dist/db-content-api/utilities/data/castFieldValue.d.ts +11 -0
  98. package/dist/db-content-api/utilities/data/castFieldValue.d.ts.map +1 -0
  99. package/dist/db-content-api/utilities/data/castFieldValue.js +66 -0
  100. package/dist/db-content-api/utilities/data/castFieldValue.js.map +1 -0
  101. package/dist/db-content-api/utilities/data/index.d.ts +30 -0
  102. package/dist/db-content-api/utilities/data/index.d.ts.map +1 -0
  103. package/dist/db-content-api/utilities/data/index.js +182 -0
  104. package/dist/db-content-api/utilities/data/index.js.map +1 -0
  105. package/dist/db-content-api/utilities/data/removeVirtualFields.d.ts +12 -0
  106. package/dist/db-content-api/utilities/data/removeVirtualFields.d.ts.map +1 -0
  107. package/dist/db-content-api/utilities/data/removeVirtualFields.js +54 -0
  108. package/dist/db-content-api/utilities/data/removeVirtualFields.js.map +1 -0
  109. package/dist/db-content-api/utilities/data/stripFields.d.ts +48 -0
  110. package/dist/db-content-api/utilities/data/stripFields.d.ts.map +1 -0
  111. package/dist/db-content-api/utilities/data/stripFields.js +195 -0
  112. package/dist/db-content-api/utilities/data/stripFields.js.map +1 -0
  113. package/dist/db-content-api/utilities/joins.d.ts +55 -0
  114. package/dist/db-content-api/utilities/joins.d.ts.map +1 -0
  115. package/dist/db-content-api/utilities/joins.js +136 -0
  116. package/dist/db-content-api/utilities/joins.js.map +1 -0
  117. package/dist/db-content-api/utilities/where.d.ts +12 -0
  118. package/dist/db-content-api/utilities/where.d.ts.map +1 -0
  119. package/dist/db-content-api/utilities/where.js +107 -0
  120. package/dist/db-content-api/utilities/where.js.map +1 -0
  121. package/dist/endpoints/health.d.ts +3 -0
  122. package/dist/endpoints/health.d.ts.map +1 -0
  123. package/dist/endpoints/health.js +11 -0
  124. package/dist/endpoints/health.js.map +1 -0
  125. package/dist/exports/client.d.ts +4 -0
  126. package/dist/exports/client.d.ts.map +1 -0
  127. package/dist/exports/client.js +5 -0
  128. package/dist/exports/client.js.map +1 -0
  129. package/dist/index.d.ts +2 -1
  130. package/dist/index.d.ts.map +1 -1
  131. package/dist/index.js +3 -1
  132. package/dist/index.js.map +1 -1
  133. package/dist/oauth/components/LoginButton/index.d.ts.map +1 -1
  134. package/dist/oauth/components/LoginButton/index.js +50 -6
  135. package/dist/oauth/components/LoginButton/index.js.map +1 -1
  136. package/dist/oauth/components/LoginButton/index.scss +50 -3
  137. package/dist/oauth/components/LogoutButton/index.d.ts.map +1 -1
  138. package/dist/oauth/components/LogoutButton/index.js +0 -1
  139. package/dist/oauth/components/LogoutButton/index.js.map +1 -1
  140. package/dist/oauth/defaults.d.ts.map +1 -1
  141. package/dist/oauth/defaults.js +29 -5
  142. package/dist/oauth/defaults.js.map +1 -1
  143. package/dist/oauth/endpoints/getLoginEndpoint.d.ts.map +1 -1
  144. package/dist/oauth/endpoints/getLoginEndpoint.js +4 -4
  145. package/dist/oauth/endpoints/getLoginEndpoint.js.map +1 -1
  146. package/dist/oauth/index.d.ts.map +1 -1
  147. package/dist/oauth/index.js +42 -7
  148. package/dist/oauth/index.js.map +1 -1
  149. package/dist/oauth/strategy/index.d.ts +0 -2
  150. package/dist/oauth/strategy/index.d.ts.map +1 -1
  151. package/dist/oauth/strategy/index.js +38 -15
  152. package/dist/oauth/strategy/index.js.map +1 -1
  153. package/dist/oauth/types.d.ts +6 -6
  154. package/dist/oauth/types.d.ts.map +1 -1
  155. package/dist/oauth/types.js.map +1 -1
  156. package/dist/oauth/utilities/createCookieOptions.d.ts.map +1 -1
  157. package/dist/oauth/utilities/createCookieOptions.js.map +1 -1
  158. package/dist/oauth/utilities/isDuplicateKeyError.d.ts +7 -0
  159. package/dist/oauth/utilities/isDuplicateKeyError.d.ts.map +1 -0
  160. package/dist/oauth/utilities/isDuplicateKeyError.js +14 -0
  161. package/dist/oauth/utilities/isDuplicateKeyError.js.map +1 -0
  162. package/dist/oauth/utilities/refreshTokens.d.ts.map +1 -1
  163. package/dist/oauth/utilities/refreshTokens.js +1 -1
  164. package/dist/oauth/utilities/refreshTokens.js.map +1 -1
  165. package/dist/plugin/build-config.d.ts +21 -4
  166. package/dist/plugin/build-config.d.ts.map +1 -1
  167. package/dist/plugin/build-config.js +114 -8
  168. package/dist/plugin/build-config.js.map +1 -1
  169. package/dist/storage-content-api/api-types.d.ts +161 -0
  170. package/dist/storage-content-api/api-types.d.ts.map +1 -0
  171. package/dist/storage-content-api/api-types.js +6 -0
  172. package/dist/storage-content-api/api-types.js.map +1 -0
  173. package/dist/storage-content-api/client-uploads/ClientUploadHandler.d.ts +9 -0
  174. package/dist/storage-content-api/client-uploads/ClientUploadHandler.d.ts.map +1 -0
  175. package/dist/storage-content-api/client-uploads/ClientUploadHandler.js +42 -0
  176. package/dist/storage-content-api/client-uploads/ClientUploadHandler.js.map +1 -0
  177. package/dist/storage-content-api/client-uploads/generateSignedURL.d.ts +13 -0
  178. package/dist/storage-content-api/client-uploads/generateSignedURL.d.ts.map +1 -0
  179. package/dist/storage-content-api/client-uploads/generateSignedURL.js +31 -0
  180. package/dist/storage-content-api/client-uploads/generateSignedURL.js.map +1 -0
  181. package/dist/storage-content-api/client.d.ts +6 -0
  182. package/dist/storage-content-api/client.d.ts.map +1 -0
  183. package/dist/storage-content-api/client.js +36 -0
  184. package/dist/storage-content-api/client.js.map +1 -0
  185. package/dist/storage-content-api/generateURL.d.ts +7 -0
  186. package/dist/storage-content-api/generateURL.d.ts.map +1 -0
  187. package/dist/storage-content-api/generateURL.js +7 -0
  188. package/dist/storage-content-api/generateURL.js.map +1 -0
  189. package/dist/storage-content-api/handleDelete.d.ts +8 -0
  190. package/dist/storage-content-api/handleDelete.d.ts.map +1 -0
  191. package/dist/storage-content-api/handleDelete.js +15 -0
  192. package/dist/storage-content-api/handleDelete.js.map +1 -0
  193. package/dist/storage-content-api/handleUpload.d.ts +11 -0
  194. package/dist/storage-content-api/handleUpload.d.ts.map +1 -0
  195. package/dist/storage-content-api/handleUpload.js +136 -0
  196. package/dist/storage-content-api/handleUpload.js.map +1 -0
  197. package/dist/storage-content-api/index.d.ts +5 -0
  198. package/dist/storage-content-api/index.d.ts.map +1 -0
  199. package/dist/storage-content-api/index.js +31 -0
  200. package/dist/storage-content-api/index.js.map +1 -0
  201. package/dist/storage-content-api/staticHandler.d.ts +10 -0
  202. package/dist/storage-content-api/staticHandler.d.ts.map +1 -0
  203. package/dist/storage-content-api/staticHandler.js +55 -0
  204. package/dist/storage-content-api/staticHandler.js.map +1 -0
  205. package/dist/storage-content-api/types.d.ts +10 -0
  206. package/dist/storage-content-api/types.d.ts.map +1 -0
  207. package/dist/storage-content-api/types.js +3 -0
  208. package/dist/storage-content-api/types.js.map +1 -0
  209. package/dist/templates/README.md +19 -0
  210. package/dist/types.d.ts +1 -0
  211. package/dist/types.d.ts.map +1 -1
  212. package/dist/types.js.map +1 -1
  213. package/dist/utils/asset-collection.d.ts +3 -6
  214. package/dist/utils/asset-collection.d.ts.map +1 -1
  215. package/dist/utils/asset-collection.js +10 -34
  216. package/dist/utils/asset-collection.js.map +1 -1
  217. package/dist/utils/build-lambda-zip.d.ts +14 -0
  218. package/dist/utils/build-lambda-zip.d.ts.map +1 -0
  219. package/dist/utils/build-lambda-zip.js +81 -0
  220. package/dist/utils/build-lambda-zip.js.map +1 -0
  221. package/dist/utils/config.js +1 -1
  222. package/dist/utils/config.js.map +1 -1
  223. package/dist/utils/env-management.d.ts +9 -8
  224. package/dist/utils/env-management.d.ts.map +1 -1
  225. package/dist/utils/env-management.js +73 -74
  226. package/dist/utils/env-management.js.map +1 -1
  227. package/dist/utils/formatter.d.ts.map +1 -1
  228. package/dist/utils/formatter.js +3 -5
  229. package/dist/utils/formatter.js.map +1 -1
  230. package/dist/utils/lambda-config.d.ts +3 -1
  231. package/dist/utils/lambda-config.d.ts.map +1 -1
  232. package/dist/utils/lambda-config.js +13 -21
  233. package/dist/utils/lambda-config.js.map +1 -1
  234. package/dist/utils/messages.d.ts.map +1 -1
  235. package/dist/utils/messages.js +8 -7
  236. package/dist/utils/messages.js.map +1 -1
  237. package/dist/utils/payload-config-ast.d.ts +22 -3
  238. package/dist/utils/payload-config-ast.d.ts.map +1 -1
  239. package/dist/utils/payload-config-ast.js +89 -31
  240. package/dist/utils/payload-config-ast.js.map +1 -1
  241. package/dist/utils/payload-config-finder.d.ts +2 -2
  242. package/dist/utils/payload-config-finder.d.ts.map +1 -1
  243. package/dist/utils/payload-config-finder.js +48 -9
  244. package/dist/utils/payload-config-finder.js.map +1 -1
  245. package/dist/utils/payload-config-modifier.d.ts.map +1 -1
  246. package/dist/utils/payload-config-modifier.js +54 -6
  247. package/dist/utils/payload-config-modifier.js.map +1 -1
  248. package/dist/utils/payload-package-check.d.ts +12 -1
  249. package/dist/utils/payload-package-check.d.ts.map +1 -1
  250. package/dist/utils/payload-package-check.js +63 -5
  251. package/dist/utils/payload-package-check.js.map +1 -1
  252. package/dist/utils/project.d.ts.map +1 -1
  253. package/dist/utils/project.js +8 -5
  254. package/dist/utils/project.js.map +1 -1
  255. package/dist/utils/s3-upload.d.ts +0 -1
  256. package/dist/utils/s3-upload.d.ts.map +1 -1
  257. package/dist/utils/s3-upload.js +10 -3
  258. package/dist/utils/s3-upload.js.map +1 -1
  259. package/dist/utils/token-display.d.ts.map +1 -1
  260. package/dist/utils/token-display.js +11 -5
  261. package/dist/utils/token-display.js.map +1 -1
  262. package/dist/utils/typescript-validator.d.ts.map +1 -1
  263. package/dist/utils/typescript-validator.js +4 -6
  264. package/dist/utils/typescript-validator.js.map +1 -1
  265. package/dist/utils/version-check.d.ts +3 -0
  266. package/dist/utils/version-check.d.ts.map +1 -0
  267. package/dist/utils/version-check.js +38 -0
  268. package/dist/utils/version-check.js.map +1 -0
  269. package/package.json +31 -7
@@ -1,5 +1,6 @@
1
1
  import { v4 as uuid } from 'uuid';
2
2
  import { hasUserTokenPropsChanged } from './utilities/hasUserTokenPropsChanged.js';
3
+ import { isDuplicateKeyError } from './utilities/isDuplicateKeyError.js';
3
4
  export const defaultScope = [
4
5
  'openid',
5
6
  'profile',
@@ -60,11 +61,34 @@ export const defaultVerify = ({ collection, strategyName, usernameField })=>asyn
60
61
  if (typeof collection.auth === 'object' && !collection.auth.disableLocalStrategy) {
61
62
  newUser.password = uuid();
62
63
  }
63
- user = await payload.create({
64
- collection: collection.slug,
65
- data: newUser,
66
- depth
67
- });
64
+ try {
65
+ user = await payload.create({
66
+ collection: collection.slug,
67
+ data: newUser,
68
+ depth,
69
+ overrideAccess: true
70
+ });
71
+ } catch (createErr) {
72
+ // Race condition: if unique constraint violation, user was created by concurrent request
73
+ if (isDuplicateKeyError(createErr)) {
74
+ const retryResults = await payload.find({
75
+ collection: collection.slug,
76
+ depth,
77
+ limit: 1,
78
+ pagination: false,
79
+ where: {
80
+ [usernameField.name]: {
81
+ equals: token[tokenUsername]
82
+ }
83
+ }
84
+ });
85
+ if (retryResults.docs.length > 0) {
86
+ user = retryResults.docs[0];
87
+ }
88
+ } else {
89
+ throw createErr;
90
+ }
91
+ }
68
92
  }
69
93
  } catch (err) {
70
94
  payload.logger.error({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/oauth/defaults.ts"],"sourcesContent":["import type { CollectionConfig, EmailField, TextField, User } from 'payload'\n\nimport { v4 as uuid } from 'uuid'\n\nimport type { VerifyFunction } from './types.js'\n\nimport { hasUserTokenPropsChanged } from './utilities/hasUserTokenPropsChanged.js'\n\nexport const defaultScope = ['openid', 'profile', 'email']\n\nexport const defaultUsernameField: TextField = {\n name: 'preferredUsername',\n type: 'text',\n admin: {\n position: 'sidebar',\n readOnly: true,\n },\n unique: true,\n}\n\nexport const defaultVerify =\n ({\n collection,\n strategyName,\n usernameField,\n }: {\n collection: CollectionConfig\n strategyName: string\n usernameField: EmailField | TextField\n }): VerifyFunction =>\n async ({ payload, token }) => {\n let tokenUsername = 'preferred_username'\n\n if (usernameField.name !== 'preferredUsername') {\n tokenUsername = usernameField.name\n }\n\n if (!token[tokenUsername]) {\n return {\n user: null,\n }\n }\n\n let user: null | User = null\n const depth = typeof collection.auth === 'object' ? collection.auth.depth : undefined\n\n try {\n const results = await payload.find({\n collection: collection.slug,\n depth,\n limit: 1,\n pagination: false,\n where: {\n [usernameField.name]: { equals: token[tokenUsername] },\n },\n })\n\n if (results.docs.length > 0) {\n user = results.docs[0] as User\n // Update user with new token data\n if (hasUserTokenPropsChanged(user, token)) {\n user = (await payload.update({\n id: user.id,\n collection: collection.slug,\n data: {\n ...token,\n },\n depth,\n })) as User\n }\n } else {\n const newUser = {\n email: token.preferredUsername || token.email,\n [usernameField.name]: token[tokenUsername],\n ...token,\n }\n\n if (typeof collection.auth === 'object' && !collection.auth.disableLocalStrategy) {\n newUser.password = uuid()\n }\n\n user = (await payload.create({\n collection: collection.slug,\n data: newUser,\n depth,\n })) as User\n }\n } catch (err: unknown) {\n payload.logger.error({\n err,\n msg: 'Error verifying user from defaultVerify.',\n })\n return {\n user: null,\n }\n }\n\n if (user) {\n user.collection = collection.slug\n user._strategy = strategyName\n user.exp = token.exp\n\n return {\n user,\n }\n }\n\n return {\n user: null,\n }\n }\n"],"names":["v4","uuid","hasUserTokenPropsChanged","defaultScope","defaultUsernameField","name","type","admin","position","readOnly","unique","defaultVerify","collection","strategyName","usernameField","payload","token","tokenUsername","user","depth","auth","undefined","results","find","slug","limit","pagination","where","equals","docs","length","update","id","data","newUser","email","preferredUsername","disableLocalStrategy","password","create","err","logger","error","msg","_strategy","exp"],"mappings":"AAEA,SAASA,MAAMC,IAAI,QAAQ,OAAM;AAIjC,SAASC,wBAAwB,QAAQ,0CAAyC;AAElF,OAAO,MAAMC,eAAe;IAAC;IAAU;IAAW;CAAQ,CAAA;AAE1D,OAAO,MAAMC,uBAAkC;IAC7CC,MAAM;IACNC,MAAM;IACNC,OAAO;QACLC,UAAU;QACVC,UAAU;IACZ;IACAC,QAAQ;AACV,EAAC;AAED,OAAO,MAAMC,gBACX,CAAC,EACCC,UAAU,EACVC,YAAY,EACZC,aAAa,EAKd,GACD,OAAO,EAAEC,OAAO,EAAEC,KAAK,EAAE;QACvB,IAAIC,gBAAgB;QAEpB,IAAIH,cAAcT,IAAI,KAAK,qBAAqB;YAC9CY,gBAAgBH,cAAcT,IAAI;QACpC;QAEA,IAAI,CAACW,KAAK,CAACC,cAAc,EAAE;YACzB,OAAO;gBACLC,MAAM;YACR;QACF;QAEA,IAAIA,OAAoB;QACxB,MAAMC,QAAQ,OAAOP,WAAWQ,IAAI,KAAK,WAAWR,WAAWQ,IAAI,CAACD,KAAK,GAAGE;QAE5E,IAAI;YACF,MAAMC,UAAU,MAAMP,QAAQQ,IAAI,CAAC;gBACjCX,YAAYA,WAAWY,IAAI;gBAC3BL;gBACAM,OAAO;gBACPC,YAAY;gBACZC,OAAO;oBACL,CAACb,cAAcT,IAAI,CAAC,EAAE;wBAAEuB,QAAQZ,KAAK,CAACC,cAAc;oBAAC;gBACvD;YACF;YAEA,IAAIK,QAAQO,IAAI,CAACC,MAAM,GAAG,GAAG;gBAC3BZ,OAAOI,QAAQO,IAAI,CAAC,EAAE;gBACtB,kCAAkC;gBAClC,IAAI3B,yBAAyBgB,MAAMF,QAAQ;oBACzCE,OAAQ,MAAMH,QAAQgB,MAAM,CAAC;wBAC3BC,IAAId,KAAKc,EAAE;wBACXpB,YAAYA,WAAWY,IAAI;wBAC3BS,MAAM;4BACJ,GAAGjB,KAAK;wBACV;wBACAG;oBACF;gBACF;YACF,OAAO;gBACL,MAAMe,UAAU;oBACdC,OAAOnB,MAAMoB,iBAAiB,IAAIpB,MAAMmB,KAAK;oBAC7C,CAACrB,cAAcT,IAAI,CAAC,EAAEW,KAAK,CAACC,cAAc;oBAC1C,GAAGD,KAAK;gBACV;gBAEA,IAAI,OAAOJ,WAAWQ,IAAI,KAAK,YAAY,CAACR,WAAWQ,IAAI,CAACiB,oBAAoB,EAAE;oBAChFH,QAAQI,QAAQ,GAAGrC;gBACrB;gBAEAiB,OAAQ,MAAMH,QAAQwB,MAAM,CAAC;oBAC3B3B,YAAYA,WAAWY,IAAI;oBAC3BS,MAAMC;oBACNf;gBACF;YACF;QACF,EAAE,OAAOqB,KAAc;YACrBzB,QAAQ0B,MAAM,CAACC,KAAK,CAAC;gBACnBF;gBACAG,KAAK;YACP;YACA,OAAO;gBACLzB,MAAM;YACR;QACF;QAEA,IAAIA,MAAM;YACRA,KAAKN,UAAU,GAAGA,WAAWY,IAAI;YACjCN,KAAK0B,SAAS,GAAG/B;YACjBK,KAAK2B,GAAG,GAAG7B,MAAM6B,GAAG;YAEpB,OAAO;gBACL3B;YACF;QACF;QAEA,OAAO;YACLA,MAAM;QACR;IACF,EAAC"}
1
+ {"version":3,"sources":["../../src/oauth/defaults.ts"],"sourcesContent":["import type { CollectionConfig, EmailField, TextField, User } from 'payload'\n\nimport { v4 as uuid } from 'uuid'\n\nimport type { VerifyFunction } from './types.js'\n\nimport { hasUserTokenPropsChanged } from './utilities/hasUserTokenPropsChanged.js'\nimport { isDuplicateKeyError } from './utilities/isDuplicateKeyError.js'\n\nexport const defaultScope = ['openid', 'profile', 'email']\n\nexport const defaultUsernameField: TextField = {\n name: 'preferredUsername',\n type: 'text',\n admin: {\n position: 'sidebar',\n readOnly: true,\n },\n unique: true,\n}\n\nexport const defaultVerify =\n ({\n collection,\n strategyName,\n usernameField,\n }: {\n collection: CollectionConfig\n strategyName: string\n usernameField: EmailField | TextField\n }): VerifyFunction =>\n async ({ payload, token }) => {\n let tokenUsername = 'preferred_username'\n\n if (usernameField.name !== 'preferredUsername') {\n tokenUsername = usernameField.name\n }\n\n if (!token[tokenUsername]) {\n return {\n user: null,\n }\n }\n\n let user: null | User = null\n const depth = typeof collection.auth === 'object' ? collection.auth.depth : undefined\n\n try {\n const results = await payload.find({\n collection: collection.slug,\n depth,\n limit: 1,\n pagination: false,\n where: {\n [usernameField.name]: { equals: token[tokenUsername] },\n },\n })\n\n if (results.docs.length > 0) {\n user = results.docs[0] as User\n // Update user with new token data\n if (hasUserTokenPropsChanged(user, token)) {\n user = (await payload.update({\n id: user.id,\n collection: collection.slug,\n data: {\n ...token,\n },\n depth,\n })) as User\n }\n } else {\n const newUser = {\n email: token.preferredUsername || token.email,\n [usernameField.name]: token[tokenUsername],\n ...token,\n }\n\n if (typeof collection.auth === 'object' && !collection.auth.disableLocalStrategy) {\n newUser.password = uuid()\n }\n\n try {\n user = (await payload.create({\n collection: collection.slug,\n data: newUser,\n depth,\n overrideAccess: true,\n })) as User\n } catch (createErr: unknown) {\n // Race condition: if unique constraint violation, user was created by concurrent request\n if (isDuplicateKeyError(createErr)) {\n const retryResults = await payload.find({\n collection: collection.slug,\n depth,\n limit: 1,\n pagination: false,\n where: {\n [usernameField.name]: { equals: token[tokenUsername] },\n },\n })\n\n if (retryResults.docs.length > 0) {\n user = retryResults.docs[0] as User\n }\n } else {\n throw createErr\n }\n }\n }\n } catch (err: unknown) {\n payload.logger.error({\n err,\n msg: 'Error verifying user from defaultVerify.',\n })\n return {\n user: null,\n }\n }\n\n if (user) {\n user.collection = collection.slug\n user._strategy = strategyName\n user.exp = token.exp\n\n return {\n user,\n }\n }\n\n return {\n user: null,\n }\n }\n"],"names":["v4","uuid","hasUserTokenPropsChanged","isDuplicateKeyError","defaultScope","defaultUsernameField","name","type","admin","position","readOnly","unique","defaultVerify","collection","strategyName","usernameField","payload","token","tokenUsername","user","depth","auth","undefined","results","find","slug","limit","pagination","where","equals","docs","length","update","id","data","newUser","email","preferredUsername","disableLocalStrategy","password","create","overrideAccess","createErr","retryResults","err","logger","error","msg","_strategy","exp"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"getLoginEndpoint.d.ts","sourceRoot":"","sources":["../../../src/oauth/endpoints/getLoginEndpoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAMzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,EAEV,iBAAiB,EACjB,aAAa,EAEd,MAAM,aAAa,CAAA;AAcpB,UAAU,IAAI;IACZ,UAAU,EAAE,gBAAgB,CAAA;IAC5B,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,aAAa,CAAA;IAC5B,QAAQ,EAAE,QAAQ,CAAA;CACnB;AAID,eAAO,MAAM,gBAAgB,8EAM1B,IAAI,KAAG,QA+OR,CAAA"}
1
+ {"version":3,"file":"getLoginEndpoint.d.ts","sourceRoot":"","sources":["../../../src/oauth/endpoints/getLoginEndpoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAKzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAY,MAAM,aAAa,CAAA;AAS7E,UAAU,IAAI;IACZ,UAAU,EAAE,gBAAgB,CAAA;IAC5B,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,aAAa,CAAA;IAC5B,QAAQ,EAAE,QAAQ,CAAA;CACnB;AAID,eAAO,MAAM,gBAAgB,8EAM1B,IAAI,KAAG,QAkPR,CAAA"}
@@ -128,14 +128,14 @@ export const getLoginEndpoint = ({ collection, collectionOptions, endpointSlug,
128
128
  grant_type: 'authorization_code',
129
129
  redirect_uri: `${redirectDestination}${config?.routes?.api || '/api'}/${collection.slug}/${endpointSlug}/login`
130
130
  };
131
+ if (strategy.collectionOptions.clientSecret) {
132
+ body.client_secret = strategy.collectionOptions.clientSecret;
133
+ }
131
134
  debugLogger.info({
132
135
  msg: 'Exchanging code for access token',
133
136
  path,
134
137
  requestBody: body
135
138
  });
136
- if (strategy.clientSecret) {
137
- body.client_secret = strategy.clientSecret;
138
- }
139
139
  const tokenRes = await fetch(strategy.meta?.token_endpoint, {
140
140
  body: new URLSearchParams(body),
141
141
  headers: {
@@ -154,7 +154,7 @@ export const getLoginEndpoint = ({ collection, collectionOptions, endpointSlug,
154
154
  tokenRes
155
155
  });
156
156
  // Swap for project token
157
- const project_token = await getProjectToken(tokenRes.access_token, 'someproject');
157
+ const project_token = await getProjectToken(tokenRes.access_token, config.custom.figma.contentSystemId);
158
158
  const refresh_token = access_token;
159
159
  // Store project token as access_token
160
160
  const token = project_token.token;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/oauth/endpoints/getLoginEndpoint.ts"],"sourcesContent":["import type { CollectionConfig, Endpoint } from 'payload'\n\nimport jwt from 'jsonwebtoken'\nimport { APIError, generateCookie, parseCookies } from 'payload'\nimport { getSafeRedirect } from 'payload/shared'\n\nimport type { Strategy } from '../strategy/index.js'\nimport type {\n AfterOAuthLoginHookResult,\n CollectionOptions,\n PluginOptions,\n StateObj,\n} from '../types.js'\n\nimport { getProjectToken } from '../../api/figma-api.js'\nimport { JWTValidationError, validateProjectToken } from '../../auth/jwt-validator.js'\nimport { ProjectTokenError } from '../../auth/project-token.js'\nimport { getEnvironment } from '../../constants.js'\nimport { createCookieOptions } from '../utilities/createCookieOptions.js'\nimport { createDebugLogger } from '../utilities/createDebugLogger.js'\nimport { extractOrigin } from '../utilities/extractOrigin.js'\nimport { getAdminPath } from '../utilities/getAdminPath.js'\nimport { getCookieExpiration } from '../utilities/getCookieExpiration.js'\nimport { getSecondsFromTokenExp } from '../utilities/getSecondsFromTokenExp.js'\nimport { getTokenExp } from '../utilities/getTokenExp.js'\n\ninterface Args {\n collection: CollectionConfig\n collectionOptions: CollectionOptions\n endpointSlug: string\n pluginOptions: PluginOptions\n strategy: Strategy\n}\n\nconst isAbsoluteURL = (url: string) => /^[a-z][a-z\\d+.-]*:/.test(url)\n\nexport const getLoginEndpoint = ({\n collection,\n collectionOptions,\n endpointSlug,\n pluginOptions,\n strategy,\n}: Args): Endpoint => ({\n handler: async (req) => {\n const { config } = req.payload\n const adminPath = getAdminPath(config)\n try {\n await strategy.ensureMeta()\n\n const path = req.pathname\n const debugLogger = createDebugLogger(req.payload, pluginOptions.debug)\n\n let jsonBody: Record<string, unknown> = {}\n\n const contentType = req.headers.get('content-type')\n\n // Type narrow PayloadRequst's Partial<Request>\n if (typeof req.json !== 'function' || typeof req.formData !== 'function') {\n debugLogger.info({\n msg: 'Request does not have json or formData methods',\n path,\n })\n\n return Response.redirect(`${pluginOptions.redirectServerURL || config.serverURL}/login`)\n }\n\n if (collectionOptions.authorizationURLParams?.response_mode === 'query') {\n if (Object.keys(req.query).length > 0) {\n jsonBody = req.query\n }\n } else if (contentType === 'application/json') {\n jsonBody = await req.json()\n } else if (contentType === 'application/x-www-form-urlencoded') {\n const formData = await req.formData()\n jsonBody = Object.fromEntries(formData.entries())\n }\n\n const stateRaw = jsonBody.state as string\n const state: StateObj = JSON.parse(Buffer.from(stateRaw, 'base64').toString('utf-8'))\n\n const redirectDestination =\n state.serverURL || pluginOptions.redirectServerURL || config.serverURL\n let failedRedirect = `${redirectDestination}${adminPath}/login`\n let redirectToUse = `${redirectDestination}${adminPath}`\n\n if (state.redirect) {\n redirectToUse = state.redirect\n }\n\n if (state.failedRedirect) {\n failedRedirect = state.failedRedirect\n }\n\n failedRedirect = getSafeRedirect({ allowAbsoluteUrls: true, redirectTo: failedRedirect })\n redirectToUse = getSafeRedirect({ allowAbsoluteUrls: true, redirectTo: redirectToUse })\n\n if (!isAbsoluteURL(failedRedirect)) {\n return Response.json({ error: 'Invalid failed redirect provided' }, { status: 403 })\n }\n if (!isAbsoluteURL(redirectToUse)) {\n return Response.json({ error: 'Invalid redirect provided' }, { status: 403 })\n }\n\n if (Array.isArray(req.payload.config.csrf) && req.payload.config.csrf.length > 0) {\n const failedRedirectOrigin = extractOrigin(failedRedirect)\n const redirectToUseOrigin = extractOrigin(redirectToUse)\n\n if (failedRedirectOrigin && !req.payload.config.csrf.includes(failedRedirectOrigin)) {\n req.payload.logger.error(\n `Failed redirect origin ${failedRedirectOrigin} is not allowed by CSRF configuration.`,\n )\n return Response.json(\n { error: 'Failed redirect origin is not allowed by CSRF configuration.' },\n { status: 403 },\n )\n }\n\n if (redirectToUseOrigin && !req.payload.config.csrf.includes(redirectToUseOrigin)) {\n req.payload.logger.error(\n `Redirect origin ${redirectToUseOrigin} is not allowed by CSRF configuration.`,\n )\n return Response.json(\n { error: 'Redirect origin is not allowed by CSRF configuration.' },\n { status: 403 },\n )\n }\n }\n\n // Verify signature\n if (strategy.name !== req.payload.decrypt(state.sig)) {\n req.payload.logger.error('Signature mismatch. Failing login and redirecting.')\n return Response.redirect(failedRedirect)\n }\n\n if (!strategy.meta?.token_endpoint) {\n debugLogger.error({\n msg: `No metadata was obtained from the identity provider. Failing login and redirecting.`,\n path,\n })\n return Response.redirect(failedRedirect)\n }\n\n debugLogger.info({ body: jsonBody, msg: 'Received login response body', path })\n\n if (!jsonBody?.code) {\n debugLogger.error({\n msg: `No authorization code present in body. Failing login and redirecting.`,\n path,\n })\n return Response.redirect(failedRedirect)\n }\n\n // Exchange `code` from body for refresh token\n const { code } = jsonBody\n\n if (typeof code !== 'string') {\n debugLogger.error({\n msg: `Authorization code present in body is not a string. Failing login and redirecting.`,\n path,\n })\n return Response.redirect(failedRedirect)\n }\n\n const body: Record<string, string> = {\n client_id: strategy.clientID,\n code,\n code_verifier: req.payload.decrypt(state.verifier),\n grant_type: 'authorization_code',\n redirect_uri: `${redirectDestination}${config?.routes?.api || '/api'}/${\n collection.slug\n }/${endpointSlug}/login`,\n }\n\n debugLogger.info({\n msg: 'Exchanging code for access token',\n path,\n requestBody: body,\n })\n\n if (strategy.clientSecret) {\n body.client_secret = strategy.clientSecret\n }\n\n const tokenRes = await fetch(strategy.meta?.token_endpoint, {\n body: new URLSearchParams(body),\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n method: 'POST',\n }).then((r) => r.json())\n\n debugLogger.info({ msg: 'Token Response', path, tokenRes })\n\n const { access_token, error, error_description, expires_in: refreshTokenExpires } = tokenRes\n\n debugLogger.info({ msg: 'tokenResss', tokenRes })\n\n // Swap for project token\n const project_token = await getProjectToken(tokenRes.access_token, 'someproject')\n const refresh_token = access_token\n\n // Store project token as access_token\n\n const token = project_token.token\n const expiresIn = project_token.expiresAt\n\n if (!token) {\n const errMsg = `No ${\n collectionOptions.token || 'access_token'\n } was returned from the identity provider.`\n req.payload.logger.error({ msg: errMsg, path })\n throw new APIError(errMsg)\n }\n\n const cookieOptions = createCookieOptions({ collection, headers: req.headers, pluginOptions })\n\n if (error) {\n req.payload.logger.error('Error swapping access code with access token:')\n req.payload.logger.error({ err: error, error_description })\n return Response.redirect(failedRedirect)\n }\n\n // get the payloadRedirect cookie value\n const cookies = parseCookies(req.headers)\n\n const payloadRedirect =\n 'payloadRedirect' in cookies ? (cookies.payloadRedirect as string) : ''\n\n if (!req.responseHeaders) {\n req.responseHeaders = new Headers()\n }\n\n if (payloadRedirect) {\n if (isAbsoluteURL(payloadRedirect)) {\n redirectToUse = payloadRedirect\n } else {\n redirectToUse += payloadRedirect\n }\n\n req.responseHeaders.append(\n 'Set-Cookie',\n `payloadRedirect=${redirectToUse}; Max-Age=0; Path=/;`,\n )\n }\n\n if (refresh_token && !collectionOptions.usePayloadJWT) {\n debugLogger.info('Setting refresh token cookie')\n const refreshCookie = generateCookie({\n returnCookieAsObject: false,\n ...cookieOptions,\n name: `${strategy.cookieName}-refresh`,\n value: refresh_token,\n // Default to 1 year if no expiration\n expires: getCookieExpiration(cookieOptions?.expires ?? refreshTokenExpires ?? 31_556_952),\n }) as string\n\n req.responseHeaders.append('Set-Cookie', refreshCookie)\n }\n\n const tokenExpires = cookieOptions?.expires\n ? getCookieExpiration(cookieOptions.expires)\n : new Date(expiresIn) // Project token uses epoch time\n const tokenCookie = generateCookie({\n ...cookieOptions,\n name: strategy.cookieName,\n expires: tokenExpires,\n returnCookieAsObject: false,\n value: token,\n }) as string\n\n req.responseHeaders.append('Set-Cookie', tokenCookie)\n\n return Response.redirect(redirectToUse)\n } catch (err: unknown) {\n req.payload.logger.error({ err, msg: 'Error while attempting to login', path: req.pathname })\n\n return Response.json({ error: 'Error while attempting to login' }, { status: 500 })\n }\n },\n method: collectionOptions.authorizationURLParams?.response_mode === 'query' ? 'get' : 'post',\n path: `/${endpointSlug}/login`,\n})\n"],"names":["APIError","generateCookie","parseCookies","getSafeRedirect","getProjectToken","createCookieOptions","createDebugLogger","extractOrigin","getAdminPath","getCookieExpiration","isAbsoluteURL","url","test","getLoginEndpoint","collection","collectionOptions","endpointSlug","pluginOptions","strategy","handler","req","config","payload","adminPath","ensureMeta","path","pathname","debugLogger","debug","jsonBody","contentType","headers","get","json","formData","info","msg","Response","redirect","redirectServerURL","serverURL","authorizationURLParams","response_mode","Object","keys","query","length","fromEntries","entries","stateRaw","state","JSON","parse","Buffer","from","toString","redirectDestination","failedRedirect","redirectToUse","allowAbsoluteUrls","redirectTo","error","status","Array","isArray","csrf","failedRedirectOrigin","redirectToUseOrigin","includes","logger","name","decrypt","sig","meta","token_endpoint","body","code","client_id","clientID","code_verifier","verifier","grant_type","redirect_uri","routes","api","slug","requestBody","clientSecret","client_secret","tokenRes","fetch","URLSearchParams","method","then","r","access_token","error_description","expires_in","refreshTokenExpires","project_token","refresh_token","token","expiresIn","expiresAt","errMsg","cookieOptions","err","cookies","payloadRedirect","responseHeaders","Headers","append","usePayloadJWT","refreshCookie","returnCookieAsObject","cookieName","value","expires","tokenExpires","Date","tokenCookie"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/oauth/endpoints/getLoginEndpoint.ts"],"sourcesContent":["import type { CollectionConfig, Endpoint } from 'payload'\n\nimport { APIError, generateCookie, parseCookies } from 'payload'\nimport { getSafeRedirect } from 'payload/shared'\n\nimport type { Strategy } from '../strategy/index.js'\nimport type { CollectionOptions, PluginOptions, StateObj } from '../types.js'\n\nimport { getProjectToken } from '../../api/figma-api.js'\nimport { createCookieOptions } from '../utilities/createCookieOptions.js'\nimport { createDebugLogger } from '../utilities/createDebugLogger.js'\nimport { extractOrigin } from '../utilities/extractOrigin.js'\nimport { getAdminPath } from '../utilities/getAdminPath.js'\nimport { getCookieExpiration } from '../utilities/getCookieExpiration.js'\n\ninterface Args {\n collection: CollectionConfig\n collectionOptions: CollectionOptions\n endpointSlug: string\n pluginOptions: PluginOptions\n strategy: Strategy\n}\n\nconst isAbsoluteURL = (url: string) => /^[a-z][a-z\\d+.-]*:/.test(url)\n\nexport const getLoginEndpoint = ({\n collection,\n collectionOptions,\n endpointSlug,\n pluginOptions,\n strategy,\n}: Args): Endpoint => ({\n handler: async (req) => {\n const { config } = req.payload\n const adminPath = getAdminPath(config)\n try {\n await strategy.ensureMeta()\n\n const path = req.pathname\n const debugLogger = createDebugLogger(req.payload, pluginOptions.debug)\n\n let jsonBody: Record<string, unknown> = {}\n\n const contentType = req.headers.get('content-type')\n\n // Type narrow PayloadRequst's Partial<Request>\n if (typeof req.json !== 'function' || typeof req.formData !== 'function') {\n debugLogger.info({\n msg: 'Request does not have json or formData methods',\n path,\n })\n\n return Response.redirect(`${pluginOptions.redirectServerURL || config.serverURL}/login`)\n }\n\n if (collectionOptions.authorizationURLParams?.response_mode === 'query') {\n if (Object.keys(req.query).length > 0) {\n jsonBody = req.query\n }\n } else if (contentType === 'application/json') {\n jsonBody = await req.json()\n } else if (contentType === 'application/x-www-form-urlencoded') {\n const formData = await req.formData()\n jsonBody = Object.fromEntries(formData.entries())\n }\n\n const stateRaw = jsonBody.state as string\n const state: StateObj = JSON.parse(Buffer.from(stateRaw, 'base64').toString('utf-8'))\n\n const redirectDestination =\n state.serverURL || pluginOptions.redirectServerURL || config.serverURL\n let failedRedirect = `${redirectDestination}${adminPath}/login`\n let redirectToUse = `${redirectDestination}${adminPath}`\n\n if (state.redirect) {\n redirectToUse = state.redirect\n }\n\n if (state.failedRedirect) {\n failedRedirect = state.failedRedirect\n }\n\n failedRedirect = getSafeRedirect({ allowAbsoluteUrls: true, redirectTo: failedRedirect })\n redirectToUse = getSafeRedirect({ allowAbsoluteUrls: true, redirectTo: redirectToUse })\n\n if (!isAbsoluteURL(failedRedirect)) {\n return Response.json({ error: 'Invalid failed redirect provided' }, { status: 403 })\n }\n if (!isAbsoluteURL(redirectToUse)) {\n return Response.json({ error: 'Invalid redirect provided' }, { status: 403 })\n }\n\n if (Array.isArray(req.payload.config.csrf) && req.payload.config.csrf.length > 0) {\n const failedRedirectOrigin = extractOrigin(failedRedirect)\n const redirectToUseOrigin = extractOrigin(redirectToUse)\n\n if (failedRedirectOrigin && !req.payload.config.csrf.includes(failedRedirectOrigin)) {\n req.payload.logger.error(\n `Failed redirect origin ${failedRedirectOrigin} is not allowed by CSRF configuration.`,\n )\n return Response.json(\n { error: 'Failed redirect origin is not allowed by CSRF configuration.' },\n { status: 403 },\n )\n }\n\n if (redirectToUseOrigin && !req.payload.config.csrf.includes(redirectToUseOrigin)) {\n req.payload.logger.error(\n `Redirect origin ${redirectToUseOrigin} is not allowed by CSRF configuration.`,\n )\n return Response.json(\n { error: 'Redirect origin is not allowed by CSRF configuration.' },\n { status: 403 },\n )\n }\n }\n\n // Verify signature\n if (strategy.name !== req.payload.decrypt(state.sig)) {\n req.payload.logger.error('Signature mismatch. Failing login and redirecting.')\n return Response.redirect(failedRedirect)\n }\n\n if (!strategy.meta?.token_endpoint) {\n debugLogger.error({\n msg: `No metadata was obtained from the identity provider. Failing login and redirecting.`,\n path,\n })\n return Response.redirect(failedRedirect)\n }\n\n debugLogger.info({ body: jsonBody, msg: 'Received login response body', path })\n\n if (!jsonBody?.code) {\n debugLogger.error({\n msg: `No authorization code present in body. Failing login and redirecting.`,\n path,\n })\n return Response.redirect(failedRedirect)\n }\n\n // Exchange `code` from body for refresh token\n const { code } = jsonBody\n\n if (typeof code !== 'string') {\n debugLogger.error({\n msg: `Authorization code present in body is not a string. Failing login and redirecting.`,\n path,\n })\n return Response.redirect(failedRedirect)\n }\n\n const body: Record<string, string> = {\n client_id: strategy.clientID,\n code,\n code_verifier: req.payload.decrypt(state.verifier),\n grant_type: 'authorization_code',\n redirect_uri: `${redirectDestination}${config?.routes?.api || '/api'}/${\n collection.slug\n }/${endpointSlug}/login`,\n }\n\n if (strategy.collectionOptions.clientSecret) {\n body.client_secret = strategy.collectionOptions.clientSecret\n }\n\n debugLogger.info({\n msg: 'Exchanging code for access token',\n path,\n requestBody: body,\n })\n\n const tokenRes = await fetch(strategy.meta?.token_endpoint, {\n body: new URLSearchParams(body),\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n method: 'POST',\n }).then((r) => r.json())\n\n debugLogger.info({ msg: 'Token Response', path, tokenRes })\n\n const { access_token, error, error_description, expires_in: refreshTokenExpires } = tokenRes\n\n debugLogger.info({ msg: 'tokenResss', tokenRes })\n\n // Swap for project token\n const project_token = await getProjectToken(\n tokenRes.access_token,\n config.custom.figma.contentSystemId,\n )\n const refresh_token = access_token\n\n // Store project token as access_token\n\n const token = project_token.token\n const expiresIn = project_token.expiresAt\n\n if (!token) {\n const errMsg = `No ${\n collectionOptions.token || 'access_token'\n } was returned from the identity provider.`\n req.payload.logger.error({ msg: errMsg, path })\n throw new APIError(errMsg)\n }\n\n const cookieOptions = createCookieOptions({ collection, headers: req.headers, pluginOptions })\n\n if (error) {\n req.payload.logger.error('Error swapping access code with access token:')\n req.payload.logger.error({ err: error, error_description })\n return Response.redirect(failedRedirect)\n }\n\n // get the payloadRedirect cookie value\n const cookies = parseCookies(req.headers)\n\n const payloadRedirect =\n 'payloadRedirect' in cookies ? (cookies.payloadRedirect as string) : ''\n\n if (!req.responseHeaders) {\n req.responseHeaders = new Headers()\n }\n\n if (payloadRedirect) {\n if (isAbsoluteURL(payloadRedirect)) {\n redirectToUse = payloadRedirect\n } else {\n redirectToUse += payloadRedirect\n }\n\n req.responseHeaders.append(\n 'Set-Cookie',\n `payloadRedirect=${redirectToUse}; Max-Age=0; Path=/;`,\n )\n }\n\n if (refresh_token && !collectionOptions.usePayloadJWT) {\n debugLogger.info('Setting refresh token cookie')\n const refreshCookie = generateCookie({\n returnCookieAsObject: false,\n ...cookieOptions,\n name: `${strategy.cookieName}-refresh`,\n value: refresh_token,\n // Default to 1 year if no expiration\n expires: getCookieExpiration(cookieOptions?.expires ?? refreshTokenExpires ?? 31_556_952),\n }) as string\n\n req.responseHeaders.append('Set-Cookie', refreshCookie)\n }\n\n const tokenExpires = cookieOptions?.expires\n ? getCookieExpiration(cookieOptions.expires)\n : new Date(expiresIn) // Project token uses epoch time\n const tokenCookie = generateCookie({\n ...cookieOptions,\n name: strategy.cookieName,\n expires: tokenExpires,\n returnCookieAsObject: false,\n value: token,\n }) as string\n\n req.responseHeaders.append('Set-Cookie', tokenCookie)\n\n return Response.redirect(redirectToUse)\n } catch (err: unknown) {\n req.payload.logger.error({ err, msg: 'Error while attempting to login', path: req.pathname })\n\n return Response.json({ error: 'Error while attempting to login' }, { status: 500 })\n }\n },\n method: collectionOptions.authorizationURLParams?.response_mode === 'query' ? 'get' : 'post',\n path: `/${endpointSlug}/login`,\n})\n"],"names":["APIError","generateCookie","parseCookies","getSafeRedirect","getProjectToken","createCookieOptions","createDebugLogger","extractOrigin","getAdminPath","getCookieExpiration","isAbsoluteURL","url","test","getLoginEndpoint","collection","collectionOptions","endpointSlug","pluginOptions","strategy","handler","req","config","payload","adminPath","ensureMeta","path","pathname","debugLogger","debug","jsonBody","contentType","headers","get","json","formData","info","msg","Response","redirect","redirectServerURL","serverURL","authorizationURLParams","response_mode","Object","keys","query","length","fromEntries","entries","stateRaw","state","JSON","parse","Buffer","from","toString","redirectDestination","failedRedirect","redirectToUse","allowAbsoluteUrls","redirectTo","error","status","Array","isArray","csrf","failedRedirectOrigin","redirectToUseOrigin","includes","logger","name","decrypt","sig","meta","token_endpoint","body","code","client_id","clientID","code_verifier","verifier","grant_type","redirect_uri","routes","api","slug","clientSecret","client_secret","requestBody","tokenRes","fetch","URLSearchParams","method","then","r","access_token","error_description","expires_in","refreshTokenExpires","project_token","custom","figma","contentSystemId","refresh_token","token","expiresIn","expiresAt","errMsg","cookieOptions","err","cookies","payloadRedirect","responseHeaders","Headers","append","usePayloadJWT","refreshCookie","returnCookieAsObject","cookieName","value","expires","tokenExpires","Date","tokenCookie"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkC,MAAM,EAAE,MAAM,SAAS,CAAA;AAErE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAc/C,eAAO,MAAM,YAAY,kBACP,aAAa,KAAG,MAoO/B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoD,MAAM,EAAE,MAAM,SAAS,CAAA;AAIvF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAc/C,eAAO,MAAM,YAAY,kBACP,aAAa,KAAG,MAgR/B,CAAA"}
@@ -1,3 +1,4 @@
1
+ import { fieldAffectsData } from 'payload/shared';
1
2
  import { defaultVerify } from './defaults.js';
2
3
  import { getLoginEndpoint } from './endpoints/getLoginEndpoint.js';
3
4
  import { getLogoutEndpoint } from './endpoints/getLogoutEndpoint.js';
@@ -46,7 +47,7 @@ export const oAuth2Plugin = (pluginOptions)=>(config)=>{
46
47
  disabled,
47
48
  endpointSlug
48
49
  },
49
- path: '@payloadcms/plugin-oauth2/client#DefaultLoginButton'
50
+ path: '@payloadcms/figma/client#DefaultLoginButton'
50
51
  };
51
52
  }
52
53
  return {
@@ -62,7 +63,7 @@ export const oAuth2Plugin = (pluginOptions)=>(config)=>{
62
63
  disabled,
63
64
  endpointSlug
64
65
  },
65
- path: '@payloadcms/plugin-oauth2/client#LogoutButton'
66
+ path: '@payloadcms/figma/client#LogoutButton'
66
67
  }
67
68
  }
68
69
  } : {},
@@ -84,14 +85,45 @@ export const oAuth2Plugin = (pluginOptions)=>(config)=>{
84
85
  if (collectionOptions.usePayloadJWT) {
85
86
  cookieName = `${config.cookiePrefix || 'payload'}-token`;
86
87
  }
88
+ // Check if email field exists, if not add it
89
+ const hasEmailField = existingCollection.fields.some((field)=>'name' in field && field.name === 'email');
90
+ // Add email field to collection before getting username field
91
+ // This ensures getUsernameField can find the email field if it's configured as the username
92
+ const collectionWithEmail = hasEmailField ? existingCollection : {
93
+ ...existingCollection,
94
+ fields: [
95
+ ...existingCollection.fields,
96
+ {
97
+ name: 'email',
98
+ type: 'email',
99
+ admin: {
100
+ description: 'Managed by Figma',
101
+ readOnly: true
102
+ },
103
+ unique: true
104
+ }
105
+ ]
106
+ };
87
107
  const usernameField = getUsernameField({
88
- collection: existingCollection,
108
+ collection: collectionWithEmail,
89
109
  collectionOptions
90
110
  });
111
+ // Make username field readOnly (and add description for email fields)
112
+ const readOnlyUsernameField = {
113
+ ...usernameField,
114
+ admin: {
115
+ ...usernameField.admin || {},
116
+ ...usernameField.name === 'email' ? {
117
+ description: 'Managed by Figma'
118
+ } : {},
119
+ readOnly: true
120
+ }
121
+ };
122
+ const isUsernameFieldString = typeof adminCollectionOptions.usernameField === 'string';
91
123
  const fields = [
92
- ...existingCollection.fields,
93
- ...typeof adminCollectionOptions.usernameField === 'string' ? [] : [
94
- usernameField
124
+ ...collectionWithEmail.fields.map((field)=>fieldAffectsData(field) && field.name === usernameField.name ? readOnlyUsernameField : field),
125
+ ...isUsernameFieldString ? [] : [
126
+ readOnlyUsernameField
95
127
  ]
96
128
  ];
97
129
  if (disabled) {
@@ -102,7 +134,6 @@ export const oAuth2Plugin = (pluginOptions)=>(config)=>{
102
134
  }
103
135
  const strategy = new Strategy({
104
136
  clientID: collectionOptions.clientID,
105
- clientSecret: collectionOptions.clientSecret,
106
137
  collection: existingCollection,
107
138
  collectionOptions,
108
139
  cookieName,
@@ -134,6 +165,10 @@ export const oAuth2Plugin = (pluginOptions)=>(config)=>{
134
165
  }
135
166
  return {
136
167
  ...existingCollection,
168
+ access: {
169
+ ...existingCollection.access || {},
170
+ create: ()=>false
171
+ },
137
172
  auth: {
138
173
  ...typeof existingCollection.auth === 'object' ? existingCollection.auth : {},
139
174
  disableLocalStrategy,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/oauth/index.ts"],"sourcesContent":["import type { AuthStrategy, IncomingAuthType, Plugin } from 'payload'\n\nimport type { PluginOptions } from './types.js'\n\nimport { defaultVerify } from './defaults.js'\nimport { getLoginEndpoint } from './endpoints/getLoginEndpoint.js'\nimport { getLogoutEndpoint } from './endpoints/getLogoutEndpoint.js'\nimport { getMetaEndpoint } from './endpoints/getMetaEndpoint.js'\nimport { getRedirectToLoginEndpoint } from './endpoints/getRedirectToLoginEndpoint.js'\nimport { getAfterLogout } from './hooks/afterLogout.js'\nimport { getMeHook } from './hooks/me.js'\nimport { getRefreshHook } from './hooks/refresh.js'\nimport { Strategy } from './strategy/index.js'\nimport { getAdminCollectionSlug } from './utilities/getAdminCollectionSlug.js'\nimport { getUsernameField } from './utilities/getUsernameField.js'\n\nexport const oAuth2Plugin =\n (pluginOptions: PluginOptions): Plugin =>\n (config) => {\n const { collections: allCollectionOptions, debug, disabled } = pluginOptions\n\n const strategyName = pluginOptions?.strategyName || 'oauth'\n // Defaults to sso, but can be overridden to accommodate multiple strategies on one collection\n const endpointSlug = pluginOptions?.strategyName || 'sso'\n\n const adminCollectionSlug = getAdminCollectionSlug(config)\n const adminCollectionOptions = allCollectionOptions.find(\n ({ slug }) => slug === adminCollectionSlug,\n )\n\n if (!adminCollectionOptions) {\n throw new Error(\n `Can't find collection options for the admin collection ${adminCollectionSlug}.`,\n )\n }\n\n let LoginButton = null\n\n if (adminCollectionOptions.LoginButton === false) {\n LoginButton = null\n } else if (typeof adminCollectionOptions.LoginButton === 'string') {\n LoginButton = {\n clientProps: {\n disabled,\n endpointSlug,\n },\n path: adminCollectionOptions.LoginButton,\n }\n } else if (typeof adminCollectionOptions.LoginButton === 'object') {\n LoginButton = {\n ...adminCollectionOptions.LoginButton,\n clientProps: {\n ...adminCollectionOptions.LoginButton.clientProps,\n disabled,\n endpointSlug,\n },\n }\n } else {\n // Default to the provided LoginButton component path\n LoginButton = {\n clientProps: {\n disabled,\n endpointSlug,\n },\n path: '@payloadcms/plugin-oauth2/client#DefaultLoginButton',\n }\n }\n\n return {\n ...config,\n admin: {\n ...(config.admin || {}),\n components: {\n ...(typeof config.admin === 'object' && typeof config.admin.components === 'object'\n ? config.admin.components\n : {}),\n ...(adminCollectionOptions.endOAuthSessionOnLogout\n ? {\n logout: {\n Button: {\n clientProps: {\n disabled,\n endpointSlug,\n },\n path: '@payloadcms/plugin-oauth2/client#LogoutButton',\n },\n },\n }\n : {}),\n beforeLogin: [\n ...(typeof config.admin === 'object' &&\n typeof config.admin.components === 'object' &&\n Array.isArray(config.admin.components.beforeLogin)\n ? config.admin.components.beforeLogin\n : []),\n ...(LoginButton ? [LoginButton] : []),\n ],\n },\n },\n collections: (config.collections || []).map((existingCollection) => {\n const collectionOptions = allCollectionOptions.find(\n ({ slug }) => slug === existingCollection.slug,\n )\n\n if (!collectionOptions) {\n return existingCollection\n }\n\n let cookieName = pluginOptions?.cookieName || `payload-${strategyName}-token`\n // If the usePayloadJWT option is enabled, use the default cookie name from Payload\n if (collectionOptions.usePayloadJWT) {\n cookieName = `${config.cookiePrefix || 'payload'}-token`\n }\n\n const usernameField = getUsernameField({\n collection: existingCollection,\n collectionOptions,\n })\n\n const fields = [\n ...existingCollection.fields,\n ...(typeof adminCollectionOptions.usernameField === 'string' ? [] : [usernameField]),\n ]\n\n if (disabled) {\n return {\n ...existingCollection,\n fields,\n }\n }\n\n const strategy = new Strategy({\n clientID: collectionOptions.clientID,\n clientSecret: collectionOptions.clientSecret,\n collection: existingCollection,\n collectionOptions,\n cookieName,\n debug,\n identityMetadata: collectionOptions.identityMetadata,\n pluginOptions,\n strategyName,\n verify:\n collectionOptions.verify ??\n defaultVerify({\n collection: existingCollection,\n strategyName,\n usernameField,\n }),\n })\n\n const authStrategy: AuthStrategy = {\n name: `${existingCollection.slug}-${strategyName}`,\n // Bind 'this' to ensure the authenticate function has the correct context\n authenticate: strategy.authenticate.bind(strategy),\n }\n\n let disableLocalStrategy: IncomingAuthType['disableLocalStrategy']\n\n if (collectionOptions.disableLocalStrategy === false) {\n // When the plugin collection option has disableLocalStrategy option set to false, do not disable the local strategy\n disableLocalStrategy = undefined\n } else if (collectionOptions.disableLocalStrategy) {\n // use the configured disableLocalStrategy which can include `enableFields`, etc.\n disableLocalStrategy = collectionOptions.disableLocalStrategy\n } else {\n // by default disableLocalStrategy\n disableLocalStrategy = true\n }\n\n return {\n ...existingCollection,\n auth: {\n ...(typeof existingCollection.auth === 'object' ? existingCollection.auth : {}),\n disableLocalStrategy,\n strategies: [\n ...(typeof existingCollection.auth === 'object' &&\n Array.isArray(existingCollection.auth.strategies)\n ? existingCollection.auth.strategies\n : []),\n authStrategy,\n ],\n },\n endpoints: [\n ...(existingCollection.endpoints || []),\n getLoginEndpoint({\n collection: existingCollection,\n collectionOptions,\n endpointSlug,\n pluginOptions,\n strategy,\n }),\n getMetaEndpoint({\n collection: existingCollection,\n collectionOptions,\n endpointSlug,\n pluginOptions,\n strategy,\n }),\n getLogoutEndpoint({\n collection: existingCollection,\n endpointSlug,\n pluginOptions,\n strategy,\n }),\n getRedirectToLoginEndpoint({\n collection: existingCollection,\n collectionOptions,\n endpointSlug,\n pluginOptions,\n strategy,\n }),\n ],\n fields,\n hooks: {\n ...(existingCollection.hooks || {}),\n afterLogout: [\n ...(typeof existingCollection.hooks === 'object' &&\n Array.isArray(existingCollection.hooks.afterLogout)\n ? existingCollection.hooks.afterLogout\n : []),\n getAfterLogout({\n collection: existingCollection,\n cookieName,\n pluginOptions,\n }),\n ],\n me: [\n ...(typeof existingCollection.hooks === 'object' &&\n Array.isArray(existingCollection.hooks.me)\n ? existingCollection.hooks.me\n : []),\n // Do not inject the me hook if the usePayloadJWT option is enabled\n ...(!collectionOptions.usePayloadJWT ? [getMeHook({ cookieName })] : []),\n ],\n refresh: [\n ...(typeof existingCollection.hooks === 'object' &&\n Array.isArray(existingCollection.hooks.refresh)\n ? existingCollection.hooks.refresh\n : []),\n getRefreshHook({ pluginOptions, strategy }),\n ],\n },\n }\n }),\n }\n }\n"],"names":["defaultVerify","getLoginEndpoint","getLogoutEndpoint","getMetaEndpoint","getRedirectToLoginEndpoint","getAfterLogout","getMeHook","getRefreshHook","Strategy","getAdminCollectionSlug","getUsernameField","oAuth2Plugin","pluginOptions","config","collections","allCollectionOptions","debug","disabled","strategyName","endpointSlug","adminCollectionSlug","adminCollectionOptions","find","slug","Error","LoginButton","clientProps","path","admin","components","endOAuthSessionOnLogout","logout","Button","beforeLogin","Array","isArray","map","existingCollection","collectionOptions","cookieName","usePayloadJWT","cookiePrefix","usernameField","collection","fields","strategy","clientID","clientSecret","identityMetadata","verify","authStrategy","name","authenticate","bind","disableLocalStrategy","undefined","auth","strategies","endpoints","hooks","afterLogout","me","refresh"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/oauth/index.ts"],"sourcesContent":["import type { AuthStrategy, CollectionConfig, IncomingAuthType, Plugin } from 'payload'\n\nimport { fieldAffectsData } from 'payload/shared'\n\nimport type { PluginOptions } from './types.js'\n\nimport { defaultVerify } from './defaults.js'\nimport { getLoginEndpoint } from './endpoints/getLoginEndpoint.js'\nimport { getLogoutEndpoint } from './endpoints/getLogoutEndpoint.js'\nimport { getMetaEndpoint } from './endpoints/getMetaEndpoint.js'\nimport { getRedirectToLoginEndpoint } from './endpoints/getRedirectToLoginEndpoint.js'\nimport { getAfterLogout } from './hooks/afterLogout.js'\nimport { getMeHook } from './hooks/me.js'\nimport { getRefreshHook } from './hooks/refresh.js'\nimport { Strategy } from './strategy/index.js'\nimport { getAdminCollectionSlug } from './utilities/getAdminCollectionSlug.js'\nimport { getUsernameField } from './utilities/getUsernameField.js'\n\nexport const oAuth2Plugin =\n (pluginOptions: PluginOptions): Plugin =>\n (config) => {\n const { collections: allCollectionOptions, debug, disabled } = pluginOptions\n\n const strategyName = pluginOptions?.strategyName || 'oauth'\n // Defaults to sso, but can be overridden to accommodate multiple strategies on one collection\n const endpointSlug = pluginOptions?.strategyName || 'sso'\n\n const adminCollectionSlug = getAdminCollectionSlug(config)\n const adminCollectionOptions = allCollectionOptions.find(\n ({ slug }) => slug === adminCollectionSlug,\n )\n\n if (!adminCollectionOptions) {\n throw new Error(\n `Can't find collection options for the admin collection ${adminCollectionSlug}.`,\n )\n }\n\n let LoginButton = null\n\n if (adminCollectionOptions.LoginButton === false) {\n LoginButton = null\n } else if (typeof adminCollectionOptions.LoginButton === 'string') {\n LoginButton = {\n clientProps: {\n disabled,\n endpointSlug,\n },\n path: adminCollectionOptions.LoginButton,\n }\n } else if (typeof adminCollectionOptions.LoginButton === 'object') {\n LoginButton = {\n ...adminCollectionOptions.LoginButton,\n clientProps: {\n ...adminCollectionOptions.LoginButton.clientProps,\n disabled,\n endpointSlug,\n },\n }\n } else {\n // Default to the provided LoginButton component path\n LoginButton = {\n clientProps: {\n disabled,\n endpointSlug,\n },\n path: '@payloadcms/figma/client#DefaultLoginButton',\n }\n }\n\n return {\n ...config,\n admin: {\n ...(config.admin || {}),\n components: {\n ...(typeof config.admin === 'object' && typeof config.admin.components === 'object'\n ? config.admin.components\n : {}),\n ...(adminCollectionOptions.endOAuthSessionOnLogout\n ? {\n logout: {\n Button: {\n clientProps: {\n disabled,\n endpointSlug,\n },\n path: '@payloadcms/figma/client#LogoutButton',\n },\n },\n }\n : {}),\n beforeLogin: [\n ...(typeof config.admin === 'object' &&\n typeof config.admin.components === 'object' &&\n Array.isArray(config.admin.components.beforeLogin)\n ? config.admin.components.beforeLogin\n : []),\n ...(LoginButton ? [LoginButton] : []),\n ],\n },\n },\n collections: (config.collections || []).map((existingCollection) => {\n const collectionOptions = allCollectionOptions.find(\n ({ slug }) => slug === existingCollection.slug,\n )\n\n if (!collectionOptions) {\n return existingCollection\n }\n\n let cookieName = pluginOptions?.cookieName || `payload-${strategyName}-token`\n // If the usePayloadJWT option is enabled, use the default cookie name from Payload\n if (collectionOptions.usePayloadJWT) {\n cookieName = `${config.cookiePrefix || 'payload'}-token`\n }\n\n // Check if email field exists, if not add it\n const hasEmailField = existingCollection.fields.some(\n (field) => 'name' in field && field.name === 'email',\n )\n\n // Add email field to collection before getting username field\n // This ensures getUsernameField can find the email field if it's configured as the username\n const collectionWithEmail: CollectionConfig = hasEmailField\n ? existingCollection\n : {\n ...existingCollection,\n fields: [\n ...existingCollection.fields,\n {\n name: 'email',\n type: 'email',\n admin: {\n description: 'Managed by Figma',\n readOnly: true,\n },\n unique: true,\n },\n ],\n }\n\n const usernameField = getUsernameField({\n collection: collectionWithEmail,\n collectionOptions,\n })\n\n // Make username field readOnly (and add description for email fields)\n const readOnlyUsernameField = {\n ...usernameField,\n admin: {\n ...(usernameField.admin || {}),\n ...(usernameField.name === 'email' ? { description: 'Managed by Figma' } : {}),\n readOnly: true,\n },\n } as typeof usernameField\n\n const isUsernameFieldString = typeof adminCollectionOptions.usernameField === 'string'\n\n const fields = [\n ...collectionWithEmail.fields.map((field) =>\n fieldAffectsData(field) && field.name === usernameField.name\n ? readOnlyUsernameField\n : field,\n ),\n ...(isUsernameFieldString ? [] : [readOnlyUsernameField]),\n ]\n\n if (disabled) {\n return {\n ...existingCollection,\n fields,\n }\n }\n\n const strategy = new Strategy({\n clientID: collectionOptions.clientID,\n collection: existingCollection,\n collectionOptions,\n cookieName,\n debug,\n identityMetadata: collectionOptions.identityMetadata,\n pluginOptions,\n strategyName,\n verify:\n collectionOptions.verify ??\n defaultVerify({\n collection: existingCollection,\n strategyName,\n usernameField,\n }),\n })\n\n const authStrategy: AuthStrategy = {\n name: `${existingCollection.slug}-${strategyName}`,\n // Bind 'this' to ensure the authenticate function has the correct context\n authenticate: strategy.authenticate.bind(strategy),\n }\n\n let disableLocalStrategy: IncomingAuthType['disableLocalStrategy']\n\n if (collectionOptions.disableLocalStrategy === false) {\n // When the plugin collection option has disableLocalStrategy option set to false, do not disable the local strategy\n disableLocalStrategy = undefined\n } else if (collectionOptions.disableLocalStrategy) {\n // use the configured disableLocalStrategy which can include `enableFields`, etc.\n disableLocalStrategy = collectionOptions.disableLocalStrategy\n } else {\n // by default disableLocalStrategy\n disableLocalStrategy = true\n }\n\n return {\n ...existingCollection,\n access: {\n ...(existingCollection.access || {}),\n create: () => false,\n },\n auth: {\n ...(typeof existingCollection.auth === 'object' ? existingCollection.auth : {}),\n disableLocalStrategy,\n strategies: [\n ...(typeof existingCollection.auth === 'object' &&\n Array.isArray(existingCollection.auth.strategies)\n ? existingCollection.auth.strategies\n : []),\n authStrategy,\n ],\n },\n endpoints: [\n ...(existingCollection.endpoints || []),\n getLoginEndpoint({\n collection: existingCollection,\n collectionOptions,\n endpointSlug,\n pluginOptions,\n strategy,\n }),\n getMetaEndpoint({\n collection: existingCollection,\n collectionOptions,\n endpointSlug,\n pluginOptions,\n strategy,\n }),\n getLogoutEndpoint({\n collection: existingCollection,\n endpointSlug,\n pluginOptions,\n strategy,\n }),\n getRedirectToLoginEndpoint({\n collection: existingCollection,\n collectionOptions,\n endpointSlug,\n pluginOptions,\n strategy,\n }),\n ],\n fields,\n hooks: {\n ...(existingCollection.hooks || {}),\n afterLogout: [\n ...(typeof existingCollection.hooks === 'object' &&\n Array.isArray(existingCollection.hooks.afterLogout)\n ? existingCollection.hooks.afterLogout\n : []),\n getAfterLogout({\n collection: existingCollection,\n cookieName,\n pluginOptions,\n }),\n ],\n me: [\n ...(typeof existingCollection.hooks === 'object' &&\n Array.isArray(existingCollection.hooks.me)\n ? existingCollection.hooks.me\n : []),\n // Do not inject the me hook if the usePayloadJWT option is enabled\n ...(!collectionOptions.usePayloadJWT ? [getMeHook({ cookieName })] : []),\n ],\n refresh: [\n ...(typeof existingCollection.hooks === 'object' &&\n Array.isArray(existingCollection.hooks.refresh)\n ? existingCollection.hooks.refresh\n : []),\n getRefreshHook({ pluginOptions, strategy }),\n ],\n },\n }\n }),\n }\n }\n"],"names":["fieldAffectsData","defaultVerify","getLoginEndpoint","getLogoutEndpoint","getMetaEndpoint","getRedirectToLoginEndpoint","getAfterLogout","getMeHook","getRefreshHook","Strategy","getAdminCollectionSlug","getUsernameField","oAuth2Plugin","pluginOptions","config","collections","allCollectionOptions","debug","disabled","strategyName","endpointSlug","adminCollectionSlug","adminCollectionOptions","find","slug","Error","LoginButton","clientProps","path","admin","components","endOAuthSessionOnLogout","logout","Button","beforeLogin","Array","isArray","map","existingCollection","collectionOptions","cookieName","usePayloadJWT","cookiePrefix","hasEmailField","fields","some","field","name","collectionWithEmail","type","description","readOnly","unique","usernameField","collection","readOnlyUsernameField","isUsernameFieldString","strategy","clientID","identityMetadata","verify","authStrategy","authenticate","bind","disableLocalStrategy","undefined","access","create","auth","strategies","endpoints","hooks","afterLogout","me","refresh"],"mappings":"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"}
@@ -4,7 +4,6 @@ import * as jose from 'jose';
4
4
  import type { CollectionOptions, PluginOptions, VerifyFunction } from '../types.js';
5
5
  export interface Options {
6
6
  clientID: string;
7
- clientSecret?: string;
8
7
  collection: CollectionConfig;
9
8
  collectionOptions: CollectionOptions;
10
9
  cookieName: string;
@@ -16,7 +15,6 @@ export interface Options {
16
15
  }
17
16
  export declare class Strategy {
18
17
  clientID: string;
19
- clientSecret?: string;
20
18
  collection: CollectionConfig;
21
19
  collectionOptions: CollectionOptions;
22
20
  cookieName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/oauth/strategy/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAA;AAEnC,OAAO,KAAK,EACV,wBAAwB,EACxB,kBAAkB,EAClB,gBAAgB,EAChB,OAAO,EACR,MAAM,SAAS,CAAA;AAEhB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAG5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAUnF,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,gBAAgB,EAAE,MAAM,CAAA;IACxB,aAAa,EAAE,aAAa,CAAA;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,cAAc,CAAA;CACvB;AAED,qBAAa,QAAQ;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,UAAU,EAAE,MAAM,CAAA;IAElB,KAAK,EAAE,OAAO,CAAA;IAGd,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;IAElC,mBAAmB,EAAE,MAAM,CAAA;IAC3B,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,CAAA;KACjB,CAAA;IACD,IAAI,CAAC,EAAE;QACL,sBAAsB,EAAE,MAAM,CAAA;QAC9B,oBAAoB,EAAE,MAAM,CAAA;QAC5B,QAAQ,EAAE,MAAM,CAAA;QAChB,cAAc,EAAE,MAAM,CAAA;QACtB,iBAAiB,EAAE,MAAM,CAAA;KAC1B,CAAA;IACD,mBAAmB,CAAC,EAAE,IAAI,CAAA;IAE1B,WAAW,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3B,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,aAAa,CAAA;IAC5B,MAAM,EAAE,cAAc,CAAA;gBAEV,OAAO,EAAE,OAAO;IAiBtB,YAAY,CAAC,EACjB,aAAa,EACb,OAAO,EACP,OAAO,GACR,EAAE,wBAAwB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAyJnD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAe3B,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAkD1B,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA6C1D,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,aAAa,GAAG,OAAO,CAAC,KAAK,GAAG,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC;CAmB3F;AAED,KAAK,aAAa,GAAG;IACnB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/oauth/strategy/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAA;AAEnC,OAAO,KAAK,EACV,wBAAwB,EACxB,kBAAkB,EAClB,gBAAgB,EAChB,OAAO,EACR,MAAM,SAAS,CAAA;AAEhB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAG5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AASnF,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,gBAAgB,EAAE,MAAM,CAAA;IACxB,aAAa,EAAE,aAAa,CAAA;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,cAAc,CAAA;CACvB;AAED,qBAAa,QAAQ;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,UAAU,EAAE,MAAM,CAAA;IAElB,KAAK,EAAE,OAAO,CAAA;IAGd,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;IAElC,mBAAmB,EAAE,MAAM,CAAA;IAC3B,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,CAAA;KACjB,CAAA;IACD,IAAI,CAAC,EAAE;QACL,sBAAsB,EAAE,MAAM,CAAA;QAC9B,oBAAoB,EAAE,MAAM,CAAA;QAC5B,QAAQ,EAAE,MAAM,CAAA;QAChB,cAAc,EAAE,MAAM,CAAA;QACtB,iBAAiB,EAAE,MAAM,CAAA;KAC1B,CAAA;IACD,mBAAmB,CAAC,EAAE,IAAI,CAAA;IAE1B,WAAW,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3B,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,aAAa,CAAA;IAC5B,MAAM,EAAE,cAAc,CAAA;gBAEV,OAAO,EAAE,OAAO;IAgBtB,YAAY,CAAC,EACjB,aAAa,EACb,OAAO,EACP,OAAO,GACR,EAAE,wBAAwB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA8KnD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAe3B,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAwD1B,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA6C1D,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,aAAa,GAAG,OAAO,CAAC,KAAK,GAAG,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC;CAmB3F;AAED,KAAK,aAAa,GAAG;IACnB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA"}
@@ -1,6 +1,6 @@
1
1
  import * as jose from 'jose';
2
2
  import { APIError, parseCookies } from 'payload';
3
- import { validateProjectToken } from '../../auth/jwt-validator.js';
3
+ import { JWTValidationError, validateProjectToken } from '../../auth/jwt-validator.js';
4
4
  import { getEnvironment } from '../../constants.js';
5
5
  import { createDebugLogger } from '../utilities/createDebugLogger.js';
6
6
  import { getTokenExp } from '../utilities/getTokenExp.js';
@@ -8,7 +8,6 @@ import { mergeHeaders } from '../utilities/mergeHeaders.js';
8
8
  import { refreshTokens } from '../utilities/refreshTokens.js';
9
9
  export class Strategy {
10
10
  clientID;
11
- clientSecret;
12
11
  collection;
13
12
  collectionOptions;
14
13
  cookieName;
@@ -28,7 +27,6 @@ export class Strategy {
28
27
  this.verify = options.verify;
29
28
  this.cookieName = options.cookieName;
30
29
  this.clientID = options.clientID;
31
- this.clientSecret = options.clientSecret;
32
30
  this.identityMetadataURL = options.identityMetadata;
33
31
  this.name = options.strategyName;
34
32
  this.collection = options.collection;
@@ -63,7 +61,11 @@ export class Strategy {
63
61
  }
64
62
  }
65
63
  if (!oauthToken) {
66
- if (refreshToken && canSetHeaders) {
64
+ // Attempt refresh even when canSetHeaders=false (e.g., during RSC navigation).
65
+ // This allows authentication to succeed for the current request even when
66
+ // cookies cannot be updated. The cookie will be refreshed on the next
67
+ // full page load when canSetHeaders=true.
68
+ if (refreshToken) {
67
69
  debugLogger.info({
68
70
  msg: 'No access token found, but refresh token exists. Attempting to refresh...',
69
71
  refreshToken
@@ -83,11 +85,20 @@ export class Strategy {
83
85
  msg: 'Token refreshed. Verifying...',
84
86
  verifyResult
85
87
  });
86
- if (verifyResult.responseHeaders) {
87
- mergeHeaders(verifyResult.responseHeaders, refreshed.headers);
88
+ // Only return response headers (to set cookies) when canSetHeaders is true.
89
+ // During RSC navigation, canSetHeaders=false because response streaming
90
+ // has already started and cookies cannot be modified.
91
+ if (canSetHeaders) {
92
+ if (verifyResult.responseHeaders) {
93
+ mergeHeaders(verifyResult.responseHeaders, refreshed.headers);
94
+ }
95
+ return {
96
+ responseHeaders: refreshed.headers,
97
+ user: verifyResult.user
98
+ };
88
99
  }
100
+ // Authenticate this request without updating cookies
89
101
  return {
90
- responseHeaders: refreshed.headers,
91
102
  user: verifyResult.user
92
103
  };
93
104
  } else {
@@ -97,11 +108,10 @@ export class Strategy {
97
108
  refreshToken
98
109
  });
99
110
  }
100
- } else {
101
- return {
102
- user: null
103
- };
104
111
  }
112
+ return {
113
+ user: null
114
+ };
105
115
  }
106
116
  let oauthTokenVerifyResult = null;
107
117
  // First, try to verify token
@@ -136,7 +146,10 @@ export class Strategy {
136
146
  });
137
147
  }
138
148
  }
139
- if (oauthTokenVerifyResult instanceof Error && oauthTokenVerifyResult.name === 'TokenExpiredError' && refreshToken && !this.collectionOptions.usePayloadJWT && canSetHeaders) {
149
+ // Handle expired access token with valid refresh token.
150
+ // Same pattern as above: refresh regardless of canSetHeaders to support RSC navigation,
151
+ // but only update cookies when canSetHeaders=true.
152
+ if (oauthTokenVerifyResult instanceof JWTValidationError && oauthTokenVerifyResult.code === 'EXPIRED' && refreshToken && !this.collectionOptions.usePayloadJWT) {
140
153
  const refreshed = await refreshTokens({
141
154
  payload,
142
155
  refreshToken,
@@ -157,11 +170,17 @@ export class Strategy {
157
170
  msg: 'Token refreshed. Verifying...',
158
171
  verifyResult
159
172
  });
160
- if (verifyResult.responseHeaders) {
161
- mergeHeaders(verifyResult.responseHeaders, refreshed.headers);
173
+ if (canSetHeaders) {
174
+ if (verifyResult.responseHeaders) {
175
+ mergeHeaders(verifyResult.responseHeaders, refreshed.headers);
176
+ }
177
+ return {
178
+ responseHeaders: refreshed.headers,
179
+ user: verifyResult.user
180
+ };
162
181
  }
182
+ // Authenticate this request without updating cookies
163
183
  return {
164
- responseHeaders: refreshed.headers,
165
184
  user: verifyResult.user
166
185
  };
167
186
  } else {
@@ -200,6 +219,10 @@ export class Strategy {
200
219
  for(let attempt = 1; attempt <= 5; attempt++){
201
220
  try {
202
221
  this.meta = await fetch(this.identityMetadataURL).then((res)=>res.json());
222
+ if (this.meta) {
223
+ // TODO: This is a hack to get the DefaultLoginButton to work with dynamic OAuth client registration
224
+ this.meta.authorization_endpoint = this.meta?.authorization_endpoint + '/cms';
225
+ }
203
226
  this.debugLog(`fetchMeta - success on attempt ${attempt}`);
204
227
  if (this.meta?.jwks_uri) {
205
228
  this.jwks = await fetch(this.meta.jwks_uri).then((res)=>res.json());