@strapi/plugin-users-permissions 5.52.2 → 5.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/server/controllers/auth.js +8 -2
  2. package/dist/server/controllers/auth.js.map +1 -1
  3. package/dist/server/controllers/auth.mjs +8 -2
  4. package/dist/server/controllers/auth.mjs.map +1 -1
  5. package/dist/server/graphql/mutations/auth/change-password.js +6 -3
  6. package/dist/server/graphql/mutations/auth/change-password.js.map +1 -1
  7. package/dist/server/graphql/mutations/auth/change-password.mjs +6 -3
  8. package/dist/server/graphql/mutations/auth/change-password.mjs.map +1 -1
  9. package/dist/server/graphql/mutations/auth/forgot-password.js +6 -3
  10. package/dist/server/graphql/mutations/auth/forgot-password.js.map +1 -1
  11. package/dist/server/graphql/mutations/auth/forgot-password.mjs +6 -3
  12. package/dist/server/graphql/mutations/auth/forgot-password.mjs.map +1 -1
  13. package/dist/server/graphql/mutations/auth/login.js +9 -6
  14. package/dist/server/graphql/mutations/auth/login.js.map +1 -1
  15. package/dist/server/graphql/mutations/auth/login.mjs +9 -6
  16. package/dist/server/graphql/mutations/auth/login.mjs.map +1 -1
  17. package/dist/server/graphql/mutations/auth/rate-limit.js +63 -0
  18. package/dist/server/graphql/mutations/auth/rate-limit.js.map +1 -0
  19. package/dist/server/graphql/mutations/auth/rate-limit.mjs +61 -0
  20. package/dist/server/graphql/mutations/auth/rate-limit.mjs.map +1 -0
  21. package/dist/server/graphql/mutations/auth/register.js +6 -3
  22. package/dist/server/graphql/mutations/auth/register.js.map +1 -1
  23. package/dist/server/graphql/mutations/auth/register.mjs +6 -3
  24. package/dist/server/graphql/mutations/auth/register.mjs.map +1 -1
  25. package/dist/server/graphql/mutations/auth/reset-password.js +6 -3
  26. package/dist/server/graphql/mutations/auth/reset-password.js.map +1 -1
  27. package/dist/server/graphql/mutations/auth/reset-password.mjs +6 -3
  28. package/dist/server/graphql/mutations/auth/reset-password.mjs.map +1 -1
  29. package/dist/server/middlewares/rateLimit.js +1 -1
  30. package/dist/server/middlewares/rateLimit.js.map +1 -1
  31. package/dist/server/middlewares/rateLimit.mjs +1 -1
  32. package/dist/server/middlewares/rateLimit.mjs.map +1 -1
  33. package/dist/server/services/providers-registry.js +80 -19
  34. package/dist/server/services/providers-registry.js.map +1 -1
  35. package/dist/server/services/providers-registry.mjs +80 -19
  36. package/dist/server/services/providers-registry.mjs.map +1 -1
  37. package/dist/server/services/providers.js +12 -8
  38. package/dist/server/services/providers.js.map +1 -1
  39. package/dist/server/services/providers.mjs +12 -8
  40. package/dist/server/services/providers.mjs.map +1 -1
  41. package/dist/server/services/user.js +7 -7
  42. package/dist/server/services/user.js.map +1 -1
  43. package/dist/server/services/user.mjs +7 -7
  44. package/dist/server/services/user.mjs.map +1 -1
  45. package/dist/server/utils/oauth-connect/index.js +11 -6
  46. package/dist/server/utils/oauth-connect/index.js.map +1 -1
  47. package/dist/server/utils/oauth-connect/index.mjs +11 -6
  48. package/dist/server/utils/oauth-connect/index.mjs.map +1 -1
  49. package/dist/server/utils/trim-grant-session-response.js +67 -0
  50. package/dist/server/utils/trim-grant-session-response.js.map +1 -0
  51. package/dist/server/utils/trim-grant-session-response.mjs +65 -0
  52. package/dist/server/utils/trim-grant-session-response.mjs.map +1 -0
  53. package/package.json +4 -4
  54. package/server/src/controllers/auth.js +13 -2
  55. package/server/src/graphql/mutations/auth/change-password.js +5 -5
  56. package/server/src/graphql/mutations/auth/forgot-password.js +5 -5
  57. package/server/src/graphql/mutations/auth/login.js +10 -6
  58. package/server/src/graphql/mutations/auth/rate-limit.js +62 -0
  59. package/server/src/graphql/mutations/auth/register.js +5 -5
  60. package/server/src/graphql/mutations/auth/reset-password.js +5 -5
  61. package/server/src/middlewares/rateLimit.js +1 -1
  62. package/server/src/services/providers-registry.js +99 -23
  63. package/server/src/services/providers.js +9 -7
  64. package/server/src/services/user.js +15 -5
  65. package/server/src/utils/oauth-connect/index.js +12 -6
  66. package/server/src/utils/trim-grant-session-response.js +70 -0
@@ -1,5 +1,6 @@
1
1
  import require$$0 from 'lodash/fp';
2
2
  import { __require as requireUtils } from '../../utils.mjs';
3
+ import { __require as requireRateLimit } from './rate-limit.mjs';
3
4
 
4
5
  var resetPassword;
5
6
  var hasRequiredResetPassword;
