@strapi/plugin-users-permissions 0.0.0-next.f4ff842a3cb7b83db540bee67554b704e042b042 → 0.0.0-next.f5312617ca16b870c2bf1adcea2c69b676979e29

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 (246) hide show
  1. package/LICENSE +18 -3
  2. package/admin/src/components/BoundRoute/index.jsx +2 -2
  3. package/admin/src/components/FormModal/Input/index.jsx +32 -31
  4. package/admin/src/components/FormModal/index.jsx +57 -68
  5. package/admin/src/components/Permissions/PermissionRow/CheckboxWrapper.jsx +4 -3
  6. package/admin/src/components/Permissions/PermissionRow/SubCategory.jsx +13 -22
  7. package/admin/src/components/Permissions/index.jsx +27 -35
  8. package/admin/src/components/Permissions/reducer.js +1 -1
  9. package/admin/src/components/Policies/index.jsx +7 -5
  10. package/admin/src/components/UsersPermissions/index.jsx +15 -7
  11. package/admin/src/components/UsersPermissions/reducer.js +1 -1
  12. package/admin/src/index.js +15 -32
  13. package/admin/src/pages/AdvancedSettings/index.jsx +83 -128
  14. package/admin/src/pages/AdvancedSettings/utils/layout.js +20 -35
  15. package/admin/src/pages/AdvancedSettings/utils/schema.js +5 -2
  16. package/admin/src/pages/EmailTemplates/components/EmailForm.jsx +119 -139
  17. package/admin/src/pages/EmailTemplates/components/EmailTable.jsx +20 -17
  18. package/admin/src/pages/EmailTemplates/index.jsx +36 -62
  19. package/admin/src/pages/EmailTemplates/utils/schema.js +18 -6
  20. package/admin/src/pages/Providers/index.jsx +98 -113
  21. package/admin/src/pages/Providers/utils/forms.js +23 -11
  22. package/admin/src/pages/Roles/constants.js +3 -3
  23. package/admin/src/pages/Roles/hooks/usePlugins.js +4 -4
  24. package/admin/src/pages/Roles/index.jsx +9 -18
  25. package/admin/src/pages/Roles/pages/CreatePage.jsx +53 -58
  26. package/admin/src/pages/Roles/pages/EditPage.jsx +63 -68
  27. package/admin/src/pages/Roles/pages/ListPage/components/TableBody.jsx +27 -31
  28. package/admin/src/pages/Roles/pages/ListPage/index.jsx +79 -55
  29. package/admin/src/translations/en.json +1 -1
  30. package/admin/src/utils/prefixPluginTranslations.js +13 -0
  31. package/dist/_chunks/{ar-t5qTFaAD.js → ar-BguGUqwK.js} +1 -1
  32. package/dist/_chunks/ar-BguGUqwK.js.map +1 -0
  33. package/dist/_chunks/{ar-MvD8Ghac.mjs → ar-CK8BRRXB.mjs} +1 -1
  34. package/dist/_chunks/ar-CK8BRRXB.mjs.map +1 -0
  35. package/dist/_chunks/{cs-BMuXwxA1.mjs → cs-BVigMk0l.mjs} +1 -1
  36. package/dist/_chunks/cs-BVigMk0l.mjs.map +1 -0
  37. package/dist/_chunks/{cs-I8N4u-Sd.js → cs-BW8-K_GY.js} +1 -1
  38. package/dist/_chunks/cs-BW8-K_GY.js.map +1 -0
  39. package/dist/_chunks/{de-zs2qqc0W.mjs → de-BKUdRFI4.mjs} +1 -1
  40. package/dist/_chunks/de-BKUdRFI4.mjs.map +1 -0
  41. package/dist/_chunks/{de-YTjtq89K.js → de-owXpVluI.js} +1 -1
  42. package/dist/_chunks/de-owXpVluI.js.map +1 -0
  43. package/dist/_chunks/{dk-HctVBMsG.mjs → dk-BQiTK50l.mjs} +1 -1
  44. package/dist/_chunks/dk-BQiTK50l.mjs.map +1 -0
  45. package/dist/_chunks/{dk-TF-dWjzl.js → dk-LXAnbuBk.js} +1 -1
  46. package/dist/_chunks/dk-LXAnbuBk.js.map +1 -0
  47. package/dist/_chunks/{en-CE3wEy_c.mjs → en-DOHtPf-2.mjs} +2 -2
  48. package/dist/_chunks/en-DOHtPf-2.mjs.map +1 -0
  49. package/dist/_chunks/{en-m608rMZx.js → en-MHo5mcsU.js} +2 -2
  50. package/dist/_chunks/en-MHo5mcsU.js.map +1 -0
  51. package/dist/_chunks/{es-XBQsB8_9.js → es-BwLCLXAQ.js} +1 -1
  52. package/dist/_chunks/es-BwLCLXAQ.js.map +1 -0
  53. package/dist/_chunks/{es-9381tih_.mjs → es-DNgOVMjD.mjs} +1 -1
  54. package/dist/_chunks/es-DNgOVMjD.mjs.map +1 -0
  55. package/dist/_chunks/{fr-CMSc77If.mjs → fr-DkgRugiU.mjs} +1 -1
  56. package/dist/_chunks/fr-DkgRugiU.mjs.map +1 -0
  57. package/dist/_chunks/{fr-6cz3U-IF.js → fr-DkhpSjjm.js} +1 -1
  58. package/dist/_chunks/fr-DkhpSjjm.js.map +1 -0
  59. package/dist/_chunks/{id-RJ934rq-.js → id-BTemOeTZ.js} +1 -1
  60. package/dist/_chunks/id-BTemOeTZ.js.map +1 -0
  61. package/dist/_chunks/{id-SDuyIkZa.mjs → id-BdEsvnaF.mjs} +1 -1
  62. package/dist/_chunks/id-BdEsvnaF.mjs.map +1 -0
  63. package/dist/_chunks/{index-rL_BoFHz.js → index-BH6NqE8I.js} +47 -51
  64. package/dist/_chunks/index-BH6NqE8I.js.map +1 -0
  65. package/dist/_chunks/index-C3i__jX-.js +281 -0
  66. package/dist/_chunks/index-C3i__jX-.js.map +1 -0
  67. package/dist/_chunks/{index--ch5E4_K.js → index-CFzpNgIL.js} +108 -106
  68. package/dist/_chunks/index-CFzpNgIL.js.map +1 -0
  69. package/dist/_chunks/index-CJUWqtrZ.mjs +344 -0
  70. package/dist/_chunks/index-CJUWqtrZ.mjs.map +1 -0
  71. package/dist/_chunks/index-CcWTKtCY.js +366 -0
  72. package/dist/_chunks/index-CcWTKtCY.js.map +1 -0
  73. package/dist/_chunks/{index-MuQRbm-o.mjs → index-CnX2wiLY.mjs} +239 -256
  74. package/dist/_chunks/index-CnX2wiLY.mjs.map +1 -0
  75. package/dist/_chunks/index-DUWx-KG9-C1E7ADbJ.mjs +11984 -0
  76. package/dist/_chunks/index-DUWx-KG9-C1E7ADbJ.mjs.map +1 -0
  77. package/dist/_chunks/index-DUWx-KG9-fMZ4nmrb.js +12008 -0
  78. package/dist/_chunks/index-DUWx-KG9-fMZ4nmrb.js.map +1 -0
  79. package/dist/_chunks/{index-WCv8yGzw.js → index-DruWuFWL.js} +255 -274
  80. package/dist/_chunks/index-DruWuFWL.js.map +1 -0
  81. package/dist/_chunks/index-PJoz36kJ.mjs +262 -0
  82. package/dist/_chunks/index-PJoz36kJ.mjs.map +1 -0
  83. package/dist/_chunks/{index-iu-7wU8h.mjs → index-R4R0dEOv.mjs} +46 -50
  84. package/dist/_chunks/index-R4R0dEOv.mjs.map +1 -0
  85. package/dist/_chunks/{index-eE2qjbfg.mjs → index-XOcQhJMB.mjs} +105 -103
  86. package/dist/_chunks/index-XOcQhJMB.mjs.map +1 -0
  87. package/dist/_chunks/{it-bvH7DgQo.mjs → it-B-rv0E24.mjs} +1 -1
  88. package/dist/_chunks/it-B-rv0E24.mjs.map +1 -0
  89. package/dist/_chunks/{it-YhZOlM2X.js → it-D1rH6V6_.js} +1 -1
  90. package/dist/_chunks/it-D1rH6V6_.js.map +1 -0
  91. package/dist/_chunks/{ja-o_-JPvQv.mjs → ja-C8K-VBPD.mjs} +1 -1
  92. package/dist/_chunks/ja-C8K-VBPD.mjs.map +1 -0
  93. package/dist/_chunks/{ja-xssHUXFv.js → ja-DqShgTMf.js} +1 -1
  94. package/dist/_chunks/ja-DqShgTMf.js.map +1 -0
  95. package/dist/_chunks/{ko-C3mHUSJa.js → ko-B9DGEPWH.js} +1 -1
  96. package/dist/_chunks/ko-B9DGEPWH.js.map +1 -0
  97. package/dist/_chunks/{ko-XJbPSez_.mjs → ko-Busb0wIY.mjs} +1 -1
  98. package/dist/_chunks/ko-Busb0wIY.mjs.map +1 -0
  99. package/dist/_chunks/{ms-II5Ea73J.mjs → ms-ByvsQjRt.mjs} +1 -1
  100. package/dist/_chunks/ms-ByvsQjRt.mjs.map +1 -0
  101. package/dist/_chunks/{ms-d0hfg65Z.js → ms-CPBU3LWf.js} +1 -1
  102. package/dist/_chunks/ms-CPBU3LWf.js.map +1 -0
  103. package/dist/_chunks/{nl-vEy6TN0K.mjs → nl-5qO8Rpcy.mjs} +1 -1
  104. package/dist/_chunks/nl-5qO8Rpcy.mjs.map +1 -0
  105. package/dist/_chunks/{nl-TA7TfK_5.js → nl-CwNB6YoO.js} +1 -1
  106. package/dist/_chunks/nl-CwNB6YoO.js.map +1 -0
  107. package/dist/_chunks/{pl-2VowaFGt.mjs → pl-BdIzifBE.mjs} +1 -1
  108. package/dist/_chunks/pl-BdIzifBE.mjs.map +1 -0
  109. package/dist/_chunks/{pl-0pUL9hdA.js → pl-Do9UD69f.js} +1 -1
  110. package/dist/_chunks/pl-Do9UD69f.js.map +1 -0
  111. package/dist/_chunks/{pt-Rf9W51IO.mjs → pt-BIO24ioG.mjs} +1 -1
  112. package/dist/_chunks/pt-BIO24ioG.mjs.map +1 -0
  113. package/dist/_chunks/{pt-BR-WNOhafR4.js → pt-BR-D7dZhxuP.js} +1 -1
  114. package/dist/_chunks/pt-BR-D7dZhxuP.js.map +1 -0
  115. package/dist/_chunks/{pt-BR-sS1Xp3Jt.mjs → pt-BR-f0p23AQZ.mjs} +1 -1
  116. package/dist/_chunks/pt-BR-f0p23AQZ.mjs.map +1 -0
  117. package/dist/_chunks/{pt-guNR9Gax.js → pt-fdvyOnUp.js} +1 -1
  118. package/dist/_chunks/pt-fdvyOnUp.js.map +1 -0
  119. package/dist/_chunks/{ru-X3BMXDds.js → ru-C94rjPGA.js} +1 -1
  120. package/dist/_chunks/ru-C94rjPGA.js.map +1 -0
  121. package/dist/_chunks/{ru-qKHnd5or.mjs → ru-VWy-IB7K.mjs} +1 -1
  122. package/dist/_chunks/ru-VWy-IB7K.mjs.map +1 -0
  123. package/dist/_chunks/{sk-NWPw1oTN.js → sk-BABEhykl.js} +1 -1
  124. package/dist/_chunks/sk-BABEhykl.js.map +1 -0
  125. package/dist/_chunks/{sk-_Ryr-eTT.mjs → sk-B_LIcepm.mjs} +1 -1
  126. package/dist/_chunks/sk-B_LIcepm.mjs.map +1 -0
  127. package/dist/_chunks/{sv-BqzScFXS.mjs → sv-ABLKOokl.mjs} +1 -1
  128. package/dist/_chunks/sv-ABLKOokl.mjs.map +1 -0
  129. package/dist/_chunks/{sv-76NnbB__.js → sv-Be43LhA9.js} +1 -1
  130. package/dist/_chunks/sv-Be43LhA9.js.map +1 -0
  131. package/dist/_chunks/{th-WsknMEpq.mjs → th-DKyP7ueR.mjs} +1 -1
  132. package/dist/_chunks/th-DKyP7ueR.mjs.map +1 -0
  133. package/dist/_chunks/{th-cbppX21D.js → th-DgVhVLhL.js} +1 -1
  134. package/dist/_chunks/th-DgVhVLhL.js.map +1 -0
  135. package/dist/_chunks/{tr-6mm_Fmz7.js → tr-B_idhkEs.js} +1 -1
  136. package/dist/_chunks/tr-B_idhkEs.js.map +1 -0
  137. package/dist/_chunks/{tr-_DB1F1GW.mjs → tr-qa1Q5UjC.mjs} +1 -1
  138. package/dist/_chunks/tr-qa1Q5UjC.mjs.map +1 -0
  139. package/dist/_chunks/{uk-yxMSQAwI.mjs → uk-BmRqbeQc.mjs} +1 -1
  140. package/dist/_chunks/uk-BmRqbeQc.mjs.map +1 -0
  141. package/dist/_chunks/{uk-sI2I1ogF.js → uk-LHOivnhP.js} +1 -1
  142. package/dist/_chunks/uk-LHOivnhP.js.map +1 -0
  143. package/dist/_chunks/{vi-A3zJxaiI.js → vi-CdVRdKDw.js} +1 -1
  144. package/dist/_chunks/vi-CdVRdKDw.js.map +1 -0
  145. package/dist/_chunks/{vi-xY0zCW3d.mjs → vi-HW-EdMea.mjs} +1 -1
  146. package/dist/_chunks/vi-HW-EdMea.mjs.map +1 -0
  147. package/dist/_chunks/{zh-OFeldzbX.mjs → zh-5hKkVPA4.mjs} +1 -1
  148. package/dist/_chunks/zh-5hKkVPA4.mjs.map +1 -0
  149. package/dist/_chunks/{zh-72SpmFXa.js → zh-Cuq8gMnF.js} +1 -1
  150. package/dist/_chunks/zh-Cuq8gMnF.js.map +1 -0
  151. package/dist/_chunks/{zh-Hans-E84cu4kP.mjs → zh-Hans-BHilK-yc.mjs} +1 -1
  152. package/dist/_chunks/zh-Hans-BHilK-yc.mjs.map +1 -0
  153. package/dist/_chunks/{zh-Hans-ArWWtyP4.js → zh-Hans-GQDMKtY4.js} +1 -1
  154. package/dist/_chunks/zh-Hans-GQDMKtY4.js.map +1 -0
  155. package/dist/admin/index.js +1 -2
  156. package/dist/admin/index.js.map +1 -1
  157. package/dist/admin/index.mjs +1 -2
  158. package/dist/admin/index.mjs.map +1 -1
  159. package/package.json +27 -28
  160. package/server/bootstrap/index.js +18 -51
  161. package/server/bootstrap/users-permissions-actions.js +6 -0
  162. package/server/content-types/user/index.js +0 -1
  163. package/server/controllers/auth.js +40 -59
  164. package/server/controllers/content-manager-user.js +28 -30
  165. package/server/controllers/role.js +17 -4
  166. package/server/controllers/user.js +8 -9
  167. package/server/controllers/validation/auth.js +81 -25
  168. package/server/middlewares/rateLimit.js +1 -1
  169. package/server/register.js +1 -1
  170. package/server/services/jwt.js +3 -3
  171. package/server/services/permission.js +3 -7
  172. package/server/services/providers-registry.js +468 -275
  173. package/server/services/providers.js +10 -5
  174. package/server/services/role.js +15 -13
  175. package/server/services/user.js +56 -19
  176. package/server/services/users-permissions.js +15 -13
  177. package/server/utils/index.d.ts +2 -1
  178. package/server/utils/sanitize/sanitizers.js +7 -3
  179. package/server/utils/sanitize/visitors/remove-user-relation-from-role-entities.js +2 -2
  180. package/admin/src/pages/Roles/pages/ListPage/utils/api.js +0 -30
  181. package/dist/_chunks/ar-MvD8Ghac.mjs.map +0 -1
  182. package/dist/_chunks/ar-t5qTFaAD.js.map +0 -1
  183. package/dist/_chunks/cs-BMuXwxA1.mjs.map +0 -1
  184. package/dist/_chunks/cs-I8N4u-Sd.js.map +0 -1
  185. package/dist/_chunks/de-YTjtq89K.js.map +0 -1
  186. package/dist/_chunks/de-zs2qqc0W.mjs.map +0 -1
  187. package/dist/_chunks/dk-HctVBMsG.mjs.map +0 -1
  188. package/dist/_chunks/dk-TF-dWjzl.js.map +0 -1
  189. package/dist/_chunks/en-CE3wEy_c.mjs.map +0 -1
  190. package/dist/_chunks/en-m608rMZx.js.map +0 -1
  191. package/dist/_chunks/es-9381tih_.mjs.map +0 -1
  192. package/dist/_chunks/es-XBQsB8_9.js.map +0 -1
  193. package/dist/_chunks/fr-6cz3U-IF.js.map +0 -1
  194. package/dist/_chunks/fr-CMSc77If.mjs.map +0 -1
  195. package/dist/_chunks/id-RJ934rq-.js.map +0 -1
  196. package/dist/_chunks/id-SDuyIkZa.mjs.map +0 -1
  197. package/dist/_chunks/index--ch5E4_K.js.map +0 -1
  198. package/dist/_chunks/index-MuQRbm-o.mjs.map +0 -1
  199. package/dist/_chunks/index-UrkRT2rC.js +0 -320
  200. package/dist/_chunks/index-UrkRT2rC.js.map +0 -1
  201. package/dist/_chunks/index-WCv8yGzw.js.map +0 -1
  202. package/dist/_chunks/index-eE2qjbfg.mjs.map +0 -1
  203. package/dist/_chunks/index-iu-7wU8h.mjs.map +0 -1
  204. package/dist/_chunks/index-mCVPA90k.mjs +0 -385
  205. package/dist/_chunks/index-mCVPA90k.mjs.map +0 -1
  206. package/dist/_chunks/index-mNv7pSw-.js +0 -407
  207. package/dist/_chunks/index-mNv7pSw-.js.map +0 -1
  208. package/dist/_chunks/index-rL_BoFHz.js.map +0 -1
  209. package/dist/_chunks/index-xXp5S4OL.mjs +0 -301
  210. package/dist/_chunks/index-xXp5S4OL.mjs.map +0 -1
  211. package/dist/_chunks/it-YhZOlM2X.js.map +0 -1
  212. package/dist/_chunks/it-bvH7DgQo.mjs.map +0 -1
  213. package/dist/_chunks/ja-o_-JPvQv.mjs.map +0 -1
  214. package/dist/_chunks/ja-xssHUXFv.js.map +0 -1
  215. package/dist/_chunks/ko-C3mHUSJa.js.map +0 -1
  216. package/dist/_chunks/ko-XJbPSez_.mjs.map +0 -1
  217. package/dist/_chunks/ms-II5Ea73J.mjs.map +0 -1
  218. package/dist/_chunks/ms-d0hfg65Z.js.map +0 -1
  219. package/dist/_chunks/nl-TA7TfK_5.js.map +0 -1
  220. package/dist/_chunks/nl-vEy6TN0K.mjs.map +0 -1
  221. package/dist/_chunks/pl-0pUL9hdA.js.map +0 -1
  222. package/dist/_chunks/pl-2VowaFGt.mjs.map +0 -1
  223. package/dist/_chunks/pt-BR-WNOhafR4.js.map +0 -1
  224. package/dist/_chunks/pt-BR-sS1Xp3Jt.mjs.map +0 -1
  225. package/dist/_chunks/pt-Rf9W51IO.mjs.map +0 -1
  226. package/dist/_chunks/pt-guNR9Gax.js.map +0 -1
  227. package/dist/_chunks/ru-X3BMXDds.js.map +0 -1
  228. package/dist/_chunks/ru-qKHnd5or.mjs.map +0 -1
  229. package/dist/_chunks/sk-NWPw1oTN.js.map +0 -1
  230. package/dist/_chunks/sk-_Ryr-eTT.mjs.map +0 -1
  231. package/dist/_chunks/sv-76NnbB__.js.map +0 -1
  232. package/dist/_chunks/sv-BqzScFXS.mjs.map +0 -1
  233. package/dist/_chunks/th-WsknMEpq.mjs.map +0 -1
  234. package/dist/_chunks/th-cbppX21D.js.map +0 -1
  235. package/dist/_chunks/tr-6mm_Fmz7.js.map +0 -1
  236. package/dist/_chunks/tr-_DB1F1GW.mjs.map +0 -1
  237. package/dist/_chunks/uk-sI2I1ogF.js.map +0 -1
  238. package/dist/_chunks/uk-yxMSQAwI.mjs.map +0 -1
  239. package/dist/_chunks/vi-A3zJxaiI.js.map +0 -1
  240. package/dist/_chunks/vi-xY0zCW3d.mjs.map +0 -1
  241. package/dist/_chunks/zh-72SpmFXa.js.map +0 -1
  242. package/dist/_chunks/zh-Hans-ArWWtyP4.js.map +0 -1
  243. package/dist/_chunks/zh-Hans-E84cu4kP.mjs.map +0 -1
  244. package/dist/_chunks/zh-OFeldzbX.mjs.map +0 -1
  245. package/server/bootstrap/grant-config.js +0 -140
  246. package/strapi-server.js +0 -3
