@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
@@ -1,57 +1,93 @@
1
- import { getFetchClient, isFetchError } from './getFetchClient.mjs';
1
+ import { logout, login } from '../reducer.mjs';
2
+ import { isFetchError, getFetchClient } from './getFetchClient.mjs';
2
3
 
3
- const simpleQuery = async (query, { signal })=>{
4
- try {
4
+ let refreshPromise = null;
5
+ const isAuthPath = (url)=>/^\/admin\/(login|logout|access-token)\b/.test(url);
6
+ const simpleQuery = async (query, api)=>{
7
+ const { signal, dispatch } = api;
8
+ const executeQuery = async (queryToExecute)=>{
5
9
  const { get, post, del, put } = getFetchClient();
6
- if (typeof query === 'string') {
7
- const result = await get(query, {
10
+ if (typeof queryToExecute === 'string') {
11
+ const result = await get(queryToExecute, {
8
12
  signal
9
13
  });
10
- return {
11
- data: result.data
12
- };
13
- } else {
14
- const { url, method = 'GET', data, config } = query;
15
- if (method === 'POST') {
16
- const result = await post(url, data, {
17
- ...config,
18
- signal
19
- });
20
- return {
21
- data: result.data
22
- };
23
- }
24
- if (method === 'DELETE') {
25
- const result = await del(url, {
26
- ...config,
27
- signal
28
- });
29
- return {
30
- data: result.data
31
- };
32
- }
33
- if (method === 'PUT') {
34
- const result = await put(url, data, {
35
- ...config,
36
- signal
37
- });
38
- return {
39
- data: result.data
40
- };
41
- }
42
- /**
43
- * Default is GET.
44
- */ const result = await get(url, {
14
+ return result;
15
+ }
16
+ const { url, method = 'GET', data, config } = queryToExecute;
17
+ if (method === 'POST') {
18
+ return post(url, data, {
45
19
  ...config,
46
20
  signal
47
21
  });
48
- return {
49
- data: result.data
50
- };
51
22
  }
23
+ if (method === 'DELETE') {
24
+ return del(url, {
25
+ ...config,
26
+ signal
27
+ });
28
+ }
29
+ if (method === 'PUT') {
30
+ return put(url, data, {
31
+ ...config,
32
+ signal
33
+ });
34
+ }
35
+ return get(url, {
36
+ ...config,
37
+ signal
38
+ });
39
+ };
40
+ try {
41
+ const result = await executeQuery(query);
42
+ return {
43
+ data: result.data
44
+ };
52
45
  } catch (err) {
53
46
  // Handle error of type FetchError
54
47
  if (isFetchError(err)) {
48
+ // Attempt auto-refresh on 401 then retry once
49
+ if (err.status === 401) {
50
+ const url = typeof query === 'string' ? query : query.url;
51
+ if (!isAuthPath(url)) {
52
+ if (!refreshPromise) {
53
+ async function refreshAccessToken() {
54
+ const { post } = getFetchClient();
55
+ const res = await post('/admin/access-token');
56
+ const token = res?.data?.data?.token;
57
+ if (!token) {
58
+ throw new Error('access_token_exchange_failed');
59
+ }
60
+ // Persist according to previous choice: localStorage presence implies persist
61
+ const persist = Boolean(localStorage.getItem('jwtToken'));
62
+ dispatch(login({
63
+ token,
64
+ persist
65
+ }));
66
+ return token;
67
+ }
68
+ refreshPromise = refreshAccessToken().finally(()=>{
69
+ refreshPromise = null;
70
+ });
71
+ }
72
+ try {
73
+ await refreshPromise;
74
+ // Retry original request once with updated Authorization
75
+ const retry = await executeQuery(query);
76
+ return {
77
+ data: retry.data
78
+ };
79
+ } catch (refreshError) {
80
+ try {
81
+ const { post } = getFetchClient();
82
+ await post('/admin/logout');
83
+ } catch {
84
+ // no-op
85
+ }
86
+ dispatch(logout());
87
+ // Fall through to return the original 401 error shape
88
+ }
89
+ }
90
+ }
55
91
  if (typeof err.response?.data === 'object' && err.response?.data !== null && 'error' in err.response?.data) {
56
92
  /**
57
93
  * This will most likely be ApiError
@@ -1 +1 @@
1
- {"version":3,"file":"baseQuery.mjs","sources":["../../../../../admin/src/utils/baseQuery.ts"],"sourcesContent":["import { SerializedError } from '@reduxjs/toolkit';\nimport { BaseQueryFn } from '@reduxjs/toolkit/query';\n\nimport { getFetchClient, type FetchOptions, ApiError, isFetchError } from '../utils/getFetchClient';\n\ninterface QueryArguments {\n url: string;\n method?: 'GET' | 'POST' | 'DELETE' | 'PUT';\n data?: unknown;\n config?: FetchOptions;\n}\n\ninterface UnknownApiError {\n name: 'UnknownError';\n message: string;\n details?: unknown;\n status?: number;\n}\n\ntype BaseQueryError = ApiError | UnknownApiError;\n\nconst simpleQuery: BaseQueryFn<string | QueryArguments, unknown, BaseQueryError> = async (\n query,\n { signal }\n) => {\n try {\n const { get, post, del, put } = getFetchClient();\n\n if (typeof query === 'string') {\n const result = await get(query, { signal });\n return { data: result.data };\n } else {\n const { url, method = 'GET', data, config } = query;\n\n if (method === 'POST') {\n const result = await post(url, data, {\n ...config,\n signal,\n });\n return { data: result.data };\n }\n\n if (method === 'DELETE') {\n const result = await del(url, {\n ...config,\n signal,\n });\n return { data: result.data };\n }\n\n if (method === 'PUT') {\n const result = await put(url, data, {\n ...config,\n signal,\n });\n return { data: result.data };\n }\n\n /**\n * Default is GET.\n */\n const result = await get(url, {\n ...config,\n signal,\n });\n return { data: result.data };\n }\n } catch (err) {\n // Handle error of type FetchError\n\n if (isFetchError(err)) {\n if (\n typeof err.response?.data === 'object' &&\n err.response?.data !== null &&\n 'error' in err.response?.data\n ) {\n /**\n * This will most likely be ApiError\n */\n return { data: undefined, error: err.response?.data.error as any };\n } else {\n return {\n data: undefined,\n error: {\n name: 'UnknownError',\n message: err.message,\n details: err.response,\n status: err.status,\n } as UnknownApiError,\n };\n }\n }\n\n const error = err as Error;\n return {\n data: undefined,\n error: {\n name: error.name,\n message: error.message,\n stack: error.stack,\n } satisfies SerializedError,\n };\n }\n};\n\nconst fetchBaseQuery = () => simpleQuery;\n\nconst isBaseQueryError = (error: BaseQueryError | SerializedError): error is BaseQueryError => {\n return error.name !== undefined;\n};\n\nexport { fetchBaseQuery, isBaseQueryError };\nexport type { BaseQueryError, UnknownApiError, QueryArguments };\n"],"names":["simpleQuery","query","signal","get","post","del","put","getFetchClient","result","data","url","method","config","err","isFetchError","response","undefined","error","name","message","details","status","stack","fetchBaseQuery","isBaseQueryError"],"mappings":"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"}
1
+ {"version":3,"file":"baseQuery.mjs","sources":["../../../../../admin/src/utils/baseQuery.ts"],"sourcesContent":["import { SerializedError } from '@reduxjs/toolkit';\nimport { BaseQueryFn } from '@reduxjs/toolkit/query';\n\nimport { login as loginAction, logout as logoutAction } from '../reducer';\nimport { getFetchClient, type FetchOptions, ApiError, isFetchError } from '../utils/getFetchClient';\n\ninterface QueryArguments {\n url: string;\n method?: 'GET' | 'POST' | 'DELETE' | 'PUT';\n data?: unknown;\n config?: FetchOptions;\n}\n\ninterface UnknownApiError {\n name: 'UnknownError';\n message: string;\n details?: unknown;\n status?: number;\n}\n\ntype BaseQueryError = ApiError | UnknownApiError;\n\nlet refreshPromise: Promise<string> | null = null;\n\nconst isAuthPath = (url: string) => /^\\/admin\\/(login|logout|access-token)\\b/.test(url);\n\nconst simpleQuery: BaseQueryFn<string | QueryArguments, unknown, BaseQueryError> = async (\n query,\n api\n) => {\n const { signal, dispatch } = api as { signal?: AbortSignal; dispatch: (a: any) => void };\n\n const executeQuery = async (queryToExecute: string | QueryArguments) => {\n const { get, post, del, put } = getFetchClient();\n if (typeof queryToExecute === 'string') {\n const result = await get(queryToExecute, { signal });\n return result;\n }\n\n const { url, method = 'GET', data, config } = queryToExecute;\n if (method === 'POST') {\n return post(url, data, { ...config, signal });\n }\n if (method === 'DELETE') {\n return del(url, { ...config, signal });\n }\n if (method === 'PUT') {\n return put(url, data, { ...config, signal });\n }\n return get(url, { ...config, signal });\n };\n\n try {\n const result = await executeQuery(query);\n return { data: result.data };\n } catch (err) {\n // Handle error of type FetchError\n\n if (isFetchError(err)) {\n // Attempt auto-refresh on 401 then retry once\n if (err.status === 401) {\n const url = typeof query === 'string' ? query : query.url;\n\n if (!isAuthPath(url)) {\n if (!refreshPromise) {\n async function refreshAccessToken(): Promise<string> {\n const { post } = getFetchClient();\n\n const res = await post('/admin/access-token');\n const token = res?.data?.data?.token as string | undefined;\n if (!token) {\n throw new Error('access_token_exchange_failed');\n }\n\n // Persist according to previous choice: localStorage presence implies persist\n const persist = Boolean(localStorage.getItem('jwtToken'));\n dispatch(loginAction({ token, persist }));\n\n return token;\n }\n\n refreshPromise = refreshAccessToken().finally(() => {\n refreshPromise = null;\n });\n }\n\n try {\n await refreshPromise;\n // Retry original request once with updated Authorization\n const retry = await executeQuery(query);\n\n return { data: retry.data };\n } catch (refreshError) {\n try {\n const { post } = getFetchClient();\n await post('/admin/logout');\n } catch {\n // no-op\n }\n\n dispatch(logoutAction());\n // Fall through to return the original 401 error shape\n }\n }\n }\n\n if (\n typeof err.response?.data === 'object' &&\n err.response?.data !== null &&\n 'error' in err.response?.data\n ) {\n /**\n * This will most likely be ApiError\n */\n return { data: undefined, error: err.response?.data.error as any };\n } else {\n return {\n data: undefined,\n error: {\n name: 'UnknownError',\n message: err.message,\n details: err.response,\n status: err.status,\n } as UnknownApiError,\n };\n }\n }\n\n const error = err as Error;\n return {\n data: undefined,\n error: {\n name: error.name,\n message: error.message,\n stack: error.stack,\n } satisfies SerializedError,\n };\n }\n};\n\nconst fetchBaseQuery = () => simpleQuery;\n\nconst isBaseQueryError = (error: BaseQueryError | SerializedError): error is BaseQueryError => {\n return error.name !== undefined;\n};\n\nexport { fetchBaseQuery, isBaseQueryError };\nexport type { BaseQueryError, UnknownApiError, QueryArguments };\n"],"names":["refreshPromise","isAuthPath","url","test","simpleQuery","query","api","signal","dispatch","executeQuery","queryToExecute","get","post","del","put","getFetchClient","result","method","data","config","err","isFetchError","status","refreshAccessToken","res","token","Error","persist","Boolean","localStorage","getItem","loginAction","finally","retry","refreshError","logoutAction","response","undefined","error","name","message","details","stack","fetchBaseQuery","isBaseQueryError"],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ 'use strict';
2
+
3
+ const fallbackUUIDv4 = ()=>{
4
+ const bytes = crypto.getRandomValues(new Uint8Array(16));
5
+ bytes[6] = bytes[6] & 0x0f | 0x40;
6
+ bytes[8] = bytes[8] & 0x3f | 0x80;
7
+ const hex = [
8
+ ...bytes
9
+ ].map((b)=>b.toString(16).padStart(2, '0'));
10
+ return [
11
+ hex.slice(0, 4).join(''),
12
+ hex.slice(4, 6).join(''),
13
+ hex.slice(6, 8).join(''),
14
+ hex.slice(8, 10).join(''),
15
+ hex.slice(10, 16).join('')
16
+ ].join('-');
17
+ };
18
+ /**
19
+ * Returns a stable device identifier for session-based authentication flows.
20
+ * Uses localStorage to persist a UUID between sessions on the same browser.
21
+ */ const getOrCreateDeviceId = ()=>{
22
+ const storageKey = 'strapi.admin.deviceId';
23
+ const existing = window.localStorage.getItem(storageKey);
24
+ if (existing) {
25
+ return existing;
26
+ }
27
+ // Use randomUUID in secure contexts, otherwise polyfill
28
+ const generated = typeof crypto?.randomUUID === 'function' ? crypto.randomUUID() : fallbackUUIDv4();
29
+ try {
30
+ window.localStorage.setItem(storageKey, generated);
31
+ } catch {
32
+ // no-op
33
+ }
34
+ return generated;
35
+ };
36
+
37
+ exports.getOrCreateDeviceId = getOrCreateDeviceId;
38
+ //# sourceMappingURL=deviceId.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deviceId.js","sources":["../../../../../admin/src/utils/deviceId.ts"],"sourcesContent":["const fallbackUUIDv4 = (): string => {\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n\n bytes[6] = (bytes[6] & 0x0f) | 0x40;\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n\n const hex = [...bytes].map((b) => b.toString(16).padStart(2, '0'));\n return [\n hex.slice(0, 4).join(''),\n hex.slice(4, 6).join(''),\n hex.slice(6, 8).join(''),\n hex.slice(8, 10).join(''),\n hex.slice(10, 16).join(''),\n ].join('-');\n};\n\n/**\n * Returns a stable device identifier for session-based authentication flows.\n * Uses localStorage to persist a UUID between sessions on the same browser.\n */\nexport const getOrCreateDeviceId = (): string => {\n const storageKey = 'strapi.admin.deviceId';\n\n const existing = window.localStorage.getItem(storageKey);\n if (existing) {\n return existing;\n }\n\n // Use randomUUID in secure contexts, otherwise polyfill\n const generated =\n typeof crypto?.randomUUID === 'function' ? crypto.randomUUID() : fallbackUUIDv4();\n\n try {\n window.localStorage.setItem(storageKey, generated);\n } catch {\n // no-op\n }\n\n return generated;\n};\n"],"names":["fallbackUUIDv4","bytes","crypto","getRandomValues","Uint8Array","hex","map","b","toString","padStart","slice","join","getOrCreateDeviceId","storageKey","existing","window","localStorage","getItem","generated","randomUUID","setItem"],"mappings":";;AAAA,MAAMA,cAAiB,GAAA,IAAA;AACrB,IAAA,MAAMC,KAAQC,GAAAA,MAAAA,CAAOC,eAAe,CAAC,IAAIC,UAAW,CAAA,EAAA,CAAA,CAAA;IAEpDH,KAAK,CAAC,EAAE,GAAIA,KAAK,CAAC,CAAA,CAAE,GAAG,IAAQ,GAAA,IAAA;IAC/BA,KAAK,CAAC,EAAE,GAAIA,KAAK,CAAC,CAAA,CAAE,GAAG,IAAQ,GAAA,IAAA;AAE/B,IAAA,MAAMI,GAAM,GAAA;AAAIJ,QAAAA,GAAAA;KAAM,CAACK,GAAG,CAAC,CAACC,CAAMA,GAAAA,CAAAA,CAAEC,QAAQ,CAAC,EAAA,CAAA,CAAIC,QAAQ,CAAC,CAAG,EAAA,GAAA,CAAA,CAAA;IAC7D,OAAO;AACLJ,QAAAA,GAAAA,CAAIK,KAAK,CAAC,CAAG,EAAA,CAAA,CAAA,CAAGC,IAAI,CAAC,EAAA,CAAA;AACrBN,QAAAA,GAAAA,CAAIK,KAAK,CAAC,CAAG,EAAA,CAAA,CAAA,CAAGC,IAAI,CAAC,EAAA,CAAA;AACrBN,QAAAA,GAAAA,CAAIK,KAAK,CAAC,CAAG,EAAA,CAAA,CAAA,CAAGC,IAAI,CAAC,EAAA,CAAA;AACrBN,QAAAA,GAAAA,CAAIK,KAAK,CAAC,CAAG,EAAA,EAAA,CAAA,CAAIC,IAAI,CAAC,EAAA,CAAA;AACtBN,QAAAA,GAAAA,CAAIK,KAAK,CAAC,EAAI,EAAA,EAAA,CAAA,CAAIC,IAAI,CAAC,EAAA;AACxB,KAAA,CAACA,IAAI,CAAC,GAAA,CAAA;AACT,CAAA;AAEA;;;UAIaC,mBAAsB,GAAA,IAAA;AACjC,IAAA,MAAMC,UAAa,GAAA,uBAAA;AAEnB,IAAA,MAAMC,QAAWC,GAAAA,MAAAA,CAAOC,YAAY,CAACC,OAAO,CAACJ,UAAAA,CAAAA;AAC7C,IAAA,IAAIC,QAAU,EAAA;QACZ,OAAOA,QAAAA;AACT;;AAGA,IAAA,MAAMI,YACJ,OAAOhB,MAAAA,EAAQiB,eAAe,UAAajB,GAAAA,MAAAA,CAAOiB,UAAU,EAAKnB,GAAAA,cAAAA,EAAAA;IAEnE,IAAI;AACFe,QAAAA,MAAAA,CAAOC,YAAY,CAACI,OAAO,CAACP,UAAYK,EAAAA,SAAAA,CAAAA;AAC1C,KAAA,CAAE,OAAM;;AAER;IAEA,OAAOA,SAAAA;AACT;;;;"}
@@ -0,0 +1,36 @@
1
+ const fallbackUUIDv4 = ()=>{
2
+ const bytes = crypto.getRandomValues(new Uint8Array(16));
3
+ bytes[6] = bytes[6] & 0x0f | 0x40;
4
+ bytes[8] = bytes[8] & 0x3f | 0x80;
5
+ const hex = [
6
+ ...bytes
7
+ ].map((b)=>b.toString(16).padStart(2, '0'));
8
+ return [
9
+ hex.slice(0, 4).join(''),
10
+ hex.slice(4, 6).join(''),
11
+ hex.slice(6, 8).join(''),
12
+ hex.slice(8, 10).join(''),
13
+ hex.slice(10, 16).join('')
14
+ ].join('-');
15
+ };
16
+ /**
17
+ * Returns a stable device identifier for session-based authentication flows.
18
+ * Uses localStorage to persist a UUID between sessions on the same browser.
19
+ */ const getOrCreateDeviceId = ()=>{
20
+ const storageKey = 'strapi.admin.deviceId';
21
+ const existing = window.localStorage.getItem(storageKey);
22
+ if (existing) {
23
+ return existing;
24
+ }
25
+ // Use randomUUID in secure contexts, otherwise polyfill
26
+ const generated = typeof crypto?.randomUUID === 'function' ? crypto.randomUUID() : fallbackUUIDv4();
27
+ try {
28
+ window.localStorage.setItem(storageKey, generated);
29
+ } catch {
30
+ // no-op
31
+ }
32
+ return generated;
33
+ };
34
+
35
+ export { getOrCreateDeviceId };
36
+ //# sourceMappingURL=deviceId.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deviceId.mjs","sources":["../../../../../admin/src/utils/deviceId.ts"],"sourcesContent":["const fallbackUUIDv4 = (): string => {\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n\n bytes[6] = (bytes[6] & 0x0f) | 0x40;\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n\n const hex = [...bytes].map((b) => b.toString(16).padStart(2, '0'));\n return [\n hex.slice(0, 4).join(''),\n hex.slice(4, 6).join(''),\n hex.slice(6, 8).join(''),\n hex.slice(8, 10).join(''),\n hex.slice(10, 16).join(''),\n ].join('-');\n};\n\n/**\n * Returns a stable device identifier for session-based authentication flows.\n * Uses localStorage to persist a UUID between sessions on the same browser.\n */\nexport const getOrCreateDeviceId = (): string => {\n const storageKey = 'strapi.admin.deviceId';\n\n const existing = window.localStorage.getItem(storageKey);\n if (existing) {\n return existing;\n }\n\n // Use randomUUID in secure contexts, otherwise polyfill\n const generated =\n typeof crypto?.randomUUID === 'function' ? crypto.randomUUID() : fallbackUUIDv4();\n\n try {\n window.localStorage.setItem(storageKey, generated);\n } catch {\n // no-op\n }\n\n return generated;\n};\n"],"names":["fallbackUUIDv4","bytes","crypto","getRandomValues","Uint8Array","hex","map","b","toString","padStart","slice","join","getOrCreateDeviceId","storageKey","existing","window","localStorage","getItem","generated","randomUUID","setItem"],"mappings":"AAAA,MAAMA,cAAiB,GAAA,IAAA;AACrB,IAAA,MAAMC,KAAQC,GAAAA,MAAAA,CAAOC,eAAe,CAAC,IAAIC,UAAW,CAAA,EAAA,CAAA,CAAA;IAEpDH,KAAK,CAAC,EAAE,GAAIA,KAAK,CAAC,CAAA,CAAE,GAAG,IAAQ,GAAA,IAAA;IAC/BA,KAAK,CAAC,EAAE,GAAIA,KAAK,CAAC,CAAA,CAAE,GAAG,IAAQ,GAAA,IAAA;AAE/B,IAAA,MAAMI,GAAM,GAAA;AAAIJ,QAAAA,GAAAA;KAAM,CAACK,GAAG,CAAC,CAACC,CAAMA,GAAAA,CAAAA,CAAEC,QAAQ,CAAC,EAAA,CAAA,CAAIC,QAAQ,CAAC,CAAG,EAAA,GAAA,CAAA,CAAA;IAC7D,OAAO;AACLJ,QAAAA,GAAAA,CAAIK,KAAK,CAAC,CAAG,EAAA,CAAA,CAAA,CAAGC,IAAI,CAAC,EAAA,CAAA;AACrBN,QAAAA,GAAAA,CAAIK,KAAK,CAAC,CAAG,EAAA,CAAA,CAAA,CAAGC,IAAI,CAAC,EAAA,CAAA;AACrBN,QAAAA,GAAAA,CAAIK,KAAK,CAAC,CAAG,EAAA,CAAA,CAAA,CAAGC,IAAI,CAAC,EAAA,CAAA;AACrBN,QAAAA,GAAAA,CAAIK,KAAK,CAAC,CAAG,EAAA,EAAA,CAAA,CAAIC,IAAI,CAAC,EAAA,CAAA;AACtBN,QAAAA,GAAAA,CAAIK,KAAK,CAAC,EAAI,EAAA,EAAA,CAAA,CAAIC,IAAI,CAAC,EAAA;AACxB,KAAA,CAACA,IAAI,CAAC,GAAA,CAAA;AACT,CAAA;AAEA;;;UAIaC,mBAAsB,GAAA,IAAA;AACjC,IAAA,MAAMC,UAAa,GAAA,uBAAA;AAEnB,IAAA,MAAMC,QAAWC,GAAAA,MAAAA,CAAOC,YAAY,CAACC,OAAO,CAACJ,UAAAA,CAAAA;AAC7C,IAAA,IAAIC,QAAU,EAAA;QACZ,OAAOA,QAAAA;AACT;;AAGA,IAAA,MAAMI,YACJ,OAAOhB,MAAAA,EAAQiB,eAAe,UAAajB,GAAAA,MAAAA,CAAOiB,UAAU,EAAKnB,GAAAA,cAAAA,EAAAA;IAEnE,IAAI;AACFe,QAAAA,MAAAA,CAAOC,YAAY,CAACI,OAAO,CAACP,UAAYK,EAAAA,SAAAA,CAAAA;AAC1C,KAAA,CAAE,OAAM;;AAER;IAEA,OAAOA,SAAAA;AACT;;;;"}
@@ -11,29 +11,38 @@ declare const useCheckPermissionsQuery: import("@reduxjs/toolkit/dist/query/reac
11
11
  permissions: (Pick<import("../../../shared/contracts/shared").Permission, "action" | "subject"> & {
12
12
  field?: string | undefined;
13
13
  })[];
14
- }, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", Check.Response, "adminApi">>, useGetMeQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", import("..").SanitizedAdminUser, "adminApi">>, useLoginMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<Pick<import("..").AdminUser, "email" | "password">, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", {
14
+ }, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", Check.Response, "adminApi">>, useGetMeQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", import("..").SanitizedAdminUser, "adminApi">>, useLoginMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<Pick<import("..").AdminUser, "email" | "password"> & {
15
+ deviceId?: string | undefined;
16
+ rememberMe?: boolean | undefined;
17
+ }, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", {
15
18
  token: string;
19
+ accessToken?: string | undefined;
16
20
  user: Omit<import("..").SanitizedAdminUser, "permissions">;
17
- }, "adminApi">>, useRenewTokenMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<{
18
- token: string;
19
- }, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", {
21
+ }, "adminApi">>, useAccessTokenExchangeMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<{} | undefined, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", {
20
22
  token: string;
21
- }, "adminApi">>, useLogoutMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", void, "adminApi">>, useUpdateMeMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<UpdateMe.BaseRequestBody, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", import("..").SanitizedAdminUser, "adminApi">>, useResetPasswordMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<{
23
+ }, "adminApi">>, useLogoutMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<void | {
24
+ deviceId?: string | undefined;
25
+ }, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", void, "adminApi">>, useUpdateMeMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<UpdateMe.BaseRequestBody, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", import("..").SanitizedAdminUser, "adminApi">>, useResetPasswordMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<{
22
26
  resetPasswordToken: string;
23
27
  password: string;
24
28
  }, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", {
25
29
  token: string;
26
30
  user: Omit<import("..").SanitizedAdminUser, "permissions">;
27
- }, "adminApi">>, useRegisterAdminMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<Pick<import("..").AdminUser, "firstname" | "lastname" | "email" | "password">, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", {
28
- token: string; /**
29
- * Auth methods
30
- */
31
+ }, "adminApi">>, useRegisterAdminMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<Pick<import("..").AdminUser, "firstname" | "lastname" | "email" | "password"> & {
32
+ deviceId?: string | undefined;
33
+ rememberMe?: boolean | undefined;
34
+ }, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", {
35
+ token: string;
36
+ accessToken?: string | undefined;
31
37
  user: Omit<import("..").SanitizedAdminUser, "permissions">;
32
38
  }, "adminApi">>, useRegisterUserMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<{
33
39
  registrationToken: string;
34
40
  userInfo: Pick<import("..").AdminUser, "firstname" | "lastname" | "email" | "password">;
41
+ deviceId?: string | undefined;
42
+ rememberMe?: boolean | undefined;
35
43
  }, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", {
36
44
  token: string;
45
+ accessToken?: string | undefined;
37
46
  user: Omit<import("..").SanitizedAdminUser, "permissions">;
38
47
  }, "adminApi">>, useGetRegistrationInfoQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<string, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", {
39
48
  email?: string | undefined;
@@ -44,4 +53,4 @@ declare const useCheckPermissionsQuery: import("@reduxjs/toolkit/dist/query/reac
44
53
  }, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", ForgotPassword.Response, "adminApi">>, useGetMyPermissionsQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", import("../../../shared/contracts/shared").Permission[], "adminApi">>, useIsSSOLockedQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", {
45
54
  isSSOLocked: boolean;
46
55
  }, "adminApi">>, useGetProvidersQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", GetProviders.Response, "adminApi">>, useGetProviderOptionsQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", ProvidersOptions.SSOProviderOptions, "adminApi">>, useUpdateProviderOptionsMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<ProvidersOptions.SSOProviderOptions, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "User" | "Me" | "ProvidersOptions", ProvidersOptions.SSOProviderOptions, "adminApi">>;
47
- export { useCheckPermissionsQuery, useLazyCheckPermissionsQuery, useGetMeQuery, useLoginMutation, useRenewTokenMutation, useLogoutMutation, useUpdateMeMutation, useResetPasswordMutation, useRegisterAdminMutation, useRegisterUserMutation, useGetRegistrationInfoQuery, useForgotPasswordMutation, useGetMyPermissionsQuery, useIsSSOLockedQuery, useGetProvidersQuery, useGetProviderOptionsQuery, useUpdateProviderOptionsMutation, };
56
+ export { useCheckPermissionsQuery, useLazyCheckPermissionsQuery, useGetMeQuery, useLoginMutation, useAccessTokenExchangeMutation, useLogoutMutation, useUpdateMeMutation, useResetPasswordMutation, useRegisterAdminMutation, useRegisterUserMutation, useGetRegistrationInfoQuery, useForgotPasswordMutation, useGetMyPermissionsQuery, useIsSSOLockedQuery, useGetProvidersQuery, useGetProviderOptionsQuery, useUpdateProviderOptionsMutation, };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Returns a stable device identifier for session-based authentication flows.
3
+ * Uses localStorage to persist a UUID between sessions on the same browser.
4
+ */
5
+ export declare const getOrCreateDeviceId: () => string;
@@ -1 +1 @@
1
- {"version":3,"file":"middlewares.d.ts","sourceRoot":"","sources":["../../../../../../ee/server/src/controllers/authentication-utils/middlewares.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAO1C,eAAO,MAAM,YAAY,EAAE,IAAI,CAAC,iBA0B/B,CAAC;AA4DF,eAAO,MAAM,gBAAgB,EAAE,IAAI,CAAC,iBAmBnC,CAAC;;;;;AAEF,wBAGE"}
1
+ {"version":3,"file":"middlewares.d.ts","sourceRoot":"","sources":["../../../../../../ee/server/src/controllers/authentication-utils/middlewares.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAa1C,eAAO,MAAM,YAAY,EAAE,IAAI,CAAC,iBA0B/B,CAAC;AA4DF,eAAO,MAAM,gBAAgB,EAAE,IAAI,CAAC,iBAuDnC,CAAC;;;;;AAEF,wBAGE"}
@@ -1 +1 @@
1
- {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../../../../ee/server/src/services/user.ts"],"names":[],"mappings":";;;;;;;;AAkOA,wBAOE"}
1
+ {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../../../../ee/server/src/services/user.ts"],"names":[],"mappings":";;;;;;;;AAmPA,wBAOE"}
@@ -5,6 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var passport = require('koa-passport');
6
6
  var index = require('../../utils/index.js');
7
7
  var utils = require('./utils.js');
8
+ var sessionAuth = require('../../../../../shared/utils/session-auth.js');
8
9
 
9
10
  const defaultConnectionError = ()=>new Error('Invalid connection payload');
10
11
  const authenticate = async (ctx, next)=>{
@@ -84,26 +85,51 @@ const nonExistingUserScenario = (ctx, next)=>async (profile, provider)=>{
84
85
  });
85
86
  return next();
86
87
  };
87
- const redirectWithAuth = (ctx)=>{
88
+ const redirectWithAuth = async (ctx)=>{
88
89
  const { params: { provider } } = ctx;
89
90
  const redirectUrls = utils.default.getPrefixedRedirectUrls();
90
- const domain = strapi.config.get('admin.auth.domain');
91
91
  const { user } = ctx.state;
92
- const jwt = index.getService('token').createJwtToken(user);
93
- const isProduction = strapi.config.get('environment') === 'production';
94
- const cookiesOptions = {
95
- httpOnly: false,
96
- secure: isProduction,
97
- overwrite: true,
98
- domain
99
- };
100
- const sanitizedUser = index.getService('user').sanitizeUser(user);
101
- strapi.eventHub.emit('admin.auth.success', {
102
- user: sanitizedUser,
103
- provider
104
- });
105
- ctx.cookies.set('jwtToken', jwt, cookiesOptions);
106
- ctx.redirect(redirectUrls.success);
92
+ try {
93
+ const sessionManager = sessionAuth.getSessionManager();
94
+ if (!sessionManager) {
95
+ strapi.log.error('SessionManager not available for SSO authentication');
96
+ return ctx.redirect(redirectUrls.error);
97
+ }
98
+ const userId = String(user.id);
99
+ const deviceId = sessionAuth.generateDeviceId();
100
+ const { token: refreshToken, absoluteExpiresAt } = await sessionManager('admin').generateRefreshToken(userId, deviceId, {
101
+ type: 'refresh'
102
+ });
103
+ const cookieOptions = sessionAuth.buildCookieOptionsWithExpiry('refresh', absoluteExpiresAt);
104
+ ctx.cookies.set(sessionAuth.REFRESH_COOKIE_NAME, refreshToken, cookieOptions);
105
+ const accessResult = await sessionManager('admin').generateAccessToken(refreshToken);
106
+ if ('error' in accessResult) {
107
+ strapi.log.error('Failed to generate access token for SSO user');
108
+ return ctx.redirect(redirectUrls.error);
109
+ }
110
+ const { token: accessToken } = accessResult;
111
+ const isProduction = strapi.config.get('environment') === 'production';
112
+ const domain = strapi.config.get('admin.auth.domain');
113
+ ctx.cookies.set('jwtToken', accessToken, {
114
+ httpOnly: false,
115
+ secure: isProduction,
116
+ overwrite: true,
117
+ domain
118
+ });
119
+ const sanitizedUser = index.getService('user').sanitizeUser(user);
120
+ strapi.eventHub.emit('admin.auth.success', {
121
+ user: sanitizedUser,
122
+ provider
123
+ });
124
+ ctx.redirect(redirectUrls.success);
125
+ } catch (error) {
126
+ strapi.log.error('SSO authentication failed during token generation', error);
127
+ strapi.eventHub.emit('admin.auth.error', {
128
+ error: error instanceof Error ? error : new Error('Unknown SSO error'),
129
+ provider
130
+ });
131
+ return ctx.redirect(redirectUrls.error);
132
+ }
107
133
  };
108
134
  var middlewares = {
109
135
  authenticate,
@@ -1 +1 @@
1
- {"version":3,"file":"middlewares.js","sources":["../../../../../../../ee/server/src/controllers/authentication-utils/middlewares.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\nimport passport from 'koa-passport';\nimport { getService } from '../../utils';\nimport utils from './utils';\n\nconst defaultConnectionError = () => new Error('Invalid connection payload');\n\nexport const authenticate: Core.MiddlewareHandler = async (ctx, next) => {\n const {\n params: { provider },\n } = ctx;\n const redirectUrls = utils.getPrefixedRedirectUrls();\n\n // @ts-expect-error - can not use null to authenticate\n return passport.authenticate(provider, null, async (error, profile) => {\n if (error || !profile || !profile.email) {\n if (error) {\n strapi.log.error(error);\n }\n\n strapi.eventHub.emit('admin.auth.error', {\n error: error || defaultConnectionError(),\n provider,\n });\n\n return ctx.redirect(redirectUrls.error);\n }\n\n const user = await getService('user').findOneByEmail(profile.email);\n const scenario = user ? existingUserScenario : nonExistingUserScenario;\n\n return scenario(ctx, next)(user || profile, provider);\n })(ctx, next);\n};\n\nconst existingUserScenario: Core.MiddlewareHandler =\n (ctx, next) => async (user: any, provider: any) => {\n const redirectUrls = utils.getPrefixedRedirectUrls();\n\n if (!user.isActive) {\n strapi.eventHub.emit('admin.auth.error', {\n error: new Error(`Deactivated user tried to login (${user.id})`),\n provider,\n });\n return ctx.redirect(redirectUrls.error);\n }\n\n ctx.state.user = user;\n return next();\n };\n\nconst nonExistingUserScenario: Core.MiddlewareHandler =\n (ctx, next) => async (profile: any, provider: any) => {\n const { email, firstname, lastname, username } = profile;\n const redirectUrls = utils.getPrefixedRedirectUrls();\n const adminStore = await utils.getAdminStore();\n const { providers } = (await adminStore.get({ key: 'auth' })) as any;\n\n // We need at least the username or the firstname/lastname combination to register a new user\n const isMissingRegisterFields = !username && (!firstname || !lastname);\n\n if (!providers.autoRegister || !providers.defaultRole || isMissingRegisterFields) {\n strapi.eventHub.emit('admin.auth.error', { error: defaultConnectionError(), provider });\n return ctx.redirect(redirectUrls.error);\n }\n\n const defaultRole = await getService('role').findOne({ id: providers.defaultRole });\n\n // If the default role has been misconfigured, redirect with an error\n if (!defaultRole) {\n strapi.eventHub.emit('admin.auth.error', { error: defaultConnectionError(), provider });\n return ctx.redirect(redirectUrls.error);\n }\n\n // Register a new user with the information given by the provider and login with it\n ctx.state.user = await getService('user').create({\n email,\n username,\n firstname,\n lastname,\n roles: [defaultRole.id],\n isActive: true,\n registrationToken: null,\n });\n\n strapi.eventHub.emit('admin.auth.autoRegistration', {\n user: ctx.state.user,\n provider,\n });\n\n return next();\n };\n\nexport const redirectWithAuth: Core.MiddlewareHandler = (ctx) => {\n const {\n params: { provider },\n } = ctx;\n const redirectUrls = utils.getPrefixedRedirectUrls();\n const domain: string | undefined = strapi.config.get('admin.auth.domain');\n const { user } = ctx.state;\n\n const jwt = getService('token').createJwtToken(user);\n\n const isProduction = strapi.config.get('environment') === 'production';\n\n const cookiesOptions = { httpOnly: false, secure: isProduction, overwrite: true, domain };\n\n const sanitizedUser = getService('user').sanitizeUser(user);\n strapi.eventHub.emit('admin.auth.success', { user: sanitizedUser, provider });\n\n ctx.cookies.set('jwtToken', jwt, cookiesOptions);\n ctx.redirect(redirectUrls.success);\n};\n\nexport default {\n authenticate,\n redirectWithAuth,\n};\n"],"names":["defaultConnectionError","Error","authenticate","ctx","next","params","provider","redirectUrls","utils","getPrefixedRedirectUrls","passport","error","profile","email","strapi","log","eventHub","emit","redirect","user","getService","findOneByEmail","scenario","existingUserScenario","nonExistingUserScenario","isActive","id","state","firstname","lastname","username","adminStore","getAdminStore","providers","get","key","isMissingRegisterFields","autoRegister","defaultRole","findOne","create","roles","registrationToken","redirectWithAuth","domain","config","jwt","createJwtToken","isProduction","cookiesOptions","httpOnly","secure","overwrite","sanitizedUser","sanitizeUser","cookies","set","success"],"mappings":"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"}
1
+ {"version":3,"file":"middlewares.js","sources":["../../../../../../../ee/server/src/controllers/authentication-utils/middlewares.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\nimport passport from 'koa-passport';\nimport { getService } from '../../utils';\nimport utils from './utils';\nimport {\n REFRESH_COOKIE_NAME,\n buildCookieOptionsWithExpiry,\n getSessionManager,\n generateDeviceId,\n} from '../../../../../shared/utils/session-auth';\n\nconst defaultConnectionError = () => new Error('Invalid connection payload');\n\nexport const authenticate: Core.MiddlewareHandler = async (ctx, next) => {\n const {\n params: { provider },\n } = ctx;\n const redirectUrls = utils.getPrefixedRedirectUrls();\n\n // @ts-expect-error - can not use null to authenticate\n return passport.authenticate(provider, null, async (error, profile) => {\n if (error || !profile || !profile.email) {\n if (error) {\n strapi.log.error(error);\n }\n\n strapi.eventHub.emit('admin.auth.error', {\n error: error || defaultConnectionError(),\n provider,\n });\n\n return ctx.redirect(redirectUrls.error);\n }\n\n const user = await getService('user').findOneByEmail(profile.email);\n const scenario = user ? existingUserScenario : nonExistingUserScenario;\n\n return scenario(ctx, next)(user || profile, provider);\n })(ctx, next);\n};\n\nconst existingUserScenario: Core.MiddlewareHandler =\n (ctx, next) => async (user: any, provider: any) => {\n const redirectUrls = utils.getPrefixedRedirectUrls();\n\n if (!user.isActive) {\n strapi.eventHub.emit('admin.auth.error', {\n error: new Error(`Deactivated user tried to login (${user.id})`),\n provider,\n });\n return ctx.redirect(redirectUrls.error);\n }\n\n ctx.state.user = user;\n return next();\n };\n\nconst nonExistingUserScenario: Core.MiddlewareHandler =\n (ctx, next) => async (profile: any, provider: any) => {\n const { email, firstname, lastname, username } = profile;\n const redirectUrls = utils.getPrefixedRedirectUrls();\n const adminStore = await utils.getAdminStore();\n const { providers } = (await adminStore.get({ key: 'auth' })) as any;\n\n // We need at least the username or the firstname/lastname combination to register a new user\n const isMissingRegisterFields = !username && (!firstname || !lastname);\n\n if (!providers.autoRegister || !providers.defaultRole || isMissingRegisterFields) {\n strapi.eventHub.emit('admin.auth.error', { error: defaultConnectionError(), provider });\n return ctx.redirect(redirectUrls.error);\n }\n\n const defaultRole = await getService('role').findOne({ id: providers.defaultRole });\n\n // If the default role has been misconfigured, redirect with an error\n if (!defaultRole) {\n strapi.eventHub.emit('admin.auth.error', { error: defaultConnectionError(), provider });\n return ctx.redirect(redirectUrls.error);\n }\n\n // Register a new user with the information given by the provider and login with it\n ctx.state.user = await getService('user').create({\n email,\n username,\n firstname,\n lastname,\n roles: [defaultRole.id],\n isActive: true,\n registrationToken: null,\n });\n\n strapi.eventHub.emit('admin.auth.autoRegistration', {\n user: ctx.state.user,\n provider,\n });\n\n return next();\n };\n\nexport const redirectWithAuth: Core.MiddlewareHandler = async (ctx) => {\n const {\n params: { provider },\n } = ctx;\n const redirectUrls = utils.getPrefixedRedirectUrls();\n const { user } = ctx.state;\n\n try {\n const sessionManager = getSessionManager();\n if (!sessionManager) {\n strapi.log.error('SessionManager not available for SSO authentication');\n return ctx.redirect(redirectUrls.error);\n }\n\n const userId = String(user.id);\n const deviceId = generateDeviceId();\n\n const { token: refreshToken, absoluteExpiresAt } = await sessionManager(\n 'admin'\n ).generateRefreshToken(userId, deviceId, {\n type: 'refresh',\n });\n\n const cookieOptions = buildCookieOptionsWithExpiry('refresh', 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 strapi.log.error('Failed to generate access token for SSO user');\n return ctx.redirect(redirectUrls.error);\n }\n\n const { token: accessToken } = accessResult;\n\n const isProduction = strapi.config.get('environment') === 'production';\n const domain: string | undefined = strapi.config.get('admin.auth.domain');\n ctx.cookies.set('jwtToken', accessToken, {\n httpOnly: false,\n secure: isProduction,\n overwrite: true,\n domain,\n });\n\n const sanitizedUser = getService('user').sanitizeUser(user);\n strapi.eventHub.emit('admin.auth.success', { user: sanitizedUser, provider });\n\n ctx.redirect(redirectUrls.success);\n } catch (error) {\n strapi.log.error('SSO authentication failed during token generation', error);\n strapi.eventHub.emit('admin.auth.error', {\n error: error instanceof Error ? error : new Error('Unknown SSO error'),\n provider,\n });\n return ctx.redirect(redirectUrls.error);\n }\n};\n\nexport default {\n authenticate,\n redirectWithAuth,\n};\n"],"names":["defaultConnectionError","Error","authenticate","ctx","next","params","provider","redirectUrls","utils","getPrefixedRedirectUrls","passport","error","profile","email","strapi","log","eventHub","emit","redirect","user","getService","findOneByEmail","scenario","existingUserScenario","nonExistingUserScenario","isActive","id","state","firstname","lastname","username","adminStore","getAdminStore","providers","get","key","isMissingRegisterFields","autoRegister","defaultRole","findOne","create","roles","registrationToken","redirectWithAuth","sessionManager","getSessionManager","userId","String","deviceId","generateDeviceId","token","refreshToken","absoluteExpiresAt","generateRefreshToken","type","cookieOptions","buildCookieOptionsWithExpiry","cookies","set","REFRESH_COOKIE_NAME","accessResult","generateAccessToken","accessToken","isProduction","config","domain","httpOnly","secure","overwrite","sanitizedUser","sanitizeUser","success"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import passport from 'koa-passport';
2
2
  import { getService } from '../../utils/index.mjs';
3
3
  import utils from './utils.mjs';
4
+ import { getSessionManager, generateDeviceId, buildCookieOptionsWithExpiry, REFRESH_COOKIE_NAME } from '../../../../../shared/utils/session-auth.mjs';
4
5
 
5
6
  const defaultConnectionError = ()=>new Error('Invalid connection payload');
6
7
  const authenticate = async (ctx, next)=>{
@@ -80,26 +81,51 @@ const nonExistingUserScenario = (ctx, next)=>async (profile, provider)=>{
80
81
  });
81
82
  return next();
82
83
  };
83
- const redirectWithAuth = (ctx)=>{
84
+ const redirectWithAuth = async (ctx)=>{
84
85
  const { params: { provider } } = ctx;
85
86
  const redirectUrls = utils.getPrefixedRedirectUrls();
86
- const domain = strapi.config.get('admin.auth.domain');
87
87
  const { user } = ctx.state;
88
- const jwt = getService('token').createJwtToken(user);
89
- const isProduction = strapi.config.get('environment') === 'production';
90
- const cookiesOptions = {
91
- httpOnly: false,
92
- secure: isProduction,
93
- overwrite: true,
94
- domain
95
- };
96
- const sanitizedUser = getService('user').sanitizeUser(user);
97
- strapi.eventHub.emit('admin.auth.success', {
98
- user: sanitizedUser,
99
- provider
100
- });
101
- ctx.cookies.set('jwtToken', jwt, cookiesOptions);
102
- ctx.redirect(redirectUrls.success);
88
+ try {
89
+ const sessionManager = getSessionManager();
90
+ if (!sessionManager) {
91
+ strapi.log.error('SessionManager not available for SSO authentication');
92
+ return ctx.redirect(redirectUrls.error);
93
+ }
94
+ const userId = String(user.id);
95
+ const deviceId = generateDeviceId();
96
+ const { token: refreshToken, absoluteExpiresAt } = await sessionManager('admin').generateRefreshToken(userId, deviceId, {
97
+ type: 'refresh'
98
+ });
99
+ const cookieOptions = buildCookieOptionsWithExpiry('refresh', absoluteExpiresAt);
100
+ ctx.cookies.set(REFRESH_COOKIE_NAME, refreshToken, cookieOptions);
101
+ const accessResult = await sessionManager('admin').generateAccessToken(refreshToken);
102
+ if ('error' in accessResult) {
103
+ strapi.log.error('Failed to generate access token for SSO user');
104
+ return ctx.redirect(redirectUrls.error);
105
+ }
106
+ const { token: accessToken } = accessResult;
107
+ const isProduction = strapi.config.get('environment') === 'production';
108
+ const domain = strapi.config.get('admin.auth.domain');
109
+ ctx.cookies.set('jwtToken', accessToken, {
110
+ httpOnly: false,
111
+ secure: isProduction,
112
+ overwrite: true,
113
+ domain
114
+ });
115
+ const sanitizedUser = getService('user').sanitizeUser(user);
116
+ strapi.eventHub.emit('admin.auth.success', {
117
+ user: sanitizedUser,
118
+ provider
119
+ });
120
+ ctx.redirect(redirectUrls.success);
121
+ } catch (error) {
122
+ strapi.log.error('SSO authentication failed during token generation', error);
123
+ strapi.eventHub.emit('admin.auth.error', {
124
+ error: error instanceof Error ? error : new Error('Unknown SSO error'),
125
+ provider
126
+ });
127
+ return ctx.redirect(redirectUrls.error);
128
+ }
103
129
  };
104
130
  var middlewares = {
105
131
  authenticate,