@strapi/admin 5.23.6 → 5.24.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 (108) hide show
  1. package/dist/admin/admin/src/features/Auth.js +9 -28
  2. package/dist/admin/admin/src/features/Auth.js.map +1 -1
  3. package/dist/admin/admin/src/features/Auth.mjs +11 -30
  4. package/dist/admin/admin/src/features/Auth.mjs.map +1 -1
  5. package/dist/admin/admin/src/pages/Auth/components/Register.js +9 -2
  6. package/dist/admin/admin/src/pages/Auth/components/Register.js.map +1 -1
  7. package/dist/admin/admin/src/pages/Auth/components/Register.mjs +9 -2
  8. package/dist/admin/admin/src/pages/Auth/components/Register.mjs.map +1 -1
  9. package/dist/admin/admin/src/services/auth.js +7 -6
  10. package/dist/admin/admin/src/services/auth.js.map +1 -1
  11. package/dist/admin/admin/src/services/auth.mjs +7 -6
  12. package/dist/admin/admin/src/services/auth.mjs.map +1 -1
  13. package/dist/admin/admin/src/utils/baseQuery.js +78 -42
  14. package/dist/admin/admin/src/utils/baseQuery.js.map +1 -1
  15. package/dist/admin/admin/src/utils/baseQuery.mjs +79 -43
  16. package/dist/admin/admin/src/utils/baseQuery.mjs.map +1 -1
  17. package/dist/admin/admin/src/utils/deviceId.js +38 -0
  18. package/dist/admin/admin/src/utils/deviceId.js.map +1 -0
  19. package/dist/admin/admin/src/utils/deviceId.mjs +36 -0
  20. package/dist/admin/admin/src/utils/deviceId.mjs.map +1 -0
  21. package/dist/admin/src/services/auth.d.ts +19 -10
  22. package/dist/admin/src/utils/deviceId.d.ts +5 -0
  23. package/dist/ee/server/src/controllers/authentication-utils/middlewares.d.ts.map +1 -1
  24. package/dist/ee/server/src/services/user.d.ts.map +1 -1
  25. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js +43 -17
  26. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js.map +1 -1
  27. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs +43 -17
  28. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs.map +1 -1
  29. package/dist/server/ee/server/src/services/user.js +14 -0
  30. package/dist/server/ee/server/src/services/user.js.map +1 -1
  31. package/dist/server/ee/server/src/services/user.mjs +14 -0
  32. package/dist/server/ee/server/src/services/user.mjs.map +1 -1
  33. package/dist/server/server/src/bootstrap.js +22 -0
  34. package/dist/server/server/src/bootstrap.js.map +1 -1
  35. package/dist/server/server/src/bootstrap.mjs +22 -0
  36. package/dist/server/server/src/bootstrap.mjs.map +1 -1
  37. package/dist/server/server/src/content-types/index.js +4 -0
  38. package/dist/server/server/src/content-types/index.js.map +1 -1
  39. package/dist/server/server/src/content-types/index.mjs +4 -0
  40. package/dist/server/server/src/content-types/index.mjs.map +1 -1
  41. package/dist/server/server/src/content-types/session.js +91 -0
  42. package/dist/server/server/src/content-types/session.js.map +1 -0
  43. package/dist/server/server/src/content-types/session.mjs +89 -0
  44. package/dist/server/server/src/content-types/session.mjs.map +1 -0
  45. package/dist/server/server/src/controllers/authentication.js +169 -38
  46. package/dist/server/server/src/controllers/authentication.js.map +1 -1
  47. package/dist/server/server/src/controllers/authentication.mjs +169 -38
  48. package/dist/server/server/src/controllers/authentication.mjs.map +1 -1
  49. package/dist/server/server/src/routes/authentication.js +2 -2
  50. package/dist/server/server/src/routes/authentication.js.map +1 -1
  51. package/dist/server/server/src/routes/authentication.mjs +2 -2
  52. package/dist/server/server/src/routes/authentication.mjs.map +1 -1
  53. package/dist/server/server/src/services/token.js +44 -31
  54. package/dist/server/server/src/services/token.js.map +1 -1
  55. package/dist/server/server/src/services/token.mjs +44 -30
  56. package/dist/server/server/src/services/token.mjs.map +1 -1
  57. package/dist/server/server/src/services/user.js +14 -0
  58. package/dist/server/server/src/services/user.js.map +1 -1
  59. package/dist/server/server/src/services/user.mjs +14 -0
  60. package/dist/server/server/src/services/user.mjs.map +1 -1
  61. package/dist/server/server/src/strategies/admin.js +23 -3
  62. package/dist/server/server/src/strategies/admin.js.map +1 -1
  63. package/dist/server/server/src/strategies/admin.mjs +23 -3
  64. package/dist/server/server/src/strategies/admin.mjs.map +1 -1
  65. package/dist/server/server/src/validation/authentication/login.js +16 -0
  66. package/dist/server/server/src/validation/authentication/login.js.map +1 -0
  67. package/dist/server/server/src/validation/authentication/login.mjs +14 -0
  68. package/dist/server/server/src/validation/authentication/login.mjs.map +1 -0
  69. package/dist/server/server/src/validation/authentication/register.js +6 -2
  70. package/dist/server/server/src/validation/authentication/register.js.map +1 -1
  71. package/dist/server/server/src/validation/authentication/register.mjs +6 -2
  72. package/dist/server/server/src/validation/authentication/register.mjs.map +1 -1
  73. package/dist/server/shared/utils/session-auth.js +76 -0
  74. package/dist/server/shared/utils/session-auth.js.map +1 -0
  75. package/dist/server/shared/utils/session-auth.mjs +65 -0
  76. package/dist/server/shared/utils/session-auth.mjs.map +1 -0
  77. package/dist/server/src/bootstrap.d.ts.map +1 -1
  78. package/dist/server/src/content-types/index.d.ts +88 -0
  79. package/dist/server/src/content-types/index.d.ts.map +1 -1
  80. package/dist/server/src/content-types/session.d.ts +88 -0
  81. package/dist/server/src/content-types/session.d.ts.map +1 -0
  82. package/dist/server/src/controllers/authentication.d.ts +5 -5
  83. package/dist/server/src/controllers/authentication.d.ts.map +1 -1
  84. package/dist/server/src/controllers/index.d.ts +5 -5
  85. package/dist/server/src/index.d.ts +93 -5
  86. package/dist/server/src/index.d.ts.map +1 -1
  87. package/dist/server/src/routes/authentication.d.ts.map +1 -1
  88. package/dist/server/src/services/token.d.ts +11 -19
  89. package/dist/server/src/services/token.d.ts.map +1 -1
  90. package/dist/server/src/services/user.d.ts.map +1 -1
  91. package/dist/server/src/strategies/admin.d.ts.map +1 -1
  92. package/dist/server/src/validation/authentication/index.d.ts +1 -1
  93. package/dist/server/src/validation/authentication/index.d.ts.map +1 -1
  94. package/dist/server/src/validation/authentication/login.d.ts +7 -0
  95. package/dist/server/src/validation/authentication/login.d.ts.map +1 -0
  96. package/dist/server/src/validation/authentication/register.d.ts +5 -0
  97. package/dist/server/src/validation/authentication/register.d.ts.map +1 -1
  98. package/dist/shared/contracts/authentication.d.ts +20 -10
  99. package/dist/shared/contracts/authentication.d.ts.map +1 -1
  100. package/dist/shared/utils/session-auth.d.ts +39 -0
  101. package/dist/shared/utils/session-auth.d.ts.map +1 -0
  102. package/package.json +7 -7
  103. package/dist/server/server/src/validation/authentication/renew-token.js +0 -11
  104. package/dist/server/server/src/validation/authentication/renew-token.js.map +0 -1
  105. package/dist/server/server/src/validation/authentication/renew-token.mjs +0 -9
  106. package/dist/server/server/src/validation/authentication/renew-token.mjs.map +0 -1
  107. package/dist/server/src/validation/authentication/renew-token.d.ts +0 -3
  108. package/dist/server/src/validation/authentication/renew-token.d.ts.map +0 -1
@@ -3,14 +3,19 @@ import compose from 'koa-compose';
3
3
  import '@strapi/types';
4
4
  import { errors } from '@strapi/utils';
5
5
  import { getService } from '../utils/index.mjs';