@@ -2,6 +2,7 @@
2
2
 
3
3
  const { strict: assert } = require('assert');
4
4
  const jwt = require('jsonwebtoken');
5
+ const urljoin = require('url-join');
5
6
  const jwkToPem = require('jwk-to-pem');
6
7
 
7
8
  const getCognitoPayload = async ({ idToken, jwksUrl, purest }) => {
@@ -45,330 +46,522 @@ const getCognitoPayload = async ({ idToken, jwksUrl, purest }) => {
45
46
  }
46
47
  };
47
48
 
48
- const getInitialProviders = ({ purest }) => ({
49
- async discord({ accessToken }) {
50
- const discord = purest({ provider: 'discord' });
51
-
52
- return discord
53
- .get('users/@me')
54
- .auth(accessToken)
55
- .request()
56
- .then(({ body }) => {
57
- // Combine username and discriminator because discord username is not unique
58
- const username = `${body.username}#${body.discriminator}`;
59
- return {
60
- username,
61
- email: body.email,
62
- };
63
- });
49
+ const initProviders = ({ baseURL, purest }) => ({
50
+ email: {
51
+ enabled: true,
52
+ icon: 'envelope',
53
+ grantConfig: {},
64
54
  },
65
- async cognito({ query, providers }) {
66
- const jwksUrl = new URL(providers.cognito.jwksurl);
67
- const idToken = query.id_token;
68
- const tokenPayload = await getCognitoPayload({ idToken, jwksUrl, purest });
69
- return {
70
- username: tokenPayload['cognito:username'],
71
- email: tokenPayload.email,
72
- };
55
+ discord: {
56
+ enabled: false,
57
+ icon: 'discord',
58
+ grantConfig: {
59
+ key: '',
60
+ secret: '',
61
+ callbackUrl: `${baseURL}/discord/callback`,
62
+ scope: ['identify', 'email'],
63
+ },
64
+ async authCallback({ accessToken }) {
65
+ const discord = purest({ provider: 'discord' });
66
+
67
+ return discord
68
+ .get('users/@me')
69
+ .auth(accessToken)
70
+ .request()
71
+ .then(({ body }) => {
72
+ // Combine username and discriminator (if discriminator exists and not equal to 0)
73
+ const username =
74
+ body.discriminator && body.discriminator !== '0'
75
+ ? `${body.username}#${body.discriminator}`
76
+ : body.username;
77
+ return {
78
+ username,
79
+ email: body.email,
80
+ };
81
+ });
82
+ },
73
83
  },
74
- async facebook({ accessToken }) {
75
- const facebook = purest({ provider: 'facebook' });
76
-
77
- return facebook
78
- .get('me')
79
- .auth(accessToken)
80
- .qs({ fields: 'name,email' })
81
- .request()
82
- .then(({ body }) => ({
83
- username: body.name,
84
- email: body.email,
85
- }));
84
+ facebook: {
85
+ enabled: false,
86
+ icon: 'facebook-square',
87
+ grantConfig: {
88
+ key: '',
89
+ secret: '',
90
+ callbackUrl: `${baseURL}/facebook/callback`,
91
+ scope: ['email'],
92
+ },
93
+ async authCallback({ accessToken }) {
94
+ const facebook = purest({ provider: 'facebook' });
95
+
96
+ return facebook
97
+ .get('me')
98
+ .auth(accessToken)
99
+ .qs({ fields: 'name,email' })
100
+ .request()
101
+ .then(({ body }) => ({
102
+ username: body.name,
103
+ email: body.email,
104
+ }));
105
+ },
86
106
  },
87
- async google({ accessToken }) {
88
- const google = purest({ provider: 'google' });
89
-
90
- return google
91
- .query('oauth')
92
- .get('tokeninfo')
93
- .qs({ accessToken })
94
- .request()
95
- .then(({ body }) => ({
96
- username: body.email.split('@')[0],
97
- email: body.email,
98
- }));
107
+ google: {
108
+ enabled: false,
109
+ icon: 'google',
110
+ grantConfig: {
111
+ key: '',
112
+ secret: '',
113
+ callbackUrl: `${baseURL}/google/callback`,
114
+ scope: ['email'],
115
+ },
116
+ async authCallback({ accessToken }) {
117
+ const google = purest({ provider: 'google' });
118
+
119
+ return google
120
+ .query('oauth')
121
+ .get('tokeninfo')
122
+ .qs({ accessToken })
123
+ .request()
124
+ .then(({ body }) => ({
125
+ username: body.email.split('@')[0],
126
+ email: body.email,
127
+ }));
128
+ },
99
129
  },
100
- async github({ accessToken }) {
101
- const github = purest({
102
- provider: 'github',
103
- defaults: {
104
- headers: {
105
- 'user-agent': 'strapi',
130
+ github: {
131
+ enabled: false,
132
+ icon: 'github',
133
+ grantConfig: {
134
+ key: '',
135
+ secret: '',
136
+ callbackUrl: `${baseURL}/github/callback`,
137
+ scope: ['user', 'user:email'],
138
+ },
139
+ async authCallback({ accessToken }) {
140
+ const github = purest({
141
+ provider: 'github',
142
+ defaults: {
143
+ headers: {
144
+ 'user-agent': 'strapi',
145
+ },
106
146
  },
107
- },
108
- });
147
+ });
148
+
149
+ const { body: userBody } = await github.get('user').auth(accessToken).request();
109
150
 
110
- const { body: userBody } = await github.get('user').auth(accessToken).request();
151
+ // This is the public email on the github profile
152
+ if (userBody.email) {
153
+ return {
154
+ username: userBody.login,
155
+ email: userBody.email,
156
+ };
157
+ }
158
+ // Get the email with Github's user/emails API
159
+ const { body: emailBody } = await github.get('user/emails').auth(accessToken).request();
111
160
 
112
- // This is the public email on the github profile
113
- if (userBody.email) {
114
161
  return {
115
162
  username: userBody.login,
116
- email: userBody.email,
163
+ email: Array.isArray(emailBody)
164
+ ? emailBody.find((email) => email.primary === true).email
165
+ : null,
117
166
  };
118
- }
119
- // Get the email with Github's user/emails API
120
- const { body: emailBody } = await github.get('user/emails').auth(accessToken).request();
121
-
122
- return {
123
- username: userBody.login,
124
- email: Array.isArray(emailBody)
125
- ? emailBody.find((email) => email.primary === true).email
126
- : null,
127
- };
167
+ },
128
168
  },
129
- async microsoft({ accessToken }) {
130
- const microsoft = purest({ provider: 'microsoft' });
131
-
132
- return microsoft
133
- .get('me')
134
- .auth(accessToken)
135
- .request()
136
- .then(({ body }) => ({
137
- username: body.userPrincipalName,
138
- email: body.userPrincipalName,
139
- }));
169
+ microsoft: {
170
+ enabled: false,
171
+ icon: 'windows',
172
+ grantConfig: {
173
+ key: '',
174
+ secret: '',
175
+ callbackUrl: `${baseURL}/microsoft/callback`,
176
+ scope: ['user.read'],
177
+ },
178
+ async authCallback({ accessToken }) {
179
+ const microsoft = purest({ provider: 'microsoft' });
180
+
181
+ return microsoft
182
+ .get('me')
183
+ .auth(accessToken)
184
+ .request()
185
+ .then(({ body }) => ({
186
+ username: body.userPrincipalName,
187
+ email: body.userPrincipalName,
188
+ }));
189
+ },
140
190
  },
141
- async twitter({ accessToken, query, providers }) {
142
- const twitter = purest({
143
- provider: 'twitter',
144
- defaults: {
145
- oauth: {
146
- consumer_key: providers.twitter.key,
147
- consumer_secret: providers.twitter.secret,
191
+
192
+ twitter: {
193
+ enabled: false,
194
+ icon: 'twitter',
195
+ grantConfig: {
196
+ key: '',
197
+ secret: '',
198
+ callbackUrl: `${baseURL}/twitter/callback`,
199
+ },
200
+ async authCallback({ accessToken, query, providers }) {
201
+ const twitter = purest({
202
+ provider: 'twitter',
203
+ defaults: {
204
+ oauth: {
205
+ consumer_key: providers.twitter.key,
206
+ consumer_secret: providers.twitter.secret,
207
+ },
148
208
  },
149
- },
150
- });
209
+ });
151
210
 
152
- return twitter
153
- .get('account/verify_credentials')
154
- .auth(accessToken, query.access_secret)
155
- .qs({ screen_name: query['raw[screen_name]'], include_email: 'true' })
156
- .request()
157
- .then(({ body }) => ({
158
- username: body.screen_name,
159
- email: body.email,
160
- }));
211
+ return twitter
212
+ .get('account/verify_credentials')
213
+ .auth(accessToken, query.access_secret)
214
+ .qs({ screen_name: query['raw[screen_name]'], include_email: 'true' })
215
+ .request()
216
+ .then(({ body }) => ({
217
+ username: body.screen_name,
218
+ email: body.email,
219
+ }));
220
+ },
161
221
  },
162
- async instagram({ accessToken }) {
163
- const instagram = purest({ provider: 'instagram' });
164
-
165
- return instagram
166
- .get('me')
167
- .auth(accessToken)
168
- .qs({ fields: 'id,username' })
169
- .request()
170
- .then(({ body }) => ({
171
- username: body.username,
172
- email: `${body.username}@strapi.io`, // dummy email as Instagram does not provide user email
173
- }));
222
+ instagram: {
223
+ enabled: false,
224
+ icon: 'instagram',
225
+ grantConfig: {
226
+ key: '',
227
+ secret: '',
228
+ callbackUrl: `${baseURL}/instagram/callback`,
229
+ scope: ['user_profile'],
230
+ },
231
+ async authCallback({ accessToken }) {
232
+ const instagram = purest({ provider: 'instagram' });
233
+
234
+ return instagram
235
+ .get('me')
236
+ .auth(accessToken)
237
+ .qs({ fields: 'id,username' })
238
+ .request()
239
+ .then(({ body }) => ({
240
+ username: body.username,
241
+ email: `${body.username}@strapi.io`, // dummy email as Instagram does not provide user email
242
+ }));
243
+ },
174
244
  },
175
- async vk({ accessToken, query }) {
176
- const vk = purest({ provider: 'vk' });
177
-
178
- return vk
179
- .get('users')
180
- .auth(accessToken)
181
- .qs({ id: query.raw.user_id, v: '5.122' })
182
- .request()
183
- .then(({ body }) => ({
184
- username: `${body.response[0].last_name} ${body.response[0].first_name}`,
185
- email: query.raw.email,
186
- }));
245
+ vk: {
246
+ enabled: false,
247
+ icon: 'vk',
248
+ grantConfig: {
249
+ key: '',
250
+ secret: '',
251
+ callbackUrl: `${baseURL}/vk/callback`,
252
+ scope: ['email'],
253
+ },
254
+ async authCallback({ accessToken, query }) {
255
+ const vk = purest({ provider: 'vk' });
256
+
257
+ return vk
258
+ .get('users')
259
+ .auth(accessToken)
260
+ .qs({ id: query.raw.user_id, v: '5.122' })
261
+ .request()
262
+ .then(({ body }) => ({
263
+ username: `${body.response[0].last_name} ${body.response[0].first_name}`,
264
+ email: query.raw.email,
265
+ }));
266
+ },
187
267
  },
188
- async twitch({ accessToken, providers }) {
189
- const twitch = purest({
190
- provider: 'twitch',
191
- config: {
192
- twitch: {
193
- default: {
194
- origin: 'https://api.twitch.tv',
195
- path: 'helix/{path}',
196
- headers: {
197
- Authorization: 'Bearer {auth}',
198
- 'Client-Id': '{auth}',
268
+
269
+ twitch: {
270
+ enabled: false,
271
+ icon: 'twitch',
272
+ grantConfig: {
273
+ key: '',
274
+ secret: '',
275
+ callbackUrl: `${baseURL}/twitch/callback`,
276
+ scope: ['user:read:email'],
277
+ },
278
+ async authCallback({ accessToken, providers }) {
279
+ const twitch = purest({
280
+ provider: 'twitch',
281
+ config: {
282
+ twitch: {
283
+ default: {
284
+ origin: 'https://api.twitch.tv',
285
+ path: 'helix/{path}',
286
+ headers: {
287
+ Authorization: 'Bearer {auth}',
288
+ 'Client-Id': '{auth}',
289
+ },
199
290
  },
200
291
  },
201
292
  },
202
- },
203
- });
293
+ });
204
294
 
205
- return twitch
206
- .get('users')
207
- .auth(accessToken, providers.twitch.key)
208
- .request()
209
- .then(({ body }) => ({
210
- username: body.data[0].login,
211
- email: body.data[0].email,
212
- }));
295
+ return twitch
296
+ .get('users')
297
+ .auth(accessToken, providers.twitch.key)
298
+ .request()
299
+ .then(({ body }) => ({
300
+ username: body.data[0].login,
301
+ email: body.data[0].email,
302
+ }));
303
+ },
213
304
  },
214
- async linkedin({ accessToken }) {
215
- const linkedIn = purest({ provider: 'linkedin' });
216
- const {
217
- body: { localizedFirstName },
218
- } = await linkedIn.get('me').auth(accessToken).request();
219
- const {
220
- body: { elements },
221
- } = await linkedIn
222
- .get('emailAddress?q=members&projection=(elements*(handle~))')
223
- .auth(accessToken)
224
- .request();
225
-
226
- const email = elements[0]['handle~'];
227
-
228
- return {
229
- username: localizedFirstName,
230
- email: email.emailAddress,
231
- };
305
+
306
+ linkedin: {
307
+ enabled: false,
308
+ icon: 'linkedin',
309
+ grantConfig: {
310
+ key: '',
311
+ secret: '',
312
+ callbackUrl: `${baseURL}/linkedin/callback`,
313
+ scope: ['r_liteprofile', 'r_emailaddress'],
314
+ },
315
+ async authCallback({ accessToken }) {
316
+ const linkedIn = purest({ provider: 'linkedin' });
317
+ const {
318
+ body: { localizedFirstName },
319
+ } = await linkedIn.get('me').auth(accessToken).request();
320
+ const {
321
+ body: { elements },
322
+ } = await linkedIn
323
+ .get('emailAddress?q=members&projection=(elements*(handle~))')
324
+ .auth(accessToken)
325
+ .request();
326
+
327
+ const email = elements[0]['handle~'];
328
+
329
+ return {
330
+ username: localizedFirstName,
331
+ email: email.emailAddress,
332
+ };
333
+ },
334
+ },
335
+
336
+ cognito: {
337
+ enabled: false,
338
+ icon: 'aws',
339
+ grantConfig: {
340
+ key: '',
341
+ secret: '',
342
+ subdomain: 'my.subdomain.com',
343
+ callback: `${baseURL}/cognito/callback`,
344
+ scope: ['email', 'openid', 'profile'],
345
+ },
346
+ async authCallback({ query, providers }) {
347
+ const jwksUrl = new URL(providers.cognito.jwksurl);
348
+ const idToken = query.id_token;
349
+ const tokenPayload = await getCognitoPayload({ idToken, jwksUrl, purest });
350
+ return {
351
+ username: tokenPayload['cognito:username'],
352
+ email: tokenPayload.email,
353
+ };
354
+ },
232
355
  },
233
- async reddit({ accessToken }) {
234
- const reddit = purest({
235
- provider: 'reddit',
236
- config: {
237
- reddit: {
238
- default: {
239
- origin: 'https://oauth.reddit.com',
240
- path: 'api/{version}/{path}',
241
- version: 'v1',
242
- headers: {
243
- Authorization: 'Bearer {auth}',
244
- 'user-agent': 'strapi',
356
+
357
+ reddit: {
358
+ enabled: false,
359
+ icon: 'reddit',
360
+ grantConfig: {
361
+ key: '',
362
+ secret: '',
363
+ callback: `${baseURL}/reddit/callback`,
364
+ scope: ['identity'],
365
+ },
366
+ async authCallback({ accessToken }) {
367
+ const reddit = purest({
368
+ provider: 'reddit',
369
+ config: {
370
+ reddit: {
371
+ default: {
372
+ origin: 'https://oauth.reddit.com',
373
+ path: 'api/{version}/{path}',
374
+ version: 'v1',
375
+ headers: {
376
+ Authorization: 'Bearer {auth}',
377
+ 'user-agent': 'strapi',
378
+ },
245
379
  },
246
380
  },
247
381
  },
248
- },
249
- });
382
+ });
250
383
 
251
- return reddit
252
- .get('me')
253
- .auth(accessToken)
254
- .request()
255
- .then(({ body }) => ({
256
- username: body.name,
257
- email: `${body.name}@strapi.io`, // dummy email as Reddit does not provide user email
258
- }));
384
+ return reddit
385
+ .get('me')
386
+ .auth(accessToken)
387
+ .request()
388
+ .then(({ body }) => ({
389
+ username: body.name,
390
+ email: `${body.name}@strapi.io`, // dummy email as Reddit does not provide user email
391
+ }));
392
+ },
259
393
  },
260
- async auth0({ accessToken, providers }) {
261
- const auth0 = purest({ provider: 'auth0' });
262
-
263
- return auth0
264
- .get('userinfo')
265
- .subdomain(providers.auth0.subdomain)
266
- .auth(accessToken)
267
- .request()
268
- .then(({ body }) => {
269
- const username = body.username || body.nickname || body.name || body.email.split('@')[0];
270
- const email = body.email || `${username.replace(/\s+/g, '.')}@strapi.io`;
271
394
 
272
- return {
273
- username,
274
- email,
275
- };
276
- });
395
+ auth0: {
396
+ enabled: false,
397
+ icon: '',
398
+ grantConfig: {
399
+ key: '',
400
+ secret: '',
401
+ subdomain: 'my-tenant.eu',
402
+ callback: `${baseURL}/auth0/callback`,
403
+ scope: ['openid', 'email', 'profile'],
404
+ },
405
+ async authCallback({ accessToken, providers }) {
406
+ const auth0 = purest({ provider: 'auth0' });
407
+
408
+ return auth0
409
+ .get('userinfo')
410
+ .subdomain(providers.auth0.subdomain)
411
+ .auth(accessToken)
412
+ .request()
413
+ .then(({ body }) => {
414
+ const username = body.username || body.nickname || body.name || body.email.split('@')[0];
415
+ const email = body.email || `${username.replace(/\s+/g, '.')}@strapi.io`;
416
+
417
+ return {
418
+ username,
419
+ email,
420
+ };
421
+ });
422
+ },
277
423
  },
278
- async cas({ accessToken, providers }) {
279
- const cas = purest({ provider: 'cas' });
280
-
281
- return cas
282
- .get('oidc/profile')
283
- .subdomain(providers.cas.subdomain)
284
- .auth(accessToken)
285
- .request()
286
- .then(({ body }) => {
287
- // CAS attribute may be in body.attributes or "FLAT", depending on CAS config
288
- const username = body.attributes
289
- ? body.attributes.strapiusername || body.id || body.sub
290
- : body.strapiusername || body.id || body.sub;
291
- const email = body.attributes
292
- ? body.attributes.strapiemail || body.attributes.email
293
- : body.strapiemail || body.email;
294
- if (!username || !email) {
295
- strapi.log.warn(
296
- `CAS Response Body did not contain required attributes: ${JSON.stringify(body)}`
297
- );
298
- }
299
- return {
300
- username,
301
- email,
302
- };
303
- });
424
+
425
+ cas: {
426
+ enabled: false,
427
+ icon: 'book',
428
+ grantConfig: {
429
+ key: '',
430
+ secret: '',
431
+ callback: `${baseURL}/cas/callback`,
432
+ scope: ['openid email'], // scopes should be space delimited
433
+ subdomain: 'my.subdomain.com/cas',
434
+ },
435
+ async authCallback({ accessToken, providers }) {
436
+ const cas = purest({ provider: 'cas' });
437
+
438
+ return cas
439
+ .get('oidc/profile')
440
+ .subdomain(providers.cas.subdomain)
441
+ .auth(accessToken)
442
+ .request()
443
+ .then(({ body }) => {
444
+ // CAS attribute may be in body.attributes or "FLAT", depending on CAS config
445
+ const username = body.attributes
446
+ ? body.attributes.strapiusername || body.id || body.sub
447
+ : body.strapiusername || body.id || body.sub;
448
+ const email = body.attributes
449
+ ? body.attributes.strapiemail || body.attributes.email
450
+ : body.strapiemail || body.email;
451
+ if (!username || !email) {
452
+ strapi.log.warn(
453
+ `CAS Response Body did not contain required attributes: ${JSON.stringify(body)}`
454
+ );
455
+ }
456
+ return {
457
+ username,
458
+ email,
459
+ };
460
+ });
461
+ },
304
462
  },
305
- async patreon({ accessToken }) {
306
- const patreon = purest({
307
- provider: 'patreon',
308
- config: {
309
- patreon: {
310
- default: {
311
- origin: 'https://www.patreon.com',
312
- path: 'api/oauth2/{path}',
313
- headers: {
314
- authorization: 'Bearer {auth}',
463
+
464
+ patreon: {
465
+ enabled: false,
466
+ icon: '',
467
+ grantConfig: {
468
+ key: '',
469
+ secret: '',
470
+ callback: `${baseURL}/patreon/callback`,
471
+ scope: ['identity', 'identity[email]'],
472
+ },
473
+ async authCallback({ accessToken }) {
474
+ const patreon = purest({
475
+ provider: 'patreon',
476
+ config: {
477
+ patreon: {
478
+ default: {
479
+ origin: 'https://www.patreon.com',
480
+ path: 'api/oauth2/{path}',
481
+ headers: {
482
+ authorization: 'Bearer {auth}',
483
+ },
315
484
  },
316
485
  },
317
486
  },
318
- },
319
- });
320
-
321
- return patreon
322
- .get('v2/identity')
323
- .auth(accessToken)
324
- .qs(new URLSearchParams({ 'fields[user]': 'full_name,email' }).toString())
325
- .request()
326
- .then(({ body }) => {
327
- const patreonData = body.data.attributes;
328
- return {
329
- username: patreonData.full_name,
330
- email: patreonData.email,
331
- };
332
487
  });
488
+
489
+ return patreon
490
+ .get('v2/identity')
491
+ .auth(accessToken)
492
+ .qs(new URLSearchParams({ 'fields[user]': 'full_name,email' }).toString())
493
+ .request()
494
+ .then(({ body }) => {
495
+ const patreonData = body.data.attributes;
496
+ return {
497
+ username: patreonData.full_name,
498
+ email: patreonData.email,
499
+ };
500
+ });
501
+ },
333
502
  },
334
- async keycloak({ accessToken, providers }) {
335
- const keycloak = purest({ provider: 'keycloak' });
336
-
337
- return keycloak
338
- .subdomain(providers.keycloak.subdomain)
339
- .get('protocol/openid-connect/userinfo')
340
- .auth(accessToken)
341
- .request()
342
- .then(({ body }) => {
343
- return {
344
- username: body.preferred_username,
345
- email: body.email,
346
- };
347
- });
503
+ keycloak: {
504
+ enabled: false,
505
+ icon: '',
506
+ grantConfig: {
507
+ key: '',
508
+ secret: '',
509
+ subdomain: 'myKeycloakProvider.com/realms/myrealm',
510
+ callback: `${baseURL}/keycloak/callback`,
511
+ scope: ['openid', 'email', 'profile'],
512
+ },
513
+ async authCallback({ accessToken, providers }) {
514
+ const keycloak = purest({ provider: 'keycloak' });
515
+
516
+ return keycloak
517
+ .subdomain(providers.keycloak.subdomain)
518
+ .get('protocol/openid-connect/userinfo')
519
+ .auth(accessToken)
520
+ .request()
521
+ .then(({ body }) => {
522
+ return {
523
+ username: body.preferred_username,
524
+ email: body.email,
525
+ };
526
+ });
527
+ },
348
528
  },
349
529
  });
350
530
 
351
531
  module.exports = () => {
352
532
  const purest = require('purest');
353
533
 
354
- const providersCallbacks = getInitialProviders({ purest });
534
+ const apiPrefix = strapi.config.get('api.rest.prefix');
535
+ const baseURL = urljoin(strapi.config.server.url, apiPrefix, 'auth');
355
536
 
356
- return {
357
- register(providerName, provider) {
358
- assert(typeof providerName === 'string', 'Provider name must be a string');
359
- assert(typeof provider === 'function', 'Provider callback must be a function');
537
+ const authProviders = initProviders({ baseURL, purest });
360
538
 
361
- providersCallbacks[providerName] = provider({ purest });
539
+ /**
540
+ * @public
541
+ */
542
+ return {
543
+ getAll() {
544
+ return authProviders;
545
+ },
546
+ get(name) {
547
+ return authProviders[name];
548
+ },
549
+ add(name, config) {
550
+ authProviders[name] = config;
551
+ },
552
+ remove(name) {
553
+ delete authProviders[name];
362
554
  },
363
555
 
556
+ /**
557
+ * @internal
558
+ */
364
559
  async run({ provider, accessToken, query, providers }) {
365
- if (!providersCallbacks[provider]) {
366
- throw new Error('Unknown provider.');
367
- }
560
+ const authProvider = authProviders[provider];
368
561
 
369
- const providerCb = providersCallbacks[provider];
562
+ assert(authProvider, 'Unknown auth provider');
370
563
 
371
- return providerCb({ accessToken, query, providers });
564
+ return authProvider.authCallback({ accessToken, query, providers, purest });
372
565
  },
373
566
  };
374
567
  };