@strapi/plugin-users-permissions 5.52.3 → 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 (61) hide show
  1. package/dist/server/controllers/auth.js +7 -1
  2. package/dist/server/controllers/auth.js.map +1 -1
  3. package/dist/server/controllers/auth.mjs +7 -1
  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/services/providers-registry.js +80 -19
  30. package/dist/server/services/providers-registry.js.map +1 -1
  31. package/dist/server/services/providers-registry.mjs +80 -19
  32. package/dist/server/services/providers-registry.mjs.map +1 -1
  33. package/dist/server/services/providers.js +12 -8
  34. package/dist/server/services/providers.js.map +1 -1
  35. package/dist/server/services/providers.mjs +12 -8
  36. package/dist/server/services/providers.mjs.map +1 -1
  37. package/dist/server/services/user.js +7 -7
  38. package/dist/server/services/user.js.map +1 -1
  39. package/dist/server/services/user.mjs +7 -7
  40. package/dist/server/services/user.mjs.map +1 -1
  41. package/dist/server/utils/oauth-connect/index.js +11 -6
  42. package/dist/server/utils/oauth-connect/index.js.map +1 -1
  43. package/dist/server/utils/oauth-connect/index.mjs +11 -6
  44. package/dist/server/utils/oauth-connect/index.mjs.map +1 -1
  45. package/dist/server/utils/trim-grant-session-response.js +67 -0
  46. package/dist/server/utils/trim-grant-session-response.js.map +1 -0
  47. package/dist/server/utils/trim-grant-session-response.mjs +65 -0
  48. package/dist/server/utils/trim-grant-session-response.mjs.map +1 -0
  49. package/package.json +4 -4
  50. package/server/src/controllers/auth.js +9 -1
  51. package/server/src/graphql/mutations/auth/change-password.js +5 -5
  52. package/server/src/graphql/mutations/auth/forgot-password.js +5 -5
  53. package/server/src/graphql/mutations/auth/login.js +10 -6
  54. package/server/src/graphql/mutations/auth/rate-limit.js +62 -0
  55. package/server/src/graphql/mutations/auth/register.js +5 -5
  56. package/server/src/graphql/mutations/auth/reset-password.js +5 -5
  57. package/server/src/services/providers-registry.js +99 -23
  58. package/server/src/services/providers.js +9 -7
  59. package/server/src/services/user.js +15 -5
  60. package/server/src/utils/oauth-connect/index.js +12 -6
  61. package/server/src/utils/trim-grant-session-response.js +70 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../server/src/utils/oauth-connect/index.js"],"sourcesContent":["'use strict';\n\nconst { errors } = require('@strapi/utils');\n\nconst builtinProviderEndpoints = require('./providers');\nconst oauth1 = require('./oauth1');\nconst oauth2 = require('./oauth2');\n\nconst CONNECT_PREFIX = '/connect';\n\nconst parseConnectPath = (requestPath, apiPrefix) => {\n const prefix = `${apiPrefix}${CONNECT_PREFIX}/`;\n if (!requestPath.startsWith(prefix)) {\n return null;\n }\n\n const remainder = requestPath.slice(prefix.length);\n const [provider, segment] = remainder.split('/').filter(Boolean);\n\n if (!provider) {\n return null;\n }\n\n return {\n provider,\n isCallback: segment === 'callback',\n };\n};\n\n/**\n * Resolve OAuth endpoint config from built-ins, falling back to store-defined\n * endpoints so custom providers registered via providers-registry still work.\n */\nconst buildProviderConfig = (providerName, storedConfig, redirectUri) => {\n const defaults = builtinProviderEndpoints[providerName];\n const endpoints = defaults || {\n oauth: storedConfig.oauth,\n authorize_url: storedConfig.authorize_url,\n access_url: storedConfig.access_url,\n request_url: storedConfig.request_url,\n scope_delimiter: storedConfig.scope_delimiter,\n token_endpoint_auth_method: storedConfig.token_endpoint_auth_method,\n };\n\n if (endpoints.oauth === 1) {\n if (!endpoints.request_url || !endpoints.authorize_url || !endpoints.access_url) {\n return null;\n }\n } else if (!endpoints.authorize_url || !endpoints.access_url) {\n return null;\n }\n\n return {\n name: providerName,\n ...endpoints,\n key: storedConfig.key,\n secret: storedConfig.secret,\n scope: storedConfig.scope,\n subdomain: storedConfig.subdomain,\n callback: storedConfig.callback,\n redirect_uri: redirectUri,\n };\n};\n\nconst redirectWithPayload = (ctx, callbackUrl, payload) => {\n const url = new URL(callbackUrl);\n const params = new URLSearchParams();\n\n Object.entries(payload).forEach(([key, value]) => {\n if (key === 'raw') {\n Object.entries(value).forEach(([rawKey, rawValue]) => {\n params.set(`raw[${rawKey}]`, String(rawValue));\n });\n return;\n }\n if (value !== undefined && value !== null) {\n params.set(key, String(value));\n }\n });\n\n url.search = params.toString();\n ctx.redirect(url.toString());\n};\n\nconst preserveGrantDynamic = (ctx) => {\n const dynamic = ctx.session.grant?.dynamic;\n return dynamic ? { dynamic } : {};\n};\n\nconst startOAuth1Flow = async (ctx, provider, parsed, redirectUri) => {\n const requestToken = await oauth1.requestToken({\n requestUrl: provider.request_url,\n redirectUri,\n consumerKey: provider.key,\n clientCredential: provider.secret,\n });\n\n ctx.session.grant = {\n ...preserveGrantDynamic(ctx),\n provider: parsed.provider,\n request: requestToken,\n };\n\n const authorizeUrl = `${provider.authorize_url}?oauth_token=${encodeURIComponent(requestToken.oauth_token)}`;\n return ctx.redirect(authorizeUrl);\n};\n\nconst startOAuth2Flow = (ctx, provider, parsed, redirectUri) => {\n const state = oauth2.generateState();\n ctx.session.grant = {\n ...preserveGrantDynamic(ctx),\n provider: parsed.provider,\n state,\n };\n\n let authorizeUrl = oauth2.buildAuthorizeUrl(provider, {\n key: provider.key,\n redirectUri,\n scope: provider.scope,\n subdomain: provider.subdomain,\n });\n\n authorizeUrl += `&state=${encodeURIComponent(state)}`;\n return ctx.redirect(authorizeUrl);\n};\n\nconst handleOAuth1Callback = async (ctx, provider, callbackUrl) => {\n const session = ctx.session.grant || {};\n const { oauth_token: oauthToken, oauth_verifier: oauthVerifier } = ctx.query;\n const requestToken = session.request;\n\n if (!requestToken?.oauth_token || oauthToken !== requestToken.oauth_token) {\n throw new Error('OAuth1 token mismatch');\n }\n\n const tokenResponse = await oauth1.accessToken({\n accessUrl: provider.access_url,\n consumerKey: provider.key,\n clientCredential: provider.secret,\n oauthToken,\n oauthVerifier,\n oauthTokenCredential: requestToken.oauth_token_secret,\n });\n\n const payload = oauth2.tokensToQueryPayload(provider, tokenResponse);\n ctx.session.grant = {};\n return redirectWithPayload(ctx, callbackUrl, payload);\n};\n\nconst handleOAuth2Callback = async (ctx, provider, callbackUrl, redirectUri) => {\n const session = ctx.session.grant || {};\n const { code, state: queryState, error, error_description: errorDescription } = ctx.query;\n\n if (error) {\n ctx.session.grant = {};\n return redirectWithPayload(ctx, callbackUrl, {\n error,\n error_description: errorDescription,\n });\n }\n\n if (!code) {\n throw new Error('OAuth2 missing code parameter');\n }\n\n // Reject when session state is missing (not only on mismatch) to close login-CSRF.\n if (!session.state || queryState !== session.state) {\n throw new Error('OAuth2 state mismatch');\n }\n\n const tokenResponse = await oauth2.exchangeAuthorizationCode(provider, {\n key: provider.key,\n secret: provider.secret,\n redirectUri,\n code,\n subdomain: provider.subdomain,\n });\n\n const payload = oauth2.tokensToQueryPayload(provider, tokenResponse);\n ctx.session.grant = {};\n return redirectWithPayload(ctx, callbackUrl, payload);\n};\n\nconst createOAuthConnectMiddleware = () => {\n return async (ctx, next) => {\n const apiPrefix = strapi.config.get('api.rest.prefix');\n const [requestPath] = ctx.request.url.split('?');\n const parsed = parseConnectPath(requestPath, apiPrefix);\n\n if (!parsed) {\n return next();\n }\n\n if (!ctx.session) {\n ctx.throw(400, 'OAuth connect requires session middleware');\n }\n\n const storedProviders = await strapi\n .store({ type: 'plugin', name: 'users-permissions', key: 'grant' })\n .get();\n\n const storedConfig = storedProviders?.[parsed.provider];\n if (!storedConfig?.enabled) {\n throw new errors.ApplicationError('This provider is disabled');\n }\n\n const { getService } = require('..');\n const redirectUri = getService('providers').buildRedirectUri(parsed.provider);\n\n const callbackOverride =\n ctx.state.oauthConnect?.callback ?? ctx.session.grant?.dynamic?.callback;\n const effectiveConfig = callbackOverride\n ? { ...storedConfig, callback: callbackOverride }\n : storedConfig;\n\n const provider = buildProviderConfig(parsed.provider, effectiveConfig, redirectUri);\n\n if (!provider) {\n throw new errors.ApplicationError('Unknown OAuth provider');\n }\n\n ctx.session.grant = ctx.session.grant || {};\n\n if (!parsed.isCallback) {\n if (provider.oauth === 1) {\n return startOAuth1Flow(ctx, provider, parsed, redirectUri);\n }\n return startOAuth2Flow(ctx, provider, parsed, redirectUri);\n }\n\n const callbackUrl = effectiveConfig.callback;\n if (!callbackUrl) {\n throw new errors.ApplicationError('Provider callback URL is not configured');\n }\n\n try {\n if (provider.oauth === 1) {\n return await handleOAuth1Callback(ctx, provider, callbackUrl);\n }\n return await handleOAuth2Callback(ctx, provider, callbackUrl, redirectUri);\n } catch (err) {\n ctx.session.grant = {};\n return redirectWithPayload(ctx, callbackUrl, {\n error: 'oauth_error',\n error_description: err.message,\n });\n }\n };\n};\n\nmodule.exports = {\n createOAuthConnectMiddleware,\n parseConnectPath,\n buildProviderConfig,\n redirectWithPayload,\n};\n"],"names":["errors","require$$0","builtinProviderEndpoints","require$$1","oauth1","require$$2","oauth2","require$$3","CONNECT_PREFIX","parseConnectPath","requestPath","apiPrefix","prefix","startsWith","remainder","slice","length","provider","segment","split","filter","Boolean","isCallback","buildProviderConfig","providerName","storedConfig","redirectUri","defaults","endpoints","oauth","authorize_url","access_url","request_url","scope_delimiter","token_endpoint_auth_method","name","key","secret","scope","subdomain","callback","redirect_uri","redirectWithPayload","ctx","callbackUrl","payload","url","URL","params","URLSearchParams","Object","entries","forEach","value","rawKey","rawValue","set","String","undefined","search","toString","redirect","preserveGrantDynamic","dynamic","session","grant","startOAuth1Flow","parsed","requestToken","requestUrl","consumerKey","clientCredential","request","authorizeUrl","encodeURIComponent","oauth_token","startOAuth2Flow","state","generateState","buildAuthorizeUrl","handleOAuth1Callback","oauthToken","oauth_verifier","oauthVerifier","query","Error","tokenResponse","accessToken","accessUrl","oauthTokenCredential","oauth_token_secret","tokensToQueryPayload","handleOAuth2Callback","code","queryState","error","error_description","errorDescription","exchangeAuthorizationCode","createOAuthConnectMiddleware","next","strapi","config","get","throw","storedProviders","store","type","enabled","ApplicationError","getService","require$$4","buildRedirectUri","callbackOverride","oauthConnect","effectiveConfig","err","message"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../../server/src/utils/oauth-connect/index.js"],"sourcesContent":["'use strict';\n\nconst { errors } = require('@strapi/utils');\n\nconst builtinProviderEndpoints = require('./providers');\nconst oauth1 = require('./oauth1');\nconst oauth2 = require('./oauth2');\nconst { trimGrantSessionResponse } = require('../trim-grant-session-response');\n\nconst CONNECT_PREFIX = '/connect';\n\nconst parseConnectPath = (requestPath, apiPrefix) => {\n const prefix = `${apiPrefix}${CONNECT_PREFIX}/`;\n if (!requestPath.startsWith(prefix)) {\n return null;\n }\n\n const remainder = requestPath.slice(prefix.length);\n const [provider, segment] = remainder.split('/').filter(Boolean);\n\n if (!provider) {\n return null;\n }\n\n return {\n provider,\n isCallback: segment === 'callback',\n };\n};\n\n/**\n * Resolve OAuth endpoint config from built-ins, falling back to store-defined\n * endpoints so custom providers registered via providers-registry still work.\n */\nconst buildProviderConfig = (providerName, storedConfig, redirectUri) => {\n const defaults = builtinProviderEndpoints[providerName];\n const endpoints = defaults || {\n oauth: storedConfig.oauth,\n authorize_url: storedConfig.authorize_url,\n access_url: storedConfig.access_url,\n request_url: storedConfig.request_url,\n scope_delimiter: storedConfig.scope_delimiter,\n token_endpoint_auth_method: storedConfig.token_endpoint_auth_method,\n };\n\n if (endpoints.oauth === 1) {\n if (!endpoints.request_url || !endpoints.authorize_url || !endpoints.access_url) {\n return null;\n }\n } else if (!endpoints.authorize_url || !endpoints.access_url) {\n return null;\n }\n\n return {\n name: providerName,\n ...endpoints,\n key: storedConfig.key,\n secret: storedConfig.secret,\n scope: storedConfig.scope,\n subdomain: storedConfig.subdomain,\n callback: storedConfig.callback,\n redirect_uri: redirectUri,\n };\n};\n\nconst redirectWithPayload = (ctx, callbackUrl, payload) => {\n const url = new URL(callbackUrl);\n const params = new URLSearchParams();\n\n Object.entries(payload).forEach(([key, value]) => {\n if (key === 'raw') {\n Object.entries(value).forEach(([rawKey, rawValue]) => {\n params.set(`raw[${rawKey}]`, String(rawValue));\n });\n return;\n }\n if (value !== undefined && value !== null) {\n params.set(key, String(value));\n }\n });\n\n url.search = params.toString();\n ctx.redirect(url.toString());\n};\n\nconst preserveGrantDynamic = (ctx) => {\n const dynamic = ctx.session.grant?.dynamic;\n return dynamic ? { dynamic } : {};\n};\n\nconst redirectWithSessionResponse = (ctx, callbackUrl, provider, tokenResponse) => {\n const grantResponse = oauth2.tokensToQueryPayload(provider, tokenResponse);\n ctx.session.grant = {\n response: trimGrantSessionResponse(grantResponse, provider.name),\n };\n\n return redirectWithPayload(ctx, callbackUrl, {});\n};\n\nconst startOAuth1Flow = async (ctx, provider, parsed, redirectUri) => {\n const requestToken = await oauth1.requestToken({\n requestUrl: provider.request_url,\n redirectUri,\n consumerKey: provider.key,\n clientCredential: provider.secret,\n });\n\n ctx.session.grant = {\n ...preserveGrantDynamic(ctx),\n provider: parsed.provider,\n request: requestToken,\n };\n\n const authorizeUrl = `${provider.authorize_url}?oauth_token=${encodeURIComponent(requestToken.oauth_token)}`;\n return ctx.redirect(authorizeUrl);\n};\n\nconst startOAuth2Flow = (ctx, provider, parsed, redirectUri) => {\n const state = oauth2.generateState();\n ctx.session.grant = {\n ...preserveGrantDynamic(ctx),\n provider: parsed.provider,\n state,\n };\n\n let authorizeUrl = oauth2.buildAuthorizeUrl(provider, {\n key: provider.key,\n redirectUri,\n scope: provider.scope,\n subdomain: provider.subdomain,\n });\n\n authorizeUrl += `&state=${encodeURIComponent(state)}`;\n return ctx.redirect(authorizeUrl);\n};\n\nconst handleOAuth1Callback = async (ctx, provider, callbackUrl) => {\n const session = ctx.session.grant || {};\n const { oauth_token: oauthToken, oauth_verifier: oauthVerifier } = ctx.query;\n const requestToken = session.request;\n\n if (!requestToken?.oauth_token || oauthToken !== requestToken.oauth_token) {\n throw new Error('OAuth1 token mismatch');\n }\n\n const tokenResponse = await oauth1.accessToken({\n accessUrl: provider.access_url,\n consumerKey: provider.key,\n clientCredential: provider.secret,\n oauthToken,\n oauthVerifier,\n oauthTokenCredential: requestToken.oauth_token_secret,\n });\n\n return redirectWithSessionResponse(ctx, callbackUrl, provider, tokenResponse);\n};\n\nconst handleOAuth2Callback = async (ctx, provider, callbackUrl, redirectUri) => {\n const session = ctx.session.grant || {};\n const { code, state: queryState, error, error_description: errorDescription } = ctx.query;\n\n if (error) {\n ctx.session.grant = {};\n return redirectWithPayload(ctx, callbackUrl, {\n error,\n error_description: errorDescription,\n });\n }\n\n if (!code) {\n throw new Error('OAuth2 missing code parameter');\n }\n\n // Reject when session state is missing (not only on mismatch) to close login-CSRF.\n if (!session.state || queryState !== session.state) {\n throw new Error('OAuth2 state mismatch');\n }\n\n const tokenResponse = await oauth2.exchangeAuthorizationCode(provider, {\n key: provider.key,\n secret: provider.secret,\n redirectUri,\n code,\n subdomain: provider.subdomain,\n });\n\n return redirectWithSessionResponse(ctx, callbackUrl, provider, tokenResponse);\n};\n\nconst createOAuthConnectMiddleware = () => {\n return async (ctx, next) => {\n const apiPrefix = strapi.config.get('api.rest.prefix');\n const [requestPath] = ctx.request.url.split('?');\n const parsed = parseConnectPath(requestPath, apiPrefix);\n\n if (!parsed) {\n return next();\n }\n\n if (!ctx.session) {\n ctx.throw(400, 'OAuth connect requires session middleware');\n }\n\n const storedProviders = await strapi\n .store({ type: 'plugin', name: 'users-permissions', key: 'grant' })\n .get();\n\n const storedConfig = storedProviders?.[parsed.provider];\n if (!storedConfig?.enabled) {\n throw new errors.ApplicationError('This provider is disabled');\n }\n\n const { getService } = require('..');\n const redirectUri = getService('providers').buildRedirectUri(parsed.provider);\n\n const callbackOverride =\n ctx.state.oauthConnect?.callback ?? ctx.session.grant?.dynamic?.callback;\n const effectiveConfig = callbackOverride\n ? { ...storedConfig, callback: callbackOverride }\n : storedConfig;\n\n const provider = buildProviderConfig(parsed.provider, effectiveConfig, redirectUri);\n\n if (!provider) {\n throw new errors.ApplicationError('Unknown OAuth provider');\n }\n\n ctx.session.grant = ctx.session.grant || {};\n\n if (!parsed.isCallback) {\n if (provider.oauth === 1) {\n return startOAuth1Flow(ctx, provider, parsed, redirectUri);\n }\n return startOAuth2Flow(ctx, provider, parsed, redirectUri);\n }\n\n const callbackUrl = effectiveConfig.callback;\n if (!callbackUrl) {\n throw new errors.ApplicationError('Provider callback URL is not configured');\n }\n\n try {\n if (provider.oauth === 1) {\n return await handleOAuth1Callback(ctx, provider, callbackUrl);\n }\n return await handleOAuth2Callback(ctx, provider, callbackUrl, redirectUri);\n } catch (err) {\n ctx.session.grant = {};\n return redirectWithPayload(ctx, callbackUrl, {\n error: 'oauth_error',\n error_description: err.message,\n });\n }\n };\n};\n\nmodule.exports = {\n createOAuthConnectMiddleware,\n parseConnectPath,\n buildProviderConfig,\n redirectWithPayload,\n};\n"],"names":["errors","require$$0","builtinProviderEndpoints","require$$1","oauth1","require$$2","oauth2","require$$3","trimGrantSessionResponse","require$$4","CONNECT_PREFIX","parseConnectPath","requestPath","apiPrefix","prefix","startsWith","remainder","slice","length","provider","segment","split","filter","Boolean","isCallback","buildProviderConfig","providerName","storedConfig","redirectUri","defaults","endpoints","oauth","authorize_url","access_url","request_url","scope_delimiter","token_endpoint_auth_method","name","key","secret","scope","subdomain","callback","redirect_uri","redirectWithPayload","ctx","callbackUrl","payload","url","URL","params","URLSearchParams","Object","entries","forEach","value","rawKey","rawValue","set","String","undefined","search","toString","redirect","preserveGrantDynamic","dynamic","session","grant","redirectWithSessionResponse","tokenResponse","grantResponse","tokensToQueryPayload","response","startOAuth1Flow","parsed","requestToken","requestUrl","consumerKey","clientCredential","request","authorizeUrl","encodeURIComponent","oauth_token","startOAuth2Flow","state","generateState","buildAuthorizeUrl","handleOAuth1Callback","oauthToken","oauth_verifier","oauthVerifier","query","Error","accessToken","accessUrl","oauthTokenCredential","oauth_token_secret","handleOAuth2Callback","code","queryState","error","error_description","errorDescription","exchangeAuthorizationCode","createOAuthConnectMiddleware","next","strapi","config","get","throw","storedProviders","store","type","enabled","ApplicationError","getService","require$$5","buildRedirectUri","callbackOverride","oauthConnect","effectiveConfig","err","message"],"mappings":"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"}
@@ -2,6 +2,7 @@ import require$$1 from '@strapi/utils';
2
2
  import { __require as requireProviders } from './providers.mjs';
3
3
  import { __require as requireOauth1 } from './oauth1.mjs';
4
4
  import { __require as requireOauth2 } from './oauth2.mjs';
5
+ import { __require as requireTrimGrantSessionResponse } from '../trim-grant-session-response.mjs';
5
6
  import { __require as requireUtils } from '../index.mjs';
6
7
 
7
8
  var oauthConnect;
@@ -13,6 +14,7 @@ function requireOauthConnect() {
13
14
  const builtinProviderEndpoints = requireProviders();
14
15
  const oauth1 = requireOauth1();
15
16
  const oauth2 = requireOauth2();
17
+ const { trimGrantSessionResponse } = requireTrimGrantSessionResponse();
16
18
  const CONNECT_PREFIX = '/connect';
17
19
  const parseConnectPath = (requestPath, apiPrefix)=>{
18
20
  const prefix = `${apiPrefix}${CONNECT_PREFIX}/`;
@@ -83,6 +85,13 @@ function requireOauthConnect() {
83
85
  dynamic
84
86
  } : {};
85
87
  };
88
+ const redirectWithSessionResponse = (ctx, callbackUrl, provider, tokenResponse)=>{
89
+ const grantResponse = oauth2.tokensToQueryPayload(provider, tokenResponse);
90
+ ctx.session.grant = {
91
+ response: trimGrantSessionResponse(grantResponse, provider.name)
92
+ };
93
+ return redirectWithPayload(ctx, callbackUrl, {});
94
+ };
86
95
  const startOAuth1Flow = async (ctx, provider, parsed, redirectUri)=>{
87
96
  const requestToken = await oauth1.requestToken({
88
97
  requestUrl: provider.request_url,
@@ -129,9 +138,7 @@ function requireOauthConnect() {
129
138
  oauthVerifier,
130
139
  oauthTokenCredential: requestToken.oauth_token_secret
131
140
  });
132
- const payload = oauth2.tokensToQueryPayload(provider, tokenResponse);
133
- ctx.session.grant = {};
134
- return redirectWithPayload(ctx, callbackUrl, payload);
141
+ return redirectWithSessionResponse(ctx, callbackUrl, provider, tokenResponse);
135
142
  };
136
143
  const handleOAuth2Callback = async (ctx, provider, callbackUrl, redirectUri)=>{
137
144
  const session = ctx.session.grant || {};
@@ -157,9 +164,7 @@ function requireOauthConnect() {
157
164
  code,
158
165
  subdomain: provider.subdomain
159
166
  });
160
- const payload = oauth2.tokensToQueryPayload(provider, tokenResponse);
161
- ctx.session.grant = {};
162
- return redirectWithPayload(ctx, callbackUrl, payload);
167
+ return redirectWithSessionResponse(ctx, callbackUrl, provider, tokenResponse);
163
168
  };
164
169
  const createOAuthConnectMiddleware = ()=>{
165
170
  return async (ctx, next)=>{
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../../../server/src/utils/oauth-connect/index.js"],"sourcesContent":["'use strict';\n\nconst { errors } = require('@strapi/utils');\n\nconst builtinProviderEndpoints = require('./providers');\nconst oauth1 = require('./oauth1');\nconst oauth2 = require('./oauth2');\n\nconst CONNECT_PREFIX = '/connect';\n\nconst parseConnectPath = (requestPath, apiPrefix) => {\n const prefix = `${apiPrefix}${CONNECT_PREFIX}/`;\n if (!requestPath.startsWith(prefix)) {\n return null;\n }\n\n const remainder = requestPath.slice(prefix.length);\n const [provider, segment] = remainder.split('/').filter(Boolean);\n\n if (!provider) {\n return null;\n }\n\n return {\n provider,\n isCallback: segment === 'callback',\n };\n};\n\n/**\n * Resolve OAuth endpoint config from built-ins, falling back to store-defined\n * endpoints so custom providers registered via providers-registry still work.\n */\nconst buildProviderConfig = (providerName, storedConfig, redirectUri) => {\n const defaults = builtinProviderEndpoints[providerName];\n const endpoints = defaults || {\n oauth: storedConfig.oauth,\n authorize_url: storedConfig.authorize_url,\n access_url: storedConfig.access_url,\n request_url: storedConfig.request_url,\n scope_delimiter: storedConfig.scope_delimiter,\n token_endpoint_auth_method: storedConfig.token_endpoint_auth_method,\n };\n\n if (endpoints.oauth === 1) {\n if (!endpoints.request_url || !endpoints.authorize_url || !endpoints.access_url) {\n return null;\n }\n } else if (!endpoints.authorize_url || !endpoints.access_url) {\n return null;\n }\n\n return {\n name: providerName,\n ...endpoints,\n key: storedConfig.key,\n secret: storedConfig.secret,\n scope: storedConfig.scope,\n subdomain: storedConfig.subdomain,\n callback: storedConfig.callback,\n redirect_uri: redirectUri,\n };\n};\n\nconst redirectWithPayload = (ctx, callbackUrl, payload) => {\n const url = new URL(callbackUrl);\n const params = new URLSearchParams();\n\n Object.entries(payload).forEach(([key, value]) => {\n if (key === 'raw') {\n Object.entries(value).forEach(([rawKey, rawValue]) => {\n params.set(`raw[${rawKey}]`, String(rawValue));\n });\n return;\n }\n if (value !== undefined && value !== null) {\n params.set(key, String(value));\n }\n });\n\n url.search = params.toString();\n ctx.redirect(url.toString());\n};\n\nconst preserveGrantDynamic = (ctx) => {\n const dynamic = ctx.session.grant?.dynamic;\n return dynamic ? { dynamic } : {};\n};\n\nconst startOAuth1Flow = async (ctx, provider, parsed, redirectUri) => {\n const requestToken = await oauth1.requestToken({\n requestUrl: provider.request_url,\n redirectUri,\n consumerKey: provider.key,\n clientCredential: provider.secret,\n });\n\n ctx.session.grant = {\n ...preserveGrantDynamic(ctx),\n provider: parsed.provider,\n request: requestToken,\n };\n\n const authorizeUrl = `${provider.authorize_url}?oauth_token=${encodeURIComponent(requestToken.oauth_token)}`;\n return ctx.redirect(authorizeUrl);\n};\n\nconst startOAuth2Flow = (ctx, provider, parsed, redirectUri) => {\n const state = oauth2.generateState();\n ctx.session.grant = {\n ...preserveGrantDynamic(ctx),\n provider: parsed.provider,\n state,\n };\n\n let authorizeUrl = oauth2.buildAuthorizeUrl(provider, {\n key: provider.key,\n redirectUri,\n scope: provider.scope,\n subdomain: provider.subdomain,\n });\n\n authorizeUrl += `&state=${encodeURIComponent(state)}`;\n return ctx.redirect(authorizeUrl);\n};\n\nconst handleOAuth1Callback = async (ctx, provider, callbackUrl) => {\n const session = ctx.session.grant || {};\n const { oauth_token: oauthToken, oauth_verifier: oauthVerifier } = ctx.query;\n const requestToken = session.request;\n\n if (!requestToken?.oauth_token || oauthToken !== requestToken.oauth_token) {\n throw new Error('OAuth1 token mismatch');\n }\n\n const tokenResponse = await oauth1.accessToken({\n accessUrl: provider.access_url,\n consumerKey: provider.key,\n clientCredential: provider.secret,\n oauthToken,\n oauthVerifier,\n oauthTokenCredential: requestToken.oauth_token_secret,\n });\n\n const payload = oauth2.tokensToQueryPayload(provider, tokenResponse);\n ctx.session.grant = {};\n return redirectWithPayload(ctx, callbackUrl, payload);\n};\n\nconst handleOAuth2Callback = async (ctx, provider, callbackUrl, redirectUri) => {\n const session = ctx.session.grant || {};\n const { code, state: queryState, error, error_description: errorDescription } = ctx.query;\n\n if (error) {\n ctx.session.grant = {};\n return redirectWithPayload(ctx, callbackUrl, {\n error,\n error_description: errorDescription,\n });\n }\n\n if (!code) {\n throw new Error('OAuth2 missing code parameter');\n }\n\n // Reject when session state is missing (not only on mismatch) to close login-CSRF.\n if (!session.state || queryState !== session.state) {\n throw new Error('OAuth2 state mismatch');\n }\n\n const tokenResponse = await oauth2.exchangeAuthorizationCode(provider, {\n key: provider.key,\n secret: provider.secret,\n redirectUri,\n code,\n subdomain: provider.subdomain,\n });\n\n const payload = oauth2.tokensToQueryPayload(provider, tokenResponse);\n ctx.session.grant = {};\n return redirectWithPayload(ctx, callbackUrl, payload);\n};\n\nconst createOAuthConnectMiddleware = () => {\n return async (ctx, next) => {\n const apiPrefix = strapi.config.get('api.rest.prefix');\n const [requestPath] = ctx.request.url.split('?');\n const parsed = parseConnectPath(requestPath, apiPrefix);\n\n if (!parsed) {\n return next();\n }\n\n if (!ctx.session) {\n ctx.throw(400, 'OAuth connect requires session middleware');\n }\n\n const storedProviders = await strapi\n .store({ type: 'plugin', name: 'users-permissions', key: 'grant' })\n .get();\n\n const storedConfig = storedProviders?.[parsed.provider];\n if (!storedConfig?.enabled) {\n throw new errors.ApplicationError('This provider is disabled');\n }\n\n const { getService } = require('..');\n const redirectUri = getService('providers').buildRedirectUri(parsed.provider);\n\n const callbackOverride =\n ctx.state.oauthConnect?.callback ?? ctx.session.grant?.dynamic?.callback;\n const effectiveConfig = callbackOverride\n ? { ...storedConfig, callback: callbackOverride }\n : storedConfig;\n\n const provider = buildProviderConfig(parsed.provider, effectiveConfig, redirectUri);\n\n if (!provider) {\n throw new errors.ApplicationError('Unknown OAuth provider');\n }\n\n ctx.session.grant = ctx.session.grant || {};\n\n if (!parsed.isCallback) {\n if (provider.oauth === 1) {\n return startOAuth1Flow(ctx, provider, parsed, redirectUri);\n }\n return startOAuth2Flow(ctx, provider, parsed, redirectUri);\n }\n\n const callbackUrl = effectiveConfig.callback;\n if (!callbackUrl) {\n throw new errors.ApplicationError('Provider callback URL is not configured');\n }\n\n try {\n if (provider.oauth === 1) {\n return await handleOAuth1Callback(ctx, provider, callbackUrl);\n }\n return await handleOAuth2Callback(ctx, provider, callbackUrl, redirectUri);\n } catch (err) {\n ctx.session.grant = {};\n return redirectWithPayload(ctx, callbackUrl, {\n error: 'oauth_error',\n error_description: err.message,\n });\n }\n };\n};\n\nmodule.exports = {\n createOAuthConnectMiddleware,\n parseConnectPath,\n buildProviderConfig,\n redirectWithPayload,\n};\n"],"names":["errors","require$$0","builtinProviderEndpoints","require$$1","oauth1","require$$2","oauth2","require$$3","CONNECT_PREFIX","parseConnectPath","requestPath","apiPrefix","prefix","startsWith","remainder","slice","length","provider","segment","split","filter","Boolean","isCallback","buildProviderConfig","providerName","storedConfig","redirectUri","defaults","endpoints","oauth","authorize_url","access_url","request_url","scope_delimiter","token_endpoint_auth_method","name","key","secret","scope","subdomain","callback","redirect_uri","redirectWithPayload","ctx","callbackUrl","payload","url","URL","params","URLSearchParams","Object","entries","forEach","value","rawKey","rawValue","set","String","undefined","search","toString","redirect","preserveGrantDynamic","dynamic","session","grant","startOAuth1Flow","parsed","requestToken","requestUrl","consumerKey","clientCredential","request","authorizeUrl","encodeURIComponent","oauth_token","startOAuth2Flow","state","generateState","buildAuthorizeUrl","handleOAuth1Callback","oauthToken","oauth_verifier","oauthVerifier","query","Error","tokenResponse","accessToken","accessUrl","oauthTokenCredential","oauth_token_secret","tokensToQueryPayload","handleOAuth2Callback","code","queryState","error","error_description","errorDescription","exchangeAuthorizationCode","createOAuthConnectMiddleware","next","strapi","config","get","throw","storedProviders","store","type","enabled","ApplicationError","getService","require$$4","buildRedirectUri","callbackOverride","oauthConnect","effectiveConfig","err","message"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../../../../server/src/utils/oauth-connect/index.js"],"sourcesContent":["'use strict';\n\nconst { errors } = require('@strapi/utils');\n\nconst builtinProviderEndpoints = require('./providers');\nconst oauth1 = require('./oauth1');\nconst oauth2 = require('./oauth2');\nconst { trimGrantSessionResponse } = require('../trim-grant-session-response');\n\nconst CONNECT_PREFIX = '/connect';\n\nconst parseConnectPath = (requestPath, apiPrefix) => {\n const prefix = `${apiPrefix}${CONNECT_PREFIX}/`;\n if (!requestPath.startsWith(prefix)) {\n return null;\n }\n\n const remainder = requestPath.slice(prefix.length);\n const [provider, segment] = remainder.split('/').filter(Boolean);\n\n if (!provider) {\n return null;\n }\n\n return {\n provider,\n isCallback: segment === 'callback',\n };\n};\n\n/**\n * Resolve OAuth endpoint config from built-ins, falling back to store-defined\n * endpoints so custom providers registered via providers-registry still work.\n */\nconst buildProviderConfig = (providerName, storedConfig, redirectUri) => {\n const defaults = builtinProviderEndpoints[providerName];\n const endpoints = defaults || {\n oauth: storedConfig.oauth,\n authorize_url: storedConfig.authorize_url,\n access_url: storedConfig.access_url,\n request_url: storedConfig.request_url,\n scope_delimiter: storedConfig.scope_delimiter,\n token_endpoint_auth_method: storedConfig.token_endpoint_auth_method,\n };\n\n if (endpoints.oauth === 1) {\n if (!endpoints.request_url || !endpoints.authorize_url || !endpoints.access_url) {\n return null;\n }\n } else if (!endpoints.authorize_url || !endpoints.access_url) {\n return null;\n }\n\n return {\n name: providerName,\n ...endpoints,\n key: storedConfig.key,\n secret: storedConfig.secret,\n scope: storedConfig.scope,\n subdomain: storedConfig.subdomain,\n callback: storedConfig.callback,\n redirect_uri: redirectUri,\n };\n};\n\nconst redirectWithPayload = (ctx, callbackUrl, payload) => {\n const url = new URL(callbackUrl);\n const params = new URLSearchParams();\n\n Object.entries(payload).forEach(([key, value]) => {\n if (key === 'raw') {\n Object.entries(value).forEach(([rawKey, rawValue]) => {\n params.set(`raw[${rawKey}]`, String(rawValue));\n });\n return;\n }\n if (value !== undefined && value !== null) {\n params.set(key, String(value));\n }\n });\n\n url.search = params.toString();\n ctx.redirect(url.toString());\n};\n\nconst preserveGrantDynamic = (ctx) => {\n const dynamic = ctx.session.grant?.dynamic;\n return dynamic ? { dynamic } : {};\n};\n\nconst redirectWithSessionResponse = (ctx, callbackUrl, provider, tokenResponse) => {\n const grantResponse = oauth2.tokensToQueryPayload(provider, tokenResponse);\n ctx.session.grant = {\n response: trimGrantSessionResponse(grantResponse, provider.name),\n };\n\n return redirectWithPayload(ctx, callbackUrl, {});\n};\n\nconst startOAuth1Flow = async (ctx, provider, parsed, redirectUri) => {\n const requestToken = await oauth1.requestToken({\n requestUrl: provider.request_url,\n redirectUri,\n consumerKey: provider.key,\n clientCredential: provider.secret,\n });\n\n ctx.session.grant = {\n ...preserveGrantDynamic(ctx),\n provider: parsed.provider,\n request: requestToken,\n };\n\n const authorizeUrl = `${provider.authorize_url}?oauth_token=${encodeURIComponent(requestToken.oauth_token)}`;\n return ctx.redirect(authorizeUrl);\n};\n\nconst startOAuth2Flow = (ctx, provider, parsed, redirectUri) => {\n const state = oauth2.generateState();\n ctx.session.grant = {\n ...preserveGrantDynamic(ctx),\n provider: parsed.provider,\n state,\n };\n\n let authorizeUrl = oauth2.buildAuthorizeUrl(provider, {\n key: provider.key,\n redirectUri,\n scope: provider.scope,\n subdomain: provider.subdomain,\n });\n\n authorizeUrl += `&state=${encodeURIComponent(state)}`;\n return ctx.redirect(authorizeUrl);\n};\n\nconst handleOAuth1Callback = async (ctx, provider, callbackUrl) => {\n const session = ctx.session.grant || {};\n const { oauth_token: oauthToken, oauth_verifier: oauthVerifier } = ctx.query;\n const requestToken = session.request;\n\n if (!requestToken?.oauth_token || oauthToken !== requestToken.oauth_token) {\n throw new Error('OAuth1 token mismatch');\n }\n\n const tokenResponse = await oauth1.accessToken({\n accessUrl: provider.access_url,\n consumerKey: provider.key,\n clientCredential: provider.secret,\n oauthToken,\n oauthVerifier,\n oauthTokenCredential: requestToken.oauth_token_secret,\n });\n\n return redirectWithSessionResponse(ctx, callbackUrl, provider, tokenResponse);\n};\n\nconst handleOAuth2Callback = async (ctx, provider, callbackUrl, redirectUri) => {\n const session = ctx.session.grant || {};\n const { code, state: queryState, error, error_description: errorDescription } = ctx.query;\n\n if (error) {\n ctx.session.grant = {};\n return redirectWithPayload(ctx, callbackUrl, {\n error,\n error_description: errorDescription,\n });\n }\n\n if (!code) {\n throw new Error('OAuth2 missing code parameter');\n }\n\n // Reject when session state is missing (not only on mismatch) to close login-CSRF.\n if (!session.state || queryState !== session.state) {\n throw new Error('OAuth2 state mismatch');\n }\n\n const tokenResponse = await oauth2.exchangeAuthorizationCode(provider, {\n key: provider.key,\n secret: provider.secret,\n redirectUri,\n code,\n subdomain: provider.subdomain,\n });\n\n return redirectWithSessionResponse(ctx, callbackUrl, provider, tokenResponse);\n};\n\nconst createOAuthConnectMiddleware = () => {\n return async (ctx, next) => {\n const apiPrefix = strapi.config.get('api.rest.prefix');\n const [requestPath] = ctx.request.url.split('?');\n const parsed = parseConnectPath(requestPath, apiPrefix);\n\n if (!parsed) {\n return next();\n }\n\n if (!ctx.session) {\n ctx.throw(400, 'OAuth connect requires session middleware');\n }\n\n const storedProviders = await strapi\n .store({ type: 'plugin', name: 'users-permissions', key: 'grant' })\n .get();\n\n const storedConfig = storedProviders?.[parsed.provider];\n if (!storedConfig?.enabled) {\n throw new errors.ApplicationError('This provider is disabled');\n }\n\n const { getService } = require('..');\n const redirectUri = getService('providers').buildRedirectUri(parsed.provider);\n\n const callbackOverride =\n ctx.state.oauthConnect?.callback ?? ctx.session.grant?.dynamic?.callback;\n const effectiveConfig = callbackOverride\n ? { ...storedConfig, callback: callbackOverride }\n : storedConfig;\n\n const provider = buildProviderConfig(parsed.provider, effectiveConfig, redirectUri);\n\n if (!provider) {\n throw new errors.ApplicationError('Unknown OAuth provider');\n }\n\n ctx.session.grant = ctx.session.grant || {};\n\n if (!parsed.isCallback) {\n if (provider.oauth === 1) {\n return startOAuth1Flow(ctx, provider, parsed, redirectUri);\n }\n return startOAuth2Flow(ctx, provider, parsed, redirectUri);\n }\n\n const callbackUrl = effectiveConfig.callback;\n if (!callbackUrl) {\n throw new errors.ApplicationError('Provider callback URL is not configured');\n }\n\n try {\n if (provider.oauth === 1) {\n return await handleOAuth1Callback(ctx, provider, callbackUrl);\n }\n return await handleOAuth2Callback(ctx, provider, callbackUrl, redirectUri);\n } catch (err) {\n ctx.session.grant = {};\n return redirectWithPayload(ctx, callbackUrl, {\n error: 'oauth_error',\n error_description: err.message,\n });\n }\n };\n};\n\nmodule.exports = {\n createOAuthConnectMiddleware,\n parseConnectPath,\n buildProviderConfig,\n redirectWithPayload,\n};\n"],"names":["errors","require$$0","builtinProviderEndpoints","require$$1","oauth1","require$$2","oauth2","require$$3","trimGrantSessionResponse","require$$4","CONNECT_PREFIX","parseConnectPath","requestPath","apiPrefix","prefix","startsWith","remainder","slice","length","provider","segment","split","filter","Boolean","isCallback","buildProviderConfig","providerName","storedConfig","redirectUri","defaults","endpoints","oauth","authorize_url","access_url","request_url","scope_delimiter","token_endpoint_auth_method","name","key","secret","scope","subdomain","callback","redirect_uri","redirectWithPayload","ctx","callbackUrl","payload","url","URL","params","URLSearchParams","Object","entries","forEach","value","rawKey","rawValue","set","String","undefined","search","toString","redirect","preserveGrantDynamic","dynamic","session","grant","redirectWithSessionResponse","tokenResponse","grantResponse","tokensToQueryPayload","response","startOAuth1Flow","parsed","requestToken","requestUrl","consumerKey","clientCredential","request","authorizeUrl","encodeURIComponent","oauth_token","startOAuth2Flow","state","generateState","buildAuthorizeUrl","handleOAuth1Callback","oauthToken","oauth_verifier","oauthVerifier","query","Error","accessToken","accessUrl","oauthTokenCredential","oauth_token_secret","handleOAuth2Callback","code","queryState","error","error_description","errorDescription","exchangeAuthorizationCode","createOAuthConnectMiddleware","next","strapi","config","get","throw","storedProviders","store","type","enabled","ApplicationError","getService","require$$5","buildRedirectUri","callbackOverride","oauthConnect","effectiveConfig","err","message"],"mappings":";;;;;;;;;;;;IAEA,MAAM,EAAEA,MAAM,EAAE,GAAGC,UAAAA;AAEnB,IAAA,MAAMC,wBAAAA,GAA2BC,gBAAAA,EAAAA;AACjC,IAAA,MAAMC,MAAAA,GAASC,aAAAA,EAAAA;AACf,IAAA,MAAMC,MAAAA,GAASC,aAAAA,EAAAA;IACf,MAAM,EAAEC,wBAAwB,EAAE,GAAGC,+BAAAA,EAAAA;AAErC,IAAA,MAAMC,cAAAA,GAAiB,UAAA;IAEvB,MAAMC,gBAAAA,GAAmB,CAACC,WAAAA,EAAaC,SAAAA,GAAAA;AACrC,QAAA,MAAMC,MAAAA,GAAS,CAAA,EAAGD,SAAAA,CAAAA,EAAYH,cAAAA,CAAe,CAAC,CAAC;AAC/C,QAAA,IAAI,CAACE,WAAAA,CAAYG,UAAU,CAACD,MAAAA,CAAAA,EAAS;YACnC,OAAO,IAAA;AACX,QAAA;AAEE,QAAA,MAAME,SAAAA,GAAYJ,WAAAA,CAAYK,KAAK,CAACH,OAAOI,MAAM,CAAA;QACjD,MAAM,CAACC,UAAUC,OAAAA,CAAQ,GAAGJ,UAAUK,KAAK,CAAC,GAAA,CAAA,CAAKC,MAAM,CAACC,OAAAA,CAAAA;AAExD,QAAA,IAAI,CAACJ,QAAAA,EAAU;YACb,OAAO,IAAA;AACX,QAAA;QAEE,OAAO;AACLA,YAAAA,QAAAA;AACAK,YAAAA,UAAAA,EAAYJ,OAAAA,KAAY;AAC5B,SAAA;AACA,IAAA,CAAA;AAEA;;;AAGA,KACA,MAAMK,mBAAAA,GAAsB,CAACC,YAAAA,EAAcC,YAAAA,EAAcC,WAAAA,GAAAA;QACvD,MAAMC,QAAAA,GAAW3B,wBAAwB,CAACwB,YAAAA,CAAa;AACvD,QAAA,MAAMI,YAAYD,QAAAA,IAAY;AAC5BE,YAAAA,KAAAA,EAAOJ,aAAaI,KAAK;AACzBC,YAAAA,aAAAA,EAAeL,aAAaK,aAAa;AACzCC,YAAAA,UAAAA,EAAYN,aAAaM,UAAU;AACnCC,YAAAA,WAAAA,EAAaP,aAAaO,WAAW;AACrCC,YAAAA,eAAAA,EAAiBR,aAAaQ,eAAe;AAC7CC,YAAAA,0BAAAA,EAA4BT,aAAaS;AAC7C,SAAA;QAEE,IAAIN,SAAAA,CAAUC,KAAK,KAAK,CAAA,EAAG;YACzB,IAAI,CAACD,SAAAA,CAAUI,WAAW,IAAI,CAACJ,SAAAA,CAAUE,aAAa,IAAI,CAACF,SAAAA,CAAUG,UAAU,EAAE;gBAC/E,OAAO,IAAA;AACb,YAAA;QACA,CAAA,MAAS,IAAI,CAACH,SAAAA,CAAUE,aAAa,IAAI,CAACF,SAAAA,CAAUG,UAAU,EAAE;YAC5D,OAAO,IAAA;AACX,QAAA;QAEE,OAAO;YACLI,IAAAA,EAAMX,YAAAA;AACN,YAAA,GAAGI,SAAS;AACZQ,YAAAA,GAAAA,EAAKX,aAAaW,GAAG;AACrBC,YAAAA,MAAAA,EAAQZ,aAAaY,MAAM;AAC3BC,YAAAA,KAAAA,EAAOb,aAAaa,KAAK;AACzBC,YAAAA,SAAAA,EAAWd,aAAac,SAAS;AACjCC,YAAAA,QAAAA,EAAUf,aAAae,QAAQ;YAC/BC,YAAAA,EAAcf;AAClB,SAAA;AACA,IAAA,CAAA;IAEA,MAAMgB,mBAAAA,GAAsB,CAACC,GAAAA,EAAKC,WAAAA,EAAaC,OAAAA,GAAAA;QAC7C,MAAMC,GAAAA,GAAM,IAAIC,GAAAA,CAAIH,WAAAA,CAAAA;AACpB,QAAA,MAAMI,SAAS,IAAIC,eAAAA,EAAAA;QAEnBC,MAAAA,CAAOC,OAAO,CAACN,OAAAA,CAAAA,CAASO,OAAO,CAAC,CAAC,CAAChB,KAAKiB,KAAAA,CAAM,GAAA;AAC3C,YAAA,IAAIjB,QAAQ,KAAA,EAAO;gBACjBc,MAAAA,CAAOC,OAAO,CAACE,KAAAA,CAAAA,CAAOD,OAAO,CAAC,CAAC,CAACE,QAAQC,QAAAA,CAAS,GAAA;oBAC/CP,MAAAA,CAAOQ,GAAG,CAAC,CAAC,IAAI,EAAEF,MAAAA,CAAO,CAAC,CAAC,EAAEG,MAAAA,CAAOF,QAAAA,CAAAA,CAAAA;AAC5C,gBAAA,CAAA,CAAA;AACM,gBAAA;AACN,YAAA;YACI,IAAIF,KAAAA,KAAUK,SAAAA,IAAaL,KAAAA,KAAU,IAAA,EAAM;gBACzCL,MAAAA,CAAOQ,GAAG,CAACpB,GAAAA,EAAKqB,MAAAA,CAAOJ,KAAAA,CAAAA,CAAAA;AAC7B,YAAA;AACA,QAAA,CAAA,CAAA;QAEEP,GAAAA,CAAIa,MAAM,GAAGX,MAAAA,CAAOY,QAAQ,EAAA;QAC5BjB,GAAAA,CAAIkB,QAAQ,CAACf,GAAAA,CAAIc,QAAQ,EAAA,CAAA;AAC3B,IAAA,CAAA;AAEA,IAAA,MAAME,uBAAuB,CAACnB,GAAAA,GAAAA;AAC5B,QAAA,MAAMoB,OAAAA,GAAUpB,GAAAA,CAAIqB,OAAO,CAACC,KAAK,EAAEF,OAAAA;AACnC,QAAA,OAAOA,OAAAA,GAAU;AAAEA,YAAAA;AAAO,SAAA,GAAK,EAAA;AACjC,IAAA,CAAA;AAEA,IAAA,MAAMG,2BAAAA,GAA8B,CAACvB,GAAAA,EAAKC,WAAAA,EAAa3B,QAAAA,EAAUkD,aAAAA,GAAAA;AAC/D,QAAA,MAAMC,aAAAA,GAAgBhE,MAAAA,CAAOiE,oBAAoB,CAACpD,QAAAA,EAAUkD,aAAAA,CAAAA;QAC5DxB,GAAAA,CAAIqB,OAAO,CAACC,KAAK,GAAG;YAClBK,QAAAA,EAAUhE,wBAAAA,CAAyB8D,aAAAA,EAAenD,QAAAA,CAASkB,IAAI;AACnE,SAAA;QAEE,OAAOO,mBAAAA,CAAoBC,GAAAA,EAAKC,WAAAA,EAAa;AAC/C,IAAA,CAAA;AAEA,IAAA,MAAM2B,eAAAA,GAAkB,OAAO5B,GAAAA,EAAK1B,QAAAA,EAAUuD,MAAAA,EAAQ9C,WAAAA,GAAAA;AACpD,QAAA,MAAM+C,YAAAA,GAAe,MAAMvE,MAAAA,CAAOuE,YAAY,CAAC;AAC7CC,YAAAA,UAAAA,EAAYzD,SAASe,WAAW;AAChCN,YAAAA,WAAAA;AACAiD,YAAAA,WAAAA,EAAa1D,SAASmB,GAAG;AACzBwC,YAAAA,gBAAAA,EAAkB3D,SAASoB;AAC/B,SAAA,CAAA;QAEEM,GAAAA,CAAIqB,OAAO,CAACC,KAAK,GAAG;AAClB,YAAA,GAAGH,qBAAqBnB,GAAAA,CAAI;AAC5B1B,YAAAA,QAAAA,EAAUuD,OAAOvD,QAAQ;YACzB4D,OAAAA,EAASJ;AACb,SAAA;QAEE,MAAMK,YAAAA,GAAe,CAAA,EAAG7D,QAAAA,CAASa,aAAa,CAAC,aAAa,EAAEiD,kBAAAA,CAAmBN,YAAAA,CAAaO,WAAW,CAAA,CAAA,CAAG;QAC5G,OAAOrC,GAAAA,CAAIkB,QAAQ,CAACiB,YAAAA,CAAAA;AACtB,IAAA,CAAA;AAEA,IAAA,MAAMG,eAAAA,GAAkB,CAACtC,GAAAA,EAAK1B,QAAAA,EAAUuD,MAAAA,EAAQ9C,WAAAA,GAAAA;QAC9C,MAAMwD,KAAAA,GAAQ9E,OAAO+E,aAAa,EAAA;QAClCxC,GAAAA,CAAIqB,OAAO,CAACC,KAAK,GAAG;AAClB,YAAA,GAAGH,qBAAqBnB,GAAAA,CAAI;AAC5B1B,YAAAA,QAAAA,EAAUuD,OAAOvD,QAAQ;AACzBiE,YAAAA;AACJ,SAAA;AAEE,QAAA,IAAIJ,YAAAA,GAAe1E,MAAAA,CAAOgF,iBAAiB,CAACnE,QAAAA,EAAU;AACpDmB,YAAAA,GAAAA,EAAKnB,SAASmB,GAAG;AACjBV,YAAAA,WAAAA;AACAY,YAAAA,KAAAA,EAAOrB,SAASqB,KAAK;AACrBC,YAAAA,SAAAA,EAAWtB,SAASsB;AACxB,SAAA,CAAA;AAEEuC,QAAAA,YAAAA,IAAgB,CAAC,OAAO,EAAEC,kBAAAA,CAAmBG,KAAAA,CAAAA,CAAAA,CAAQ;QACrD,OAAOvC,GAAAA,CAAIkB,QAAQ,CAACiB,YAAAA,CAAAA;AACtB,IAAA,CAAA;IAEA,MAAMO,oBAAAA,GAAuB,OAAO1C,GAAAA,EAAK1B,QAAAA,EAAU2B,WAAAA,GAAAA;AACjD,QAAA,MAAMoB,UAAUrB,GAAAA,CAAIqB,OAAO,CAACC,KAAK,IAAI,EAAA;QACrC,MAAM,EAAEe,aAAaM,UAAU,EAAEC,gBAAgBC,aAAa,EAAE,GAAG7C,GAAAA,CAAI8C,KAAK;QAC5E,MAAMhB,YAAAA,GAAeT,QAAQa,OAAO;AAEpC,QAAA,IAAI,CAACJ,YAAAA,EAAcO,WAAAA,IAAeM,UAAAA,KAAeb,YAAAA,CAAaO,WAAW,EAAE;AACzE,YAAA,MAAM,IAAIU,KAAAA,CAAM,uBAAA,CAAA;AACpB,QAAA;AAEE,QAAA,MAAMvB,aAAAA,GAAgB,MAAMjE,MAAAA,CAAOyF,WAAW,CAAC;AAC7CC,YAAAA,SAAAA,EAAW3E,SAASc,UAAU;AAC9B4C,YAAAA,WAAAA,EAAa1D,SAASmB,GAAG;AACzBwC,YAAAA,gBAAAA,EAAkB3D,SAASoB,MAAM;AACjCiD,YAAAA,UAAAA;AACAE,YAAAA,aAAAA;AACAK,YAAAA,oBAAAA,EAAsBpB,aAAaqB;AACvC,SAAA,CAAA;QAEE,OAAO5B,2BAAAA,CAA4BvB,GAAAA,EAAKC,WAAAA,EAAa3B,QAAAA,EAAUkD,aAAAA,CAAAA;AACjE,IAAA,CAAA;AAEA,IAAA,MAAM4B,oBAAAA,GAAuB,OAAOpD,GAAAA,EAAK1B,QAAAA,EAAU2B,WAAAA,EAAalB,WAAAA,GAAAA;AAC9D,QAAA,MAAMsC,UAAUrB,GAAAA,CAAIqB,OAAO,CAACC,KAAK,IAAI,EAAA;AACrC,QAAA,MAAM,EAAE+B,IAAI,EAAEd,KAAAA,EAAOe,UAAU,EAAEC,KAAK,EAAEC,iBAAAA,EAAmBC,gBAAgB,EAAE,GAAGzD,IAAI8C,KAAK;AAEzF,QAAA,IAAIS,KAAAA,EAAO;AACTvD,YAAAA,GAAAA,CAAIqB,OAAO,CAACC,KAAK,GAAG,EAAA;YACpB,OAAOvB,mBAAAA,CAAoBC,KAAKC,WAAAA,EAAa;AAC3CsD,gBAAAA,KAAAA;gBACAC,iBAAAA,EAAmBC;AACzB,aAAA,CAAA;AACA,QAAA;AAEE,QAAA,IAAI,CAACJ,IAAAA,EAAM;AACT,YAAA,MAAM,IAAIN,KAAAA,CAAM,+BAAA,CAAA;AACpB,QAAA;;AAGE,QAAA,IAAI,CAAC1B,OAAAA,CAAQkB,KAAK,IAAIe,UAAAA,KAAejC,OAAAA,CAAQkB,KAAK,EAAE;AAClD,YAAA,MAAM,IAAIQ,KAAAA,CAAM,uBAAA,CAAA;AACpB,QAAA;AAEE,QAAA,MAAMvB,aAAAA,GAAgB,MAAM/D,MAAAA,CAAOiG,yBAAyB,CAACpF,QAAAA,EAAU;AACrEmB,YAAAA,GAAAA,EAAKnB,SAASmB,GAAG;AACjBC,YAAAA,MAAAA,EAAQpB,SAASoB,MAAM;AACvBX,YAAAA,WAAAA;AACAsE,YAAAA,IAAAA;AACAzD,YAAAA,SAAAA,EAAWtB,SAASsB;AACxB,SAAA,CAAA;QAEE,OAAO2B,2BAAAA,CAA4BvB,GAAAA,EAAKC,WAAAA,EAAa3B,QAAAA,EAAUkD,aAAAA,CAAAA;AACjE,IAAA,CAAA;AAEA,IAAA,MAAMmC,4BAAAA,GAA+B,IAAA;AACnC,QAAA,OAAO,OAAO3D,GAAAA,EAAK4D,IAAAA,GAAAA;AACjB,YAAA,MAAM5F,SAAAA,GAAY6F,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,iBAAA,CAAA;YACpC,MAAM,CAAChG,YAAY,GAAGiC,GAAAA,CAAIkC,OAAO,CAAC/B,GAAG,CAAC3B,KAAK,CAAC,GAAA,CAAA;YAC5C,MAAMqD,MAAAA,GAAS/D,iBAAiBC,WAAAA,EAAaC,SAAAA,CAAAA;AAE7C,YAAA,IAAI,CAAC6D,MAAAA,EAAQ;gBACX,OAAO+B,IAAAA,EAAAA;AACb,YAAA;YAEI,IAAI,CAAC5D,GAAAA,CAAIqB,OAAO,EAAE;gBAChBrB,GAAAA,CAAIgE,KAAK,CAAC,GAAA,EAAK,2CAAA,CAAA;AACrB,YAAA;AAEI,YAAA,MAAMC,eAAAA,GAAkB,MAAMJ,MAAAA,CAC3BK,KAAK,CAAC;gBAAEC,IAAAA,EAAM,QAAA;gBAAU3E,IAAAA,EAAM,mBAAA;gBAAqBC,GAAAA,EAAK;AAAO,aAAA,CAAA,CAC/DsE,GAAG,EAAA;AAEN,YAAA,MAAMjF,YAAAA,GAAemF,eAAAA,GAAkBpC,MAAAA,CAAOvD,QAAQ,CAAC;YACvD,IAAI,CAACQ,cAAcsF,OAAAA,EAAS;gBAC1B,MAAM,IAAIjH,MAAAA,CAAOkH,gBAAgB,CAAC,2BAAA,CAAA;AACxC,YAAA;YAEI,MAAM,EAAEC,UAAU,EAAE,GAAGC,YAAAA,EAAAA;AACvB,YAAA,MAAMxF,cAAcuF,UAAAA,CAAW,WAAA,CAAA,CAAaE,gBAAgB,CAAC3C,OAAOvD,QAAQ,CAAA;AAE5E,YAAA,MAAMmG,gBAAAA,GACJzE,GAAAA,CAAIuC,KAAK,CAACmC,YAAY,EAAE7E,QAAAA,IAAYG,GAAAA,CAAIqB,OAAO,CAACC,KAAK,EAAEF,OAAAA,EAASvB,QAAAA;AAClE,YAAA,MAAM8E,kBAAkBF,gBAAAA,GACpB;AAAE,gBAAA,GAAG3F,YAAY;gBAAEe,QAAAA,EAAU4E;aAAgB,GAC7C3F,YAAAA;AAEJ,YAAA,MAAMR,QAAAA,GAAWM,mBAAAA,CAAoBiD,MAAAA,CAAOvD,QAAQ,EAAEqG,eAAAA,EAAiB5F,WAAAA,CAAAA;AAEvE,YAAA,IAAI,CAACT,QAAAA,EAAU;gBACb,MAAM,IAAInB,MAAAA,CAAOkH,gBAAgB,CAAC,wBAAA,CAAA;AACxC,YAAA;YAEIrE,GAAAA,CAAIqB,OAAO,CAACC,KAAK,GAAGtB,IAAIqB,OAAO,CAACC,KAAK,IAAI,EAAA;YAEzC,IAAI,CAACO,MAAAA,CAAOlD,UAAU,EAAE;gBACtB,IAAIL,QAAAA,CAASY,KAAK,KAAK,CAAA,EAAG;oBACxB,OAAO0C,eAAAA,CAAgB5B,GAAAA,EAAK1B,QAAAA,EAAUuD,MAAAA,EAAQ9C,WAAAA,CAAAA;AACtD,gBAAA;gBACM,OAAOuD,eAAAA,CAAgBtC,GAAAA,EAAK1B,QAAAA,EAAUuD,MAAAA,EAAQ9C,WAAAA,CAAAA;AACpD,YAAA;YAEI,MAAMkB,WAAAA,GAAc0E,gBAAgB9E,QAAQ;AAC5C,YAAA,IAAI,CAACI,WAAAA,EAAa;gBAChB,MAAM,IAAI9C,MAAAA,CAAOkH,gBAAgB,CAAC,yCAAA,CAAA;AACxC,YAAA;YAEI,IAAI;gBACF,IAAI/F,QAAAA,CAASY,KAAK,KAAK,CAAA,EAAG;oBACxB,OAAO,MAAMwD,oBAAAA,CAAqB1C,GAAAA,EAAK1B,QAAAA,EAAU2B,WAAAA,CAAAA;AACzD,gBAAA;AACM,gBAAA,OAAO,MAAMmD,oBAAAA,CAAqBpD,GAAAA,EAAK1B,QAAAA,EAAU2B,WAAAA,EAAalB,WAAAA,CAAAA;AACpE,YAAA,CAAA,CAAM,OAAO6F,GAAAA,EAAK;AACZ5E,gBAAAA,GAAAA,CAAIqB,OAAO,CAACC,KAAK,GAAG,EAAA;gBACpB,OAAOvB,mBAAAA,CAAoBC,KAAKC,WAAAA,EAAa;oBAC3CsD,KAAAA,EAAO,aAAA;AACPC,oBAAAA,iBAAAA,EAAmBoB,IAAIC;AAC/B,iBAAA,CAAA;AACA,YAAA;AACA,QAAA,CAAA;AACA,IAAA,CAAA;IAEAH,YAAAA,GAAiB;AACff,QAAAA,4BAAAA;AACA7F,QAAAA,gBAAAA;AACAc,QAAAA,mBAAAA;AACAmB,QAAAA;AACF,KAAA;;;;;;"}
@@ -0,0 +1,67 @@
1
+ 'use strict';
2
+
3
+ var trimGrantSessionResponse_1;
4
+ var hasRequiredTrimGrantSessionResponse;
5
+ function requireTrimGrantSessionResponse() {
6
+ if (hasRequiredTrimGrantSessionResponse) return trimGrantSessionResponse_1;
7
+ hasRequiredTrimGrantSessionResponse = 1;
8
+ const compact = (value)=>{
9
+ if (value === null || value === undefined) {
10
+ return undefined;
11
+ }
12
+ if (typeof value !== 'object' || Array.isArray(value)) {
13
+ return value;
14
+ }
15
+ return Object.fromEntries(Object.entries(value).map(([key, entry])=>[
16
+ key,
17
+ compact(entry)
18
+ ]).filter(([, entry])=>entry !== undefined));
19
+ };
20
+ /**
21
+ * Compact grant's OAuth token response before it is written to the signed
22
+ * koa-session cookie. The full token exchange payload (especially Cognito's
23
+ * dual JWTs plus a duplicated raw blob) can exceed the browser's ~4 KB
24
+ * per-cookie limit and silently break the auth callback.
25
+ *
26
+ * Keep only fields that auth.callback / providers-registry actually read.
27
+ */ const trimGrantSessionResponse = (grantResponse, provider)=>{
28
+ if (!grantResponse || typeof grantResponse !== 'object') {
29
+ return grantResponse;
30
+ }
31
+ switch(provider){
32
+ case 'cognito':
33
+ return compact({
34
+ id_token: grantResponse.id_token
35
+ });
36
+ case 'twitter':
37
+ return compact({
38
+ access_token: grantResponse.access_token,
39
+ access_secret: grantResponse.access_secret,
40
+ raw: grantResponse.raw?.screen_name ? {
41
+ screen_name: grantResponse.raw.screen_name
42
+ } : undefined
43
+ });
44
+ case 'vk':
45
+ return compact({
46
+ access_token: grantResponse.access_token,
47
+ raw: grantResponse.raw?.email != null && grantResponse.raw?.user_id != null ? {
48
+ email: grantResponse.raw.email,
49
+ user_id: grantResponse.raw.user_id
50
+ } : undefined
51
+ });
52
+ default:
53
+ return compact({
54
+ access_token: grantResponse.access_token,
55
+ oauth_token: grantResponse.oauth_token,
56
+ id_token: grantResponse.id_token
57
+ });
58
+ }
59
+ };
60
+ trimGrantSessionResponse_1 = {
61
+ trimGrantSessionResponse
62
+ };
63
+ return trimGrantSessionResponse_1;
64
+ }
65
+
66
+ exports.__require = requireTrimGrantSessionResponse;
67
+ //# sourceMappingURL=trim-grant-session-response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trim-grant-session-response.js","sources":["../../../server/src/utils/trim-grant-session-response.js"],"sourcesContent":["'use strict';\n\nconst compact = (value) => {\n if (value === null || value === undefined) {\n return undefined;\n }\n\n if (typeof value !== 'object' || Array.isArray(value)) {\n return value;\n }\n\n return Object.fromEntries(\n Object.entries(value)\n .map(([key, entry]) => [key, compact(entry)])\n .filter(([, entry]) => entry !== undefined)\n );\n};\n\n/**\n * Compact grant's OAuth token response before it is written to the signed\n * koa-session cookie. The full token exchange payload (especially Cognito's\n * dual JWTs plus a duplicated raw blob) can exceed the browser's ~4 KB\n * per-cookie limit and silently break the auth callback.\n *\n * Keep only fields that auth.callback / providers-registry actually read.\n */\nconst trimGrantSessionResponse = (grantResponse, provider) => {\n if (!grantResponse || typeof grantResponse !== 'object') {\n return grantResponse;\n }\n\n switch (provider) {\n case 'cognito':\n return compact({\n id_token: grantResponse.id_token,\n });\n\n case 'twitter':\n return compact({\n access_token: grantResponse.access_token,\n access_secret: grantResponse.access_secret,\n raw: grantResponse.raw?.screen_name\n ? { screen_name: grantResponse.raw.screen_name }\n : undefined,\n });\n\n case 'vk':\n return compact({\n access_token: grantResponse.access_token,\n raw:\n grantResponse.raw?.email != null && grantResponse.raw?.user_id != null\n ? {\n email: grantResponse.raw.email,\n user_id: grantResponse.raw.user_id,\n }\n : undefined,\n });\n\n default:\n return compact({\n access_token: grantResponse.access_token,\n oauth_token: grantResponse.oauth_token,\n id_token: grantResponse.id_token,\n });\n }\n};\n\nmodule.exports = {\n trimGrantSessionResponse,\n};\n"],"names":["compact","value","undefined","Array","isArray","Object","fromEntries","entries","map","key","entry","filter","trimGrantSessionResponse","grantResponse","provider","id_token","access_token","access_secret","raw","screen_name","email","user_id","oauth_token","trimGrantSessionResponse_1"],"mappings":";;;;;;;AAEA,IAAA,MAAMA,UAAU,CAACC,KAAAA,GAAAA;QACf,IAAIA,KAAAA,KAAU,IAAA,IAAQA,KAAAA,KAAUC,SAAAA,EAAW;YACzC,OAAOA,SAAAA;AACX,QAAA;AAEE,QAAA,IAAI,OAAOD,KAAAA,KAAU,QAAA,IAAYE,KAAAA,CAAMC,OAAO,CAACH,KAAAA,CAAAA,EAAQ;YACrD,OAAOA,KAAAA;AACX,QAAA;AAEE,QAAA,OAAOI,MAAAA,CAAOC,WAAW,CACvBD,MAAAA,CAAOE,OAAO,CAACN,KAAAA,CAAAA,CACZO,GAAG,CAAC,CAAC,CAACC,GAAAA,EAAKC,MAAM,GAAK;AAACD,gBAAAA,GAAAA;gBAAKT,OAAAA,CAAQU,KAAAA;AAAO,aAAA,CAAA,CAC3CC,MAAM,CAAC,CAAC,GAAGD,KAAAA,CAAM,GAAKA,KAAAA,KAAUR,SAAAA,CAAAA,CAAAA;AAEvC,IAAA,CAAA;AAEA;;;;;;;KAQA,MAAMU,wBAAAA,GAA2B,CAACC,aAAAA,EAAeC,QAAAA,GAAAA;AAC/C,QAAA,IAAI,CAACD,aAAAA,IAAiB,OAAOA,aAAAA,KAAkB,QAAA,EAAU;YACvD,OAAOA,aAAAA;AACX,QAAA;QAEE,OAAQC,QAAAA;YACN,KAAK,SAAA;AACH,gBAAA,OAAOd,OAAAA,CAAQ;AACbe,oBAAAA,QAAAA,EAAUF,cAAcE;AAChC,iBAAA,CAAA;YAEI,KAAK,SAAA;AACH,gBAAA,OAAOf,OAAAA,CAAQ;AACbgB,oBAAAA,YAAAA,EAAcH,cAAcG,YAAY;AACxCC,oBAAAA,aAAAA,EAAeJ,cAAcI,aAAa;oBAC1CC,GAAAA,EAAKL,aAAAA,CAAcK,GAAG,EAAEC,WAAAA,GACpB;wBAAEA,WAAAA,EAAaN,aAAAA,CAAcK,GAAG,CAACC;qBAAW,GAC5CjB;AACZ,iBAAA,CAAA;YAEI,KAAK,IAAA;AACH,gBAAA,OAAOF,OAAAA,CAAQ;AACbgB,oBAAAA,YAAAA,EAAcH,cAAcG,YAAY;oBACxCE,GAAAA,EACEL,aAAAA,CAAcK,GAAG,EAAEE,KAAAA,IAAS,QAAQP,aAAAA,CAAcK,GAAG,EAAEG,OAAAA,IAAW,IAAA,GAC9D;wBACED,KAAAA,EAAOP,aAAAA,CAAcK,GAAG,CAACE,KAAK;wBAC9BC,OAAAA,EAASR,aAAAA,CAAcK,GAAG,CAACG;qBAC3C,GACcnB;AACd,iBAAA,CAAA;AAEI,YAAA;AACE,gBAAA,OAAOF,OAAAA,CAAQ;AACbgB,oBAAAA,YAAAA,EAAcH,cAAcG,YAAY;AACxCM,oBAAAA,WAAAA,EAAaT,cAAcS,WAAW;AACtCP,oBAAAA,QAAAA,EAAUF,cAAcE;AAChC,iBAAA,CAAA;AACA;AACA,IAAA,CAAA;IAEAQ,0BAAAA,GAAiB;AACfX,QAAAA;AACF,KAAA;;;;;;"}
@@ -0,0 +1,65 @@
1
+ var trimGrantSessionResponse_1;
2
+ var hasRequiredTrimGrantSessionResponse;
3
+ function requireTrimGrantSessionResponse() {
4
+ if (hasRequiredTrimGrantSessionResponse) return trimGrantSessionResponse_1;
5
+ hasRequiredTrimGrantSessionResponse = 1;
6
+ const compact = (value)=>{
7
+ if (value === null || value === undefined) {
8
+ return undefined;
9
+ }
10
+ if (typeof value !== 'object' || Array.isArray(value)) {
11
+ return value;
12
+ }
13
+ return Object.fromEntries(Object.entries(value).map(([key, entry])=>[
14
+ key,
15
+ compact(entry)
16
+ ]).filter(([, entry])=>entry !== undefined));
17
+ };
18
+ /**
19
+ * Compact grant's OAuth token response before it is written to the signed
20
+ * koa-session cookie. The full token exchange payload (especially Cognito's
21
+ * dual JWTs plus a duplicated raw blob) can exceed the browser's ~4 KB
22
+ * per-cookie limit and silently break the auth callback.
23
+ *
24
+ * Keep only fields that auth.callback / providers-registry actually read.
25
+ */ const trimGrantSessionResponse = (grantResponse, provider)=>{
26
+ if (!grantResponse || typeof grantResponse !== 'object') {
27
+ return grantResponse;
28
+ }
29
+ switch(provider){
30
+ case 'cognito':
31
+ return compact({
32
+ id_token: grantResponse.id_token
33
+ });
34
+ case 'twitter':
35
+ return compact({
36
+ access_token: grantResponse.access_token,
37
+ access_secret: grantResponse.access_secret,
38
+ raw: grantResponse.raw?.screen_name ? {
39
+ screen_name: grantResponse.raw.screen_name
40
+ } : undefined
41
+ });
42
+ case 'vk':
43
+ return compact({
44
+ access_token: grantResponse.access_token,
45
+ raw: grantResponse.raw?.email != null && grantResponse.raw?.user_id != null ? {
46
+ email: grantResponse.raw.email,
47
+ user_id: grantResponse.raw.user_id
48
+ } : undefined
49
+ });
50
+ default:
51
+ return compact({
52
+ access_token: grantResponse.access_token,
53
+ oauth_token: grantResponse.oauth_token,
54
+ id_token: grantResponse.id_token
55
+ });
56
+ }
57
+ };
58
+ trimGrantSessionResponse_1 = {
59
+ trimGrantSessionResponse
60
+ };
61
+ return trimGrantSessionResponse_1;
62
+ }
63
+
64
+ export { requireTrimGrantSessionResponse as __require };
65
+ //# sourceMappingURL=trim-grant-session-response.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trim-grant-session-response.mjs","sources":["../../../server/src/utils/trim-grant-session-response.js"],"sourcesContent":["'use strict';\n\nconst compact = (value) => {\n if (value === null || value === undefined) {\n return undefined;\n }\n\n if (typeof value !== 'object' || Array.isArray(value)) {\n return value;\n }\n\n return Object.fromEntries(\n Object.entries(value)\n .map(([key, entry]) => [key, compact(entry)])\n .filter(([, entry]) => entry !== undefined)\n );\n};\n\n/**\n * Compact grant's OAuth token response before it is written to the signed\n * koa-session cookie. The full token exchange payload (especially Cognito's\n * dual JWTs plus a duplicated raw blob) can exceed the browser's ~4 KB\n * per-cookie limit and silently break the auth callback.\n *\n * Keep only fields that auth.callback / providers-registry actually read.\n */\nconst trimGrantSessionResponse = (grantResponse, provider) => {\n if (!grantResponse || typeof grantResponse !== 'object') {\n return grantResponse;\n }\n\n switch (provider) {\n case 'cognito':\n return compact({\n id_token: grantResponse.id_token,\n });\n\n case 'twitter':\n return compact({\n access_token: grantResponse.access_token,\n access_secret: grantResponse.access_secret,\n raw: grantResponse.raw?.screen_name\n ? { screen_name: grantResponse.raw.screen_name }\n : undefined,\n });\n\n case 'vk':\n return compact({\n access_token: grantResponse.access_token,\n raw:\n grantResponse.raw?.email != null && grantResponse.raw?.user_id != null\n ? {\n email: grantResponse.raw.email,\n user_id: grantResponse.raw.user_id,\n }\n : undefined,\n });\n\n default:\n return compact({\n access_token: grantResponse.access_token,\n oauth_token: grantResponse.oauth_token,\n id_token: grantResponse.id_token,\n });\n }\n};\n\nmodule.exports = {\n trimGrantSessionResponse,\n};\n"],"names":["compact","value","undefined","Array","isArray","Object","fromEntries","entries","map","key","entry","filter","trimGrantSessionResponse","grantResponse","provider","id_token","access_token","access_secret","raw","screen_name","email","user_id","oauth_token","trimGrantSessionResponse_1"],"mappings":";;;;;AAEA,IAAA,MAAMA,UAAU,CAACC,KAAAA,GAAAA;QACf,IAAIA,KAAAA,KAAU,IAAA,IAAQA,KAAAA,KAAUC,SAAAA,EAAW;YACzC,OAAOA,SAAAA;AACX,QAAA;AAEE,QAAA,IAAI,OAAOD,KAAAA,KAAU,QAAA,IAAYE,KAAAA,CAAMC,OAAO,CAACH,KAAAA,CAAAA,EAAQ;YACrD,OAAOA,KAAAA;AACX,QAAA;AAEE,QAAA,OAAOI,MAAAA,CAAOC,WAAW,CACvBD,MAAAA,CAAOE,OAAO,CAACN,KAAAA,CAAAA,CACZO,GAAG,CAAC,CAAC,CAACC,GAAAA,EAAKC,MAAM,GAAK;AAACD,gBAAAA,GAAAA;gBAAKT,OAAAA,CAAQU,KAAAA;AAAO,aAAA,CAAA,CAC3CC,MAAM,CAAC,CAAC,GAAGD,KAAAA,CAAM,GAAKA,KAAAA,KAAUR,SAAAA,CAAAA,CAAAA;AAEvC,IAAA,CAAA;AAEA;;;;;;;KAQA,MAAMU,wBAAAA,GAA2B,CAACC,aAAAA,EAAeC,QAAAA,GAAAA;AAC/C,QAAA,IAAI,CAACD,aAAAA,IAAiB,OAAOA,aAAAA,KAAkB,QAAA,EAAU;YACvD,OAAOA,aAAAA;AACX,QAAA;QAEE,OAAQC,QAAAA;YACN,KAAK,SAAA;AACH,gBAAA,OAAOd,OAAAA,CAAQ;AACbe,oBAAAA,QAAAA,EAAUF,cAAcE;AAChC,iBAAA,CAAA;YAEI,KAAK,SAAA;AACH,gBAAA,OAAOf,OAAAA,CAAQ;AACbgB,oBAAAA,YAAAA,EAAcH,cAAcG,YAAY;AACxCC,oBAAAA,aAAAA,EAAeJ,cAAcI,aAAa;oBAC1CC,GAAAA,EAAKL,aAAAA,CAAcK,GAAG,EAAEC,WAAAA,GACpB;wBAAEA,WAAAA,EAAaN,aAAAA,CAAcK,GAAG,CAACC;qBAAW,GAC5CjB;AACZ,iBAAA,CAAA;YAEI,KAAK,IAAA;AACH,gBAAA,OAAOF,OAAAA,CAAQ;AACbgB,oBAAAA,YAAAA,EAAcH,cAAcG,YAAY;oBACxCE,GAAAA,EACEL,aAAAA,CAAcK,GAAG,EAAEE,KAAAA,IAAS,QAAQP,aAAAA,CAAcK,GAAG,EAAEG,OAAAA,IAAW,IAAA,GAC9D;wBACED,KAAAA,EAAOP,aAAAA,CAAcK,GAAG,CAACE,KAAK;wBAC9BC,OAAAA,EAASR,aAAAA,CAAcK,GAAG,CAACG;qBAC3C,GACcnB;AACd,iBAAA,CAAA;AAEI,YAAA;AACE,gBAAA,OAAOF,OAAAA,CAAQ;AACbgB,oBAAAA,YAAAA,EAAcH,cAAcG,YAAY;AACxCM,oBAAAA,WAAAA,EAAaT,cAAcS,WAAW;AACtCP,oBAAAA,QAAAA,EAAUF,cAAcE;AAChC,iBAAA,CAAA;AACA;AACA,IAAA,CAAA;IAEAQ,0BAAAA,GAAiB;AACfX,QAAAA;AACF,KAAA;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/plugin-users-permissions",
3
- "version": "5.52.3",
3
+ "version": "5.53.0",
4
4
  "description": "Protect your API with a full-authentication process based on JWT",
5
5
  "homepage": "https://strapi.io",
6
6
  "bugs": {
@@ -55,7 +55,7 @@
55
55
  "dependencies": {
56
56
  "@strapi/design-system": "2.2.4",
57
57
  "@strapi/icons": "2.2.4",
58
- "@strapi/utils": "5.52.3",
58
+ "@strapi/utils": "5.53.0",
59
59
  "bcryptjs": "2.4.3",
60
60
  "formik": "2.4.9",
61
61
  "immer": "9.0.21",
@@ -72,8 +72,8 @@
72
72
  "zod": "4.4.3"
73
73
  },
74
74
  "devDependencies": {
75
- "@strapi/admin": "5.52.3",
76
- "@strapi/strapi": "5.52.3",
75
+ "@strapi/admin": "5.53.0",
76
+ "@strapi/strapi": "5.53.0",
77
77
  "@testing-library/dom": "10.4.1",
78
78
  "@testing-library/jest-dom": "6.9.1",
79
79
  "@testing-library/react": "16.3.2",
@@ -205,7 +205,15 @@ module.exports = ({ strapi }) => ({
205
205
 
206
206
  // Connect the user with the third-party provider.
207
207
  try {
208
- const user = await getService('providers').connect(provider, ctx.query);
208
+ const grantResponse = _.get(ctx, 'session.grant.response');
209
+
210
+ if (!grantResponse) {
211
+ throw new ApplicationError('OAuth authentication requires a completed provider session');
212
+ }
213
+
214
+ const user = await getService('providers').connect(provider, grantResponse, {
215
+ grantResponse,
216
+ });
209
217
 
210
218
  if (user.blocked) {
211
219
  throw new ForbiddenError('Your account has been blocked by an administrator');
@@ -3,9 +3,11 @@
3
3
  const { toPlainObject } = require('lodash/fp');
4
4
 
5
5
  const { checkBadRequest } = require('../../utils');
6
+ const { createRateLimitRunner } = require('./rate-limit');
6
7
 
7
8
  module.exports = ({ nexus, strapi }) => {
8
9
  const { nonNull } = nexus;
10
+ const runRateLimit = createRateLimitRunner(strapi, '/auth/change-password');
9
11
 
10
12
  return {
11
13
  type: 'UsersPermissionsLoginPayload',
@@ -21,11 +23,9 @@ module.exports = ({ nexus, strapi }) => {
21
23
  async resolve(parent, args, context) {
22
24
  const { koaContext } = context;
23
25
 
24
- koaContext.request.body = toPlainObject(args);
25
-
26
- await strapi.plugin('users-permissions').controller('auth').changePassword(koaContext);
27
-
28
- const output = koaContext.body;
26
+ const output = await runRateLimit(koaContext, { body: toPlainObject(args) }, (ctx) =>
27
+ strapi.plugin('users-permissions').controller('auth').changePassword(ctx)
28
+ );
29
29
 
30
30
  checkBadRequest(output);
31
31
 
@@ -3,9 +3,11 @@
3
3
  const { toPlainObject } = require('lodash/fp');
4
4
 
5
5
  const { checkBadRequest } = require('../../utils');
6
+ const { createRateLimitRunner } = require('./rate-limit');
6
7
 
7
8
  module.exports = ({ nexus, strapi }) => {
8
9
  const { nonNull } = nexus;
10
+ const runRateLimit = createRateLimitRunner(strapi, '/auth/forgot-password');
9
11
 
10
12
  return {
11
13
  type: 'UsersPermissionsPasswordPayload',
@@ -19,11 +21,9 @@ module.exports = ({ nexus, strapi }) => {
19
21
  async resolve(parent, args, context) {
20
22
  const { koaContext } = context;
21
23
 
22
- koaContext.request.body = toPlainObject(args);
23
-
24
- await strapi.plugin('users-permissions').controller('auth').forgotPassword(koaContext);
25
-
26
- const output = koaContext.body;
24
+ const output = await runRateLimit(koaContext, { body: toPlainObject(args) }, (ctx) =>
25
+ strapi.plugin('users-permissions').controller('auth').forgotPassword(ctx)
26
+ );
27
27
 
28
28
  checkBadRequest(output);
29
29
 
@@ -3,9 +3,11 @@
3
3
  const { toPlainObject } = require('lodash/fp');
4
4
 
5
5
  const { checkBadRequest } = require('../../utils');
6
+ const { createRateLimitRunner } = require('./rate-limit');
6
7
 
7
8
  module.exports = ({ nexus, strapi }) => {
8
9
  const { nonNull } = nexus;
10
+ const runRateLimit = createRateLimitRunner(strapi, '/auth/local');
9
11
 
10
12
  return {
11
13
  type: nonNull('UsersPermissionsLoginPayload'),
@@ -17,12 +19,14 @@ module.exports = ({ nexus, strapi }) => {
17
19
  async resolve(parent, args, context) {
18
20
  const { koaContext } = context;
19
21
 
20
- koaContext.params = { provider: args.input.provider };
21
- koaContext.request.body = toPlainObject(args.input);
22
-
23
- await strapi.plugin('users-permissions').controller('auth').callback(koaContext);
24
-
25
- const output = koaContext.body;
22
+ const output = await runRateLimit(
23
+ koaContext,
24
+ {
25
+ body: toPlainObject(args.input),
26
+ params: { provider: args.input.provider },
27
+ },
28
+ (ctx) => strapi.plugin('users-permissions').controller('auth').callback(ctx)
29
+ );
26
30
 
27
31
  checkBadRequest(output);
28
32
 
@@ -0,0 +1,62 @@
1
+ 'use strict';
2
+
3
+ const RATE_LIMIT_MIDDLEWARE = 'plugin::users-permissions.rateLimit';
4
+ const contextQueues = new WeakMap();
5
+
6
+ const getRateLimitPath = (strapi, routeSuffix) => {
7
+ const configuredPrefix = strapi.config.get('api.rest.prefix', '/api');
8
+ const prefix = typeof configuredPrefix === 'string' ? configuredPrefix : '/api';
9
+ const normalizedPrefix = prefix.replace(/^\/+|\/+$/g, '');
10
+ const normalizedSuffix = routeSuffix.replace(/^\/+/, '');
11
+
12
+ return `/${[normalizedPrefix, normalizedSuffix].filter(Boolean).join('/')}`;
13
+ };
14
+
15
+ const enqueueContextOperation = (koaContext, operation) => {
16
+ const previous = contextQueues.get(koaContext) || Promise.resolve();
17
+ const result = previous.catch(() => undefined).then(operation);
18
+
19
+ contextQueues.set(
20
+ koaContext,
21
+ result.catch(() => undefined)
22
+ );
23
+
24
+ return result;
25
+ };
26
+
27
+ const createRateLimitRunner = (strapi, routeSuffix) => {
28
+ const rateLimit = strapi.middleware(RATE_LIMIT_MIDDLEWARE)({}, { strapi });
29
+ const routePath = getRateLimitPath(strapi, routeSuffix);
30
+
31
+ return (koaContext, { body, params }, controller) =>
32
+ enqueueContextOperation(koaContext, async () => {
33
+ const originalBody = koaContext.request.body;
34
+ const originalPath = koaContext.request.path;
35
+ const originalParams = koaContext.params;
36
+ const originalResponseBody = koaContext.body;
37
+ let responseStatus = 200;
38
+
39
+ koaContext.request.path = routePath;
40
+ koaContext.request.body = body;
41
+ if (params) {
42
+ koaContext.params = params;
43
+ }
44
+
45
+ try {
46
+ await rateLimit(koaContext, () => controller(koaContext));
47
+ responseStatus = koaContext.status;
48
+ return koaContext.body;
49
+ } finally {
50
+ koaContext.request.path = originalPath;
51
+ koaContext.request.body = originalBody;
52
+ koaContext.params = originalParams;
53
+ koaContext.body = originalResponseBody;
54
+ koaContext.status = responseStatus;
55
+ }
56
+ });
57
+ };
58
+
59
+ module.exports = {
60
+ createRateLimitRunner,
61
+ getRateLimitPath,
62
+ };
@@ -3,9 +3,11 @@
3
3
  const { toPlainObject } = require('lodash/fp');
4
4
 
5
5
  const { checkBadRequest } = require('../../utils');
6
+ const { createRateLimitRunner } = require('./rate-limit');
6
7
 
7
8
  module.exports = ({ nexus, strapi }) => {
8
9
  const { nonNull } = nexus;
10
+ const runRateLimit = createRateLimitRunner(strapi, '/auth/local/register');
9
11
 
10
12
  return {
11
13
  type: nonNull('UsersPermissionsLoginPayload'),
@@ -19,11 +21,9 @@ module.exports = ({ nexus, strapi }) => {
19
21
  async resolve(parent, args, context) {
20
22
  const { koaContext } = context;
21
23
 
22
- koaContext.request.body = toPlainObject(args.input);
23
-
24
- await strapi.plugin('users-permissions').controller('auth').register(koaContext);
25
-
26
- const output = koaContext.body;
24
+ const output = await runRateLimit(koaContext, { body: toPlainObject(args.input) }, (ctx) =>
25
+ strapi.plugin('users-permissions').controller('auth').register(ctx)
26
+ );
27
27
 
28
28
  checkBadRequest(output);
29
29