6
+ import { getSessionManager, extractDeviceParams, buildCookieOptionsWithExpiry, REFRESH_COOKIE_NAME, generateDeviceId, getRefreshCookieOptions } from '../../../shared/utils/session-auth.mjs';
6
7
  import { validateRegistrationInfoQuery, validateRegistrationInput, validateAdminRegistrationInput } from '../validation/authentication/register.mjs';
7
8
  import validateForgotPasswordInput from '../validation/authentication/forgot-password.mjs';
8
9
  import validateResetPasswordInput from '../validation/authentication/reset-password.mjs';
9
- import validateRenewTokenInput from '../validation/authentication/renew-token.mjs';
10
+ import validateLoginSessionInput from '../validation/authentication/login.mjs';
10
11
 
11
12
  const { ApplicationError, ValidationError } = errors;
12
13
  var authentication = {
13
14
  login: compose([
15
+ async (ctx, next)=>{
16
+ await validateLoginSessionInput(ctx.request.body ?? {});
17
+ return next();
18
+ },
14
19
  (ctx, next)=>{
15
20
  return passport.authenticate('local', {
16
21
  session: false
@@ -44,31 +49,38 @@ var authentication = {
44
49
  return next();
45
50
  })(ctx, next);
46
51
  },
47
- (ctx)=>{
52
+ async (ctx)=>{
48
53
  const { user } = ctx.state;
49
- ctx.body = {
50
- data: {
51
- token: getService('token').createJwtToken(user),
52
- user: getService('user').sanitizeUser(ctx.state.user)
54
+ try {
55
+ const sessionManager = getSessionManager();
56
+ if (!sessionManager) {
57
+ return ctx.internalServerError();
53
58
  }
54
- };
59
+ const userId = String(user.id);
60
+ const { deviceId, rememberMe } = extractDeviceParams(ctx.request.body);
61
+ const { token: refreshToken, absoluteExpiresAt } = await sessionManager('admin').generateRefreshToken(userId, deviceId, {
62
+ type: rememberMe ? 'refresh' : 'session'
63
+ });
64
+ const cookieOptions = buildCookieOptionsWithExpiry(rememberMe ? 'refresh' : 'session', absoluteExpiresAt);
65
+ ctx.cookies.set(REFRESH_COOKIE_NAME, refreshToken, cookieOptions);
66
+ const accessResult = await sessionManager('admin').generateAccessToken(refreshToken);
67
+ if ('error' in accessResult) {
68
+ return ctx.internalServerError();
69
+ }
70
+ const { token: accessToken } = accessResult;
71
+ ctx.body = {
72
+ data: {
73
+ token: accessToken,
74
+ accessToken,
75
+ user: getService('user').sanitizeUser(ctx.state.user)
76
+ }
77
+ };
78
+ } catch (error) {
79
+ strapi.log.error('Failed to create admin refresh session', error);
80
+ return ctx.internalServerError();
81
+ }
55
82
  }
56
83
  ]),
57
- async renewToken (ctx) {
58
- await validateRenewTokenInput(ctx.request.body);
59
- const { token } = ctx.request.body;
60
- const { isValid, payload } = getService('token').decodeJwtToken(token);
61
- if (!isValid) {
62
- throw new ValidationError('Invalid token');
63
- }
64
- ctx.body = {
65
- data: {
66
- token: getService('token').createJwtToken({
67
- id: payload.id
68
- })
69
- }
70
- };
71
- },
72
84
  async registrationInfo (ctx) {
73
85
  await validateRegistrationInfoQuery(ctx.request.query);
74
86
  const { registrationToken } = ctx.request.query;
@@ -84,12 +96,34 @@ var authentication = {
84
96
  const input = ctx.request.body;
85
97
  await validateRegistrationInput(input);
86
98
  const user = await getService('user').register(input);
87
- ctx.body = {
88
- data: {
89
- token: getService('token').createJwtToken(user),
90
- user: getService('user').sanitizeUser(user)
99
+ try {
100
+ const sessionManager = getSessionManager();
101
+ if (!sessionManager) {
102
+ return ctx.internalServerError();
91
103
  }
92
- };
104
+ const userId = String(user.id);
105
+ const { deviceId, rememberMe } = extractDeviceParams(ctx.request.body);
106
+ const { token: refreshToken, absoluteExpiresAt } = await sessionManager('admin').generateRefreshToken(userId, deviceId, {
107
+ type: rememberMe ? 'refresh' : 'session'
108
+ });
109
+ const cookieOptions = buildCookieOptionsWithExpiry(rememberMe ? 'refresh' : 'session', absoluteExpiresAt);
110
+ ctx.cookies.set(REFRESH_COOKIE_NAME, refreshToken, cookieOptions);
111
+ const accessResult = await sessionManager('admin').generateAccessToken(refreshToken);
112
+ if ('error' in accessResult) {
113
+ return ctx.internalServerError();
114
+ }
115
+ const { token: accessToken } = accessResult;
116
+ ctx.body = {
117
+ data: {
118
+ token: accessToken,
119
+ accessToken,
120
+ user: getService('user').sanitizeUser(user)
121
+ }
122
+ };
123
+ } catch (error) {
124
+ strapi.log.error('Failed to create admin refresh session during register', error);
125
+ return ctx.internalServerError();
126
+ }
93
127
  },
94
128
  async registerAdmin (ctx) {
95
129
  const input = ctx.request.body;
@@ -111,12 +145,34 @@ var authentication = {
111
145
  ] : []
112
146
  });
113
147
  strapi.telemetry.send('didCreateFirstAdmin');
114
- ctx.body = {
115
- data: {
116
- token: getService('token').createJwtToken(user),
117
- user: getService('user').sanitizeUser(user)
148
+ try {
149
+ const sessionManager = getSessionManager();
150
+ if (!sessionManager) {
151
+ return ctx.internalServerError();
118
152
  }
119
- };
153
+ const userId = String(user.id);
154
+ const { deviceId, rememberMe } = extractDeviceParams(ctx.request.body);
155
+ const { token: refreshToken, absoluteExpiresAt } = await sessionManager('admin').generateRefreshToken(userId, deviceId, {
156
+ type: rememberMe ? 'refresh' : 'session'
157
+ });
158
+ const cookieOptions = buildCookieOptionsWithExpiry(rememberMe ? 'refresh' : 'session', absoluteExpiresAt);
159
+ ctx.cookies.set(REFRESH_COOKIE_NAME, refreshToken, cookieOptions);
160
+ const accessResult = await sessionManager('admin').generateAccessToken(refreshToken);
161
+ if ('error' in accessResult) {
162
+ return ctx.internalServerError();
163
+ }
164
+ const { token: accessToken } = accessResult;
165
+ ctx.body = {
166
+ data: {
167
+ token: accessToken,
168
+ accessToken,
169
+ user: getService('user').sanitizeUser(user)
170
+ }
171
+ };
172
+ } catch (error) {
173
+ strapi.log.error('Failed to create admin refresh session during register-admin', error);
174
+ return ctx.internalServerError();
175
+ }
120
176
  },
121
177
  async forgotPassword (ctx) {
122
178
  const input = ctx.request.body;
@@ -128,18 +184,93 @@ var authentication = {
128
184
  const input = ctx.request.body;
129
185
  await validateResetPasswordInput(input);
130
186
  const user = await getService('auth').resetPassword(input);
131
- ctx.body = {
132
- data: {
133
- token: getService('token').createJwtToken(user),
134
- user: getService('user').sanitizeUser(user)
187
+ // Issue a new admin refresh session and access token after password reset.
188
+ try {
189
+ const sessionManager = getSessionManager();
190
+ if (!sessionManager) {
191
+ return ctx.internalServerError();
135
192
  }
136
- };
193
+ const userId = String(user.id);
194
+ const deviceId = generateDeviceId();
195
+ // Invalidate all existing sessions before creating a new one
196
+ await sessionManager('admin').invalidateRefreshToken(userId);
197
+ const { token: refreshToken, absoluteExpiresAt } = await sessionManager('admin').generateRefreshToken(userId, deviceId, {
198
+ type: 'session'
199
+ });
200
+ // No rememberMe flow here; expire with session by default (session cookie)
201
+ const cookieOptions = buildCookieOptionsWithExpiry('session', absoluteExpiresAt);
202
+ ctx.cookies.set(REFRESH_COOKIE_NAME, refreshToken, cookieOptions);
203
+ const accessResult = await sessionManager('admin').generateAccessToken(refreshToken);
204
+ if ('error' in accessResult) {
205
+ return ctx.internalServerError();
206
+ }
207
+ const { token } = accessResult;
208
+ ctx.body = {
209
+ data: {
210
+ token,
211
+ user: getService('user').sanitizeUser(user)
212
+ }
213
+ };
214
+ } catch (err) {
215
+ strapi.log.error('Failed to create admin refresh session during reset-password', err);
216
+ return ctx.internalServerError();
217
+ }
137
218
  },
138
- logout (ctx) {
219
+ async accessToken (ctx) {
220
+ const refreshToken = ctx.cookies.get(REFRESH_COOKIE_NAME);
221
+ if (!refreshToken) {
222
+ return ctx.unauthorized('Missing refresh token');
223
+ }
224
+ try {
225
+ const sessionManager = getSessionManager();
226
+ if (!sessionManager) {
227
+ return ctx.internalServerError();
228
+ }
229
+ // Single-use renewal: rotate on access exchange, then create access token
230
+ // from the new refresh token
231
+ const rotation = await sessionManager('admin').rotateRefreshToken(refreshToken);
232
+ if ('error' in rotation) {
233
+ return ctx.unauthorized('Invalid refresh token');
234
+ }
235
+ const result = await sessionManager('admin').generateAccessToken(rotation.token);
236
+ if ('error' in result) {
237
+ return ctx.unauthorized('Invalid refresh token');
238
+ }
239
+ const { token } = result;
240
+ // Preserve session-vs-remember mode using rotation.type and rotation.absoluteExpiresAt
241
+ const opts = buildCookieOptionsWithExpiry(rotation.type, rotation.absoluteExpiresAt);
242
+ ctx.cookies.set(REFRESH_COOKIE_NAME, rotation.token, opts);
243
+ ctx.body = {
244
+ data: {
245
+ token
246
+ }
247
+ };
248
+ } catch (err) {
249
+ strapi.log.error('Failed to generate access token from refresh token', err);
250
+ return ctx.internalServerError();
251
+ }
252
+ },
253
+ async logout (ctx) {
139
254
  const sanitizedUser = getService('user').sanitizeUser(ctx.state.user);
140
255
  strapi.eventHub.emit('admin.logout', {
141
256
  user: sanitizedUser
142
257
  });
258
+ const bodyDeviceId = ctx.request.body?.deviceId;
259
+ const deviceId = typeof bodyDeviceId === 'string' ? bodyDeviceId : undefined;
260
+ // Clear cookie regardless of token validity
261
+ ctx.cookies.set(REFRESH_COOKIE_NAME, '', {
262
+ ...getRefreshCookieOptions(),
263
+ expires: new Date(0)
264
+ });
265
+ try {
266
+ const sessionManager = getSessionManager();
267
+ if (sessionManager) {
268
+ const userId = String(ctx.state.user.id);
269
+ await sessionManager('admin').invalidateRefreshToken(userId, deviceId);
270
+ }
271
+ } catch (err) {
272
+ strapi.log.error('Failed to revoke admin sessions during logout', err);
273
+ }
143
274
  ctx.body = {
144
275
  data: {}
145
276
  };
@@ -1 +1 @@
1
- {"version":3,"file":"authentication.mjs","sources":["../../../../../server/src/controllers/authentication.ts"],"sourcesContent":["import type { Context, Next } from 'koa';\nimport passport from 'koa-passport';\nimport compose from 'koa-compose';\nimport '@strapi/types';\nimport { errors } from '@strapi/utils';\nimport { getService } from '../utils';\nimport {\n validateRegistrationInput,\n validateAdminRegistrationInput,\n validateRegistrationInfoQuery,\n validateForgotPasswordInput,\n validateResetPasswordInput,\n validateRenewTokenInput,\n} from '../validation/authentication';\n\nimport type {\n ForgotPassword,\n Login,\n Register,\n RegistrationInfo,\n RenewToken,\n ResetPassword,\n} from '../../../shared/contracts/authentication';\nimport { AdminUser } from '../../../shared/contracts/shared';\n\nconst { ApplicationError, ValidationError } = errors;\n\nexport default {\n login: compose([\n (ctx: Context, next: Next) => {\n return passport.authenticate('local', { session: false }, (err, user, info) => {\n if (err) {\n strapi.eventHub.emit('admin.auth.error', { error: err, provider: 'local' });\n // if this is a recognized error, allow it to bubble up to user\n if (err.details?.code === 'LOGIN_NOT_ALLOWED') {\n throw err;\n }\n\n // for all other errors throw a generic error to prevent leaking info\n return ctx.notImplemented();\n }\n\n if (!user) {\n strapi.eventHub.emit('admin.auth.error', {\n error: new Error(info.message),\n provider: 'local',\n });\n throw new ApplicationError(info.message);\n }\n\n const query = ctx.state as Login.Request['query'];\n query.user = user;\n\n const sanitizedUser = getService('user').sanitizeUser(user);\n strapi.eventHub.emit('admin.auth.success', { user: sanitizedUser, provider: 'local' });\n\n return next();\n })(ctx, next);\n },\n (ctx: Context) => {\n const { user } = ctx.state as { user: AdminUser };\n\n ctx.body = {\n data: {\n token: getService('token').createJwtToken(user),\n user: getService('user').sanitizeUser(ctx.state.user), // TODO: fetch more detailed info\n },\n } satisfies Login.Response;\n },\n ]),\n\n async renewToken(ctx: Context) {\n await validateRenewTokenInput(ctx.request.body);\n\n const { token } = ctx.request.body as RenewToken.Request['body'];\n\n const { isValid, payload } = getService('token').decodeJwtToken(token);\n\n if (!isValid) {\n throw new ValidationError('Invalid token');\n }\n\n ctx.body = {\n data: {\n token: getService('token').createJwtToken({ id: payload.id }),\n },\n } satisfies RenewToken.Response;\n },\n\n async registrationInfo(ctx: Context) {\n await validateRegistrationInfoQuery(ctx.request.query);\n\n const { registrationToken } = ctx.request.query as RegistrationInfo.Request['query'];\n\n const registrationInfo = await getService('user').findRegistrationInfo(registrationToken);\n\n if (!registrationInfo) {\n throw new ValidationError('Invalid registrationToken');\n }\n\n ctx.body = { data: registrationInfo } satisfies RegistrationInfo.Response;\n },\n\n async register(ctx: Context) {\n const input = ctx.request.body as Register.Request['body'];\n\n await validateRegistrationInput(input);\n\n const user = await getService('user').register(input);\n\n ctx.body = {\n data: {\n token: getService('token').createJwtToken(user),\n user: getService('user').sanitizeUser(user),\n },\n } satisfies Register.Response;\n },\n\n async registerAdmin(ctx: Context) {\n const input = ctx.request.body as Register.Request['body'];\n\n await validateAdminRegistrationInput(input);\n\n const hasAdmin = await getService('user').exists();\n\n if (hasAdmin) {\n throw new ApplicationError('You cannot register a new super admin');\n }\n\n const superAdminRole = await getService('role').getSuperAdmin();\n\n if (!superAdminRole) {\n throw new ApplicationError(\n \"Cannot register the first admin because the super admin role doesn't exist.\"\n );\n }\n\n const user = await getService('user').create({\n ...input,\n registrationToken: null,\n isActive: true,\n roles: superAdminRole ? [superAdminRole.id] : [],\n });\n\n strapi.telemetry.send('didCreateFirstAdmin');\n\n ctx.body = {\n data: {\n token: getService('token').createJwtToken(user),\n user: getService('user').sanitizeUser(user),\n },\n };\n },\n\n async forgotPassword(ctx: Context) {\n const input = ctx.request.body as ForgotPassword.Request['body'];\n\n await validateForgotPasswordInput(input);\n\n getService('auth').forgotPassword(input);\n\n ctx.status = 204;\n },\n\n async resetPassword(ctx: Context) {\n const input = ctx.request.body as ResetPassword.Request['body'];\n\n await validateResetPasswordInput(input);\n\n const user = await getService('auth').resetPassword(input);\n\n ctx.body = {\n data: {\n token: getService('token').createJwtToken(user),\n user: getService('user').sanitizeUser(user),\n },\n } satisfies ResetPassword.Response;\n },\n\n logout(ctx: Context) {\n const sanitizedUser = getService('user').sanitizeUser(ctx.state.user);\n strapi.eventHub.emit('admin.logout', { user: sanitizedUser });\n ctx.body = { data: {} };\n },\n};\n"],"names":["ApplicationError","ValidationError","errors","login","compose","ctx","next","passport","authenticate","session","err","user","info","strapi","eventHub","emit","error","provider","details","code","notImplemented","Error","message","query","state","sanitizedUser","getService","sanitizeUser","body","data","token","createJwtToken","renewToken","validateRenewTokenInput","request","isValid","payload","decodeJwtToken","id","registrationInfo","validateRegistrationInfoQuery","registrationToken","findRegistrationInfo","register","input","validateRegistrationInput","registerAdmin","validateAdminRegistrationInput","hasAdmin","exists","superAdminRole","getSuperAdmin","create","isActive","roles","telemetry","send","forgotPassword","validateForgotPasswordInput","status","resetPassword","validateResetPasswordInput","logout"],"mappings":"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"}
1
+ {"version":3,"file":"authentication.mjs","sources":["../../../../../server/src/controllers/authentication.ts"],"sourcesContent":["import type { Context, Next } from 'koa';\nimport passport from 'koa-passport';\nimport compose from 'koa-compose';\nimport '@strapi/types';\nimport { errors } from '@strapi/utils';\nimport { getService } from '../utils';\nimport {\n REFRESH_COOKIE_NAME,\n buildCookieOptionsWithExpiry,\n getSessionManager,\n extractDeviceParams,\n generateDeviceId,\n getRefreshCookieOptions,\n} from '../../../shared/utils/session-auth';\n\nimport {\n validateRegistrationInput,\n validateAdminRegistrationInput,\n validateRegistrationInfoQuery,\n validateForgotPasswordInput,\n validateResetPasswordInput,\n validateLoginSessionInput,\n} from '../validation/authentication';\n\nimport type {\n ForgotPassword,\n Login,\n Register,\n RegistrationInfo,\n ResetPassword,\n} from '../../../shared/contracts/authentication';\nimport { AdminUser } from '../../../shared/contracts/shared';\n\nconst { ApplicationError, ValidationError } = errors;\n\nexport default {\n login: compose([\n async (ctx: Context, next: Next) => {\n await validateLoginSessionInput(ctx.request.body ?? {});\n return next();\n },\n (ctx: Context, next: Next) => {\n return passport.authenticate('local', { session: false }, (err, user, info) => {\n if (err) {\n strapi.eventHub.emit('admin.auth.error', { error: err, provider: 'local' });\n // if this is a recognized error, allow it to bubble up to user\n if (err.details?.code === 'LOGIN_NOT_ALLOWED') {\n throw err;\n }\n\n // for all other errors throw a generic error to prevent leaking info\n return ctx.notImplemented();\n }\n\n if (!user) {\n strapi.eventHub.emit('admin.auth.error', {\n error: new Error(info.message),\n provider: 'local',\n });\n throw new ApplicationError(info.message);\n }\n\n const query = ctx.state as Login.Request['query'];\n query.user = user;\n\n const sanitizedUser = getService('user').sanitizeUser(user);\n strapi.eventHub.emit('admin.auth.success', { user: sanitizedUser, provider: 'local' });\n\n return next();\n })(ctx, next);\n },\n async (ctx: Context) => {\n const { user } = ctx.state as { user: AdminUser };\n\n try {\n const sessionManager = getSessionManager();\n if (!sessionManager) {\n return ctx.internalServerError();\n }\n const userId = String(user.id);\n const { deviceId, rememberMe } = extractDeviceParams(ctx.request.body);\n\n const { token: refreshToken, absoluteExpiresAt } = await sessionManager(\n 'admin'\n ).generateRefreshToken(userId, deviceId, {\n type: rememberMe ? 'refresh' : 'session',\n });\n\n const cookieOptions = buildCookieOptionsWithExpiry(\n rememberMe ? 'refresh' : 'session',\n absoluteExpiresAt\n );\n ctx.cookies.set(REFRESH_COOKIE_NAME, refreshToken, cookieOptions);\n\n const accessResult = await sessionManager('admin').generateAccessToken(refreshToken);\n if ('error' in accessResult) {\n return ctx.internalServerError();\n }\n\n const { token: accessToken } = accessResult;\n\n ctx.body = {\n data: {\n token: accessToken,\n accessToken,\n user: getService('user').sanitizeUser(ctx.state.user),\n },\n } satisfies Login.Response;\n } catch (error) {\n strapi.log.error('Failed to create admin refresh session', error);\n return ctx.internalServerError();\n }\n },\n ]),\n\n async registrationInfo(ctx: Context) {\n await validateRegistrationInfoQuery(ctx.request.query);\n\n const { registrationToken } = ctx.request.query as RegistrationInfo.Request['query'];\n\n const registrationInfo = await getService('user').findRegistrationInfo(registrationToken);\n\n if (!registrationInfo) {\n throw new ValidationError('Invalid registrationToken');\n }\n\n ctx.body = { data: registrationInfo } satisfies RegistrationInfo.Response;\n },\n\n async register(ctx: Context) {\n const input = ctx.request.body as Register.Request['body'];\n\n await validateRegistrationInput(input);\n\n const user = await getService('user').register(input);\n\n try {\n const sessionManager = getSessionManager();\n if (!sessionManager) {\n return ctx.internalServerError();\n }\n const userId = String(user.id);\n const { deviceId, rememberMe } = extractDeviceParams(ctx.request.body);\n\n const { token: refreshToken, absoluteExpiresAt } = await sessionManager(\n 'admin'\n ).generateRefreshToken(userId, deviceId, { type: rememberMe ? 'refresh' : 'session' });\n\n const cookieOptions = buildCookieOptionsWithExpiry(\n rememberMe ? 'refresh' : 'session',\n absoluteExpiresAt\n );\n ctx.cookies.set(REFRESH_COOKIE_NAME, refreshToken, cookieOptions);\n\n const accessResult = await sessionManager('admin').generateAccessToken(refreshToken);\n if ('error' in accessResult) {\n return ctx.internalServerError();\n }\n\n const { token: accessToken } = accessResult;\n\n ctx.body = {\n data: {\n token: accessToken,\n accessToken,\n user: getService('user').sanitizeUser(user),\n },\n } satisfies Register.Response;\n } catch (error) {\n strapi.log.error('Failed to create admin refresh session during register', error);\n return ctx.internalServerError();\n }\n },\n\n async registerAdmin(ctx: Context) {\n const input = ctx.request.body as Register.Request['body'];\n\n await validateAdminRegistrationInput(input);\n\n const hasAdmin = await getService('user').exists();\n\n if (hasAdmin) {\n throw new ApplicationError('You cannot register a new super admin');\n }\n\n const superAdminRole = await getService('role').getSuperAdmin();\n\n if (!superAdminRole) {\n throw new ApplicationError(\n \"Cannot register the first admin because the super admin role doesn't exist.\"\n );\n }\n\n const user = await getService('user').create({\n ...input,\n registrationToken: null,\n isActive: true,\n roles: superAdminRole ? [superAdminRole.id] : [],\n });\n\n strapi.telemetry.send('didCreateFirstAdmin');\n\n try {\n const sessionManager = getSessionManager();\n if (!sessionManager) {\n return ctx.internalServerError();\n }\n const userId = String(user.id);\n const { deviceId, rememberMe } = extractDeviceParams(ctx.request.body);\n\n const { token: refreshToken, absoluteExpiresAt } = await sessionManager(\n 'admin'\n ).generateRefreshToken(userId, deviceId, { type: rememberMe ? 'refresh' : 'session' });\n\n const cookieOptions = buildCookieOptionsWithExpiry(\n rememberMe ? 'refresh' : 'session',\n absoluteExpiresAt\n );\n ctx.cookies.set(REFRESH_COOKIE_NAME, refreshToken, cookieOptions);\n\n const accessResult = await sessionManager('admin').generateAccessToken(refreshToken);\n if ('error' in accessResult) {\n return ctx.internalServerError();\n }\n\n const { token: accessToken } = accessResult;\n\n ctx.body = {\n data: {\n token: accessToken,\n accessToken,\n user: getService('user').sanitizeUser(user),\n },\n };\n } catch (error) {\n strapi.log.error('Failed to create admin refresh session during register-admin', error);\n return ctx.internalServerError();\n }\n },\n\n async forgotPassword(ctx: Context) {\n const input = ctx.request.body as ForgotPassword.Request['body'];\n\n await validateForgotPasswordInput(input);\n\n getService('auth').forgotPassword(input);\n\n ctx.status = 204;\n },\n\n async resetPassword(ctx: Context) {\n const input = ctx.request.body as ResetPassword.Request['body'];\n\n await validateResetPasswordInput(input);\n\n const user = await getService('auth').resetPassword(input);\n\n // Issue a new admin refresh session and access token after password reset.\n try {\n const sessionManager = getSessionManager();\n if (!sessionManager) {\n return ctx.internalServerError();\n }\n\n const userId = String(user.id);\n const deviceId = generateDeviceId();\n\n // Invalidate all existing sessions before creating a new one\n await sessionManager('admin').invalidateRefreshToken(userId);\n\n const { token: refreshToken, absoluteExpiresAt } = await sessionManager(\n 'admin'\n ).generateRefreshToken(userId, deviceId, { type: 'session' });\n\n // No rememberMe flow here; expire with session by default (session cookie)\n const cookieOptions = buildCookieOptionsWithExpiry('session', absoluteExpiresAt);\n ctx.cookies.set(REFRESH_COOKIE_NAME, refreshToken, cookieOptions);\n\n const accessResult = await sessionManager('admin').generateAccessToken(refreshToken);\n if ('error' in accessResult) {\n return ctx.internalServerError();\n }\n\n const { token } = accessResult;\n\n ctx.body = {\n data: {\n token,\n user: getService('user').sanitizeUser(user),\n },\n } satisfies ResetPassword.Response;\n } catch (err) {\n strapi.log.error('Failed to create admin refresh session during reset-password', err as any);\n return ctx.internalServerError();\n }\n },\n\n async accessToken(ctx: Context) {\n const refreshToken = ctx.cookies.get(REFRESH_COOKIE_NAME);\n\n if (!refreshToken) {\n return ctx.unauthorized('Missing refresh token');\n }\n\n try {\n const sessionManager = getSessionManager();\n if (!sessionManager) {\n return ctx.internalServerError();\n }\n\n // Single-use renewal: rotate on access exchange, then create access token\n // from the new refresh token\n const rotation = await sessionManager('admin').rotateRefreshToken(refreshToken);\n if ('error' in rotation) {\n return ctx.unauthorized('Invalid refresh token');\n }\n\n const result = await sessionManager('admin').generateAccessToken(rotation.token);\n if ('error' in result) {\n return ctx.unauthorized('Invalid refresh token');\n }\n\n const { token } = result;\n // Preserve session-vs-remember mode using rotation.type and rotation.absoluteExpiresAt\n const opts = buildCookieOptionsWithExpiry(rotation.type, rotation.absoluteExpiresAt);\n\n ctx.cookies.set(REFRESH_COOKIE_NAME, rotation.token, opts);\n ctx.body = { data: { token } };\n } catch (err) {\n strapi.log.error('Failed to generate access token from refresh token', err as any);\n return ctx.internalServerError();\n }\n },\n\n async logout(ctx: Context) {\n const sanitizedUser = getService('user').sanitizeUser(ctx.state.user);\n strapi.eventHub.emit('admin.logout', { user: sanitizedUser });\n\n const bodyDeviceId = ctx.request.body?.deviceId as string | undefined;\n const deviceId = typeof bodyDeviceId === 'string' ? bodyDeviceId : undefined;\n\n // Clear cookie regardless of token validity\n ctx.cookies.set(REFRESH_COOKIE_NAME, '', {\n ...getRefreshCookieOptions(),\n expires: new Date(0),\n });\n\n try {\n const sessionManager = getSessionManager();\n if (sessionManager) {\n const userId = String(ctx.state.user.id);\n await sessionManager('admin').invalidateRefreshToken(userId, deviceId);\n }\n } catch (err) {\n strapi.log.error('Failed to revoke admin sessions during logout', err as any);\n }\n\n ctx.body = { data: {} };\n },\n};\n"],"names":["ApplicationError","ValidationError","errors","login","compose","ctx","next","validateLoginSessionInput","request","body","passport","authenticate","session","err","user","info","strapi","eventHub","emit","error","provider","details","code","notImplemented","Error","message","query","state","sanitizedUser","getService","sanitizeUser","sessionManager","getSessionManager","internalServerError","userId","String","id","deviceId","rememberMe","extractDeviceParams","token","refreshToken","absoluteExpiresAt","generateRefreshToken","type","cookieOptions","buildCookieOptionsWithExpiry","cookies","set","REFRESH_COOKIE_NAME","accessResult","generateAccessToken","accessToken","data","log","registrationInfo","validateRegistrationInfoQuery","registrationToken","findRegistrationInfo","register","input","validateRegistrationInput","registerAdmin","validateAdminRegistrationInput","hasAdmin","exists","superAdminRole","getSuperAdmin","create","isActive","roles","telemetry","send","forgotPassword","validateForgotPasswordInput","status","resetPassword","validateResetPasswordInput","generateDeviceId","invalidateRefreshToken","get","unauthorized","rotation","rotateRefreshToken","result","opts","logout","bodyDeviceId","undefined","getRefreshCookieOptions","expires","Date"],"mappings":"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"}
@@ -14,8 +14,8 @@ var authentication = [
14
14
  },
15
15
  {
16
16
  method: 'POST',
17
- path: '/renew-token',
18
- handler: 'authentication.renewToken',
17
+ path: '/access-token',
18
+ handler: 'authentication.accessToken',
19
19
  config: {
20
20
  auth: false
21
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"authentication.js","sources":["../../../../../server/src/routes/authentication.ts"],"sourcesContent":["export default [\n {\n method: 'POST',\n path: '/login',\n handler: 'authentication.login',\n config: {\n auth: false,\n middlewares: ['admin::rateLimit'],\n },\n },\n {\n method: 'POST',\n path: '/renew-token',\n handler: 'authentication.renewToken',\n config: { auth: false },\n },\n {\n method: 'POST',\n path: '/register-admin',\n handler: 'authentication.registerAdmin',\n config: { auth: false },\n },\n {\n method: 'GET',\n path: '/registration-info',\n handler: 'authentication.registrationInfo',\n config: { auth: false },\n },\n {\n method: 'POST',\n path: '/register',\n handler: 'authentication.register',\n config: { auth: false },\n },\n {\n method: 'POST',\n path: '/forgot-password',\n handler: 'authentication.forgotPassword',\n config: {\n auth: false,\n middlewares: ['plugin::email.rateLimit'],\n },\n },\n {\n method: 'POST',\n path: '/reset-password',\n handler: 'authentication.resetPassword',\n config: { auth: false },\n },\n {\n method: 'POST',\n path: '/logout',\n handler: 'authentication.logout',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n];\n"],"names":["method","path","handler","config","auth","middlewares","policies"],"mappings":";;AAAA,qBAAe;AACb,IAAA;QACEA,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,QAAA;QACNC,OAAS,EAAA,sBAAA;QACTC,MAAQ,EAAA;YACNC,IAAM,EAAA,KAAA;YACNC,WAAa,EAAA;AAAC,gBAAA;AAAmB;AACnC;AACF,KAAA;AACA,IAAA;QACEL,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,cAAA;QACNC,OAAS,EAAA,2BAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,iBAAA;QACNC,OAAS,EAAA,8BAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,KAAA;QACRC,IAAM,EAAA,oBAAA;QACNC,OAAS,EAAA,iCAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,WAAA;QACNC,OAAS,EAAA,yBAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,kBAAA;QACNC,OAAS,EAAA,+BAAA;QACTC,MAAQ,EAAA;YACNC,IAAM,EAAA,KAAA;YACNC,WAAa,EAAA;AAAC,gBAAA;AAA0B;AAC1C;AACF,KAAA;AACA,IAAA;QACEL,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,iBAAA;QACNC,OAAS,EAAA,8BAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,SAAA;QACNC,OAAS,EAAA,uBAAA;QACTC,MAAQ,EAAA;YACNG,QAAU,EAAA;AAAC,gBAAA;AAA8B;AAC3C;AACF;CACD;;;;"}
1
+ {"version":3,"file":"authentication.js","sources":["../../../../../server/src/routes/authentication.ts"],"sourcesContent":["export default [\n {\n method: 'POST',\n path: '/login',\n handler: 'authentication.login',\n config: {\n auth: false,\n middlewares: ['admin::rateLimit'],\n },\n },\n {\n method: 'POST',\n path: '/access-token',\n handler: 'authentication.accessToken',\n config: {\n auth: false,\n },\n },\n {\n method: 'POST',\n path: '/register-admin',\n handler: 'authentication.registerAdmin',\n config: { auth: false },\n },\n {\n method: 'GET',\n path: '/registration-info',\n handler: 'authentication.registrationInfo',\n config: { auth: false },\n },\n {\n method: 'POST',\n path: '/register',\n handler: 'authentication.register',\n config: { auth: false },\n },\n {\n method: 'POST',\n path: '/forgot-password',\n handler: 'authentication.forgotPassword',\n config: {\n auth: false,\n middlewares: ['plugin::email.rateLimit'],\n },\n },\n {\n method: 'POST',\n path: '/reset-password',\n handler: 'authentication.resetPassword',\n config: { auth: false },\n },\n {\n method: 'POST',\n path: '/logout',\n handler: 'authentication.logout',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n];\n"],"names":["method","path","handler","config","auth","middlewares","policies"],"mappings":";;AAAA,qBAAe;AACb,IAAA;QACEA,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,QAAA;QACNC,OAAS,EAAA,sBAAA;QACTC,MAAQ,EAAA;YACNC,IAAM,EAAA,KAAA;YACNC,WAAa,EAAA;AAAC,gBAAA;AAAmB;AACnC;AACF,KAAA;AACA,IAAA;QACEL,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,eAAA;QACNC,OAAS,EAAA,4BAAA;QACTC,MAAQ,EAAA;YACNC,IAAM,EAAA;AACR;AACF,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,iBAAA;QACNC,OAAS,EAAA,8BAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,KAAA;QACRC,IAAM,EAAA,oBAAA;QACNC,OAAS,EAAA,iCAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,WAAA;QACNC,OAAS,EAAA,yBAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,kBAAA;QACNC,OAAS,EAAA,+BAAA;QACTC,MAAQ,EAAA;YACNC,IAAM,EAAA,KAAA;YACNC,WAAa,EAAA;AAAC,gBAAA;AAA0B;AAC1C;AACF,KAAA;AACA,IAAA;QACEL,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,iBAAA;QACNC,OAAS,EAAA,8BAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,SAAA;QACNC,OAAS,EAAA,uBAAA;QACTC,MAAQ,EAAA;YACNG,QAAU,EAAA;AAAC,gBAAA;AAA8B;AAC3C;AACF;CACD;;;;"}
@@ -12,8 +12,8 @@ var authentication = [
12
12
  },
13
13
  {
14
14
  method: 'POST',
15
- path: '/renew-token',
16
- handler: 'authentication.renewToken',
15
+ path: '/access-token',
16
+ handler: 'authentication.accessToken',
17
17
  config: {
18
18
  auth: false
19
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"authentication.mjs","sources":["../../../../../server/src/routes/authentication.ts"],"sourcesContent":["export default [\n {\n method: 'POST',\n path: '/login',\n handler: 'authentication.login',\n config: {\n auth: false,\n middlewares: ['admin::rateLimit'],\n },\n },\n {\n method: 'POST',\n path: '/renew-token',\n handler: 'authentication.renewToken',\n config: { auth: false },\n },\n {\n method: 'POST',\n path: '/register-admin',\n handler: 'authentication.registerAdmin',\n config: { auth: false },\n },\n {\n method: 'GET',\n path: '/registration-info',\n handler: 'authentication.registrationInfo',\n config: { auth: false },\n },\n {\n method: 'POST',\n path: '/register',\n handler: 'authentication.register',\n config: { auth: false },\n },\n {\n method: 'POST',\n path: '/forgot-password',\n handler: 'authentication.forgotPassword',\n config: {\n auth: false,\n middlewares: ['plugin::email.rateLimit'],\n },\n },\n {\n method: 'POST',\n path: '/reset-password',\n handler: 'authentication.resetPassword',\n config: { auth: false },\n },\n {\n method: 'POST',\n path: '/logout',\n handler: 'authentication.logout',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n];\n"],"names":["method","path","handler","config","auth","middlewares","policies"],"mappings":"AAAA,qBAAe;AACb,IAAA;QACEA,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,QAAA;QACNC,OAAS,EAAA,sBAAA;QACTC,MAAQ,EAAA;YACNC,IAAM,EAAA,KAAA;YACNC,WAAa,EAAA;AAAC,gBAAA;AAAmB;AACnC;AACF,KAAA;AACA,IAAA;QACEL,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,cAAA;QACNC,OAAS,EAAA,2BAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,iBAAA;QACNC,OAAS,EAAA,8BAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,KAAA;QACRC,IAAM,EAAA,oBAAA;QACNC,OAAS,EAAA,iCAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,WAAA;QACNC,OAAS,EAAA,yBAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,kBAAA;QACNC,OAAS,EAAA,+BAAA;QACTC,MAAQ,EAAA;YACNC,IAAM,EAAA,KAAA;YACNC,WAAa,EAAA;AAAC,gBAAA;AAA0B;AAC1C;AACF,KAAA;AACA,IAAA;QACEL,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,iBAAA;QACNC,OAAS,EAAA,8BAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,SAAA;QACNC,OAAS,EAAA,uBAAA;QACTC,MAAQ,EAAA;YACNG,QAAU,EAAA;AAAC,gBAAA;AAA8B;AAC3C;AACF;CACD;;;;"}
1
+ {"version":3,"file":"authentication.mjs","sources":["../../../../../server/src/routes/authentication.ts"],"sourcesContent":["export default [\n {\n method: 'POST',\n path: '/login',\n handler: 'authentication.login',\n config: {\n auth: false,\n middlewares: ['admin::rateLimit'],\n },\n },\n {\n method: 'POST',\n path: '/access-token',\n handler: 'authentication.accessToken',\n config: {\n auth: false,\n },\n },\n {\n method: 'POST',\n path: '/register-admin',\n handler: 'authentication.registerAdmin',\n config: { auth: false },\n },\n {\n method: 'GET',\n path: '/registration-info',\n handler: 'authentication.registrationInfo',\n config: { auth: false },\n },\n {\n method: 'POST',\n path: '/register',\n handler: 'authentication.register',\n config: { auth: false },\n },\n {\n method: 'POST',\n path: '/forgot-password',\n handler: 'authentication.forgotPassword',\n config: {\n auth: false,\n middlewares: ['plugin::email.rateLimit'],\n },\n },\n {\n method: 'POST',\n path: '/reset-password',\n handler: 'authentication.resetPassword',\n config: { auth: false },\n },\n {\n method: 'POST',\n path: '/logout',\n handler: 'authentication.logout',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n];\n"],"names":["method","path","handler","config","auth","middlewares","policies"],"mappings":"AAAA,qBAAe;AACb,IAAA;QACEA,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,QAAA;QACNC,OAAS,EAAA,sBAAA;QACTC,MAAQ,EAAA;YACNC,IAAM,EAAA,KAAA;YACNC,WAAa,EAAA;AAAC,gBAAA;AAAmB;AACnC;AACF,KAAA;AACA,IAAA;QACEL,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,eAAA;QACNC,OAAS,EAAA,4BAAA;QACTC,MAAQ,EAAA;YACNC,IAAM,EAAA;AACR;AACF,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,iBAAA;QACNC,OAAS,EAAA,8BAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,KAAA;QACRC,IAAM,EAAA,oBAAA;QACNC,OAAS,EAAA,iCAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,WAAA;QACNC,OAAS,EAAA,yBAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,kBAAA;QACNC,OAAS,EAAA,+BAAA;QACTC,MAAQ,EAAA;YACNC,IAAM,EAAA,KAAA;YACNC,WAAa,EAAA;AAAC,gBAAA;AAA0B;AAC1C;AACF,KAAA;AACA,IAAA;QACEL,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,iBAAA;QACNC,OAAS,EAAA,8BAAA;QACTC,MAAQ,EAAA;YAAEC,IAAM,EAAA;AAAM;AACxB,KAAA;AACA,IAAA;QACEJ,MAAQ,EAAA,MAAA;QACRC,IAAM,EAAA,SAAA;QACNC,OAAS,EAAA,uBAAA;QACTC,MAAQ,EAAA;YACNG,QAAU,EAAA;AAAC,gBAAA;AAA8B;AAC3C;AACF;CACD;;;;"}
@@ -2,7 +2,6 @@
2
2
 
3
3
  var crypto = require('crypto');
4
4
  var _ = require('lodash');
5
- var jwt = require('jsonwebtoken');
6
5
 
7
6
  const defaultJwtOptions = {
8
7
  expiresIn: '30d'
@@ -19,44 +18,58 @@ const getTokenOptions = ()=>{
19
18
  */ const createToken = ()=>{
20
19
  return crypto.randomBytes(20).toString('hex');
21
20
  };
22
- /**
23
- * Creates a JWT token for an administration user
24
- * @param user - admin user
25
- */ const createJwtToken = (user)=>{
26
- const { options, secret } = getTokenOptions();
27
- return jwt.sign({
28
- id: user.id
29
- }, secret, options);
30
- };
31
- /**
32
- * Tries to decode a token an return its payload and if it is valid
33
- * @param token - a token to decode
34
- * @return decodeInfo - the decoded info
35
- */ const decodeJwtToken = (token)=>{
36
- const { secret } = getTokenOptions();
37
- try {
38
- const payload = jwt.verify(token, secret);
39
- return {
40
- payload,
41
- isValid: true
42
- };
43
- } catch (err) {
44
- return {
45
- payload: null,
46
- isValid: false
47
- };
48
- }
49
- };
50
21
  const checkSecretIsDefined = ()=>{
51
22
  if (strapi.config.get('admin.serveAdminPanel') && !strapi.config.get('admin.auth.secret')) {
52
23
  throw new Error(`Missing auth.secret. Please set auth.secret in config/admin.js (ex: you can generate one using Node with \`crypto.randomBytes(16).toString('base64')\`).
53
24
  For security reasons, prefer storing the secret in an environment variable and read it in config/admin.js. See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`);
54
25
  }
55
26
  };
27
+ /**
28
+ * Convert an expiresIn value (string or number) into seconds.
29
+ * Supported formats:
30
+ * - number: treated as seconds
31
+ * - numeric string (e.g. "180"): treated as seconds
32
+ * - shorthand string: "Xs", "Xm", "Xh", "Xd", "Xw" (case-insensitive)
33
+ * Returns undefined when value is not set or invalid.
34
+ */ const expiresInToSeconds = (expiresIn)=>{
35
+ if (expiresIn == null) return undefined;
36
+ // Numeric input => seconds
37
+ if (typeof expiresIn === 'number' && Number.isFinite(expiresIn)) {
38
+ return Math.max(0, Math.floor(expiresIn));
39
+ }
40
+ if (typeof expiresIn !== 'string') return undefined;
41
+ const value = expiresIn.trim().toLowerCase();
42
+ // Pure numeric string => seconds
43
+ if (/^\d+$/.test(value)) {
44
+ const seconds = Number.parseInt(value, 10);
45
+ return Number.isFinite(seconds) ? Math.max(0, seconds) : undefined;
46
+ }
47
+ // Shorthand formats (s, m, h, d, w)
48
+ const match = value.match(/^(\d+)\s*(ms|s|m|h|d|w)$/i);
49
+ if (!match) return undefined;
50
+ const amount = Number.parseInt(match[1], 10);
51
+ if (!Number.isFinite(amount)) return undefined;
52
+ const unit = match[2];
53
+ switch(unit){
54
+ case 'ms':
55
+ return Math.max(0, Math.floor(amount / 1000));
56
+ case 's':
57
+ return Math.max(0, amount);
58
+ case 'm':
59
+ return Math.max(0, amount * 60);
60
+ case 'h':
61
+ return Math.max(0, amount * 60 * 60);
62
+ case 'd':
63
+ return Math.max(0, amount * 24 * 60 * 60);
64
+ case 'w':
65
+ return Math.max(0, amount * 7 * 24 * 60 * 60);
66
+ default:
67
+ return undefined;
68
+ }
69
+ };
56
70
 
57
71
  exports.checkSecretIsDefined = checkSecretIsDefined;
58
- exports.createJwtToken = createJwtToken;
59
72
  exports.createToken = createToken;
60
- exports.decodeJwtToken = decodeJwtToken;
73
+ exports.expiresInToSeconds = expiresInToSeconds;
61
74
  exports.getTokenOptions = getTokenOptions;
62
75
  //# sourceMappingURL=token.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"token.js","sources":["../../../../../server/src/services/token.ts"],"sourcesContent":["import crypto from 'crypto';\nimport _ from 'lodash';\nimport jwt from 'jsonwebtoken';\nimport type { AdminUser } from '../../../shared/contracts/shared';\n\nconst defaultJwtOptions = { expiresIn: '30d' };\n\nexport type TokenOptions = {\n expiresIn?: string;\n [key: string]: unknown;\n};\n\nexport type TokenPayload = {\n id: AdminUser['id'];\n};\n\nexport type AdminAuthConfig = {\n secret: string;\n options: TokenOptions;\n};\n\nconst getTokenOptions = () => {\n const { options, secret } = strapi.config.get<AdminAuthConfig>(\n 'admin.auth',\n {} as AdminAuthConfig\n );\n\n return {\n secret,\n options: _.merge(defaultJwtOptions, options),\n };\n};\n\n/**\n * Create a random token\n */\nconst createToken = (): string => {\n return crypto.randomBytes(20).toString('hex');\n};\n\n/**\n * Creates a JWT token for an administration user\n * @param user - admin user\n */\nconst createJwtToken = (user: { id: AdminUser['id'] }) => {\n const { options, secret } = getTokenOptions();\n\n return jwt.sign({ id: user.id }, secret, options);\n};\n\n/**\n * Tries to decode a token an return its payload and if it is valid\n * @param token - a token to decode\n * @return decodeInfo - the decoded info\n */\nconst decodeJwtToken = (\n token: string\n): { payload: TokenPayload; isValid: true } | { payload: null; isValid: false } => {\n const { secret } = getTokenOptions();\n\n try {\n const payload = jwt.verify(token, secret) as TokenPayload;\n return { payload, isValid: true };\n } catch (err) {\n return { payload: null, isValid: false };\n }\n};\n\nconst checkSecretIsDefined = () => {\n if (strapi.config.get('admin.serveAdminPanel') && !strapi.config.get('admin.auth.secret')) {\n throw new Error(\n `Missing auth.secret. Please set auth.secret in config/admin.js (ex: you can generate one using Node with \\`crypto.randomBytes(16).toString('base64')\\`).\nFor security reasons, prefer storing the secret in an environment variable and read it in config/admin.js. See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`\n );\n }\n};\n\nexport { createToken, createJwtToken, getTokenOptions, decodeJwtToken, checkSecretIsDefined };\n"],"names":["defaultJwtOptions","expiresIn","getTokenOptions","options","secret","strapi","config","get","_","merge","createToken","crypto","randomBytes","toString","createJwtToken","user","jwt","sign","id","decodeJwtToken","token","payload","verify","isValid","err","checkSecretIsDefined","Error"],"mappings":";;;;;;AAKA,MAAMA,iBAAoB,GAAA;IAAEC,SAAW,EAAA;AAAM,CAAA;AAgB7C,MAAMC,eAAkB,GAAA,IAAA;AACtB,IAAA,MAAM,EAAEC,OAAO,EAAEC,MAAM,EAAE,GAAGC,MAAOC,CAAAA,MAAM,CAACC,GAAG,CAC3C,YAAA,EACA,EAAC,CAAA;IAGH,OAAO;AACLH,QAAAA,MAAAA;QACAD,OAASK,EAAAA,CAAAA,CAAEC,KAAK,CAACT,iBAAmBG,EAAAA,OAAAA;AACtC,KAAA;AACF;AAEA;;AAEC,UACKO,WAAc,GAAA,IAAA;AAClB,IAAA,OAAOC,MAAOC,CAAAA,WAAW,CAAC,EAAA,CAAA,CAAIC,QAAQ,CAAC,KAAA,CAAA;AACzC;AAEA;;;IAIA,MAAMC,iBAAiB,CAACC,IAAAA,GAAAA;AACtB,IAAA,MAAM,EAAEZ,OAAO,EAAEC,MAAM,EAAE,GAAGF,eAAAA,EAAAA;IAE5B,OAAOc,GAAAA,CAAIC,IAAI,CAAC;AAAEC,QAAAA,EAAAA,EAAIH,KAAKG;AAAG,KAAA,EAAGd,MAAQD,EAAAA,OAAAA,CAAAA;AAC3C;AAEA;;;;IAKA,MAAMgB,iBAAiB,CACrBC,KAAAA,GAAAA;IAEA,MAAM,EAAEhB,MAAM,EAAE,GAAGF,eAAAA,EAAAA;IAEnB,IAAI;AACF,QAAA,MAAMmB,OAAUL,GAAAA,GAAAA,CAAIM,MAAM,CAACF,KAAOhB,EAAAA,MAAAA,CAAAA;QAClC,OAAO;AAAEiB,YAAAA,OAAAA;YAASE,OAAS,EAAA;AAAK,SAAA;AAClC,KAAA,CAAE,OAAOC,GAAK,EAAA;QACZ,OAAO;YAAEH,OAAS,EAAA,IAAA;YAAME,OAAS,EAAA;AAAM,SAAA;AACzC;AACF;AAEA,MAAME,oBAAuB,GAAA,IAAA;AAC3B,IAAA,IAAIpB,MAAOC,CAAAA,MAAM,CAACC,GAAG,CAAC,uBAAA,CAAA,IAA4B,CAACF,MAAAA,CAAOC,MAAM,CAACC,GAAG,CAAC,mBAAsB,CAAA,EAAA;QACzF,MAAM,IAAImB,MACR,CAAC;uQACgQ,CAAC,CAAA;AAEtQ;AACF;;;;;;;;"}
1
+ {"version":3,"file":"token.js","sources":["../../../../../server/src/services/token.ts"],"sourcesContent":["import crypto from 'crypto';\nimport _ from 'lodash';\nimport type { Algorithm } from 'jsonwebtoken';\nimport type { AdminUser } from '../../../shared/contracts/shared';\n\nconst defaultJwtOptions = { expiresIn: '30d' };\n\nexport type TokenOptions = {\n expiresIn?: string;\n algorithm?: Algorithm;\n [key: string]: unknown;\n};\n\nexport type TokenPayload = {\n id: AdminUser['id'];\n};\n\nexport type AdminAuthConfig = {\n secret: string;\n options: TokenOptions;\n};\n\nconst getTokenOptions = () => {\n const { options, secret } = strapi.config.get<AdminAuthConfig>(\n 'admin.auth',\n {} as AdminAuthConfig\n );\n\n return {\n secret,\n options: _.merge(defaultJwtOptions, options),\n };\n};\n\n/**\n * Create a random token\n */\nconst createToken = (): string => {\n return crypto.randomBytes(20).toString('hex');\n};\n\nconst checkSecretIsDefined = () => {\n if (strapi.config.get('admin.serveAdminPanel') && !strapi.config.get('admin.auth.secret')) {\n throw new Error(\n `Missing auth.secret. Please set auth.secret in config/admin.js (ex: you can generate one using Node with \\`crypto.randomBytes(16).toString('base64')\\`).\nFor security reasons, prefer storing the secret in an environment variable and read it in config/admin.js. See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`\n );\n }\n};\n\nexport { createToken, getTokenOptions, checkSecretIsDefined };\n\n/**\n * Convert an expiresIn value (string or number) into seconds.\n * Supported formats:\n * - number: treated as seconds\n * - numeric string (e.g. \"180\"): treated as seconds\n * - shorthand string: \"Xs\", \"Xm\", \"Xh\", \"Xd\", \"Xw\" (case-insensitive)\n * Returns undefined when value is not set or invalid.\n */\nexport const expiresInToSeconds = (expiresIn: unknown): number | undefined => {\n if (expiresIn == null) return undefined;\n\n // Numeric input => seconds\n if (typeof expiresIn === 'number' && Number.isFinite(expiresIn)) {\n return Math.max(0, Math.floor(expiresIn));\n }\n\n if (typeof expiresIn !== 'string') return undefined;\n\n const value = expiresIn.trim().toLowerCase();\n\n // Pure numeric string => seconds\n if (/^\\d+$/.test(value)) {\n const seconds = Number.parseInt(value, 10);\n return Number.isFinite(seconds) ? Math.max(0, seconds) : undefined;\n }\n\n // Shorthand formats (s, m, h, d, w)\n const match = value.match(/^(\\d+)\\s*(ms|s|m|h|d|w)$/i);\n if (!match) return undefined;\n\n const amount = Number.parseInt(match[1], 10);\n if (!Number.isFinite(amount)) return undefined;\n\n const unit = match[2];\n switch (unit) {\n case 'ms':\n return Math.max(0, Math.floor(amount / 1000));\n case 's':\n return Math.max(0, amount);\n case 'm':\n return Math.max(0, amount * 60);\n case 'h':\n return Math.max(0, amount * 60 * 60);\n case 'd':\n return Math.max(0, amount * 24 * 60 * 60);\n case 'w':\n return Math.max(0, amount * 7 * 24 * 60 * 60);\n default:\n return undefined;\n }\n};\n"],"names":["defaultJwtOptions","expiresIn","getTokenOptions","options","secret","strapi","config","get","_","merge","createToken","crypto","randomBytes","toString","checkSecretIsDefined","Error","expiresInToSeconds","undefined","Number","isFinite","Math","max","floor","value","trim","toLowerCase","test","seconds","parseInt","match","amount","unit"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  import crypto from 'crypto';
2
2
  import ___default from 'lodash';
3
- import jwt from 'jsonwebtoken';
4
3
 
5
4
  const defaultJwtOptions = {
6
5
  expiresIn: '30d'
@@ -17,40 +16,55 @@ const getTokenOptions = ()=>{
17
16
  */ const createToken = ()=>{
18
17
  return crypto.randomBytes(20).toString('hex');
19
18
  };
20
- /**
21
- * Creates a JWT token for an administration user
22
- * @param user - admin user
23
- */ const createJwtToken = (user)=>{
24
- const { options, secret } = getTokenOptions();
25
- return jwt.sign({
26
- id: user.id
27
- }, secret, options);
28
- };
29
- /**
30
- * Tries to decode a token an return its payload and if it is valid
31
- * @param token - a token to decode
32
- * @return decodeInfo - the decoded info
33
- */ const decodeJwtToken = (token)=>{
34
- const { secret } = getTokenOptions();
35
- try {
36
- const payload = jwt.verify(token, secret);
37
- return {
38
- payload,
39
- isValid: true
40
- };
41
- } catch (err) {
42
- return {
43
- payload: null,
44
- isValid: false
45
- };
46
- }
47
- };
48
19
  const checkSecretIsDefined = ()=>{
49
20
  if (strapi.config.get('admin.serveAdminPanel') && !strapi.config.get('admin.auth.secret')) {
50
21
  throw new Error(`Missing auth.secret. Please set auth.secret in config/admin.js (ex: you can generate one using Node with \`crypto.randomBytes(16).toString('base64')\`).
51
22
  For security reasons, prefer storing the secret in an environment variable and read it in config/admin.js. See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`);
52
23
  }
53
24
  };
25
+ /**
26
+ * Convert an expiresIn value (string or number) into seconds.
27
+ * Supported formats:
28
+ * - number: treated as seconds
29
+ * - numeric string (e.g. "180"): treated as seconds
30
+ * - shorthand string: "Xs", "Xm", "Xh", "Xd", "Xw" (case-insensitive)
31
+ * Returns undefined when value is not set or invalid.
32
+ */ const expiresInToSeconds = (expiresIn)=>{
33
+ if (expiresIn == null) return undefined;
34
+ // Numeric input => seconds
35
+ if (typeof expiresIn === 'number' && Number.isFinite(expiresIn)) {
36
+ return Math.max(0, Math.floor(expiresIn));
37
+ }
38
+ if (typeof expiresIn !== 'string') return undefined;
39
+ const value = expiresIn.trim().toLowerCase();
40
+ // Pure numeric string => seconds
41
+ if (/^\d+$/.test(value)) {
42
+ const seconds = Number.parseInt(value, 10);
43
+ return Number.isFinite(seconds) ? Math.max(0, seconds) : undefined;
44
+ }
45
+ // Shorthand formats (s, m, h, d, w)
46
+ const match = value.match(/^(\d+)\s*(ms|s|m|h|d|w)$/i);
47
+ if (!match) return undefined;
48
+ const amount = Number.parseInt(match[1], 10);
49
+ if (!Number.isFinite(amount)) return undefined;
50
+ const unit = match[2];
51
+ switch(unit){
52
+ case 'ms':
53
+ return Math.max(0, Math.floor(amount / 1000));
54
+ case 's':
55
+ return Math.max(0, amount);
56
+ case 'm':
57
+ return Math.max(0, amount * 60);
58
+ case 'h':
59
+ return Math.max(0, amount * 60 * 60);
60
+ case 'd':
61
+ return Math.max(0, amount * 24 * 60 * 60);
62
+ case 'w':
63
+ return Math.max(0, amount * 7 * 24 * 60 * 60);
64
+ default:
65
+ return undefined;
66
+ }
67
+ };
54
68
 
55
- export { checkSecretIsDefined, createJwtToken, createToken, decodeJwtToken, getTokenOptions };
69
+ export { checkSecretIsDefined, createToken, expiresInToSeconds, getTokenOptions };
56
70
  //# sourceMappingURL=token.mjs.map