@@ -8,8 +9,10 @@ function requireResetPassword() {
8
9
  hasRequiredResetPassword = 1;
9
10
  const { toPlainObject } = require$$0;
10
11
  const { checkBadRequest } = requireUtils();
12
+ const { createRateLimitRunner } = requireRateLimit();
11
13
  resetPassword = ({ nexus, strapi })=>{
12
14
  const { nonNull } = nexus;
15
+ const runRateLimit = createRateLimitRunner(strapi, '/auth/reset-password');
13
16
  return {
14
17
  type: 'UsersPermissionsLoginPayload',
15
18
  args: {
@@ -20,9 +23,9 @@ function requireResetPassword() {
20
23
  description: 'Reset user password. Confirm with a code (resetToken from forgotPassword)',
21
24
  async resolve (parent, args, context) {
22
25
  const { koaContext } = context;
23
- koaContext.request.body = toPlainObject(args);
24
- await strapi.plugin('users-permissions').controller('auth').resetPassword(koaContext);
25
- const output = koaContext.body;
26
+ const output = await runRateLimit(koaContext, {
27
+ body: toPlainObject(args)
28
+ }, (ctx)=>strapi.plugin('users-permissions').controller('auth').resetPassword(ctx));
26
29
  checkBadRequest(output);
27
30
  return {
28
31
  user: output.user || output,
@@ -1 +1 @@
1
- {"version":3,"file":"reset-password.mjs","sources":["../../../../../server/src/graphql/mutations/auth/reset-password.js"],"sourcesContent":["'use strict';\n\nconst { toPlainObject } = require('lodash/fp');\n\nconst { checkBadRequest } = require('../../utils');\n\nmodule.exports = ({ nexus, strapi }) => {\n const { nonNull } = nexus;\n\n return {\n type: 'UsersPermissionsLoginPayload',\n\n args: {\n password: nonNull('String'),\n passwordConfirmation: nonNull('String'),\n code: nonNull('String'),\n },\n\n description: 'Reset user password. Confirm with a code (resetToken from forgotPassword)',\n\n async resolve(parent, args, context) {\n const { koaContext } = context;\n\n koaContext.request.body = toPlainObject(args);\n\n await strapi.plugin('users-permissions').controller('auth').resetPassword(koaContext);\n\n const output = koaContext.body;\n\n checkBadRequest(output);\n\n return {\n user: output.user || output,\n jwt: output.jwt,\n };\n },\n };\n};\n"],"names":["toPlainObject","require$$0","checkBadRequest","require$$1","resetPassword","nexus","strapi","nonNull","type","args","password","passwordConfirmation","code","description","resolve","parent","context","koaContext","request","body","plugin","controller","output","user","jwt"],"mappings":";;;;;;;;IAEA,MAAM,EAAEA,aAAa,EAAE,GAAGC,UAAAA;IAE1B,MAAM,EAAEC,eAAe,EAAE,GAAGC,YAAAA,EAAAA;AAE5BC,IAAAA,aAAAA,GAAiB,CAAC,EAAEC,KAAK,EAAEC,MAAM,EAAE,GAAA;QACjC,MAAM,EAAEC,OAAO,EAAE,GAAGF,KAAAA;QAEpB,OAAO;YACLG,IAAAA,EAAM,8BAAA;YAENC,IAAAA,EAAM;AACJC,gBAAAA,QAAAA,EAAUH,OAAAA,CAAQ,QAAA,CAAA;AAClBI,gBAAAA,oBAAAA,EAAsBJ,OAAAA,CAAQ,QAAA,CAAA;AAC9BK,gBAAAA,IAAAA,EAAML,OAAAA,CAAQ,QAAA;AACpB,aAAA;YAEIM,WAAAA,EAAa,2EAAA;AAEb,YAAA,MAAMC,OAAAA,CAAAA,CAAQC,MAAM,EAAEN,IAAI,EAAEO,OAAO,EAAA;gBACjC,MAAM,EAAEC,UAAU,EAAE,GAAGD,OAAAA;AAEvBC,gBAAAA,UAAAA,CAAWC,OAAO,CAACC,IAAI,GAAGnB,aAAAA,CAAcS,IAAAA,CAAAA;gBAExC,MAAMH,MAAAA,CAAOc,MAAM,CAAC,mBAAA,CAAA,CAAqBC,UAAU,CAAC,MAAA,CAAA,CAAQjB,aAAa,CAACa,UAAAA,CAAAA;gBAE1E,MAAMK,MAAAA,GAASL,WAAWE,IAAI;gBAE9BjB,eAAAA,CAAgBoB,MAAAA,CAAAA;gBAEhB,OAAO;oBACLC,IAAAA,EAAMD,MAAAA,CAAOC,IAAI,IAAID,MAAAA;AACrBE,oBAAAA,GAAAA,EAAKF,OAAOE;AACpB,iBAAA;AACA,YAAA;AACA,SAAA;AACA,IAAA,CAAA;;;;;;"}
1
+ {"version":3,"file":"reset-password.mjs","sources":["../../../../../server/src/graphql/mutations/auth/reset-password.js"],"sourcesContent":["'use strict';\n\nconst { toPlainObject } = require('lodash/fp');\n\nconst { checkBadRequest } = require('../../utils');\nconst { createRateLimitRunner } = require('./rate-limit');\n\nmodule.exports = ({ nexus, strapi }) => {\n const { nonNull } = nexus;\n const runRateLimit = createRateLimitRunner(strapi, '/auth/reset-password');\n\n return {\n type: 'UsersPermissionsLoginPayload',\n\n args: {\n password: nonNull('String'),\n passwordConfirmation: nonNull('String'),\n code: nonNull('String'),\n },\n\n description: 'Reset user password. Confirm with a code (resetToken from forgotPassword)',\n\n async resolve(parent, args, context) {\n const { koaContext } = context;\n\n const output = await runRateLimit(koaContext, { body: toPlainObject(args) }, (ctx) =>\n strapi.plugin('users-permissions').controller('auth').resetPassword(ctx)\n );\n\n checkBadRequest(output);\n\n return {\n user: output.user || output,\n jwt: output.jwt,\n };\n },\n };\n};\n"],"names":["toPlainObject","require$$0","checkBadRequest","require$$1","createRateLimitRunner","require$$2","resetPassword","nexus","strapi","nonNull","runRateLimit","type","args","password","passwordConfirmation","code","description","resolve","parent","context","koaContext","output","body","ctx","plugin","controller","user","jwt"],"mappings":";;;;;;;;;IAEA,MAAM,EAAEA,aAAa,EAAE,GAAGC,UAAAA;IAE1B,MAAM,EAAEC,eAAe,EAAE,GAAGC,YAAAA,EAAAA;IAC5B,MAAM,EAAEC,qBAAqB,EAAE,GAAGC,gBAAAA,EAAAA;AAElCC,IAAAA,aAAAA,GAAiB,CAAC,EAAEC,KAAK,EAAEC,MAAM,EAAE,GAAA;QACjC,MAAM,EAAEC,OAAO,EAAE,GAAGF,KAAAA;QACpB,MAAMG,YAAAA,GAAeN,sBAAsBI,MAAAA,EAAQ,sBAAA,CAAA;QAEnD,OAAO;YACLG,IAAAA,EAAM,8BAAA;YAENC,IAAAA,EAAM;AACJC,gBAAAA,QAAAA,EAAUJ,OAAAA,CAAQ,QAAA,CAAA;AAClBK,gBAAAA,oBAAAA,EAAsBL,OAAAA,CAAQ,QAAA,CAAA;AAC9BM,gBAAAA,IAAAA,EAAMN,OAAAA,CAAQ,QAAA;AACpB,aAAA;YAEIO,WAAAA,EAAa,2EAAA;AAEb,YAAA,MAAMC,OAAAA,CAAAA,CAAQC,MAAM,EAAEN,IAAI,EAAEO,OAAO,EAAA;gBACjC,MAAM,EAAEC,UAAU,EAAE,GAAGD,OAAAA;gBAEvB,MAAME,MAAAA,GAAS,MAAMX,YAAAA,CAAaU,UAAAA,EAAY;AAAEE,oBAAAA,IAAAA,EAAMtB,aAAAA,CAAcY,IAAAA;iBAAK,EAAI,CAACW,GAAAA,GAC5Ef,MAAAA,CAAOgB,MAAM,CAAC,qBAAqBC,UAAU,CAAC,MAAA,CAAA,CAAQnB,aAAa,CAACiB,GAAAA,CAAAA,CAAAA;gBAGtErB,eAAAA,CAAgBmB,MAAAA,CAAAA;gBAEhB,OAAO;oBACLK,IAAAA,EAAML,MAAAA,CAAOK,IAAI,IAAIL,MAAAA;AACrBM,oBAAAA,GAAAA,EAAKN,OAAOM;AACpB,iBAAA;AACA,YAAA;AACA,SAAA;AACA,IAAA,CAAA;;;;;;"}
@@ -59,7 +59,7 @@ function requireRateLimit() {
59
59
  * lower-cased, trailing slashes removed so `/api/auth/local` and
60
60
  * `/api/auth/local/` share one bucket.
61
61
  */ const normalizeRequestPathForRateLimit = (requestPath)=>{
62
- const normalized = path.normalize(requestPath);
62
+ const normalized = path.posix.normalize(requestPath);
63
63
  const lower = toLower(normalized);
64
64
  return lower.replace(/\/+$/, '') || '/';
65
65
  };
@@ -1 +1 @@
1
- {"version":3,"file":"rateLimit.js","sources":["../../../server/src/middlewares/rateLimit.js"],"sourcesContent":["'use strict';\n\nconst path = require('path');\nconst utils = require('@strapi/utils');\nconst { isString, has, toLower } = require('lodash/fp');\n\nconst { RateLimitError } = utils.errors;\n\n/**\n * Routes where the rate-limit key MUST NOT include a user identifier\n * derived from `ctx.request.body.email`.\n *\n * On these routes the request body either has no `email` field\n * (e.g. /auth/local uses `identifier`, /auth/reset-password uses\n * `code`, /auth/change-password uses `currentPassword`) or the\n * field is not part of the route contract. Including the\n * attacker-controlled `body.email` in the rate-limit key on these\n * routes lets a caller obtain a fresh key on every request by\n * varying that field, effectively bypassing per-IP throttling.\n *\n * Comparison uses endsWith so the check is stable under any router\n * mount prefix (e.g. `/api/auth/local`).\n *\n * @see https://github.com/strapi/strapi/security/advisories/GHSA-7mqx-wwh4-f9fw\n *\n * When adding a new `rateLimit`-protected auth route whose body does not\n * use `email` as the real identifier, add its path suffix here (or an\n * equivalent `routeUsesEmailIdentifier` rule) so the key cannot be split\n * with arbitrary `body.email` values.\n */\nconst ROUTES_WITHOUT_IDENTIFIER = ['/auth/local', '/auth/reset-password', '/auth/change-password'];\n\nconst isOAuthCallbackPath = (requestPath) => requestPath.includes('/connect/');\n\nconst routeUsesEmailIdentifier = (requestPath) => {\n if (isOAuthCallbackPath(requestPath)) {\n return false;\n }\n\n return !ROUTES_WITHOUT_IDENTIFIER.some((route) => requestPath.endsWith(route));\n};\n\n/**\n * Paths suitable for route matching and prefix keys: POSIX-normalized,\n * lower-cased, trailing slashes removed so `/api/auth/local` and\n * `/api/auth/local/` share one bucket.\n */\nconst normalizeRequestPathForRateLimit = (requestPath) => {\n const normalized = path.normalize(requestPath);\n const lower = toLower(normalized);\n return lower.replace(/\\/+$/, '') || '/';\n};\n\nconst getEmailIdentifierForKey = (body) => {\n if (!body || !isString(body.email) || body.email === '') {\n return 'unknownIdentifier';\n }\n\n return toLower(body.email);\n};\n\nconst buildPrefixKey = (ctx) => {\n let requestPath;\n if (!isString(ctx.request.path)) {\n requestPath = 'invalidPath';\n } else {\n requestPath = normalizeRequestPathForRateLimit(ctx.request.path);\n if (requestPath === '.' || requestPath === '..') {\n requestPath = 'invalidPath';\n }\n }\n\n if (!routeUsesEmailIdentifier(requestPath)) {\n return `noIdentifier:${requestPath}:${ctx.request.ip}`;\n }\n\n const userIdentifier = getEmailIdentifierForKey(ctx.request.body);\n return `${userIdentifier}:${requestPath}:${ctx.request.ip}`;\n};\n\nconst buildRateLimitLoadConfig = (ctx, rateLimitConfig, routeMiddlewareConfig) => {\n return {\n interval: { min: 5 },\n max: 5,\n ...rateLimitConfig,\n ...routeMiddlewareConfig,\n handler() {\n throw new RateLimitError();\n },\n prefixKey: buildPrefixKey(ctx),\n };\n};\n\nmodule.exports =\n (config, { strapi }) =>\n async (ctx, next) => {\n let rateLimitConfig = strapi.config.get('plugin::users-permissions.ratelimit');\n\n if (!rateLimitConfig) {\n rateLimitConfig = {\n enabled: true,\n };\n }\n\n if (!has('enabled', rateLimitConfig)) {\n rateLimitConfig.enabled = true;\n }\n\n if (rateLimitConfig.enabled === true) {\n const rateLimit = require('koa2-ratelimit').RateLimit;\n\n const loadConfig = buildRateLimitLoadConfig(ctx, rateLimitConfig, config);\n\n return rateLimit.middleware(loadConfig)(ctx, next);\n }\n\n return next();\n };\n\nmodule.exports.buildPrefixKey = buildPrefixKey;\nmodule.exports.ROUTES_WITHOUT_IDENTIFIER = ROUTES_WITHOUT_IDENTIFIER;\nmodule.exports.normalizeRequestPathForRateLimit = normalizeRequestPathForRateLimit;\nmodule.exports.buildRateLimitLoadConfig = buildRateLimitLoadConfig;\n"],"names":["path","require$$0","utils","require$$1","isString","has","toLower","require$$2","RateLimitError","errors","ROUTES_WITHOUT_IDENTIFIER","isOAuthCallbackPath","requestPath","includes","routeUsesEmailIdentifier","some","route","endsWith","normalizeRequestPathForRateLimit","normalized","normalize","lower","replace","getEmailIdentifierForKey","body","email","buildPrefixKey","ctx","request","ip","userIdentifier","buildRateLimitLoadConfig","rateLimitConfig","routeMiddlewareConfig","interval","min","max","handler","prefixKey","rateLimitModule","exports","config","strapi","next","get","enabled","rateLimit","require$$3","RateLimit","loadConfig","middleware"],"mappings":"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"}
1
+ {"version":3,"file":"rateLimit.js","sources":["../../../server/src/middlewares/rateLimit.js"],"sourcesContent":["'use strict';\n\nconst path = require('path');\nconst utils = require('@strapi/utils');\nconst { isString, has, toLower } = require('lodash/fp');\n\nconst { RateLimitError } = utils.errors;\n\n/**\n * Routes where the rate-limit key MUST NOT include a user identifier\n * derived from `ctx.request.body.email`.\n *\n * On these routes the request body either has no `email` field\n * (e.g. /auth/local uses `identifier`, /auth/reset-password uses\n * `code`, /auth/change-password uses `currentPassword`) or the\n * field is not part of the route contract. Including the\n * attacker-controlled `body.email` in the rate-limit key on these\n * routes lets a caller obtain a fresh key on every request by\n * varying that field, effectively bypassing per-IP throttling.\n *\n * Comparison uses endsWith so the check is stable under any router\n * mount prefix (e.g. `/api/auth/local`).\n *\n * @see https://github.com/strapi/strapi/security/advisories/GHSA-7mqx-wwh4-f9fw\n *\n * When adding a new `rateLimit`-protected auth route whose body does not\n * use `email` as the real identifier, add its path suffix here (or an\n * equivalent `routeUsesEmailIdentifier` rule) so the key cannot be split\n * with arbitrary `body.email` values.\n */\nconst ROUTES_WITHOUT_IDENTIFIER = ['/auth/local', '/auth/reset-password', '/auth/change-password'];\n\nconst isOAuthCallbackPath = (requestPath) => requestPath.includes('/connect/');\n\nconst routeUsesEmailIdentifier = (requestPath) => {\n if (isOAuthCallbackPath(requestPath)) {\n return false;\n }\n\n return !ROUTES_WITHOUT_IDENTIFIER.some((route) => requestPath.endsWith(route));\n};\n\n/**\n * Paths suitable for route matching and prefix keys: POSIX-normalized,\n * lower-cased, trailing slashes removed so `/api/auth/local` and\n * `/api/auth/local/` share one bucket.\n */\nconst normalizeRequestPathForRateLimit = (requestPath) => {\n const normalized = path.posix.normalize(requestPath);\n const lower = toLower(normalized);\n return lower.replace(/\\/+$/, '') || '/';\n};\n\nconst getEmailIdentifierForKey = (body) => {\n if (!body || !isString(body.email) || body.email === '') {\n return 'unknownIdentifier';\n }\n\n return toLower(body.email);\n};\n\nconst buildPrefixKey = (ctx) => {\n let requestPath;\n if (!isString(ctx.request.path)) {\n requestPath = 'invalidPath';\n } else {\n requestPath = normalizeRequestPathForRateLimit(ctx.request.path);\n if (requestPath === '.' || requestPath === '..') {\n requestPath = 'invalidPath';\n }\n }\n\n if (!routeUsesEmailIdentifier(requestPath)) {\n return `noIdentifier:${requestPath}:${ctx.request.ip}`;\n }\n\n const userIdentifier = getEmailIdentifierForKey(ctx.request.body);\n return `${userIdentifier}:${requestPath}:${ctx.request.ip}`;\n};\n\nconst buildRateLimitLoadConfig = (ctx, rateLimitConfig, routeMiddlewareConfig) => {\n return {\n interval: { min: 5 },\n max: 5,\n ...rateLimitConfig,\n ...routeMiddlewareConfig,\n handler() {\n throw new RateLimitError();\n },\n prefixKey: buildPrefixKey(ctx),\n };\n};\n\nmodule.exports =\n (config, { strapi }) =>\n async (ctx, next) => {\n let rateLimitConfig = strapi.config.get('plugin::users-permissions.ratelimit');\n\n if (!rateLimitConfig) {\n rateLimitConfig = {\n enabled: true,\n };\n }\n\n if (!has('enabled', rateLimitConfig)) {\n rateLimitConfig.enabled = true;\n }\n\n if (rateLimitConfig.enabled === true) {\n const rateLimit = require('koa2-ratelimit').RateLimit;\n\n const loadConfig = buildRateLimitLoadConfig(ctx, rateLimitConfig, config);\n\n return rateLimit.middleware(loadConfig)(ctx, next);\n }\n\n return next();\n };\n\nmodule.exports.buildPrefixKey = buildPrefixKey;\nmodule.exports.ROUTES_WITHOUT_IDENTIFIER = ROUTES_WITHOUT_IDENTIFIER;\nmodule.exports.normalizeRequestPathForRateLimit = normalizeRequestPathForRateLimit;\nmodule.exports.buildRateLimitLoadConfig = buildRateLimitLoadConfig;\n"],"names":["path","require$$0","utils","require$$1","isString","has","toLower","require$$2","RateLimitError","errors","ROUTES_WITHOUT_IDENTIFIER","isOAuthCallbackPath","requestPath","includes","routeUsesEmailIdentifier","some","route","endsWith","normalizeRequestPathForRateLimit","normalized","posix","normalize","lower","replace","getEmailIdentifierForKey","body","email","buildPrefixKey","ctx","request","ip","userIdentifier","buildRateLimitLoadConfig","rateLimitConfig","routeMiddlewareConfig","interval","min","max","handler","prefixKey","rateLimitModule","exports","config","strapi","next","get","enabled","rateLimit","require$$3","RateLimit","loadConfig","middleware"],"mappings":"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"}
@@ -50,7 +50,7 @@ function requireRateLimit() {
50
50
  * lower-cased, trailing slashes removed so `/api/auth/local` and
51
51
  * `/api/auth/local/` share one bucket.
52
52
  */ const normalizeRequestPathForRateLimit = (requestPath)=>{
53
- const normalized = path.normalize(requestPath);
53
+ const normalized = path.posix.normalize(requestPath);
54
54
  const lower = toLower(normalized);
55
55
  return lower.replace(/\/+$/, '') || '/';
56
56
  };
@@ -1 +1 @@
1
- {"version":3,"file":"rateLimit.mjs","sources":["../../../server/src/middlewares/rateLimit.js"],"sourcesContent":["'use strict';\n\nconst path = require('path');\nconst utils = require('@strapi/utils');\nconst { isString, has, toLower } = require('lodash/fp');\n\nconst { RateLimitError } = utils.errors;\n\n/**\n * Routes where the rate-limit key MUST NOT include a user identifier\n * derived from `ctx.request.body.email`.\n *\n * On these routes the request body either has no `email` field\n * (e.g. /auth/local uses `identifier`, /auth/reset-password uses\n * `code`, /auth/change-password uses `currentPassword`) or the\n * field is not part of the route contract. Including the\n * attacker-controlled `body.email` in the rate-limit key on these\n * routes lets a caller obtain a fresh key on every request by\n * varying that field, effectively bypassing per-IP throttling.\n *\n * Comparison uses endsWith so the check is stable under any router\n * mount prefix (e.g. `/api/auth/local`).\n *\n * @see https://github.com/strapi/strapi/security/advisories/GHSA-7mqx-wwh4-f9fw\n *\n * When adding a new `rateLimit`-protected auth route whose body does not\n * use `email` as the real identifier, add its path suffix here (or an\n * equivalent `routeUsesEmailIdentifier` rule) so the key cannot be split\n * with arbitrary `body.email` values.\n */\nconst ROUTES_WITHOUT_IDENTIFIER = ['/auth/local', '/auth/reset-password', '/auth/change-password'];\n\nconst isOAuthCallbackPath = (requestPath) => requestPath.includes('/connect/');\n\nconst routeUsesEmailIdentifier = (requestPath) => {\n if (isOAuthCallbackPath(requestPath)) {\n return false;\n }\n\n return !ROUTES_WITHOUT_IDENTIFIER.some((route) => requestPath.endsWith(route));\n};\n\n/**\n * Paths suitable for route matching and prefix keys: POSIX-normalized,\n * lower-cased, trailing slashes removed so `/api/auth/local` and\n * `/api/auth/local/` share one bucket.\n */\nconst normalizeRequestPathForRateLimit = (requestPath) => {\n const normalized = path.normalize(requestPath);\n const lower = toLower(normalized);\n return lower.replace(/\\/+$/, '') || '/';\n};\n\nconst getEmailIdentifierForKey = (body) => {\n if (!body || !isString(body.email) || body.email === '') {\n return 'unknownIdentifier';\n }\n\n return toLower(body.email);\n};\n\nconst buildPrefixKey = (ctx) => {\n let requestPath;\n if (!isString(ctx.request.path)) {\n requestPath = 'invalidPath';\n } else {\n requestPath = normalizeRequestPathForRateLimit(ctx.request.path);\n if (requestPath === '.' || requestPath === '..') {\n requestPath = 'invalidPath';\n }\n }\n\n if (!routeUsesEmailIdentifier(requestPath)) {\n return `noIdentifier:${requestPath}:${ctx.request.ip}`;\n }\n\n const userIdentifier = getEmailIdentifierForKey(ctx.request.body);\n return `${userIdentifier}:${requestPath}:${ctx.request.ip}`;\n};\n\nconst buildRateLimitLoadConfig = (ctx, rateLimitConfig, routeMiddlewareConfig) => {\n return {\n interval: { min: 5 },\n max: 5,\n ...rateLimitConfig,\n ...routeMiddlewareConfig,\n handler() {\n throw new RateLimitError();\n },\n prefixKey: buildPrefixKey(ctx),\n };\n};\n\nmodule.exports =\n (config, { strapi }) =>\n async (ctx, next) => {\n let rateLimitConfig = strapi.config.get('plugin::users-permissions.ratelimit');\n\n if (!rateLimitConfig) {\n rateLimitConfig = {\n enabled: true,\n };\n }\n\n if (!has('enabled', rateLimitConfig)) {\n rateLimitConfig.enabled = true;\n }\n\n if (rateLimitConfig.enabled === true) {\n const rateLimit = require('koa2-ratelimit').RateLimit;\n\n const loadConfig = buildRateLimitLoadConfig(ctx, rateLimitConfig, config);\n\n return rateLimit.middleware(loadConfig)(ctx, next);\n }\n\n return next();\n };\n\nmodule.exports.buildPrefixKey = buildPrefixKey;\nmodule.exports.ROUTES_WITHOUT_IDENTIFIER = ROUTES_WITHOUT_IDENTIFIER;\nmodule.exports.normalizeRequestPathForRateLimit = normalizeRequestPathForRateLimit;\nmodule.exports.buildRateLimitLoadConfig = buildRateLimitLoadConfig;\n"],"names":["path","require$$0","utils","require$$1","isString","has","toLower","require$$2","RateLimitError","errors","ROUTES_WITHOUT_IDENTIFIER","isOAuthCallbackPath","requestPath","includes","routeUsesEmailIdentifier","some","route","endsWith","normalizeRequestPathForRateLimit","normalized","normalize","lower","replace","getEmailIdentifierForKey","body","email","buildPrefixKey","ctx","request","ip","userIdentifier","buildRateLimitLoadConfig","rateLimitConfig","routeMiddlewareConfig","interval","min","max","handler","prefixKey","rateLimitModule","exports","config","strapi","next","get","enabled","rateLimit","require$$3","RateLimit","loadConfig","middleware"],"mappings":"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"}
1
+ {"version":3,"file":"rateLimit.mjs","sources":["../../../server/src/middlewares/rateLimit.js"],"sourcesContent":["'use strict';\n\nconst path = require('path');\nconst utils = require('@strapi/utils');\nconst { isString, has, toLower } = require('lodash/fp');\n\nconst { RateLimitError } = utils.errors;\n\n/**\n * Routes where the rate-limit key MUST NOT include a user identifier\n * derived from `ctx.request.body.email`.\n *\n * On these routes the request body either has no `email` field\n * (e.g. /auth/local uses `identifier`, /auth/reset-password uses\n * `code`, /auth/change-password uses `currentPassword`) or the\n * field is not part of the route contract. Including the\n * attacker-controlled `body.email` in the rate-limit key on these\n * routes lets a caller obtain a fresh key on every request by\n * varying that field, effectively bypassing per-IP throttling.\n *\n * Comparison uses endsWith so the check is stable under any router\n * mount prefix (e.g. `/api/auth/local`).\n *\n * @see https://github.com/strapi/strapi/security/advisories/GHSA-7mqx-wwh4-f9fw\n *\n * When adding a new `rateLimit`-protected auth route whose body does not\n * use `email` as the real identifier, add its path suffix here (or an\n * equivalent `routeUsesEmailIdentifier` rule) so the key cannot be split\n * with arbitrary `body.email` values.\n */\nconst ROUTES_WITHOUT_IDENTIFIER = ['/auth/local', '/auth/reset-password', '/auth/change-password'];\n\nconst isOAuthCallbackPath = (requestPath) => requestPath.includes('/connect/');\n\nconst routeUsesEmailIdentifier = (requestPath) => {\n if (isOAuthCallbackPath(requestPath)) {\n return false;\n }\n\n return !ROUTES_WITHOUT_IDENTIFIER.some((route) => requestPath.endsWith(route));\n};\n\n/**\n * Paths suitable for route matching and prefix keys: POSIX-normalized,\n * lower-cased, trailing slashes removed so `/api/auth/local` and\n * `/api/auth/local/` share one bucket.\n */\nconst normalizeRequestPathForRateLimit = (requestPath) => {\n const normalized = path.posix.normalize(requestPath);\n const lower = toLower(normalized);\n return lower.replace(/\\/+$/, '') || '/';\n};\n\nconst getEmailIdentifierForKey = (body) => {\n if (!body || !isString(body.email) || body.email === '') {\n return 'unknownIdentifier';\n }\n\n return toLower(body.email);\n};\n\nconst buildPrefixKey = (ctx) => {\n let requestPath;\n if (!isString(ctx.request.path)) {\n requestPath = 'invalidPath';\n } else {\n requestPath = normalizeRequestPathForRateLimit(ctx.request.path);\n if (requestPath === '.' || requestPath === '..') {\n requestPath = 'invalidPath';\n }\n }\n\n if (!routeUsesEmailIdentifier(requestPath)) {\n return `noIdentifier:${requestPath}:${ctx.request.ip}`;\n }\n\n const userIdentifier = getEmailIdentifierForKey(ctx.request.body);\n return `${userIdentifier}:${requestPath}:${ctx.request.ip}`;\n};\n\nconst buildRateLimitLoadConfig = (ctx, rateLimitConfig, routeMiddlewareConfig) => {\n return {\n interval: { min: 5 },\n max: 5,\n ...rateLimitConfig,\n ...routeMiddlewareConfig,\n handler() {\n throw new RateLimitError();\n },\n prefixKey: buildPrefixKey(ctx),\n };\n};\n\nmodule.exports =\n (config, { strapi }) =>\n async (ctx, next) => {\n let rateLimitConfig = strapi.config.get('plugin::users-permissions.ratelimit');\n\n if (!rateLimitConfig) {\n rateLimitConfig = {\n enabled: true,\n };\n }\n\n if (!has('enabled', rateLimitConfig)) {\n rateLimitConfig.enabled = true;\n }\n\n if (rateLimitConfig.enabled === true) {\n const rateLimit = require('koa2-ratelimit').RateLimit;\n\n const loadConfig = buildRateLimitLoadConfig(ctx, rateLimitConfig, config);\n\n return rateLimit.middleware(loadConfig)(ctx, next);\n }\n\n return next();\n };\n\nmodule.exports.buildPrefixKey = buildPrefixKey;\nmodule.exports.ROUTES_WITHOUT_IDENTIFIER = ROUTES_WITHOUT_IDENTIFIER;\nmodule.exports.normalizeRequestPathForRateLimit = normalizeRequestPathForRateLimit;\nmodule.exports.buildRateLimitLoadConfig = buildRateLimitLoadConfig;\n"],"names":["path","require$$0","utils","require$$1","isString","has","toLower","require$$2","RateLimitError","errors","ROUTES_WITHOUT_IDENTIFIER","isOAuthCallbackPath","requestPath","includes","routeUsesEmailIdentifier","some","route","endsWith","normalizeRequestPathForRateLimit","normalized","posix","normalize","lower","replace","getEmailIdentifierForKey","body","email","buildPrefixKey","ctx","request","ip","userIdentifier","buildRateLimitLoadConfig","rateLimitConfig","routeMiddlewareConfig","interval","min","max","handler","prefixKey","rateLimitModule","exports","config","strapi","next","get","enabled","rateLimit","require$$3","RateLimit","loadConfig","middleware"],"mappings":"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"}
@@ -40,6 +40,9 @@ function requireProvidersRegistry() {
40
40
  },
41
41
  async authCallback ({ accessToken }) {
42
42
  const { body } = await bearerGet('https://discord.com/api/users/@me', accessToken);
43
+ if (body.verified !== true) {
44
+ throw new Error('Email not verified by Discord');
45
+ }
43
46
  const username = body.discriminator && body.discriminator !== '0' ? `${body.username}#${body.discriminator}` : body.username;
44
47
  return {
45
48
  username,
@@ -64,6 +67,9 @@ function requireProvidersRegistry() {
64
67
  fields: 'name,email'
65
68
  }
66
69
  });
70
+ if (!body.email) {
71
+ throw new Error('Email not verified by Facebook');
72
+ }
67
73
  return {
68
74
  username: body.name,
69
75
  email: body.email
@@ -83,6 +89,10 @@ function requireProvidersRegistry() {
83
89
  },
84
90
  async authCallback ({ accessToken }) {
85
91
  const { body } = await fetchJson(`https://oauth2.googleapis.com/tokeninfo?access_token=${encodeURIComponent(accessToken)}`);
92
+ const verified = body.verified_email ?? body.email_verified;
93
+ if (verified !== true && verified !== 'true') {
94
+ throw new Error('Email not verified by Google');
95
+ }
86
96
  return {
87
97
  username: body.email.split('@')[0],
88
98
  email: body.email
@@ -107,20 +117,28 @@ function requireProvidersRegistry() {
107
117
  'user-agent': 'strapi'
108
118
  }
109
119
  });
120
+ const { body: emailBody } = await bearerGet('https://api.github.com/user/emails', accessToken, {
121
+ headers: {
122
+ 'user-agent': 'strapi'
123
+ }
124
+ });
110
125
  if (userBody.email) {
126
+ const verifiedPublicEmail = Array.isArray(emailBody) ? emailBody.find((entry)=>entry.email === userBody.email && entry.verified === true) : null;
127
+ if (!verifiedPublicEmail) {
128
+ throw new Error('Email not verified by GitHub');
129
+ }
111
130
  return {
112
131
  username: userBody.login,
113
132
  email: userBody.email
114
133
  };
115
134
  }
116
- const { body: emailBody } = await bearerGet('https://api.github.com/user/emails', accessToken, {
117
- headers: {
118
- 'user-agent': 'strapi'
119
- }
120
- });
135
+ const primaryEmail = Array.isArray(emailBody) ? emailBody.find((email)=>email.primary === true) : null;
136
+ if (!primaryEmail || primaryEmail.verified !== true) {
137
+ throw new Error('Email not verified by GitHub');
138
+ }
121
139
  return {
122
140
  username: userBody.login,
123
- email: Array.isArray(emailBody) ? emailBody.find((email)=>email.primary === true).email : null
141
+ email: primaryEmail.email
124
142
  };
125
143
  }
126
144
  },
@@ -151,19 +169,27 @@ function requireProvidersRegistry() {
151
169
  secret: '',
152
170
  callbackUrl: `${baseURL}/twitter/callback`
153
171
  },
154
- async authCallback ({ accessToken, query, providers }) {
172
+ async authCallback ({ accessToken, providers, grantResponse }) {
173
+ const accessSecret = grantResponse?.access_secret;
174
+ const screenName = grantResponse?.raw?.screen_name;
175
+ if (!accessSecret) {
176
+ throw new Error('Twitter authentication requires a completed OAuth session');
177
+ }
155
178
  const { twitterGet } = oauth1.__require();
156
179
  const { body } = await twitterGet({
157
180
  url: 'https://api.twitter.com/1.1/account/verify_credentials.json',
158
181
  accessToken,
159
- accessCredential: query.access_secret,
182
+ accessCredential: accessSecret,
160
183
  consumerKey: providers.twitter.key,
161
184
  clientCredential: providers.twitter.secret,
162
185
  qs: {
163
186
  include_email: 'true',
164
- screen_name: query['raw[screen_name]']
187
+ screen_name: screenName
165
188
  }
166
189
  });
190
+ if (!body.email) {
191
+ throw new Error('Email not verified by Twitter');
192
+ }
167
193
  return {
168
194
  username: body.screen_name,
169
195
  email: body.email
@@ -204,16 +230,24 @@ function requireProvidersRegistry() {
204
230
  'email'
205
231
  ]
206
232
  },
207
- async authCallback ({ accessToken, query }) {
233
+ async authCallback ({ accessToken, grantResponse }) {
234
+ const email = grantResponse?.raw?.email;
235
+ const userId = grantResponse?.raw?.user_id;
236
+ if (!email || !userId) {
237
+ throw new Error('VK authentication requires a completed OAuth session');
238
+ }
208
239
  const { body } = await bearerGet('https://api.vk.com/method/users.get', accessToken, {
209
240
  qs: {
210
- user_ids: query.raw.user_id,
241
+ user_ids: userId,
211
242
  v: '5.122'
212
243
  }
213
244
  });
245
+ if (!body.response?.[0]) {
246
+ throw new Error('Invalid VK access token');
247
+ }
214
248
  return {
215
249
  username: `${body.response[0].last_name} ${body.response[0].first_name}`,
216
- email: query.raw.email
250
+ email
217
251
  };
218
252
  }
219
253
  },
@@ -234,9 +268,13 @@ function requireProvidersRegistry() {
234
268
  'Client-Id': providers.twitch.key
235
269
  }
236
270
  });
271
+ const email = body.data?.[0]?.email;
272
+ if (!email) {
273
+ throw new Error('Email not verified by Twitch');
274
+ }
237
275
  return {
238
276
  username: body.data[0].login,
239
- email: body.data[0].email
277
+ email
240
278
  };
241
279
  }
242
280
  },
@@ -255,7 +293,10 @@ function requireProvidersRegistry() {
255
293
  async authCallback ({ accessToken }) {
256
294
  const { body: profileBody } = await bearerGet('https://api.linkedin.com/v2/me', accessToken);
257
295
  const { body: emailBody } = await bearerGet('https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))', accessToken);
258
- const email = emailBody.elements[0]['handle~'];
296
+ const email = emailBody.elements[0]?.['handle~'];
297
+ if (!email?.emailAddress) {
298
+ throw new Error('Email not verified by LinkedIn');
299
+ }
259
300
  return {
260
301
  username: profileBody.localizedFirstName,
261
302
  email: email.emailAddress
@@ -276,13 +317,19 @@ function requireProvidersRegistry() {
276
317
  'profile'
277
318
  ]
278
319
  },
279
- async authCallback ({ query, providers }) {
320
+ async authCallback ({ providers, grantResponse }) {
280
321
  const jwksUrl = new URL(providers.cognito.jwksurl);
281
- const idToken = query.id_token;
322
+ const idToken = grantResponse?.id_token;
323
+ if (!idToken) {
324
+ throw new Error('Cognito authentication requires a completed OAuth session');
325
+ }
282
326
  const tokenPayload = await verifyJwtWithJwks$1({
283
327
  idToken,
284
328
  jwksUrl
285
329
  });
330
+ if (tokenPayload.email_verified !== true) {
331
+ throw new Error('Email not verified by Cognito');
332
+ }
286
333
  return {
287
334
  username: tokenPayload['cognito:username'],
288
335
  email: tokenPayload.email
@@ -328,6 +375,9 @@ function requireProvidersRegistry() {
328
375
  },
329
376
  async authCallback ({ accessToken, providers }) {
330
377
  const { body } = await bearerGet(`https://${providers.auth0.subdomain}.auth0.com/userinfo`, accessToken);
378
+ if (body.email && body.email_verified !== true) {
379
+ throw new Error('Email not verified by Auth0');
380
+ }
331
381
  const username = body.username || body.nickname || body.name || body.email.split('@')[0];
332
382
  const email = body.email || `${username.replace(/\s+/g, '.')}@strapi.io`;
333
383
  return {
@@ -352,9 +402,13 @@ function requireProvidersRegistry() {
352
402
  const { body } = await bearerGet(`https://${providers.cas.subdomain}/oidc/profile`, accessToken);
353
403
  const username = body.attributes ? body.attributes.strapiusername || body.id || body.sub : body.strapiusername || body.id || body.sub;
354
404
  const email = body.attributes ? body.attributes.strapiemail || body.attributes.email : body.strapiemail || body.email;
405
+ const emailVerified = body.email_verified ?? body.attributes?.email_verified;
355
406
  if (!username || !email) {
356
407
  strapi.log.warn(`CAS Response Body did not contain required attributes: ${JSON.stringify(body)}`);
357
408
  }
409
+ if (email && emailVerified !== true) {
410
+ throw new Error('Email not verified by CAS');
411
+ }
358
412
  return {
359
413
  username,
360
414
  email
@@ -374,8 +428,11 @@ function requireProvidersRegistry() {
374
428
  ]
375
429
  },
376
430
  async authCallback ({ accessToken }) {
377
- const { body } = await bearerGet('https://www.patreon.com/api/oauth2/v2/identity?fields[user]=full_name,email', accessToken);
431
+ const { body } = await bearerGet('https://www.patreon.com/api/oauth2/v2/identity?fields[user]=full_name,email,is_email_verified', accessToken);
378
432
  const patreonData = body.data.attributes;
433
+ if (patreonData.is_email_verified !== true) {
434
+ throw new Error('Email not verified by Patreon');
435
+ }
379
436
  return {
380
437
  username: patreonData.full_name,
381
438
  email: patreonData.email
@@ -398,6 +455,9 @@ function requireProvidersRegistry() {
398
455
  },
399
456
  async authCallback ({ accessToken, providers }) {
400
457
  const { body } = await bearerGet(`https://${providers.keycloak.subdomain}/protocol/openid-connect/userinfo`, accessToken);
458
+ if (body.email_verified !== true) {
459
+ throw new Error('Email not verified by Keycloak');
460
+ }
401
461
  return {
402
462
  username: body.preferred_username,
403
463
  email: body.email
@@ -424,13 +484,14 @@ function requireProvidersRegistry() {
424
484
  remove (name) {
425
485
  delete authProviders[name];
426
486
  },
427
- async run ({ provider, accessToken, query, providers }) {
487
+ async run ({ provider, accessToken, query, providers, grantResponse }) {
428
488
  const authProvider = authProviders[provider];
429
489
  assert(authProvider, 'Unknown auth provider');
430
490
  return authProvider.authCallback({
431
491
  accessToken,
432
492
  query,
433
- providers
493
+ providers,
494
+ grantResponse
434
495
  });
435
496
  }
436
497
  };
@@ -1 +1 @@
1
- {"version":3,"file":"providers-registry.js","sources":["../../../server/src/services/providers-registry.js"],"sourcesContent":["'use strict';\n\nconst { strict: assert } = require('assert');\nconst urljoin = require('url-join');\n\nconst { verifyJwtWithJwks } = require('../utils/verify-jwt-with-jwks');\nconst { bearerGet, fetchJson } = require('../utils/provider-http');\n\nconst initProviders = ({ baseURL }) => ({\n email: {\n enabled: true,\n icon: 'envelope',\n grantConfig: {},\n },\n discord: {\n enabled: false,\n icon: 'discord',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/discord/callback`,\n scope: ['identify', 'email'],\n },\n async authCallback({ accessToken }) {\n const { body } = await bearerGet('https://discord.com/api/users/@me', accessToken);\n const username =\n body.discriminator && body.discriminator !== '0'\n ? `${body.username}#${body.discriminator}`\n : body.username;\n return {\n username,\n email: body.email,\n };\n },\n },\n facebook: {\n enabled: false,\n icon: 'facebook-square',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/facebook/callback`,\n scope: ['email'],\n },\n async authCallback({ accessToken }) {\n const { body } = await bearerGet('https://graph.facebook.com/me', accessToken, {\n qs: { fields: 'name,email' },\n });\n return {\n username: body.name,\n email: body.email,\n };\n },\n },\n google: {\n enabled: false,\n icon: 'google',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/google/callback`,\n scope: ['email'],\n },\n async authCallback({ accessToken }) {\n const { body } = await fetchJson(\n `https://oauth2.googleapis.com/tokeninfo?access_token=${encodeURIComponent(accessToken)}`\n );\n return {\n username: body.email.split('@')[0],\n email: body.email,\n };\n },\n },\n github: {\n enabled: false,\n icon: 'github',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/github/callback`,\n scope: ['user', 'user:email'],\n },\n async authCallback({ accessToken }) {\n const { body: userBody } = await bearerGet('https://api.github.com/user', accessToken, {\n headers: { 'user-agent': 'strapi' },\n });\n\n if (userBody.email) {\n return {\n username: userBody.login,\n email: userBody.email,\n };\n }\n\n const { body: emailBody } = await bearerGet(\n 'https://api.github.com/user/emails',\n accessToken,\n {\n headers: { 'user-agent': 'strapi' },\n }\n );\n\n return {\n username: userBody.login,\n email: Array.isArray(emailBody)\n ? emailBody.find((email) => email.primary === true).email\n : null,\n };\n },\n },\n microsoft: {\n enabled: false,\n icon: 'windows',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/microsoft/callback`,\n scope: ['user.read'],\n },\n async authCallback({ accessToken }) {\n const { body } = await bearerGet('https://graph.microsoft.com/v1.0/me', accessToken);\n return {\n username: body.userPrincipalName,\n email: body.userPrincipalName,\n };\n },\n },\n\n twitter: {\n enabled: false,\n icon: 'twitter',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/twitter/callback`,\n },\n async authCallback({ accessToken, query, providers }) {\n const { twitterGet } = require('../utils/oauth-connect/oauth1');\n const { body } = await twitterGet({\n url: 'https://api.twitter.com/1.1/account/verify_credentials.json',\n accessToken,\n accessCredential: query.access_secret,\n consumerKey: providers.twitter.key,\n clientCredential: providers.twitter.secret,\n qs: { include_email: 'true', screen_name: query['raw[screen_name]'] },\n });\n\n return {\n username: body.screen_name,\n email: body.email,\n };\n },\n },\n instagram: {\n enabled: false,\n icon: 'instagram',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/instagram/callback`,\n scope: ['user_profile'],\n },\n async authCallback({ accessToken }) {\n const { body } = await bearerGet('https://graph.instagram.com/me', accessToken, {\n qs: { fields: 'id,username' },\n });\n return {\n username: body.username,\n email: `${body.username}@strapi.io`,\n };\n },\n },\n vk: {\n enabled: false,\n icon: 'vk',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/vk/callback`,\n scope: ['email'],\n },\n async authCallback({ accessToken, query }) {\n const { body } = await bearerGet('https://api.vk.com/method/users.get', accessToken, {\n qs: { user_ids: query.raw.user_id, v: '5.122' },\n });\n return {\n username: `${body.response[0].last_name} ${body.response[0].first_name}`,\n email: query.raw.email,\n };\n },\n },\n\n twitch: {\n enabled: false,\n icon: 'twitch',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/twitch/callback`,\n scope: ['user:read:email'],\n },\n async authCallback({ accessToken, providers }) {\n const { body } = await bearerGet('https://api.twitch.tv/helix/users', accessToken, {\n headers: {\n 'Client-Id': providers.twitch.key,\n },\n });\n return {\n username: body.data[0].login,\n email: body.data[0].email,\n };\n },\n },\n\n linkedin: {\n enabled: false,\n icon: 'linkedin',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/linkedin/callback`,\n scope: ['r_liteprofile', 'r_emailaddress'],\n },\n async authCallback({ accessToken }) {\n const { body: profileBody } = await bearerGet('https://api.linkedin.com/v2/me', accessToken);\n const { body: emailBody } = await bearerGet(\n 'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))',\n accessToken\n );\n\n const email = emailBody.elements[0]['handle~'];\n\n return {\n username: profileBody.localizedFirstName,\n email: email.emailAddress,\n };\n },\n },\n\n cognito: {\n enabled: false,\n icon: 'aws',\n grantConfig: {\n key: '',\n secret: '',\n subdomain: 'my.subdomain.com',\n callback: `${baseURL}/cognito/callback`,\n scope: ['email', 'openid', 'profile'],\n },\n async authCallback({ query, providers }) {\n const jwksUrl = new URL(providers.cognito.jwksurl);\n const idToken = query.id_token;\n const tokenPayload = await verifyJwtWithJwks({ idToken, jwksUrl });\n return {\n username: tokenPayload['cognito:username'],\n email: tokenPayload.email,\n };\n },\n },\n\n reddit: {\n enabled: false,\n icon: 'reddit',\n grantConfig: {\n key: '',\n secret: '',\n callback: `${baseURL}/reddit/callback`,\n scope: ['identity'],\n },\n async authCallback({ accessToken }) {\n const { body } = await bearerGet('https://oauth.reddit.com/api/v1/me', accessToken, {\n headers: { 'user-agent': 'strapi' },\n });\n return {\n username: body.name,\n email: `${body.name}@strapi.io`,\n };\n },\n },\n\n auth0: {\n enabled: false,\n icon: '',\n grantConfig: {\n key: '',\n secret: '',\n subdomain: 'my-tenant.eu',\n callback: `${baseURL}/auth0/callback`,\n scope: ['openid', 'email', 'profile'],\n },\n async authCallback({ accessToken, providers }) {\n const { body } = await bearerGet(\n `https://${providers.auth0.subdomain}.auth0.com/userinfo`,\n accessToken\n );\n const username = body.username || body.nickname || body.name || body.email.split('@')[0];\n const email = body.email || `${username.replace(/\\s+/g, '.')}@strapi.io`;\n\n return {\n username,\n email,\n };\n },\n },\n\n cas: {\n enabled: false,\n icon: 'book',\n grantConfig: {\n key: '',\n secret: '',\n callback: `${baseURL}/cas/callback`,\n scope: ['openid email'],\n subdomain: 'my.subdomain.com/cas',\n },\n async authCallback({ accessToken, providers }) {\n const { body } = await bearerGet(\n `https://${providers.cas.subdomain}/oidc/profile`,\n accessToken\n );\n const username = body.attributes\n ? body.attributes.strapiusername || body.id || body.sub\n : body.strapiusername || body.id || body.sub;\n const email = body.attributes\n ? body.attributes.strapiemail || body.attributes.email\n : body.strapiemail || body.email;\n if (!username || !email) {\n strapi.log.warn(\n `CAS Response Body did not contain required attributes: ${JSON.stringify(body)}`\n );\n }\n return {\n username,\n email,\n };\n },\n },\n\n patreon: {\n enabled: false,\n icon: '',\n grantConfig: {\n key: '',\n secret: '',\n callback: `${baseURL}/patreon/callback`,\n scope: ['identity', 'identity[email]'],\n },\n async authCallback({ accessToken }) {\n const { body } = await bearerGet(\n 'https://www.patreon.com/api/oauth2/v2/identity?fields[user]=full_name,email',\n accessToken\n );\n const patreonData = body.data.attributes;\n return {\n username: patreonData.full_name,\n email: patreonData.email,\n };\n },\n },\n keycloak: {\n enabled: false,\n icon: '',\n grantConfig: {\n key: '',\n secret: '',\n subdomain: 'myKeycloakProvider.com/realms/myrealm',\n callback: `${baseURL}/keycloak/callback`,\n scope: ['openid', 'email', 'profile'],\n },\n async authCallback({ accessToken, providers }) {\n const { body } = await bearerGet(\n `https://${providers.keycloak.subdomain}/protocol/openid-connect/userinfo`,\n accessToken\n );\n return {\n username: body.preferred_username,\n email: body.email,\n };\n },\n },\n});\n\nmodule.exports = () => {\n const apiPrefix = strapi.config.get('api.rest.prefix');\n const baseURL = urljoin(strapi.config.server.url, apiPrefix, 'auth');\n\n const authProviders = initProviders({ baseURL });\n\n return {\n getAll() {\n return authProviders;\n },\n get(name) {\n return authProviders[name];\n },\n add(name, config) {\n authProviders[name] = config;\n },\n remove(name) {\n delete authProviders[name];\n },\n\n async run({ provider, accessToken, query, providers }) {\n const authProvider = authProviders[provider];\n\n assert(authProvider, 'Unknown auth provider');\n\n return authProvider.authCallback({ accessToken, query, providers });\n },\n };\n};\n"],"names":["strict","assert","require$$0","urljoin","require$$1","verifyJwtWithJwks","require$$2","bearerGet","fetchJson","require$$3","initProviders","baseURL","email","enabled","icon","grantConfig","discord","key","secret","callbackUrl","scope","authCallback","accessToken","body","username","discriminator","facebook","qs","fields","name","google","encodeURIComponent","split","github","userBody","headers","login","emailBody","Array","isArray","find","primary","microsoft","userPrincipalName","twitter","query","providers","twitterGet","require$$4","url","accessCredential","access_secret","consumerKey","clientCredential","include_email","screen_name","instagram","vk","user_ids","raw","user_id","v","response","last_name","first_name","twitch","data","linkedin","profileBody","elements","localizedFirstName","emailAddress","cognito","subdomain","callback","jwksUrl","URL","jwksurl","idToken","id_token","tokenPayload","reddit","auth0","nickname","replace","cas","attributes","strapiusername","id","sub","strapiemail","strapi","log","warn","JSON","stringify","patreon","patreonData","full_name","keycloak","preferred_username","providersRegistry","apiPrefix","config","get","server","authProviders","getAll","add","remove","run","provider","authProvider"],"mappings":"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"}
1
+ {"version":3,"file":"providers-registry.js","sources":["../../../server/src/services/providers-registry.js"],"sourcesContent":["'use strict';\n\nconst { strict: assert } = require('assert');\nconst urljoin = require('url-join');\n\nconst { verifyJwtWithJwks } = require('../utils/verify-jwt-with-jwks');\nconst { bearerGet, fetchJson } = require('../utils/provider-http');\n\nconst initProviders = ({ baseURL }) => ({\n email: {\n enabled: true,\n icon: 'envelope',\n grantConfig: {},\n },\n discord: {\n enabled: false,\n icon: 'discord',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/discord/callback`,\n scope: ['identify', 'email'],\n },\n async authCallback({ accessToken }) {\n const { body } = await bearerGet('https://discord.com/api/users/@me', accessToken);\n if (body.verified !== true) {\n throw new Error('Email not verified by Discord');\n }\n const username =\n body.discriminator && body.discriminator !== '0'\n ? `${body.username}#${body.discriminator}`\n : body.username;\n return {\n username,\n email: body.email,\n };\n },\n },\n facebook: {\n enabled: false,\n icon: 'facebook-square',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/facebook/callback`,\n scope: ['email'],\n },\n async authCallback({ accessToken }) {\n const { body } = await bearerGet('https://graph.facebook.com/me', accessToken, {\n qs: { fields: 'name,email' },\n });\n if (!body.email) {\n throw new Error('Email not verified by Facebook');\n }\n return {\n username: body.name,\n email: body.email,\n };\n },\n },\n google: {\n enabled: false,\n icon: 'google',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/google/callback`,\n scope: ['email'],\n },\n async authCallback({ accessToken }) {\n const { body } = await fetchJson(\n `https://oauth2.googleapis.com/tokeninfo?access_token=${encodeURIComponent(accessToken)}`\n );\n const verified = body.verified_email ?? body.email_verified;\n if (verified !== true && verified !== 'true') {\n throw new Error('Email not verified by Google');\n }\n return {\n username: body.email.split('@')[0],\n email: body.email,\n };\n },\n },\n github: {\n enabled: false,\n icon: 'github',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/github/callback`,\n scope: ['user', 'user:email'],\n },\n async authCallback({ accessToken }) {\n const { body: userBody } = await bearerGet('https://api.github.com/user', accessToken, {\n headers: { 'user-agent': 'strapi' },\n });\n\n const { body: emailBody } = await bearerGet(\n 'https://api.github.com/user/emails',\n accessToken,\n {\n headers: { 'user-agent': 'strapi' },\n }\n );\n\n if (userBody.email) {\n const verifiedPublicEmail = Array.isArray(emailBody)\n ? emailBody.find((entry) => entry.email === userBody.email && entry.verified === true)\n : null;\n\n if (!verifiedPublicEmail) {\n throw new Error('Email not verified by GitHub');\n }\n\n return {\n username: userBody.login,\n email: userBody.email,\n };\n }\n\n const primaryEmail = Array.isArray(emailBody)\n ? emailBody.find((email) => email.primary === true)\n : null;\n\n if (!primaryEmail || primaryEmail.verified !== true) {\n throw new Error('Email not verified by GitHub');\n }\n\n return {\n username: userBody.login,\n email: primaryEmail.email,\n };\n },\n },\n microsoft: {\n enabled: false,\n icon: 'windows',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/microsoft/callback`,\n scope: ['user.read'],\n },\n async authCallback({ accessToken }) {\n const { body } = await bearerGet('https://graph.microsoft.com/v1.0/me', accessToken);\n return {\n username: body.userPrincipalName,\n email: body.userPrincipalName,\n };\n },\n },\n\n twitter: {\n enabled: false,\n icon: 'twitter',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/twitter/callback`,\n },\n async authCallback({ accessToken, providers, grantResponse }) {\n const accessSecret = grantResponse?.access_secret;\n const screenName = grantResponse?.raw?.screen_name;\n\n if (!accessSecret) {\n throw new Error('Twitter authentication requires a completed OAuth session');\n }\n\n const { twitterGet } = require('../utils/oauth-connect/oauth1');\n const { body } = await twitterGet({\n url: 'https://api.twitter.com/1.1/account/verify_credentials.json',\n accessToken,\n accessCredential: accessSecret,\n consumerKey: providers.twitter.key,\n clientCredential: providers.twitter.secret,\n qs: { include_email: 'true', screen_name: screenName },\n });\n\n if (!body.email) {\n throw new Error('Email not verified by Twitter');\n }\n\n return {\n username: body.screen_name,\n email: body.email,\n };\n },\n },\n instagram: {\n enabled: false,\n icon: 'instagram',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/instagram/callback`,\n scope: ['user_profile'],\n },\n async authCallback({ accessToken }) {\n const { body } = await bearerGet('https://graph.instagram.com/me', accessToken, {\n qs: { fields: 'id,username' },\n });\n return {\n username: body.username,\n email: `${body.username}@strapi.io`,\n };\n },\n },\n vk: {\n enabled: false,\n icon: 'vk',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/vk/callback`,\n scope: ['email'],\n },\n async authCallback({ accessToken, grantResponse }) {\n const email = grantResponse?.raw?.email;\n const userId = grantResponse?.raw?.user_id;\n\n if (!email || !userId) {\n throw new Error('VK authentication requires a completed OAuth session');\n }\n\n const { body } = await bearerGet('https://api.vk.com/method/users.get', accessToken, {\n qs: { user_ids: userId, v: '5.122' },\n });\n\n if (!body.response?.[0]) {\n throw new Error('Invalid VK access token');\n }\n\n return {\n username: `${body.response[0].last_name} ${body.response[0].first_name}`,\n email,\n };\n },\n },\n\n twitch: {\n enabled: false,\n icon: 'twitch',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/twitch/callback`,\n scope: ['user:read:email'],\n },\n async authCallback({ accessToken, providers }) {\n const { body } = await bearerGet('https://api.twitch.tv/helix/users', accessToken, {\n headers: {\n 'Client-Id': providers.twitch.key,\n },\n });\n const email = body.data?.[0]?.email;\n if (!email) {\n throw new Error('Email not verified by Twitch');\n }\n return {\n username: body.data[0].login,\n email,\n };\n },\n },\n\n linkedin: {\n enabled: false,\n icon: 'linkedin',\n grantConfig: {\n key: '',\n secret: '',\n callbackUrl: `${baseURL}/linkedin/callback`,\n scope: ['r_liteprofile', 'r_emailaddress'],\n },\n async authCallback({ accessToken }) {\n const { body: profileBody } = await bearerGet('https://api.linkedin.com/v2/me', accessToken);\n const { body: emailBody } = await bearerGet(\n 'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))',\n accessToken\n );\n\n const email = emailBody.elements[0]?.['handle~'];\n\n if (!email?.emailAddress) {\n throw new Error('Email not verified by LinkedIn');\n }\n\n return {\n username: profileBody.localizedFirstName,\n email: email.emailAddress,\n };\n },\n },\n\n cognito: {\n enabled: false,\n icon: 'aws',\n grantConfig: {\n key: '',\n secret: '',\n subdomain: 'my.subdomain.com',\n callback: `${baseURL}/cognito/callback`,\n scope: ['email', 'openid', 'profile'],\n },\n async authCallback({ providers, grantResponse }) {\n const jwksUrl = new URL(providers.cognito.jwksurl);\n const idToken = grantResponse?.id_token;\n\n if (!idToken) {\n throw new Error('Cognito authentication requires a completed OAuth session');\n }\n\n const tokenPayload = await verifyJwtWithJwks({ idToken, jwksUrl });\n if (tokenPayload.email_verified !== true) {\n throw new Error('Email not verified by Cognito');\n }\n return {\n username: tokenPayload['cognito:username'],\n email: tokenPayload.email,\n };\n },\n },\n\n reddit: {\n enabled: false,\n icon: 'reddit',\n grantConfig: {\n key: '',\n secret: '',\n callback: `${baseURL}/reddit/callback`,\n scope: ['identity'],\n },\n async authCallback({ accessToken }) {\n const { body } = await bearerGet('https://oauth.reddit.com/api/v1/me', accessToken, {\n headers: { 'user-agent': 'strapi' },\n });\n return {\n username: body.name,\n email: `${body.name}@strapi.io`,\n };\n },\n },\n\n auth0: {\n enabled: false,\n icon: '',\n grantConfig: {\n key: '',\n secret: '',\n subdomain: 'my-tenant.eu',\n callback: `${baseURL}/auth0/callback`,\n scope: ['openid', 'email', 'profile'],\n },\n async authCallback({ accessToken, providers }) {\n const { body } = await bearerGet(\n `https://${providers.auth0.subdomain}.auth0.com/userinfo`,\n accessToken\n );\n if (body.email && body.email_verified !== true) {\n throw new Error('Email not verified by Auth0');\n }\n const username = body.username || body.nickname || body.name || body.email.split('@')[0];\n const email = body.email || `${username.replace(/\\s+/g, '.')}@strapi.io`;\n\n return {\n username,\n email,\n };\n },\n },\n\n cas: {\n enabled: false,\n icon: 'book',\n grantConfig: {\n key: '',\n secret: '',\n callback: `${baseURL}/cas/callback`,\n scope: ['openid email'],\n subdomain: 'my.subdomain.com/cas',\n },\n async authCallback({ accessToken, providers }) {\n const { body } = await bearerGet(\n `https://${providers.cas.subdomain}/oidc/profile`,\n accessToken\n );\n const username = body.attributes\n ? body.attributes.strapiusername || body.id || body.sub\n : body.strapiusername || body.id || body.sub;\n const email = body.attributes\n ? body.attributes.strapiemail || body.attributes.email\n : body.strapiemail || body.email;\n const emailVerified = body.email_verified ?? body.attributes?.email_verified;\n if (!username || !email) {\n strapi.log.warn(\n `CAS Response Body did not contain required attributes: ${JSON.stringify(body)}`\n );\n }\n if (email && emailVerified !== true) {\n throw new Error('Email not verified by CAS');\n }\n return {\n username,\n email,\n };\n },\n },\n\n patreon: {\n enabled: false,\n icon: '',\n grantConfig: {\n key: '',\n secret: '',\n callback: `${baseURL}/patreon/callback`,\n scope: ['identity', 'identity[email]'],\n },\n async authCallback({ accessToken }) {\n const { body } = await bearerGet(\n 'https://www.patreon.com/api/oauth2/v2/identity?fields[user]=full_name,email,is_email_verified',\n accessToken\n );\n const patreonData = body.data.attributes;\n if (patreonData.is_email_verified !== true) {\n throw new Error('Email not verified by Patreon');\n }\n return {\n username: patreonData.full_name,\n email: patreonData.email,\n };\n },\n },\n keycloak: {\n enabled: false,\n icon: '',\n grantConfig: {\n key: '',\n secret: '',\n subdomain: 'myKeycloakProvider.com/realms/myrealm',\n callback: `${baseURL}/keycloak/callback`,\n scope: ['openid', 'email', 'profile'],\n },\n async authCallback({ accessToken, providers }) {\n const { body } = await bearerGet(\n `https://${providers.keycloak.subdomain}/protocol/openid-connect/userinfo`,\n accessToken\n );\n if (body.email_verified !== true) {\n throw new Error('Email not verified by Keycloak');\n }\n return {\n username: body.preferred_username,\n email: body.email,\n };\n },\n },\n});\n\nmodule.exports = () => {\n const apiPrefix = strapi.config.get('api.rest.prefix');\n const baseURL = urljoin(strapi.config.server.url, apiPrefix, 'auth');\n\n const authProviders = initProviders({ baseURL });\n\n return {\n getAll() {\n return authProviders;\n },\n get(name) {\n return authProviders[name];\n },\n add(name, config) {\n authProviders[name] = config;\n },\n remove(name) {\n delete authProviders[name];\n },\n\n async run({ provider, accessToken, query, providers, grantResponse }) {\n const authProvider = authProviders[provider];\n\n assert(authProvider, 'Unknown auth provider');\n\n return authProvider.authCallback({ accessToken, query, providers, grantResponse });\n },\n };\n};\n"],"names":["strict","assert","require$$0","urljoin","require$$1","verifyJwtWithJwks","require$$2","bearerGet","fetchJson","require$$3","initProviders","baseURL","email","enabled","icon","grantConfig","discord","key","secret","callbackUrl","scope","authCallback","accessToken","body","verified","Error","username","discriminator","facebook","qs","fields","name","google","encodeURIComponent","verified_email","email_verified","split","github","userBody","headers","emailBody","verifiedPublicEmail","Array","isArray","find","entry","login","primaryEmail","primary","microsoft","userPrincipalName","twitter","providers","grantResponse","accessSecret","access_secret","screenName","raw","screen_name","twitterGet","require$$4","url","accessCredential","consumerKey","clientCredential","include_email","instagram","vk","userId","user_id","user_ids","v","response","last_name","first_name","twitch","data","linkedin","profileBody","elements","emailAddress","localizedFirstName","cognito","subdomain","callback","jwksUrl","URL","jwksurl","idToken","id_token","tokenPayload","reddit","auth0","nickname","replace","cas","attributes","strapiusername","id","sub","strapiemail","emailVerified","strapi","log","warn","JSON","stringify","patreon","patreonData","is_email_verified","full_name","keycloak","preferred_username","providersRegistry","apiPrefix","config","get","server","authProviders","getAll","add","remove","run","provider","query","authProvider"],"mappings":"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"}