@thunderid/nextjs 1.0.3 → 1.0.5

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 (96) hide show
  1. package/dist/ThunderIDNextClient.d.ts +2 -1
  2. package/dist/ThunderIDNextClient.d.ts.map +1 -1
  3. package/dist/ThunderIDNextClient.js +16 -1
  4. package/dist/ThunderIDNextClient.js.map +1 -1
  5. package/dist/cjs/ThunderIDNextClient.cjs +15 -0
  6. package/dist/cjs/ThunderIDNextClient.cjs.map +1 -1
  7. package/dist/cjs/client/components/presentation/UserProfile/UserProfile.cjs +2 -1
  8. package/dist/cjs/client/components/presentation/UserProfile/UserProfile.cjs.map +1 -1
  9. package/dist/cjs/client/contexts/ThunderID/ThunderIDProvider.cjs +9 -2
  10. package/dist/cjs/client/contexts/ThunderID/ThunderIDProvider.cjs.map +1 -1
  11. package/dist/cjs/index.cjs +2 -0
  12. package/dist/cjs/server/ThunderIDProvider.cjs +7 -0
  13. package/dist/cjs/server/ThunderIDProvider.cjs.map +1 -1
  14. package/dist/cjs/server/actions/clearSession.cjs +2 -1
  15. package/dist/cjs/server/actions/clearSession.cjs.map +1 -1
  16. package/dist/cjs/server/actions/getAccessToken.cjs +2 -1
  17. package/dist/cjs/server/actions/getAccessToken.cjs.map +1 -1
  18. package/dist/cjs/server/actions/getFlowMetaAction.cjs +44 -0
  19. package/dist/cjs/server/actions/getFlowMetaAction.cjs.map +1 -0
  20. package/dist/cjs/server/actions/getSessionId.cjs +2 -1
  21. package/dist/cjs/server/actions/getSessionId.cjs.map +1 -1
  22. package/dist/cjs/server/actions/getSessionPayload.cjs +2 -1
  23. package/dist/cjs/server/actions/getSessionPayload.cjs.map +1 -1
  24. package/dist/cjs/server/actions/getUserSchemaAction.cjs +31 -0
  25. package/dist/cjs/server/actions/getUserSchemaAction.cjs.map +1 -0
  26. package/dist/cjs/server/actions/handleOAuthCallbackAction.cjs +2 -1
  27. package/dist/cjs/server/actions/handleOAuthCallbackAction.cjs.map +1 -1
  28. package/dist/cjs/server/actions/refreshToken.cjs +4 -3
  29. package/dist/cjs/server/actions/refreshToken.cjs.map +1 -1
  30. package/dist/cjs/server/actions/signInAction.cjs +3 -2
  31. package/dist/cjs/server/actions/signInAction.cjs.map +1 -1
  32. package/dist/cjs/server/actions/signOutAction.cjs +2 -1
  33. package/dist/cjs/server/actions/signOutAction.cjs.map +1 -1
  34. package/dist/cjs/server/index.cjs +2 -0
  35. package/dist/cjs/server/proxy/thunderIDProxy.cjs +54 -28
  36. package/dist/cjs/server/proxy/thunderIDProxy.cjs.map +1 -1
  37. package/dist/cjs/utils/chunkedCookie.cjs +50 -0
  38. package/dist/cjs/utils/chunkedCookie.cjs.map +1 -0
  39. package/dist/cjs/utils/sessionUtils.cjs +2 -1
  40. package/dist/cjs/utils/sessionUtils.cjs.map +1 -1
  41. package/dist/client/components/presentation/UserProfile/UserProfile.d.ts.map +1 -1
  42. package/dist/client/components/presentation/UserProfile/UserProfile.js +2 -1
  43. package/dist/client/components/presentation/UserProfile/UserProfile.js.map +1 -1
  44. package/dist/client/contexts/ThunderID/ThunderIDProvider.d.ts +13 -1
  45. package/dist/client/contexts/ThunderID/ThunderIDProvider.d.ts.map +1 -1
  46. package/dist/client/contexts/ThunderID/ThunderIDProvider.js +9 -2
  47. package/dist/client/contexts/ThunderID/ThunderIDProvider.js.map +1 -1
  48. package/dist/index.js +2 -2
  49. package/dist/server/ThunderIDProvider.d.ts.map +1 -1
  50. package/dist/server/ThunderIDProvider.js +7 -0
  51. package/dist/server/ThunderIDProvider.js.map +1 -1
  52. package/dist/server/actions/clearSession.d.ts.map +1 -1
  53. package/dist/server/actions/clearSession.js +2 -1
  54. package/dist/server/actions/clearSession.js.map +1 -1
  55. package/dist/server/actions/getAccessToken.d.ts.map +1 -1
  56. package/dist/server/actions/getAccessToken.js +2 -1
  57. package/dist/server/actions/getAccessToken.js.map +1 -1
  58. package/dist/server/actions/getFlowMetaAction.d.ts +17 -0
  59. package/dist/server/actions/getFlowMetaAction.d.ts.map +1 -0
  60. package/dist/server/actions/getFlowMetaAction.js +42 -0
  61. package/dist/server/actions/getFlowMetaAction.js.map +1 -0
  62. package/dist/server/actions/getSessionId.d.ts.map +1 -1
  63. package/dist/server/actions/getSessionId.js +2 -1
  64. package/dist/server/actions/getSessionId.js.map +1 -1
  65. package/dist/server/actions/getSessionPayload.d.ts.map +1 -1
  66. package/dist/server/actions/getSessionPayload.js +2 -1
  67. package/dist/server/actions/getSessionPayload.js.map +1 -1
  68. package/dist/server/actions/getUserSchemaAction.d.ts +15 -0
  69. package/dist/server/actions/getUserSchemaAction.d.ts.map +1 -0
  70. package/dist/server/actions/getUserSchemaAction.js +31 -0
  71. package/dist/server/actions/getUserSchemaAction.js.map +1 -0
  72. package/dist/server/actions/handleOAuthCallbackAction.d.ts.map +1 -1
  73. package/dist/server/actions/handleOAuthCallbackAction.js +2 -1
  74. package/dist/server/actions/handleOAuthCallbackAction.js.map +1 -1
  75. package/dist/server/actions/refreshToken.d.ts.map +1 -1
  76. package/dist/server/actions/refreshToken.js +4 -3
  77. package/dist/server/actions/refreshToken.js.map +1 -1
  78. package/dist/server/actions/signInAction.d.ts.map +1 -1
  79. package/dist/server/actions/signInAction.js +3 -2
  80. package/dist/server/actions/signInAction.js.map +1 -1
  81. package/dist/server/actions/signOutAction.d.ts.map +1 -1
  82. package/dist/server/actions/signOutAction.js +2 -1
  83. package/dist/server/actions/signOutAction.js.map +1 -1
  84. package/dist/server/index.js +2 -2
  85. package/dist/server/proxy/thunderIDProxy.d.ts +13 -0
  86. package/dist/server/proxy/thunderIDProxy.d.ts.map +1 -1
  87. package/dist/server/proxy/thunderIDProxy.js +52 -29
  88. package/dist/server/proxy/thunderIDProxy.js.map +1 -1
  89. package/dist/utils/chunkedCookie.d.ts +46 -0
  90. package/dist/utils/chunkedCookie.d.ts.map +1 -0
  91. package/dist/utils/chunkedCookie.js +46 -0
  92. package/dist/utils/chunkedCookie.js.map +1 -0
  93. package/dist/utils/sessionUtils.d.ts.map +1 -1
  94. package/dist/utils/sessionUtils.js +2 -1
  95. package/dist/utils/sessionUtils.js.map +1 -1
  96. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"clearSession.js","names":["cookieStore: RequestCookies","SessionManager"],"sources":["../../../src/server/actions/clearSession.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {cookies} from 'next/headers';\nimport logger from '../../utils/logger';\nimport SessionManager from '../../utils/SessionManager';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Deletes all ThunderID session cookies from the browser without contacting the\n * identity server.\n *\n * Use this for error-recovery scenarios where the local session must be wiped\n * immediately: refresh token failures, corrupt sessions, or forced local sign-out\n * when the identity server is unreachable.\n *\n * For a complete sign-out that also revokes the server-side session and obtains the\n * after-sign-out redirect URL, use `signOutAction` instead.\n *\n * @example\n * ```typescript\n * import { clearSession } from '@thunderid/nextjs/server';\n *\n * // Inside a Server Action or Route Handler:\n * await clearSession();\n * redirect('/sign-in');\n * ```\n */\nconst clearSession = async (): Promise<void> => {\n const cookieStore: RequestCookies = await cookies();\n cookieStore.delete(SessionManager.getSessionCookieName());\n cookieStore.delete(SessionManager.getTempSessionCookieName());\n logger.debug('[clearSession] Session cookies cleared.');\n};\n\nexport default clearSession;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,MAAM,eAAe,YAA2B;CAC9C,MAAMA,cAA8B,MAAM,SAAS;AACnD,aAAY,OAAOC,uBAAe,sBAAsB,CAAC;AACzD,aAAY,OAAOA,uBAAe,0BAA0B,CAAC;AAC7D,gBAAO,MAAM,0CAA0C;;AAGzD,2BAAe"}
1
+ {"version":3,"file":"clearSession.js","names":["cookieStore: RequestCookies","SessionManager"],"sources":["../../../src/server/actions/clearSession.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {cookies} from 'next/headers';\nimport {deleteChunkedCookie} from '../../utils/chunkedCookie';\nimport logger from '../../utils/logger';\nimport SessionManager from '../../utils/SessionManager';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Deletes all ThunderID session cookies from the browser without contacting the\n * identity server.\n *\n * Use this for error-recovery scenarios where the local session must be wiped\n * immediately: refresh token failures, corrupt sessions, or forced local sign-out\n * when the identity server is unreachable.\n *\n * For a complete sign-out that also revokes the server-side session and obtains the\n * after-sign-out redirect URL, use `signOutAction` instead.\n *\n * @example\n * ```typescript\n * import { clearSession } from '@thunderid/nextjs/server';\n *\n * // Inside a Server Action or Route Handler:\n * await clearSession();\n * redirect('/sign-in');\n * ```\n */\nconst clearSession = async (): Promise<void> => {\n const cookieStore: RequestCookies = await cookies();\n deleteChunkedCookie(cookieStore, SessionManager.getSessionCookieName());\n cookieStore.delete(SessionManager.getTempSessionCookieName());\n logger.debug('[clearSession] Session cookies cleared.');\n};\n\nexport default clearSession;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,MAAM,eAAe,YAA2B;CAC9C,MAAMA,cAA8B,MAAM,SAAS;AACnD,qBAAoB,aAAaC,uBAAe,sBAAsB,CAAC;AACvE,aAAY,OAAOA,uBAAe,0BAA0B,CAAC;AAC7D,gBAAO,MAAM,0CAA0C;;AAGzD,2BAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"getAccessToken.d.ts","sourceRoot":"","sources":["../../../src/server/actions/getAccessToken.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,QAAA,MAAM,cAAc,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAgB1D,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"getAccessToken.d.ts","sourceRoot":"","sources":["../../../src/server/actions/getAccessToken.ts"],"names":[],"mappings":"AAWA;;;;GAIG;AACH,QAAA,MAAM,cAAc,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAgB1D,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -1,6 +1,7 @@
1
1
  'use server';
2
2
 
3
3
 
4
+ import { getChunkedCookie } from "../../utils/chunkedCookie.js";
4
5
  import SessionManager_default from "../../utils/SessionManager.js";
5
6
  import { cookies } from "next/headers";
6
7
 
@@ -11,7 +12,7 @@ import { cookies } from "next/headers";
11
12
  * @returns The access token if it exists, undefined otherwise
12
13
  */
13
14
  const getAccessToken = async () => {
14
- const sessionToken = (await cookies()).get(SessionManager_default.getSessionCookieName())?.value;
15
+ const sessionToken = getChunkedCookie(await cookies(), SessionManager_default.getSessionCookieName());
15
16
  if (sessionToken) try {
16
17
  return (await SessionManager_default.verifySessionToken(sessionToken))["accessToken"];
17
18
  } catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"getAccessToken.js","names":["sessionToken: string | undefined","SessionManager"],"sources":["../../../src/server/actions/getAccessToken.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {cookies} from 'next/headers';\nimport SessionManager, {SessionTokenPayload} from '../../utils/SessionManager';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Get the access token from the session cookie.\n *\n * @returns The access token if it exists, undefined otherwise\n */\nconst getAccessToken = async (): Promise<string | undefined> => {\n const cookieStore: RequestCookies = await cookies();\n\n const sessionToken: string | undefined = cookieStore.get(SessionManager.getSessionCookieName())?.value;\n\n if (sessionToken) {\n try {\n const sessionPayload: SessionTokenPayload = await SessionManager.verifySessionToken(sessionToken);\n\n return sessionPayload['accessToken'] as string;\n } catch (error) {\n return undefined;\n }\n }\n\n return undefined;\n};\n\nexport default getAccessToken;\n"],"mappings":";;;;;;;;;;;;AAeA,MAAM,iBAAiB,YAAyC;CAG9D,MAAMA,gBAF8B,MAAM,SAAS,EAEE,IAAIC,uBAAe,sBAAsB,CAAC,EAAE;AAEjG,KAAI,aACF,KAAI;AAGF,UAF4C,MAAMA,uBAAe,mBAAmB,aAAa,EAE3E;UACf,OAAO;AACd;;;AAON,6BAAe"}
1
+ {"version":3,"file":"getAccessToken.js","names":["sessionToken: string | undefined","SessionManager"],"sources":["../../../src/server/actions/getAccessToken.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {cookies} from 'next/headers';\nimport {getChunkedCookie} from '../../utils/chunkedCookie';\nimport SessionManager, {SessionTokenPayload} from '../../utils/SessionManager';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Get the access token from the session cookie.\n *\n * @returns The access token if it exists, undefined otherwise\n */\nconst getAccessToken = async (): Promise<string | undefined> => {\n const cookieStore: RequestCookies = await cookies();\n\n const sessionToken: string | undefined = getChunkedCookie(cookieStore, SessionManager.getSessionCookieName());\n\n if (sessionToken) {\n try {\n const sessionPayload: SessionTokenPayload = await SessionManager.verifySessionToken(sessionToken);\n\n return sessionPayload['accessToken'] as string;\n } catch (error) {\n return undefined;\n }\n }\n\n return undefined;\n};\n\nexport default getAccessToken;\n"],"mappings":";;;;;;;;;;;;;AAgBA,MAAM,iBAAiB,YAAyC;CAG9D,MAAMA,eAAmC,iBAFL,MAAM,SAAS,EAEoBC,uBAAe,sBAAsB,CAAC;AAE7G,KAAI,aACF,KAAI;AAGF,UAF4C,MAAMA,uBAAe,mBAAmB,aAAa,EAE3E;UACf,OAAO;AACd;;;AAON,6BAAe"}
@@ -0,0 +1,17 @@
1
+ import { FlowMetadataResponse } from '@thunderid/node';
2
+ /**
3
+ * Server Action that fetches `GET /flow/meta` server-side.
4
+ *
5
+ * `FlowMetaProvider` (from `@thunderid/react`) otherwise fetches this endpoint directly from the
6
+ * browser against `baseUrl`, which requires the ThunderID server to allow CORS for the app's
7
+ * origin. Routing it through this action instead means the browser never talks to `baseUrl`
8
+ * directly — the request happens server-to-server, same as `signInAction`/`signUpAction`.
9
+ *
10
+ * @param language - Optional language override, used by `FlowMetaProvider.switchLanguage()`.
11
+ */
12
+ declare const getFlowMetaAction: (params?: {
13
+ applicationId?: string;
14
+ language?: string;
15
+ }) => Promise<FlowMetadataResponse>;
16
+ export default getFlowMetaAction;
17
+ //# sourceMappingURL=getFlowMetaAction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getFlowMetaAction.d.ts","sourceRoot":"","sources":["../../../src/server/actions/getFlowMetaAction.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,oBAAoB,EAAqD,MAAM,iBAAiB,CAAC;AAKzG;;;;;;;;;GASG;AACH,QAAA,MAAM,iBAAiB,GAAU,SAAS;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,KAAG,OAAO,CAAC,oBAAoB,CAkB/B,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,42 @@
1
+ 'use server';
2
+
3
+
4
+ import getClient_default from "../getClient.js";
5
+ import logger_default from "../../utils/logger.js";
6
+ import { FlowMetaType, getFlowMeta, resolveResourceEndpoint } from "@thunderid/node";
7
+
8
+ //#region src/server/actions/getFlowMetaAction.ts
9
+ /**
10
+ * Server Action that fetches `GET /flow/meta` server-side.
11
+ *
12
+ * `FlowMetaProvider` (from `@thunderid/react`) otherwise fetches this endpoint directly from the
13
+ * browser against `baseUrl`, which requires the ThunderID server to allow CORS for the app's
14
+ * origin. Routing it through this action instead means the browser never talks to `baseUrl`
15
+ * directly — the request happens server-to-server, same as `signInAction`/`signUpAction`.
16
+ *
17
+ * @param language - Optional language override, used by `FlowMetaProvider.switchLanguage()`.
18
+ */
19
+ const getFlowMetaAction = async (params) => {
20
+ const config = await getClient_default().getConfiguration();
21
+ const applicationId = params?.applicationId ?? config?.applicationId;
22
+ try {
23
+ return await getFlowMeta({
24
+ baseUrl: config?.baseUrl,
25
+ url: resolveResourceEndpoint("flowMeta", config),
26
+ ...applicationId ? {
27
+ id: applicationId,
28
+ type: FlowMetaType.App
29
+ } : {},
30
+ ...params?.language ? { language: params.language } : {}
31
+ });
32
+ } catch (error) {
33
+ const message = error instanceof Error ? error.message : String(error);
34
+ logger_default.error(`[getFlowMetaAction] Error fetching flow metadata: ${message}`);
35
+ throw error;
36
+ }
37
+ };
38
+ var getFlowMetaAction_default = getFlowMetaAction;
39
+
40
+ //#endregion
41
+ export { getFlowMetaAction_default as default };
42
+ //# sourceMappingURL=getFlowMetaAction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getFlowMetaAction.js","names":["config: ThunderIDNextConfig","getClient","applicationId: string | undefined"],"sources":["../../../src/server/actions/getFlowMetaAction.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {FlowMetadataResponse, FlowMetaType, getFlowMeta, resolveResourceEndpoint} from '@thunderid/node';\nimport {ThunderIDNextConfig} from '../../models/config';\nimport logger from '../../utils/logger';\nimport getClient from '../getClient';\n\n/**\n * Server Action that fetches `GET /flow/meta` server-side.\n *\n * `FlowMetaProvider` (from `@thunderid/react`) otherwise fetches this endpoint directly from the\n * browser against `baseUrl`, which requires the ThunderID server to allow CORS for the app's\n * origin. Routing it through this action instead means the browser never talks to `baseUrl`\n * directly — the request happens server-to-server, same as `signInAction`/`signUpAction`.\n *\n * @param language - Optional language override, used by `FlowMetaProvider.switchLanguage()`.\n */\nconst getFlowMetaAction = async (params?: {\n applicationId?: string;\n language?: string;\n}): Promise<FlowMetadataResponse> => {\n const client = getClient();\n const config: ThunderIDNextConfig = await client.getConfiguration();\n\n const applicationId: string | undefined = params?.applicationId ?? config?.applicationId;\n\n try {\n return await getFlowMeta({\n baseUrl: config?.baseUrl,\n url: resolveResourceEndpoint('flowMeta', config),\n ...(applicationId ? {id: applicationId, type: FlowMetaType.App} : {}),\n ...(params?.language ? {language: params.language} : {}),\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`[getFlowMetaAction] Error fetching flow metadata: ${message}`);\n throw error;\n }\n};\n\nexport default getFlowMetaAction;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoBA,MAAM,oBAAoB,OAAO,WAGI;CAEnC,MAAMA,SAA8B,MADrBC,mBAAW,CACuB,kBAAkB;CAEnE,MAAMC,gBAAoC,QAAQ,iBAAiB,QAAQ;AAE3E,KAAI;AACF,SAAO,MAAM,YAAY;GACvB,SAAS,QAAQ;GACjB,KAAK,wBAAwB,YAAY,OAAO;GAChD,GAAI,gBAAgB;IAAC,IAAI;IAAe,MAAM,aAAa;IAAI,GAAG,EAAE;GACpE,GAAI,QAAQ,WAAW,EAAC,UAAU,OAAO,UAAS,GAAG,EAAE;GACxD,CAAC;UACK,OAAO;EACd,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACtE,iBAAO,MAAM,qDAAqD,UAAU;AAC5E,QAAM;;;AAIV,gCAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"getSessionId.d.ts","sourceRoot":"","sources":["../../../src/server/actions/getSessionId.ts"],"names":[],"mappings":"AAUA;;;;;GAKG;AACH,QAAA,MAAM,YAAY,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAgBxD,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"getSessionId.d.ts","sourceRoot":"","sources":["../../../src/server/actions/getSessionId.ts"],"names":[],"mappings":"AAWA;;;;;GAKG;AACH,QAAA,MAAM,YAAY,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAgBxD,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -1,6 +1,7 @@
1
1
  'use server';
2
2
 
3
3
 
4
+ import { getChunkedCookie } from "../../utils/chunkedCookie.js";
4
5
  import SessionManager_default from "../../utils/SessionManager.js";
5
6
  import { cookies } from "next/headers";
6
7
 
@@ -12,7 +13,7 @@ import { cookies } from "next/headers";
12
13
  * @returns The session ID if it exists, undefined otherwise
13
14
  */
14
15
  const getSessionId = async () => {
15
- const sessionToken = (await cookies()).get(SessionManager_default.getSessionCookieName())?.value;
16
+ const sessionToken = getChunkedCookie(await cookies(), SessionManager_default.getSessionCookieName());
16
17
  if (sessionToken) try {
17
18
  return (await SessionManager_default.verifySessionToken(sessionToken)).sessionId;
18
19
  } catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"getSessionId.js","names":["sessionToken: string | undefined","SessionManager"],"sources":["../../../src/server/actions/getSessionId.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {cookies} from 'next/headers';\nimport SessionManager, {SessionTokenPayload} from '../../utils/SessionManager';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Get the session ID from cookies.\n * Tries JWT session first, then falls back to legacy session ID.\n *\n * @returns The session ID if it exists, undefined otherwise\n */\nconst getSessionId = async (): Promise<string | undefined> => {\n const cookieStore: RequestCookies = await cookies();\n\n const sessionToken: string | undefined = cookieStore.get(SessionManager.getSessionCookieName())?.value;\n\n if (sessionToken) {\n try {\n const sessionPayload: SessionTokenPayload = await SessionManager.verifySessionToken(sessionToken);\n\n return sessionPayload.sessionId;\n } catch (error) {\n return undefined;\n }\n }\n\n return undefined;\n};\n\nexport default getSessionId;\n"],"mappings":";;;;;;;;;;;;;AAgBA,MAAM,eAAe,YAAyC;CAG5D,MAAMA,gBAF8B,MAAM,SAAS,EAEE,IAAIC,uBAAe,sBAAsB,CAAC,EAAE;AAEjG,KAAI,aACF,KAAI;AAGF,UAF4C,MAAMA,uBAAe,mBAAmB,aAAa,EAE3E;UACf,OAAO;AACd;;;AAON,2BAAe"}
1
+ {"version":3,"file":"getSessionId.js","names":["sessionToken: string | undefined","SessionManager"],"sources":["../../../src/server/actions/getSessionId.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {cookies} from 'next/headers';\nimport {getChunkedCookie} from '../../utils/chunkedCookie';\nimport SessionManager, {SessionTokenPayload} from '../../utils/SessionManager';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Get the session ID from cookies.\n * Tries JWT session first, then falls back to legacy session ID.\n *\n * @returns The session ID if it exists, undefined otherwise\n */\nconst getSessionId = async (): Promise<string | undefined> => {\n const cookieStore: RequestCookies = await cookies();\n\n const sessionToken: string | undefined = getChunkedCookie(cookieStore, SessionManager.getSessionCookieName());\n\n if (sessionToken) {\n try {\n const sessionPayload: SessionTokenPayload = await SessionManager.verifySessionToken(sessionToken);\n\n return sessionPayload.sessionId;\n } catch (error) {\n return undefined;\n }\n }\n\n return undefined;\n};\n\nexport default getSessionId;\n"],"mappings":";;;;;;;;;;;;;;AAiBA,MAAM,eAAe,YAAyC;CAG5D,MAAMA,eAAmC,iBAFL,MAAM,SAAS,EAEoBC,uBAAe,sBAAsB,CAAC;AAE7G,KAAI,aACF,KAAI;AAGF,UAF4C,MAAMA,uBAAe,mBAAmB,aAAa,EAE3E;UACf,OAAO;AACd;;;AAON,2BAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"getSessionPayload.d.ts","sourceRoot":"","sources":["../../../src/server/actions/getSessionPayload.ts"],"names":[],"mappings":"AAMA,OAAuB,EAAC,mBAAmB,EAAC,MAAM,4BAA4B,CAAC;AAI/E;;;;;GAKG;AACH,QAAA,MAAM,iBAAiB,QAAa,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAa1E,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"getSessionPayload.d.ts","sourceRoot":"","sources":["../../../src/server/actions/getSessionPayload.ts"],"names":[],"mappings":"AAOA,OAAuB,EAAC,mBAAmB,EAAC,MAAM,4BAA4B,CAAC;AAI/E;;;;;GAKG;AACH,QAAA,MAAM,iBAAiB,QAAa,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAa1E,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  'use server';
2
2
 
3
3
 
4
+ import { getChunkedCookie } from "../../utils/chunkedCookie.js";
4
5
  import SessionManager_default from "../../utils/SessionManager.js";
5
6
  import { cookies } from "next/headers";
6
7
 
@@ -12,7 +13,7 @@ import { cookies } from "next/headers";
12
13
  * @returns The session payload if valid JWT session exists, undefined otherwise
13
14
  */
14
15
  const getSessionPayload = async () => {
15
- const sessionToken = (await cookies()).get(SessionManager_default.getSessionCookieName())?.value;
16
+ const sessionToken = getChunkedCookie(await cookies(), SessionManager_default.getSessionCookieName());
16
17
  if (!sessionToken) return;
17
18
  try {
18
19
  return await SessionManager_default.verifySessionToken(sessionToken);
@@ -1 +1 @@
1
- {"version":3,"file":"getSessionPayload.js","names":["sessionToken: string | undefined","SessionManager"],"sources":["../../../src/server/actions/getSessionPayload.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {cookies} from 'next/headers';\nimport SessionManager, {SessionTokenPayload} from '../../utils/SessionManager';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Get the session payload from JWT session cookie.\n * This includes user ID, session ID, scopes, and organization ID.\n *\n * @returns The session payload if valid JWT session exists, undefined otherwise\n */\nconst getSessionPayload = async (): Promise<SessionTokenPayload | undefined> => {\n const cookieStore: RequestCookies = await cookies();\n\n const sessionToken: string | undefined = cookieStore.get(SessionManager.getSessionCookieName())?.value;\n if (!sessionToken) {\n return undefined;\n }\n\n try {\n return await SessionManager.verifySessionToken(sessionToken);\n } catch {\n return undefined;\n }\n};\n\nexport default getSessionPayload;\n"],"mappings":";;;;;;;;;;;;;AAgBA,MAAM,oBAAoB,YAAsD;CAG9E,MAAMA,gBAF8B,MAAM,SAAS,EAEE,IAAIC,uBAAe,sBAAsB,CAAC,EAAE;AACjG,KAAI,CAAC,aACH;AAGF,KAAI;AACF,SAAO,MAAMA,uBAAe,mBAAmB,aAAa;SACtD;AACN;;;AAIJ,gCAAe"}
1
+ {"version":3,"file":"getSessionPayload.js","names":["sessionToken: string | undefined","SessionManager"],"sources":["../../../src/server/actions/getSessionPayload.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {cookies} from 'next/headers';\nimport {getChunkedCookie} from '../../utils/chunkedCookie';\nimport SessionManager, {SessionTokenPayload} from '../../utils/SessionManager';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Get the session payload from JWT session cookie.\n * This includes user ID, session ID, scopes, and organization ID.\n *\n * @returns The session payload if valid JWT session exists, undefined otherwise\n */\nconst getSessionPayload = async (): Promise<SessionTokenPayload | undefined> => {\n const cookieStore: RequestCookies = await cookies();\n\n const sessionToken: string | undefined = getChunkedCookie(cookieStore, SessionManager.getSessionCookieName());\n if (!sessionToken) {\n return undefined;\n }\n\n try {\n return await SessionManager.verifySessionToken(sessionToken);\n } catch {\n return undefined;\n }\n};\n\nexport default getSessionPayload;\n"],"mappings":";;;;;;;;;;;;;;AAiBA,MAAM,oBAAoB,YAAsD;CAG9E,MAAMA,eAAmC,iBAFL,MAAM,SAAS,EAEoBC,uBAAe,sBAAsB,CAAC;AAC7G,KAAI,CAAC,aACH;AAGF,KAAI;AACF,SAAO,MAAMA,uBAAe,mBAAmB,aAAa;SACtD;AACN;;;AAIJ,gCAAe"}
@@ -0,0 +1,15 @@
1
+ import { AttributeSchema } from '@thunderid/node';
2
+ /**
3
+ * Server action to get the user attribute schema from `/users/me/meta`.
4
+ * Used to render profile fields dynamically (labels, required/regex validation)
5
+ * instead of falling back to raw, unlabeled attribute keys.
6
+ */
7
+ declare const getUserSchemaAction: (sessionId: string) => Promise<{
8
+ data: {
9
+ userSchema: Record<string, AttributeSchema> | null;
10
+ };
11
+ error: string | null;
12
+ success: boolean;
13
+ }>;
14
+ export default getUserSchemaAction;
15
+ //# sourceMappingURL=getUserSchemaAction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getUserSchemaAction.d.ts","sourceRoot":"","sources":["../../../src/server/actions/getUserSchemaAction.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,eAAe,EAAC,MAAM,iBAAiB,CAAC;AAGhD;;;;GAIG;AACH,QAAA,MAAM,mBAAmB,GACvB,WAAW,MAAM,KAChB,OAAO,CAAC;IAAC,IAAI,EAAE;QAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,IAAI,CAAA;KAAC,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAC,CAY9G,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
@@ -0,0 +1,31 @@
1
+ 'use server';
2
+
3
+
4
+ import getClient_default from "../getClient.js";
5
+
6
+ //#region src/server/actions/getUserSchemaAction.ts
7
+ /**
8
+ * Server action to get the user attribute schema from `/users/me/meta`.
9
+ * Used to render profile fields dynamically (labels, required/regex validation)
10
+ * instead of falling back to raw, unlabeled attribute keys.
11
+ */
12
+ const getUserSchemaAction = async (sessionId) => {
13
+ try {
14
+ return {
15
+ data: { userSchema: await getClient_default().getUserSchema(sessionId) },
16
+ error: null,
17
+ success: true
18
+ };
19
+ } catch (error) {
20
+ return {
21
+ data: { userSchema: null },
22
+ error: "Failed to get user schema",
23
+ success: false
24
+ };
25
+ }
26
+ };
27
+ var getUserSchemaAction_default = getUserSchemaAction;
28
+
29
+ //#endregion
30
+ export { getUserSchemaAction_default as default };
31
+ //# sourceMappingURL=getUserSchemaAction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getUserSchemaAction.js","names":["getClient"],"sources":["../../../src/server/actions/getUserSchemaAction.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {AttributeSchema} from '@thunderid/node';\nimport getClient from '../getClient';\n\n/**\n * Server action to get the user attribute schema from `/users/me/meta`.\n * Used to render profile fields dynamically (labels, required/regex validation)\n * instead of falling back to raw, unlabeled attribute keys.\n */\nconst getUserSchemaAction = async (\n sessionId: string,\n): Promise<{data: {userSchema: Record<string, AttributeSchema> | null}; error: string | null; success: boolean}> => {\n try {\n const client = getClient();\n const userSchema: Record<string, AttributeSchema> | null = await client.getUserSchema(sessionId);\n return {data: {userSchema}, error: null, success: true};\n } catch (error) {\n return {\n data: {userSchema: null},\n error: 'Failed to get user schema',\n success: false,\n };\n }\n};\n\nexport default getUserSchemaAction;\n"],"mappings":";;;;;;;;;;;AAaA,MAAM,sBAAsB,OAC1B,cACkH;AAClH,KAAI;AAGF,SAAO;GAAC,MAAM,EAAC,YAD4C,MAD5CA,mBAAW,CAC8C,cAAc,UAAU,EACtE;GAAE,OAAO;GAAM,SAAS;GAAK;UAChD,OAAO;AACd,SAAO;GACL,MAAM,EAAC,YAAY,MAAK;GACxB,OAAO;GACP,SAAS;GACV;;;AAIL,kCAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"handleOAuthCallbackAction.d.ts","sourceRoot":"","sources":["../../../src/server/actions/handleOAuthCallbackAction.ts"],"names":[],"mappings":"AAcA;;;;;;;;;GASG;AACH,QAAA,MAAM,yBAAyB,GAC7B,MAAM,MAAM,EACZ,OAAO,MAAM,EACb,eAAe,MAAM,KACpB,OAAO,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;CAClB,CAyHA,CAAC;AAEF,eAAe,yBAAyB,CAAC"}
1
+ {"version":3,"file":"handleOAuthCallbackAction.d.ts","sourceRoot":"","sources":["../../../src/server/actions/handleOAuthCallbackAction.ts"],"names":[],"mappings":"AAeA;;;;;;;;;GASG;AACH,QAAA,MAAM,yBAAyB,GAC7B,MAAM,MAAM,EACZ,OAAO,MAAM,EACb,eAAe,MAAM,KACpB,OAAO,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;CAClB,CA0HA,CAAC;AAEF,eAAe,yBAAyB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  'use server';
2
2
 
3
3
 
4
+ import { setChunkedCookie } from "../../utils/chunkedCookie.js";
4
5
  import SessionManager_default from "../../utils/SessionManager.js";
5
6
  import getClient_default from "../getClient.js";
6
7
  import logger_default from "../../utils/logger.js";
@@ -59,7 +60,7 @@ const handleOAuthCallbackAction = async (code, state, sessionState) => {
59
60
  const expiresIn = signInResult["expiresIn"];
60
61
  const sessionCookieExpiryTime = SessionManager_default.resolveSessionCookieExpiry(config.sessionCookie?.expiryTime);
61
62
  const sessionToken = await SessionManager_default.createSessionToken(accessToken, userIdFromToken, sessionId, scopes, expiresIn, refreshToken, organizationId);
62
- cookieStore.set(SessionManager_default.getSessionCookieName(), sessionToken, SessionManager_default.getSessionCookieOptions(sessionCookieExpiryTime));
63
+ setChunkedCookie(cookieStore, SessionManager_default.getSessionCookieName(), sessionToken, SessionManager_default.getSessionCookieOptions(sessionCookieExpiryTime));
63
64
  cookieStore.delete(SessionManager_default.getTempSessionCookieName());
64
65
  } catch (error) {
65
66
  logger_default.error(`[handleOAuthCallbackAction] Failed to create JWT session, continuing with legacy session:
@@ -1 +1 @@
1
- {"version":3,"file":"handleOAuthCallbackAction.js","names":["getClient","cookieStore: RequestCookies","sessionId: string | undefined","tempSessionToken: string | undefined","SessionManager","signInResult: Record<string, unknown>","config: ThunderIDNextConfig","idToken: IdToken","accessToken: string","refreshToken: string","userIdFromToken: string","scopes: string","organizationId: string | undefined","expiresIn: number","sessionCookieExpiryTime: number","sessionToken: string"],"sources":["../../../src/server/actions/handleOAuthCallbackAction.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {IdToken} from '@thunderid/node';\nimport {cookies} from 'next/headers';\nimport {ThunderIDNextConfig} from '../../models/config';\nimport logger from '../../utils/logger';\nimport SessionManager from '../../utils/SessionManager';\nimport getClient from '../getClient';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Server action to handle OAuth callback with authorization code.\n * This action processes the authorization code received from the OAuth provider\n * and exchanges it for tokens to complete the authentication flow.\n *\n * @param code - Authorization code from OAuth provider\n * @param state - State parameter from OAuth provider for CSRF protection\n * @param sessionState - Session state parameter from OAuth provider\n * @returns Promise that resolves with success status and optional error message\n */\nconst handleOAuthCallbackAction = async (\n code: string,\n state: string,\n sessionState?: string,\n): Promise<{\n error?: string;\n redirectUrl?: string;\n success: boolean;\n}> => {\n try {\n if (!code || !state) {\n return {\n error: 'Missing required OAuth parameters: code and state are required',\n success: false,\n };\n }\n\n const thunderIDClient = getClient();\n\n if (!thunderIDClient.isInitialized) {\n return {\n error: 'ThunderID client is not initialized',\n success: false,\n };\n }\n\n const cookieStore: RequestCookies = await cookies();\n let sessionId: string | undefined;\n\n const tempSessionToken: string | undefined = cookieStore.get(SessionManager.getTempSessionCookieName())?.value;\n\n if (tempSessionToken) {\n try {\n const tempSession: {sessionId: string} = await SessionManager.verifyTempSession(tempSessionToken);\n sessionId = tempSession.sessionId;\n } catch {\n logger.error(\n '[handleOAuthCallbackAction] Invalid temporary session token, falling back to session ID from cookies.',\n );\n }\n }\n\n if (!sessionId) {\n logger.error('[handleOAuthCallbackAction] No session ID found in cookies or temporary session token.');\n\n return {\n error: 'No session found. Please start the authentication flow again.',\n success: false,\n };\n }\n\n // Exchange the authorization code for tokens\n const signInResult: Record<string, unknown> = await thunderIDClient.signIn(\n {\n code,\n session_state: sessionState,\n state,\n } as any,\n {},\n sessionId,\n );\n\n const config: ThunderIDNextConfig = await thunderIDClient.getConfiguration();\n\n if (signInResult) {\n try {\n const idToken: IdToken = await thunderIDClient.getDecodedIdToken(\n sessionId,\n (signInResult['id_token'] || signInResult['idToken']) as string,\n );\n const accessToken: string = (signInResult['accessToken'] || signInResult['access_token']) as string;\n const refreshToken: string = (signInResult['refreshToken'] as string | undefined) ?? '';\n const userIdFromToken: string = (idToken.sub || signInResult['sub'] || sessionId) as string;\n const scopes: string = signInResult['scope'] as string;\n const organizationId: string | undefined = (idToken['user_org'] || idToken['organization_id']) as\n | string\n | undefined;\n const expiresIn: number = signInResult['expiresIn'] as number;\n const sessionCookieExpiryTime: number = SessionManager.resolveSessionCookieExpiry(\n config.sessionCookie?.expiryTime,\n );\n\n const sessionToken: string = await SessionManager.createSessionToken(\n accessToken,\n userIdFromToken,\n sessionId,\n scopes,\n expiresIn,\n refreshToken,\n organizationId,\n );\n\n cookieStore.set(\n SessionManager.getSessionCookieName(),\n sessionToken,\n SessionManager.getSessionCookieOptions(sessionCookieExpiryTime),\n );\n\n cookieStore.delete(SessionManager.getTempSessionCookieName());\n } catch (error) {\n logger.error(\n `[handleOAuthCallbackAction] Failed to create JWT session, continuing with legacy session:\n ${typeof error === 'string' ? error : JSON.stringify(error)}`,\n );\n }\n }\n\n const afterSignInUrl: string = config.afterSignInUrl || '/';\n\n return {\n redirectUrl: afterSignInUrl,\n success: true,\n };\n } catch (error) {\n let errorMessage = 'Authentication failed';\n\n if (error instanceof Error) {\n errorMessage = error.message;\n } else if (error && typeof error === 'object' && 'message' in error) {\n errorMessage = String((error as {message: unknown}).message);\n } else if (typeof error === 'string') {\n errorMessage = error;\n }\n\n return {\n error: errorMessage,\n success: false,\n };\n }\n};\n\nexport default handleOAuthCallbackAction;\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAwBA,MAAM,4BAA4B,OAChC,MACA,OACA,iBAKI;AACJ,KAAI;AACF,MAAI,CAAC,QAAQ,CAAC,MACZ,QAAO;GACL,OAAO;GACP,SAAS;GACV;EAGH,MAAM,kBAAkBA,mBAAW;AAEnC,MAAI,CAAC,gBAAgB,cACnB,QAAO;GACL,OAAO;GACP,SAAS;GACV;EAGH,MAAMC,cAA8B,MAAM,SAAS;EACnD,IAAIC;EAEJ,MAAMC,mBAAuC,YAAY,IAAIC,uBAAe,0BAA0B,CAAC,EAAE;AAEzG,MAAI,iBACF,KAAI;AAEF,gBADyC,MAAMA,uBAAe,kBAAkB,iBAAiB,EACzE;UAClB;AACN,kBAAO,MACL,wGACD;;AAIL,MAAI,CAAC,WAAW;AACd,kBAAO,MAAM,yFAAyF;AAEtG,UAAO;IACL,OAAO;IACP,SAAS;IACV;;EAIH,MAAMC,eAAwC,MAAM,gBAAgB,OAClE;GACE;GACA,eAAe;GACf;GACD,EACD,EAAE,EACF,UACD;EAED,MAAMC,SAA8B,MAAM,gBAAgB,kBAAkB;AAE5E,MAAI,aACF,KAAI;GACF,MAAMC,UAAmB,MAAM,gBAAgB,kBAC7C,WACC,aAAa,eAAe,aAAa,WAC3C;GACD,MAAMC,cAAuB,aAAa,kBAAkB,aAAa;GACzE,MAAMC,eAAwB,aAAa,mBAA0C;GACrF,MAAMC,kBAA2B,QAAQ,OAAO,aAAa,UAAU;GACvE,MAAMC,SAAiB,aAAa;GACpC,MAAMC,iBAAsC,QAAQ,eAAe,QAAQ;GAG3E,MAAMC,YAAoB,aAAa;GACvC,MAAMC,0BAAkCV,uBAAe,2BACrD,OAAO,eAAe,WACvB;GAED,MAAMW,eAAuB,MAAMX,uBAAe,mBAChD,aACA,iBACA,WACA,QACA,WACA,cACA,eACD;AAED,eAAY,IACVA,uBAAe,sBAAsB,EACrC,cACAA,uBAAe,wBAAwB,wBAAwB,CAChE;AAED,eAAY,OAAOA,uBAAe,0BAA0B,CAAC;WACtD,OAAO;AACd,kBAAO,MACL;YACE,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,MAAM,GAC5D;;AAML,SAAO;GACL,aAH6B,OAAO,kBAAkB;GAItD,SAAS;GACV;UACM,OAAO;EACd,IAAI,eAAe;AAEnB,MAAI,iBAAiB,MACnB,gBAAe,MAAM;WACZ,SAAS,OAAO,UAAU,YAAY,aAAa,MAC5D,gBAAe,OAAQ,MAA6B,QAAQ;WACnD,OAAO,UAAU,SAC1B,gBAAe;AAGjB,SAAO;GACL,OAAO;GACP,SAAS;GACV;;;AAIL,wCAAe"}
1
+ {"version":3,"file":"handleOAuthCallbackAction.js","names":["getClient","cookieStore: RequestCookies","sessionId: string | undefined","tempSessionToken: string | undefined","SessionManager","signInResult: Record<string, unknown>","config: ThunderIDNextConfig","idToken: IdToken","accessToken: string","refreshToken: string","userIdFromToken: string","scopes: string","organizationId: string | undefined","expiresIn: number","sessionCookieExpiryTime: number","sessionToken: string"],"sources":["../../../src/server/actions/handleOAuthCallbackAction.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {IdToken} from '@thunderid/node';\nimport {cookies} from 'next/headers';\nimport {ThunderIDNextConfig} from '../../models/config';\nimport {setChunkedCookie} from '../../utils/chunkedCookie';\nimport logger from '../../utils/logger';\nimport SessionManager from '../../utils/SessionManager';\nimport getClient from '../getClient';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Server action to handle OAuth callback with authorization code.\n * This action processes the authorization code received from the OAuth provider\n * and exchanges it for tokens to complete the authentication flow.\n *\n * @param code - Authorization code from OAuth provider\n * @param state - State parameter from OAuth provider for CSRF protection\n * @param sessionState - Session state parameter from OAuth provider\n * @returns Promise that resolves with success status and optional error message\n */\nconst handleOAuthCallbackAction = async (\n code: string,\n state: string,\n sessionState?: string,\n): Promise<{\n error?: string;\n redirectUrl?: string;\n success: boolean;\n}> => {\n try {\n if (!code || !state) {\n return {\n error: 'Missing required OAuth parameters: code and state are required',\n success: false,\n };\n }\n\n const thunderIDClient = getClient();\n\n if (!thunderIDClient.isInitialized) {\n return {\n error: 'ThunderID client is not initialized',\n success: false,\n };\n }\n\n const cookieStore: RequestCookies = await cookies();\n let sessionId: string | undefined;\n\n const tempSessionToken: string | undefined = cookieStore.get(SessionManager.getTempSessionCookieName())?.value;\n\n if (tempSessionToken) {\n try {\n const tempSession: {sessionId: string} = await SessionManager.verifyTempSession(tempSessionToken);\n sessionId = tempSession.sessionId;\n } catch {\n logger.error(\n '[handleOAuthCallbackAction] Invalid temporary session token, falling back to session ID from cookies.',\n );\n }\n }\n\n if (!sessionId) {\n logger.error('[handleOAuthCallbackAction] No session ID found in cookies or temporary session token.');\n\n return {\n error: 'No session found. Please start the authentication flow again.',\n success: false,\n };\n }\n\n // Exchange the authorization code for tokens\n const signInResult: Record<string, unknown> = await thunderIDClient.signIn(\n {\n code,\n session_state: sessionState,\n state,\n } as any,\n {},\n sessionId,\n );\n\n const config: ThunderIDNextConfig = await thunderIDClient.getConfiguration();\n\n if (signInResult) {\n try {\n const idToken: IdToken = await thunderIDClient.getDecodedIdToken(\n sessionId,\n (signInResult['id_token'] || signInResult['idToken']) as string,\n );\n const accessToken: string = (signInResult['accessToken'] || signInResult['access_token']) as string;\n const refreshToken: string = (signInResult['refreshToken'] as string | undefined) ?? '';\n const userIdFromToken: string = (idToken.sub || signInResult['sub'] || sessionId) as string;\n const scopes: string = signInResult['scope'] as string;\n const organizationId: string | undefined = (idToken['user_org'] || idToken['organization_id']) as\n | string\n | undefined;\n const expiresIn: number = signInResult['expiresIn'] as number;\n const sessionCookieExpiryTime: number = SessionManager.resolveSessionCookieExpiry(\n config.sessionCookie?.expiryTime,\n );\n\n const sessionToken: string = await SessionManager.createSessionToken(\n accessToken,\n userIdFromToken,\n sessionId,\n scopes,\n expiresIn,\n refreshToken,\n organizationId,\n );\n\n setChunkedCookie(\n cookieStore,\n SessionManager.getSessionCookieName(),\n sessionToken,\n SessionManager.getSessionCookieOptions(sessionCookieExpiryTime),\n );\n\n cookieStore.delete(SessionManager.getTempSessionCookieName());\n } catch (error) {\n logger.error(\n `[handleOAuthCallbackAction] Failed to create JWT session, continuing with legacy session:\n ${typeof error === 'string' ? error : JSON.stringify(error)}`,\n );\n }\n }\n\n const afterSignInUrl: string = config.afterSignInUrl || '/';\n\n return {\n redirectUrl: afterSignInUrl,\n success: true,\n };\n } catch (error) {\n let errorMessage = 'Authentication failed';\n\n if (error instanceof Error) {\n errorMessage = error.message;\n } else if (error && typeof error === 'object' && 'message' in error) {\n errorMessage = String((error as {message: unknown}).message);\n } else if (typeof error === 'string') {\n errorMessage = error;\n }\n\n return {\n error: errorMessage,\n success: false,\n };\n }\n};\n\nexport default handleOAuthCallbackAction;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAyBA,MAAM,4BAA4B,OAChC,MACA,OACA,iBAKI;AACJ,KAAI;AACF,MAAI,CAAC,QAAQ,CAAC,MACZ,QAAO;GACL,OAAO;GACP,SAAS;GACV;EAGH,MAAM,kBAAkBA,mBAAW;AAEnC,MAAI,CAAC,gBAAgB,cACnB,QAAO;GACL,OAAO;GACP,SAAS;GACV;EAGH,MAAMC,cAA8B,MAAM,SAAS;EACnD,IAAIC;EAEJ,MAAMC,mBAAuC,YAAY,IAAIC,uBAAe,0BAA0B,CAAC,EAAE;AAEzG,MAAI,iBACF,KAAI;AAEF,gBADyC,MAAMA,uBAAe,kBAAkB,iBAAiB,EACzE;UAClB;AACN,kBAAO,MACL,wGACD;;AAIL,MAAI,CAAC,WAAW;AACd,kBAAO,MAAM,yFAAyF;AAEtG,UAAO;IACL,OAAO;IACP,SAAS;IACV;;EAIH,MAAMC,eAAwC,MAAM,gBAAgB,OAClE;GACE;GACA,eAAe;GACf;GACD,EACD,EAAE,EACF,UACD;EAED,MAAMC,SAA8B,MAAM,gBAAgB,kBAAkB;AAE5E,MAAI,aACF,KAAI;GACF,MAAMC,UAAmB,MAAM,gBAAgB,kBAC7C,WACC,aAAa,eAAe,aAAa,WAC3C;GACD,MAAMC,cAAuB,aAAa,kBAAkB,aAAa;GACzE,MAAMC,eAAwB,aAAa,mBAA0C;GACrF,MAAMC,kBAA2B,QAAQ,OAAO,aAAa,UAAU;GACvE,MAAMC,SAAiB,aAAa;GACpC,MAAMC,iBAAsC,QAAQ,eAAe,QAAQ;GAG3E,MAAMC,YAAoB,aAAa;GACvC,MAAMC,0BAAkCV,uBAAe,2BACrD,OAAO,eAAe,WACvB;GAED,MAAMW,eAAuB,MAAMX,uBAAe,mBAChD,aACA,iBACA,WACA,QACA,WACA,cACA,eACD;AAED,oBACE,aACAA,uBAAe,sBAAsB,EACrC,cACAA,uBAAe,wBAAwB,wBAAwB,CAChE;AAED,eAAY,OAAOA,uBAAe,0BAA0B,CAAC;WACtD,OAAO;AACd,kBAAO,MACL;YACE,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,MAAM,GAC5D;;AAML,SAAO;GACL,aAH6B,OAAO,kBAAkB;GAItD,SAAS;GACV;UACM,OAAO;EACd,IAAI,eAAe;AAEnB,MAAI,iBAAiB,MACnB,gBAAe,MAAM;WACZ,SAAS,OAAO,UAAU,YAAY,aAAa,MAC5D,gBAAe,OAAQ,MAA6B,QAAQ;WACnD,OAAO,UAAU,SAC1B,gBAAe;AAGjB,SAAO;GACL,OAAO;GACP,SAAS;GACV;;;AAIL,wCAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"refreshToken.d.ts","sourceRoot":"","sources":["../../../src/server/actions/refreshToken.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,QAAA,MAAM,YAAY,QAAa,OAAO,CAAC,aAAa,CAmEnD,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"refreshToken.d.ts","sourceRoot":"","sources":["../../../src/server/actions/refreshToken.ts"],"names":[],"mappings":"AAeA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,QAAA,MAAM,YAAY,QAAa,OAAO,CAAC,aAAa,CAoEnD,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -1,6 +1,7 @@
1
1
  'use server';
2
2
 
3
3
 
4
+ import { deleteChunkedCookie, getChunkedCookie, setChunkedCookie } from "../../utils/chunkedCookie.js";
4
5
  import SessionManager_default from "../../utils/SessionManager.js";
5
6
  import getClient_default from "../getClient.js";
6
7
  import handleRefreshToken_default from "../../utils/handleRefreshToken.js";
@@ -22,7 +23,7 @@ import { cookies } from "next/headers";
22
23
  const refreshToken = async () => {
23
24
  try {
24
25
  const cookieStore = await cookies();
25
- const sessionToken = cookieStore.get(SessionManager_default.getSessionCookieName())?.value;
26
+ const sessionToken = getChunkedCookie(cookieStore, SessionManager_default.getSessionCookieName());
26
27
  if (!sessionToken) throw new ThunderIDAPIError("No active session found. User must be signed in to refresh the token.", "refreshToken-ServerActionError-002", "nextjs", 401);
27
28
  const sessionPayload = await SessionManager_default.verifySessionTokenForRefresh(sessionToken);
28
29
  const config = await getClient_default().getConfiguration();
@@ -33,7 +34,7 @@ const refreshToken = async () => {
33
34
  sessionCookie: config.sessionCookie
34
35
  });
35
36
  try {
36
- cookieStore.set(SessionManager_default.getSessionCookieName(), result.newSessionToken, SessionManager_default.getSessionCookieOptions(result.sessionCookieExpiryTime));
37
+ setChunkedCookie(cookieStore, SessionManager_default.getSessionCookieName(), result.newSessionToken, SessionManager_default.getSessionCookieOptions(result.sessionCookieExpiryTime));
37
38
  } catch {
38
39
  logger.warn("[refreshToken] Could not write session cookie — called from SSR rendering context.");
39
40
  }
@@ -45,7 +46,7 @@ const refreshToken = async () => {
45
46
  return { expiresAt };
46
47
  } catch (error) {
47
48
  try {
48
- (await cookies()).delete(SessionManager_default.getSessionCookieName());
49
+ deleteChunkedCookie(await cookies(), SessionManager_default.getSessionCookieName());
49
50
  logger.debug("[refreshToken] Cleared session cookie after refresh failure.");
50
51
  } catch {}
51
52
  throw new ThunderIDAPIError(`Failed to refresh the session: ${error instanceof Error ? error.message : JSON.stringify(error)}`, "refreshToken-ServerActionError-001", "nextjs", error instanceof ThunderIDAPIError ? error.statusCode : void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"refreshToken.js","names":["cookieStore: RequestCookies","sessionToken: string | undefined","SessionManager","sessionPayload: SessionTokenPayload","config: ThunderIDNextConfig","getClient","result: HandleRefreshTokenResult","handleRefreshToken","rawExpiresIn: string | undefined","expiresInSeconds: number","expiresAt: number"],"sources":["../../../src/server/actions/refreshToken.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {ThunderIDAPIError, logger} from '@thunderid/node';\nimport {cookies} from 'next/headers';\nimport {ThunderIDNextConfig} from '../../models/config';\nimport handleRefreshToken, {HandleRefreshTokenResult} from '../../utils/handleRefreshToken';\nimport SessionManager, {SessionTokenPayload} from '../../utils/SessionManager';\nimport getClient from '../getClient';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Client-safe result of a token refresh.\n *\n * Intentionally omits accessToken, refreshToken, idToken, and scopes — those stay\n * server-side in the HttpOnly session cookie. Returning tokens from a Server Action\n * serializes them into browser memory, defeating the HttpOnly boundary and exposing\n * them to XSS, browser extensions, and error-tracking SDKs.\n *\n * `expiresAt` is epoch seconds for the new access token; the client uses it to\n * schedule the next refresh.\n */\nexport interface RefreshResult {\n expiresAt: number;\n}\n\n/**\n * Server action to refresh the access token using the stored refresh token.\n * Exchanges the refresh token for a new token set and updates the session cookie.\n *\n * Delegates the HTTP exchange to handleRefreshToken so the same logic is shared\n * with the middleware token refresh path.\n *\n * Called from the client side (e.g. ThunderIDClientProvider refreshOnMount) where\n * Next.js allows cookie mutation. When invoked during SSR rendering the cookie\n * write is silently skipped and a warning is logged.\n */\nconst refreshToken = async (): Promise<RefreshResult> => {\n try {\n const cookieStore: RequestCookies = await cookies();\n const sessionToken: string | undefined = cookieStore.get(SessionManager.getSessionCookieName())?.value;\n\n if (!sessionToken) {\n throw new ThunderIDAPIError(\n 'No active session found. User must be signed in to refresh the token.',\n 'refreshToken-ServerActionError-002',\n 'nextjs',\n 401,\n );\n }\n\n const sessionPayload: SessionTokenPayload = await SessionManager.verifySessionTokenForRefresh(sessionToken);\n const client = getClient();\n const config: ThunderIDNextConfig = await client.getConfiguration();\n\n const result: HandleRefreshTokenResult = await handleRefreshToken(sessionPayload, {\n baseUrl: config.baseUrl ?? '',\n clientId: config.clientId ?? '',\n clientSecret: config.clientSecret ?? '',\n sessionCookie: config.sessionCookie,\n });\n\n try {\n cookieStore.set(\n SessionManager.getSessionCookieName(),\n result.newSessionToken,\n SessionManager.getSessionCookieOptions(result.sessionCookieExpiryTime),\n );\n } catch {\n // cookies().set() is only permitted inside a Server Action invoked from the client\n // or a Route Handler. When this action is called during SSR rendering the write\n // is blocked by Next.js. The middleware refresh path handles that case instead.\n logger.warn('[refreshToken] Could not write session cookie — called from SSR rendering context.');\n }\n\n const rawExpiresIn: string | undefined = result.tokenResponse.expiresIn;\n const expiresInSeconds: number = parseInt(rawExpiresIn ?? '', 10);\n if (Number.isNaN(expiresInSeconds)) {\n throw new Error(`[refreshToken] Invalid expiresIn value received: ${rawExpiresIn}`);\n }\n const expiresAt: number = Math.floor(Date.now() / 1000) + expiresInSeconds;\n\n logger.debug('[refreshToken] Token refresh succeeded.');\n return {expiresAt};\n } catch (error) {\n // Clear the dead session cookie before throwing so the browser is not left\n // holding a stale credential. This is best-effort — if called from an SSR\n // rendering context Next.js blocks cookie mutation; the middleware cleanup\n // path covers that case on the next request.\n try {\n const cookieStore: RequestCookies = await cookies();\n cookieStore.delete(SessionManager.getSessionCookieName());\n logger.debug('[refreshToken] Cleared session cookie after refresh failure.');\n } catch {\n // Intentionally swallowed — middleware handles cleanup when mutation is blocked.\n }\n\n throw new ThunderIDAPIError(\n `Failed to refresh the session: ${error instanceof Error ? error.message : JSON.stringify(error)}`,\n 'refreshToken-ServerActionError-001',\n 'nextjs',\n error instanceof ThunderIDAPIError ? error.statusCode : undefined,\n );\n }\n};\n\nexport default refreshToken;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwCA,MAAM,eAAe,YAAoC;AACvD,KAAI;EACF,MAAMA,cAA8B,MAAM,SAAS;EACnD,MAAMC,eAAmC,YAAY,IAAIC,uBAAe,sBAAsB,CAAC,EAAE;AAEjG,MAAI,CAAC,aACH,OAAM,IAAI,kBACR,yEACA,sCACA,UACA,IACD;EAGH,MAAMC,iBAAsC,MAAMD,uBAAe,6BAA6B,aAAa;EAE3G,MAAME,SAA8B,MADrBC,mBAAW,CACuB,kBAAkB;EAEnE,MAAMC,SAAmC,MAAMC,2BAAmB,gBAAgB;GAChF,SAAS,OAAO,WAAW;GAC3B,UAAU,OAAO,YAAY;GAC7B,cAAc,OAAO,gBAAgB;GACrC,eAAe,OAAO;GACvB,CAAC;AAEF,MAAI;AACF,eAAY,IACVL,uBAAe,sBAAsB,EACrC,OAAO,iBACPA,uBAAe,wBAAwB,OAAO,wBAAwB,CACvE;UACK;AAIN,UAAO,KAAK,qFAAqF;;EAGnG,MAAMM,eAAmC,OAAO,cAAc;EAC9D,MAAMC,mBAA2B,SAAS,gBAAgB,IAAI,GAAG;AACjE,MAAI,OAAO,MAAM,iBAAiB,CAChC,OAAM,IAAI,MAAM,oDAAoD,eAAe;EAErF,MAAMC,YAAoB,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,GAAG;AAE1D,SAAO,MAAM,0CAA0C;AACvD,SAAO,EAAC,WAAU;UACX,OAAO;AAKd,MAAI;AAEF,IADoC,MAAM,SAAS,EACvC,OAAOR,uBAAe,sBAAsB,CAAC;AACzD,UAAO,MAAM,+DAA+D;UACtE;AAIR,QAAM,IAAI,kBACR,kCAAkC,iBAAiB,QAAQ,MAAM,UAAU,KAAK,UAAU,MAAM,IAChG,sCACA,UACA,iBAAiB,oBAAoB,MAAM,aAAa,OACzD;;;AAIL,2BAAe"}
1
+ {"version":3,"file":"refreshToken.js","names":["cookieStore: RequestCookies","sessionToken: string | undefined","SessionManager","sessionPayload: SessionTokenPayload","config: ThunderIDNextConfig","getClient","result: HandleRefreshTokenResult","handleRefreshToken","rawExpiresIn: string | undefined","expiresInSeconds: number","expiresAt: number"],"sources":["../../../src/server/actions/refreshToken.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {ThunderIDAPIError, logger} from '@thunderid/node';\nimport {cookies} from 'next/headers';\nimport {ThunderIDNextConfig} from '../../models/config';\nimport {deleteChunkedCookie, getChunkedCookie, setChunkedCookie} from '../../utils/chunkedCookie';\nimport handleRefreshToken, {HandleRefreshTokenResult} from '../../utils/handleRefreshToken';\nimport SessionManager, {SessionTokenPayload} from '../../utils/SessionManager';\nimport getClient from '../getClient';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Client-safe result of a token refresh.\n *\n * Intentionally omits accessToken, refreshToken, idToken, and scopes — those stay\n * server-side in the HttpOnly session cookie. Returning tokens from a Server Action\n * serializes them into browser memory, defeating the HttpOnly boundary and exposing\n * them to XSS, browser extensions, and error-tracking SDKs.\n *\n * `expiresAt` is epoch seconds for the new access token; the client uses it to\n * schedule the next refresh.\n */\nexport interface RefreshResult {\n expiresAt: number;\n}\n\n/**\n * Server action to refresh the access token using the stored refresh token.\n * Exchanges the refresh token for a new token set and updates the session cookie.\n *\n * Delegates the HTTP exchange to handleRefreshToken so the same logic is shared\n * with the middleware token refresh path.\n *\n * Called from the client side (e.g. ThunderIDClientProvider refreshOnMount) where\n * Next.js allows cookie mutation. When invoked during SSR rendering the cookie\n * write is silently skipped and a warning is logged.\n */\nconst refreshToken = async (): Promise<RefreshResult> => {\n try {\n const cookieStore: RequestCookies = await cookies();\n const sessionToken: string | undefined = getChunkedCookie(cookieStore, SessionManager.getSessionCookieName());\n\n if (!sessionToken) {\n throw new ThunderIDAPIError(\n 'No active session found. User must be signed in to refresh the token.',\n 'refreshToken-ServerActionError-002',\n 'nextjs',\n 401,\n );\n }\n\n const sessionPayload: SessionTokenPayload = await SessionManager.verifySessionTokenForRefresh(sessionToken);\n const client = getClient();\n const config: ThunderIDNextConfig = await client.getConfiguration();\n\n const result: HandleRefreshTokenResult = await handleRefreshToken(sessionPayload, {\n baseUrl: config.baseUrl ?? '',\n clientId: config.clientId ?? '',\n clientSecret: config.clientSecret ?? '',\n sessionCookie: config.sessionCookie,\n });\n\n try {\n setChunkedCookie(\n cookieStore,\n SessionManager.getSessionCookieName(),\n result.newSessionToken,\n SessionManager.getSessionCookieOptions(result.sessionCookieExpiryTime),\n );\n } catch {\n // cookies().set() is only permitted inside a Server Action invoked from the client\n // or a Route Handler. When this action is called during SSR rendering the write\n // is blocked by Next.js. The middleware refresh path handles that case instead.\n logger.warn('[refreshToken] Could not write session cookie — called from SSR rendering context.');\n }\n\n const rawExpiresIn: string | undefined = result.tokenResponse.expiresIn;\n const expiresInSeconds: number = parseInt(rawExpiresIn ?? '', 10);\n if (Number.isNaN(expiresInSeconds)) {\n throw new Error(`[refreshToken] Invalid expiresIn value received: ${rawExpiresIn}`);\n }\n const expiresAt: number = Math.floor(Date.now() / 1000) + expiresInSeconds;\n\n logger.debug('[refreshToken] Token refresh succeeded.');\n return {expiresAt};\n } catch (error) {\n // Clear the dead session cookie before throwing so the browser is not left\n // holding a stale credential. This is best-effort — if called from an SSR\n // rendering context Next.js blocks cookie mutation; the middleware cleanup\n // path covers that case on the next request.\n try {\n const cookieStore: RequestCookies = await cookies();\n deleteChunkedCookie(cookieStore, SessionManager.getSessionCookieName());\n logger.debug('[refreshToken] Cleared session cookie after refresh failure.');\n } catch {\n // Intentionally swallowed — middleware handles cleanup when mutation is blocked.\n }\n\n throw new ThunderIDAPIError(\n `Failed to refresh the session: ${error instanceof Error ? error.message : JSON.stringify(error)}`,\n 'refreshToken-ServerActionError-001',\n 'nextjs',\n error instanceof ThunderIDAPIError ? error.statusCode : undefined,\n );\n }\n};\n\nexport default refreshToken;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAyCA,MAAM,eAAe,YAAoC;AACvD,KAAI;EACF,MAAMA,cAA8B,MAAM,SAAS;EACnD,MAAMC,eAAmC,iBAAiB,aAAaC,uBAAe,sBAAsB,CAAC;AAE7G,MAAI,CAAC,aACH,OAAM,IAAI,kBACR,yEACA,sCACA,UACA,IACD;EAGH,MAAMC,iBAAsC,MAAMD,uBAAe,6BAA6B,aAAa;EAE3G,MAAME,SAA8B,MADrBC,mBAAW,CACuB,kBAAkB;EAEnE,MAAMC,SAAmC,MAAMC,2BAAmB,gBAAgB;GAChF,SAAS,OAAO,WAAW;GAC3B,UAAU,OAAO,YAAY;GAC7B,cAAc,OAAO,gBAAgB;GACrC,eAAe,OAAO;GACvB,CAAC;AAEF,MAAI;AACF,oBACE,aACAL,uBAAe,sBAAsB,EACrC,OAAO,iBACPA,uBAAe,wBAAwB,OAAO,wBAAwB,CACvE;UACK;AAIN,UAAO,KAAK,qFAAqF;;EAGnG,MAAMM,eAAmC,OAAO,cAAc;EAC9D,MAAMC,mBAA2B,SAAS,gBAAgB,IAAI,GAAG;AACjE,MAAI,OAAO,MAAM,iBAAiB,CAChC,OAAM,IAAI,MAAM,oDAAoD,eAAe;EAErF,MAAMC,YAAoB,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,GAAG;AAE1D,SAAO,MAAM,0CAA0C;AACvD,SAAO,EAAC,WAAU;UACX,OAAO;AAKd,MAAI;AAEF,uBADoC,MAAM,SAAS,EAClBR,uBAAe,sBAAsB,CAAC;AACvE,UAAO,MAAM,+DAA+D;UACtE;AAIR,QAAM,IAAI,kBACR,kCAAkC,iBAAiB,QAAQ,MAAM,UAAU,KAAK,UAAU,MAAM,IAChG,sCACA,UACA,iBAAiB,oBAAoB,MAAM,aAAa,OACzD;;;AAIL,2BAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"signInAction.d.ts","sourceRoot":"","sources":["../../../src/server/actions/signInAction.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,gCAAgC,EAGjC,MAAM,iBAAiB,CAAC;AASzB;;;;;;;GAOG;AACH,QAAA,MAAM,YAAY,GAChB,UAAU,GAAG,EACb,UAAU,gCAAgC,KACzC,OAAO,CAAC;IACT,IAAI,CAAC,EACD;QACE,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GACD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB,CA6GA,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"signInAction.d.ts","sourceRoot":"","sources":["../../../src/server/actions/signInAction.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,gCAAgC,EAGjC,MAAM,iBAAiB,CAAC;AAUzB;;;;;;;GAOG;AACH,QAAA,MAAM,YAAY,GAChB,UAAU,GAAG,EACb,UAAU,gCAAgC,KACzC,OAAO,CAAC;IACT,IAAI,CAAC,EACD;QACE,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GACD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB,CAiHA,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -1,6 +1,7 @@
1
1
  'use server';
2
2
 
3
3
 
4
+ import { getChunkedCookie, setChunkedCookie } from "../../utils/chunkedCookie.js";
4
5
  import SessionManager_default from "../../utils/SessionManager.js";
5
6
  import getClient_default from "../getClient.js";
6
7
  import logger_default from "../../utils/logger.js";
@@ -21,7 +22,7 @@ const signInAction = async (payload, request) => {
21
22
  const client = getClient_default();
22
23
  const cookieStore = await cookies();
23
24
  let sessionId;
24
- const existingSessionToken = cookieStore.get(SessionManager_default.getSessionCookieName())?.value;
25
+ const existingSessionToken = getChunkedCookie(cookieStore, SessionManager_default.getSessionCookieName());
25
26
  if (existingSessionToken) try {
26
27
  sessionId = (await SessionManager_default.verifySessionToken(existingSessionToken)).sessionId;
27
28
  } catch {}
@@ -56,7 +57,7 @@ const signInAction = async (payload, request) => {
56
57
  const config = await client.getConfiguration();
57
58
  const sessionCookieExpiryTime = SessionManager_default.resolveSessionCookieExpiry(config.sessionCookie?.expiryTime);
58
59
  const sessionToken = await SessionManager_default.createSessionToken(response.assertion, userIdFromToken, sessionId, scopes, expiresIn, "", organizationId);
59
- cookieStore.set(SessionManager_default.getSessionCookieName(), sessionToken, SessionManager_default.getSessionCookieOptions(sessionCookieExpiryTime));
60
+ setChunkedCookie(cookieStore, SessionManager_default.getSessionCookieName(), sessionToken, SessionManager_default.getSessionCookieOptions(sessionCookieExpiryTime));
60
61
  cookieStore.delete(SessionManager_default.getTempSessionCookieName());
61
62
  const afterSignInUrl = await (await client.getStorageManager()).getConfigDataParameter("afterSignInUrl");
62
63
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"signInAction.js","names":["getClient","cookieStore: RequestCookies","sessionId: string | undefined","existingSessionToken: string | undefined","SessionManager","tempSessionToken: string | undefined","tempSessionToken: string","defaultSignInUrl: string","response: any","idToken: IdToken","userIdFromToken: string","organizationId: string | undefined","scopes: string","iat: number","exp: number","expiresIn: number","config: ThunderIDNextConfig","sessionCookieExpiryTime: number","sessionToken: string","afterSignInUrl: string"],"sources":["../../../src/server/actions/signInAction.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {\n generateSessionId,\n EmbeddedSignInFlowStatus,\n EmbeddedFlowExecuteRequestConfig,\n IdToken,\n isEmpty,\n} from '@thunderid/node';\nimport {cookies} from 'next/headers';\nimport {ThunderIDNextConfig} from '../../models/config';\nimport logger from '../../utils/logger';\nimport SessionManager, {SessionTokenPayload} from '../../utils/SessionManager';\nimport getClient from '../getClient';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Server action for signing in a user.\n * Handles the embedded sign-in flow and manages session cookies.\n *\n * @param payload - The embedded sign-in flow payload\n * @param request - The embedded flow execute request config\n * @returns Promise that resolves when sign-in is complete\n */\nconst signInAction = async (\n payload?: any,\n request?: EmbeddedFlowExecuteRequestConfig,\n): Promise<{\n data?:\n | {\n afterSignInUrl?: string;\n signInUrl?: string;\n }\n | Record<string, unknown>;\n error?: string;\n success: boolean;\n}> => {\n try {\n const client = getClient();\n const cookieStore: RequestCookies = await cookies();\n\n let sessionId: string | undefined;\n\n const existingSessionToken: string | undefined = cookieStore.get(SessionManager.getSessionCookieName())?.value;\n\n if (existingSessionToken) {\n try {\n const sessionPayload: SessionTokenPayload = await SessionManager.verifySessionToken(existingSessionToken);\n sessionId = sessionPayload.sessionId;\n } catch {\n // Invalid session token, will create new temp session\n }\n }\n\n if (!sessionId) {\n const tempSessionToken: string | undefined = cookieStore.get(SessionManager.getTempSessionCookieName())?.value;\n\n if (tempSessionToken) {\n try {\n const tempSession: {sessionId: string} = await SessionManager.verifyTempSession(tempSessionToken);\n sessionId = tempSession.sessionId;\n } catch {\n // Invalid temp session, will create new one\n }\n }\n }\n\n if (!sessionId) {\n sessionId = generateSessionId();\n\n const tempSessionToken: string = await SessionManager.createTempSession(sessionId);\n\n cookieStore.set(\n SessionManager.getTempSessionCookieName(),\n tempSessionToken,\n SessionManager.getTempSessionCookieOptions(),\n );\n }\n\n // If no payload provided, redirect to sign-in URL for redirect-based sign-in.\n if (!payload || isEmpty(payload)) {\n const defaultSignInUrl: string = await client.getAuthorizeRequestUrl({}, sessionId);\n return {data: {signInUrl: String(defaultSignInUrl)}, success: true};\n }\n\n // Handle embedded sign-in flow\n const response: any = await client.signIn(payload, request!, sessionId);\n\n if (response.flowStatus === EmbeddedSignInFlowStatus.Complete) {\n // On the V2 platform, a completed embedded flow (without a preceding `/authorize` redirect,\n // i.e. no `authId`) returns a self-contained JWT `assertion` rather than an authorization\n // code to exchange. This mirrors how @thunderid/react and @thunderid/vue treat it: the\n // assertion is used directly as the bearer session token.\n if (!response.assertion) {\n throw new Error('[signInAction] Flow completed without an assertion.');\n }\n\n const idToken: IdToken = await client.getDecodedIdToken(sessionId, response.assertion);\n const userIdFromToken: string = (idToken.sub as string | undefined) ?? sessionId;\n const organizationId: string | undefined = (idToken['user_org'] || idToken['organization_id']) as\n | string\n | undefined;\n const scopes: string = (idToken['scope'] as string | undefined) ?? '';\n const iat: number = (idToken['iat'] as number | undefined) ?? Math.floor(Date.now() / 1000);\n const exp: number = (idToken['exp'] as number | undefined) ?? iat + 3600;\n const expiresIn: number = Math.max(exp - iat, 0);\n\n const config: ThunderIDNextConfig = await client.getConfiguration();\n const sessionCookieExpiryTime: number = SessionManager.resolveSessionCookieExpiry(\n config.sessionCookie?.expiryTime,\n );\n\n const sessionToken: string = await SessionManager.createSessionToken(\n response.assertion,\n userIdFromToken,\n sessionId,\n scopes,\n expiresIn,\n '',\n organizationId,\n );\n\n cookieStore.set(\n SessionManager.getSessionCookieName(),\n sessionToken,\n SessionManager.getSessionCookieOptions(sessionCookieExpiryTime),\n );\n\n cookieStore.delete(SessionManager.getTempSessionCookieName());\n\n const afterSignInUrl: string = await (await client.getStorageManager()).getConfigDataParameter('afterSignInUrl');\n return {data: {afterSignInUrl: String(afterSignInUrl)}, success: true};\n }\n\n return {data: response as Record<string, unknown>, success: true};\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : typeof (error as any)?.message === 'string'\n ? (error as any).message\n : String(error);\n logger.error(`[signInAction] Error during sign-in: ${message}`);\n return {error: message, success: false};\n }\n};\n\nexport default signInAction;\n"],"mappings":";;;;;;;;;;;;;;;;;;AA4BA,MAAM,eAAe,OACnB,SACA,YAUI;AACJ,KAAI;EACF,MAAM,SAASA,mBAAW;EAC1B,MAAMC,cAA8B,MAAM,SAAS;EAEnD,IAAIC;EAEJ,MAAMC,uBAA2C,YAAY,IAAIC,uBAAe,sBAAsB,CAAC,EAAE;AAEzG,MAAI,qBACF,KAAI;AAEF,gBAD4C,MAAMA,uBAAe,mBAAmB,qBAAqB,EAC9E;UACrB;AAKV,MAAI,CAAC,WAAW;GACd,MAAMC,mBAAuC,YAAY,IAAID,uBAAe,0BAA0B,CAAC,EAAE;AAEzG,OAAI,iBACF,KAAI;AAEF,iBADyC,MAAMA,uBAAe,kBAAkB,iBAAiB,EACzE;WAClB;;AAMZ,MAAI,CAAC,WAAW;AACd,eAAY,mBAAmB;GAE/B,MAAME,mBAA2B,MAAMF,uBAAe,kBAAkB,UAAU;AAElF,eAAY,IACVA,uBAAe,0BAA0B,EACzC,kBACAA,uBAAe,6BAA6B,CAC7C;;AAIH,MAAI,CAAC,WAAW,QAAQ,QAAQ,EAAE;GAChC,MAAMG,mBAA2B,MAAM,OAAO,uBAAuB,EAAE,EAAE,UAAU;AACnF,UAAO;IAAC,MAAM,EAAC,WAAW,OAAO,iBAAiB,EAAC;IAAE,SAAS;IAAK;;EAIrE,MAAMC,WAAgB,MAAM,OAAO,OAAO,SAAS,SAAU,UAAU;AAEvE,MAAI,SAAS,eAAe,yBAAyB,UAAU;AAK7D,OAAI,CAAC,SAAS,UACZ,OAAM,IAAI,MAAM,sDAAsD;GAGxE,MAAMC,UAAmB,MAAM,OAAO,kBAAkB,WAAW,SAAS,UAAU;GACtF,MAAMC,kBAA2B,QAAQ,OAA8B;GACvE,MAAMC,iBAAsC,QAAQ,eAAe,QAAQ;GAG3E,MAAMC,SAAkB,QAAQ,YAAmC;GACnE,MAAMC,MAAe,QAAQ,UAAiC,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK;GAC3F,MAAMC,MAAe,QAAQ,UAAiC,MAAM;GACpE,MAAMC,YAAoB,KAAK,IAAI,MAAM,KAAK,EAAE;GAEhD,MAAMC,SAA8B,MAAM,OAAO,kBAAkB;GACnE,MAAMC,0BAAkCb,uBAAe,2BACrD,OAAO,eAAe,WACvB;GAED,MAAMc,eAAuB,MAAMd,uBAAe,mBAChD,SAAS,WACT,iBACA,WACA,QACA,WACA,IACA,eACD;AAED,eAAY,IACVA,uBAAe,sBAAsB,EACrC,cACAA,uBAAe,wBAAwB,wBAAwB,CAChE;AAED,eAAY,OAAOA,uBAAe,0BAA0B,CAAC;GAE7D,MAAMe,iBAAyB,OAAO,MAAM,OAAO,mBAAmB,EAAE,uBAAuB,iBAAiB;AAChH,UAAO;IAAC,MAAM,EAAC,gBAAgB,OAAO,eAAe,EAAC;IAAE,SAAS;IAAK;;AAGxE,SAAO;GAAC,MAAM;GAAqC,SAAS;GAAK;UAC1D,OAAO;EACd,MAAM,UACJ,iBAAiB,QACb,MAAM,UACN,OAAQ,OAAe,YAAY,WAChC,MAAc,UACf,OAAO,MAAM;AACrB,iBAAO,MAAM,wCAAwC,UAAU;AAC/D,SAAO;GAAC,OAAO;GAAS,SAAS;GAAM;;;AAI3C,2BAAe"}
1
+ {"version":3,"file":"signInAction.js","names":["getClient","cookieStore: RequestCookies","sessionId: string | undefined","existingSessionToken: string | undefined","SessionManager","tempSessionToken: string | undefined","tempSessionToken: string","defaultSignInUrl: string","response: any","idToken: IdToken","userIdFromToken: string","organizationId: string | undefined","scopes: string","iat: number","exp: number","expiresIn: number","config: ThunderIDNextConfig","sessionCookieExpiryTime: number","sessionToken: string","afterSignInUrl: string"],"sources":["../../../src/server/actions/signInAction.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {\n generateSessionId,\n EmbeddedSignInFlowStatus,\n EmbeddedFlowExecuteRequestConfig,\n IdToken,\n isEmpty,\n} from '@thunderid/node';\nimport {cookies} from 'next/headers';\nimport {ThunderIDNextConfig} from '../../models/config';\nimport {getChunkedCookie, setChunkedCookie} from '../../utils/chunkedCookie';\nimport logger from '../../utils/logger';\nimport SessionManager, {SessionTokenPayload} from '../../utils/SessionManager';\nimport getClient from '../getClient';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Server action for signing in a user.\n * Handles the embedded sign-in flow and manages session cookies.\n *\n * @param payload - The embedded sign-in flow payload\n * @param request - The embedded flow execute request config\n * @returns Promise that resolves when sign-in is complete\n */\nconst signInAction = async (\n payload?: any,\n request?: EmbeddedFlowExecuteRequestConfig,\n): Promise<{\n data?:\n | {\n afterSignInUrl?: string;\n signInUrl?: string;\n }\n | Record<string, unknown>;\n error?: string;\n success: boolean;\n}> => {\n try {\n const client = getClient();\n const cookieStore: RequestCookies = await cookies();\n\n let sessionId: string | undefined;\n\n const existingSessionToken: string | undefined = getChunkedCookie(\n cookieStore,\n SessionManager.getSessionCookieName(),\n );\n\n if (existingSessionToken) {\n try {\n const sessionPayload: SessionTokenPayload = await SessionManager.verifySessionToken(existingSessionToken);\n sessionId = sessionPayload.sessionId;\n } catch {\n // Invalid session token, will create new temp session\n }\n }\n\n if (!sessionId) {\n const tempSessionToken: string | undefined = cookieStore.get(SessionManager.getTempSessionCookieName())?.value;\n\n if (tempSessionToken) {\n try {\n const tempSession: {sessionId: string} = await SessionManager.verifyTempSession(tempSessionToken);\n sessionId = tempSession.sessionId;\n } catch {\n // Invalid temp session, will create new one\n }\n }\n }\n\n if (!sessionId) {\n sessionId = generateSessionId();\n\n const tempSessionToken: string = await SessionManager.createTempSession(sessionId);\n\n cookieStore.set(\n SessionManager.getTempSessionCookieName(),\n tempSessionToken,\n SessionManager.getTempSessionCookieOptions(),\n );\n }\n\n // If no payload provided, redirect to sign-in URL for redirect-based sign-in.\n if (!payload || isEmpty(payload)) {\n const defaultSignInUrl: string = await client.getAuthorizeRequestUrl({}, sessionId);\n return {data: {signInUrl: String(defaultSignInUrl)}, success: true};\n }\n\n // Handle embedded sign-in flow\n const response: any = await client.signIn(payload, request!, sessionId);\n\n if (response.flowStatus === EmbeddedSignInFlowStatus.Complete) {\n // On the V2 platform, a completed embedded flow (without a preceding `/authorize` redirect,\n // i.e. no `authId`) returns a self-contained JWT `assertion` rather than an authorization\n // code to exchange. This mirrors how @thunderid/react and @thunderid/vue treat it: the\n // assertion is used directly as the bearer session token.\n if (!response.assertion) {\n throw new Error('[signInAction] Flow completed without an assertion.');\n }\n\n const idToken: IdToken = await client.getDecodedIdToken(sessionId, response.assertion);\n const userIdFromToken: string = (idToken.sub as string | undefined) ?? sessionId;\n const organizationId: string | undefined = (idToken['user_org'] || idToken['organization_id']) as\n | string\n | undefined;\n const scopes: string = (idToken['scope'] as string | undefined) ?? '';\n const iat: number = (idToken['iat'] as number | undefined) ?? Math.floor(Date.now() / 1000);\n const exp: number = (idToken['exp'] as number | undefined) ?? iat + 3600;\n const expiresIn: number = Math.max(exp - iat, 0);\n\n const config: ThunderIDNextConfig = await client.getConfiguration();\n const sessionCookieExpiryTime: number = SessionManager.resolveSessionCookieExpiry(\n config.sessionCookie?.expiryTime,\n );\n\n const sessionToken: string = await SessionManager.createSessionToken(\n response.assertion,\n userIdFromToken,\n sessionId,\n scopes,\n expiresIn,\n '',\n organizationId,\n );\n\n setChunkedCookie(\n cookieStore,\n SessionManager.getSessionCookieName(),\n sessionToken,\n SessionManager.getSessionCookieOptions(sessionCookieExpiryTime),\n );\n\n cookieStore.delete(SessionManager.getTempSessionCookieName());\n\n const afterSignInUrl: string = await (await client.getStorageManager()).getConfigDataParameter('afterSignInUrl');\n return {data: {afterSignInUrl: String(afterSignInUrl)}, success: true};\n }\n\n return {data: response as Record<string, unknown>, success: true};\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : typeof (error as any)?.message === 'string'\n ? (error as any).message\n : String(error);\n logger.error(`[signInAction] Error during sign-in: ${message}`);\n return {error: message, success: false};\n }\n};\n\nexport default signInAction;\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA6BA,MAAM,eAAe,OACnB,SACA,YAUI;AACJ,KAAI;EACF,MAAM,SAASA,mBAAW;EAC1B,MAAMC,cAA8B,MAAM,SAAS;EAEnD,IAAIC;EAEJ,MAAMC,uBAA2C,iBAC/C,aACAC,uBAAe,sBAAsB,CACtC;AAED,MAAI,qBACF,KAAI;AAEF,gBAD4C,MAAMA,uBAAe,mBAAmB,qBAAqB,EAC9E;UACrB;AAKV,MAAI,CAAC,WAAW;GACd,MAAMC,mBAAuC,YAAY,IAAID,uBAAe,0BAA0B,CAAC,EAAE;AAEzG,OAAI,iBACF,KAAI;AAEF,iBADyC,MAAMA,uBAAe,kBAAkB,iBAAiB,EACzE;WAClB;;AAMZ,MAAI,CAAC,WAAW;AACd,eAAY,mBAAmB;GAE/B,MAAME,mBAA2B,MAAMF,uBAAe,kBAAkB,UAAU;AAElF,eAAY,IACVA,uBAAe,0BAA0B,EACzC,kBACAA,uBAAe,6BAA6B,CAC7C;;AAIH,MAAI,CAAC,WAAW,QAAQ,QAAQ,EAAE;GAChC,MAAMG,mBAA2B,MAAM,OAAO,uBAAuB,EAAE,EAAE,UAAU;AACnF,UAAO;IAAC,MAAM,EAAC,WAAW,OAAO,iBAAiB,EAAC;IAAE,SAAS;IAAK;;EAIrE,MAAMC,WAAgB,MAAM,OAAO,OAAO,SAAS,SAAU,UAAU;AAEvE,MAAI,SAAS,eAAe,yBAAyB,UAAU;AAK7D,OAAI,CAAC,SAAS,UACZ,OAAM,IAAI,MAAM,sDAAsD;GAGxE,MAAMC,UAAmB,MAAM,OAAO,kBAAkB,WAAW,SAAS,UAAU;GACtF,MAAMC,kBAA2B,QAAQ,OAA8B;GACvE,MAAMC,iBAAsC,QAAQ,eAAe,QAAQ;GAG3E,MAAMC,SAAkB,QAAQ,YAAmC;GACnE,MAAMC,MAAe,QAAQ,UAAiC,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK;GAC3F,MAAMC,MAAe,QAAQ,UAAiC,MAAM;GACpE,MAAMC,YAAoB,KAAK,IAAI,MAAM,KAAK,EAAE;GAEhD,MAAMC,SAA8B,MAAM,OAAO,kBAAkB;GACnE,MAAMC,0BAAkCb,uBAAe,2BACrD,OAAO,eAAe,WACvB;GAED,MAAMc,eAAuB,MAAMd,uBAAe,mBAChD,SAAS,WACT,iBACA,WACA,QACA,WACA,IACA,eACD;AAED,oBACE,aACAA,uBAAe,sBAAsB,EACrC,cACAA,uBAAe,wBAAwB,wBAAwB,CAChE;AAED,eAAY,OAAOA,uBAAe,0BAA0B,CAAC;GAE7D,MAAMe,iBAAyB,OAAO,MAAM,OAAO,mBAAmB,EAAE,uBAAuB,iBAAiB;AAChH,UAAO;IAAC,MAAM,EAAC,gBAAgB,OAAO,eAAe,EAAC;IAAE,SAAS;IAAK;;AAGxE,SAAO;GAAC,MAAM;GAAqC,SAAS;GAAK;UAC1D,OAAO;EACd,MAAM,UACJ,iBAAiB,QACb,MAAM,UACN,OAAQ,OAAe,YAAY,WAChC,MAAc,UACf,OAAO,MAAM;AACrB,iBAAO,MAAM,wCAAwC,UAAU;AAC/D,SAAO;GAAC,OAAO;GAAS,SAAS;GAAM;;;AAI3C,2BAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"signOutAction.d.ts","sourceRoot":"","sources":["../../../src/server/actions/signOutAction.ts"],"names":[],"mappings":"AAaA;;;;;GAKG;AACH,QAAA,MAAM,aAAa,QAAa,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAC,CA8C7G,CAAC;AAEF,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"signOutAction.d.ts","sourceRoot":"","sources":["../../../src/server/actions/signOutAction.ts"],"names":[],"mappings":"AAcA;;;;;GAKG;AACH,QAAA,MAAM,aAAa,QAAa,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAC,CA8C7G,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -1,6 +1,7 @@
1
1
  'use server';
2
2
 
3
3
 
4
+ import { deleteChunkedCookie } from "../../utils/chunkedCookie.js";
4
5
  import SessionManager_default from "../../utils/SessionManager.js";
5
6
  import getSessionId_default from "./getSessionId.js";
6
7
  import getClient_default from "../getClient.js";
@@ -18,7 +19,7 @@ const signOutAction = async () => {
18
19
  logger_default.debug("[signOutAction] Initiating sign out process from the server action.");
19
20
  const clearSessionCookies = async () => {
20
21
  const cookieStore = await cookies();
21
- cookieStore.delete(SessionManager_default.getSessionCookieName());
22
+ deleteChunkedCookie(cookieStore, SessionManager_default.getSessionCookieName());
22
23
  cookieStore.delete(SessionManager_default.getTempSessionCookieName());
23
24
  };
24
25
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"signOutAction.js","names":["cookieStore: RequestCookies","SessionManager","getClient","sessionId: string | undefined","getSessionId","errorMessage: unknown"],"sources":["../../../src/server/actions/signOutAction.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {cookies} from 'next/headers';\nimport getSessionId from './getSessionId';\nimport logger from '../../utils/logger';\nimport SessionManager from '../../utils/SessionManager';\nimport getClient from '../getClient';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Server action for signing out a user.\n * Clears both JWT and legacy session cookies.\n *\n * @returns Promise that resolves with success status and optional after sign-out URL\n */\nconst signOutAction = async (): Promise<{data?: {afterSignOutUrl?: string}; error?: unknown; success: boolean}> => {\n logger.debug('[signOutAction] Initiating sign out process from the server action.');\n\n const clearSessionCookies = async (): Promise<void> => {\n const cookieStore: RequestCookies = await cookies();\n\n cookieStore.delete(SessionManager.getSessionCookieName());\n cookieStore.delete(SessionManager.getTempSessionCookieName());\n };\n\n try {\n const client = getClient();\n const sessionId: string | undefined = await getSessionId();\n\n let afterSignOutUrl = '/';\n\n if (sessionId) {\n logger.debug('[signOutAction] Session ID found, invoking the `signOut` to obtain the `afterSignOutUrl`.');\n\n afterSignOutUrl = await client.signOut({}, sessionId);\n }\n\n await clearSessionCookies();\n\n return {data: {afterSignOutUrl}, success: true};\n } catch (error) {\n logger.error('[signOutAction] Error during sign out from the server action:', error);\n\n logger.debug('[signOutAction] Clearing session cookies due to error as a fallback.');\n\n await clearSessionCookies();\n\n let errorMessage: unknown;\n if (typeof error === 'string') {\n errorMessage = error;\n } else if (error instanceof Error) {\n errorMessage = error.message;\n } else {\n errorMessage = JSON.stringify(error);\n }\n\n return {\n error: errorMessage,\n success: false,\n };\n }\n};\n\nexport default signOutAction;\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,MAAM,gBAAgB,YAA6F;AACjH,gBAAO,MAAM,sEAAsE;CAEnF,MAAM,sBAAsB,YAA2B;EACrD,MAAMA,cAA8B,MAAM,SAAS;AAEnD,cAAY,OAAOC,uBAAe,sBAAsB,CAAC;AACzD,cAAY,OAAOA,uBAAe,0BAA0B,CAAC;;AAG/D,KAAI;EACF,MAAM,SAASC,mBAAW;EAC1B,MAAMC,YAAgC,MAAMC,sBAAc;EAE1D,IAAI,kBAAkB;AAEtB,MAAI,WAAW;AACb,kBAAO,MAAM,4FAA4F;AAEzG,qBAAkB,MAAM,OAAO,QAAQ,EAAE,EAAE,UAAU;;AAGvD,QAAM,qBAAqB;AAE3B,SAAO;GAAC,MAAM,EAAC,iBAAgB;GAAE,SAAS;GAAK;UACxC,OAAO;AACd,iBAAO,MAAM,iEAAiE,MAAM;AAEpF,iBAAO,MAAM,uEAAuE;AAEpF,QAAM,qBAAqB;EAE3B,IAAIC;AACJ,MAAI,OAAO,UAAU,SACnB,gBAAe;WACN,iBAAiB,MAC1B,gBAAe,MAAM;MAErB,gBAAe,KAAK,UAAU,MAAM;AAGtC,SAAO;GACL,OAAO;GACP,SAAS;GACV;;;AAIL,4BAAe"}
1
+ {"version":3,"file":"signOutAction.js","names":["cookieStore: RequestCookies","SessionManager","getClient","sessionId: string | undefined","getSessionId","errorMessage: unknown"],"sources":["../../../src/server/actions/signOutAction.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {cookies} from 'next/headers';\nimport getSessionId from './getSessionId';\nimport {deleteChunkedCookie} from '../../utils/chunkedCookie';\nimport logger from '../../utils/logger';\nimport SessionManager from '../../utils/SessionManager';\nimport getClient from '../getClient';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Server action for signing out a user.\n * Clears both JWT and legacy session cookies.\n *\n * @returns Promise that resolves with success status and optional after sign-out URL\n */\nconst signOutAction = async (): Promise<{data?: {afterSignOutUrl?: string}; error?: unknown; success: boolean}> => {\n logger.debug('[signOutAction] Initiating sign out process from the server action.');\n\n const clearSessionCookies = async (): Promise<void> => {\n const cookieStore: RequestCookies = await cookies();\n\n deleteChunkedCookie(cookieStore, SessionManager.getSessionCookieName());\n cookieStore.delete(SessionManager.getTempSessionCookieName());\n };\n\n try {\n const client = getClient();\n const sessionId: string | undefined = await getSessionId();\n\n let afterSignOutUrl = '/';\n\n if (sessionId) {\n logger.debug('[signOutAction] Session ID found, invoking the `signOut` to obtain the `afterSignOutUrl`.');\n\n afterSignOutUrl = await client.signOut({}, sessionId);\n }\n\n await clearSessionCookies();\n\n return {data: {afterSignOutUrl}, success: true};\n } catch (error) {\n logger.error('[signOutAction] Error during sign out from the server action:', error);\n\n logger.debug('[signOutAction] Clearing session cookies due to error as a fallback.');\n\n await clearSessionCookies();\n\n let errorMessage: unknown;\n if (typeof error === 'string') {\n errorMessage = error;\n } else if (error instanceof Error) {\n errorMessage = error.message;\n } else {\n errorMessage = JSON.stringify(error);\n }\n\n return {\n error: errorMessage,\n success: false,\n };\n }\n};\n\nexport default signOutAction;\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBA,MAAM,gBAAgB,YAA6F;AACjH,gBAAO,MAAM,sEAAsE;CAEnF,MAAM,sBAAsB,YAA2B;EACrD,MAAMA,cAA8B,MAAM,SAAS;AAEnD,sBAAoB,aAAaC,uBAAe,sBAAsB,CAAC;AACvE,cAAY,OAAOA,uBAAe,0BAA0B,CAAC;;AAG/D,KAAI;EACF,MAAM,SAASC,mBAAW;EAC1B,MAAMC,YAAgC,MAAMC,sBAAc;EAE1D,IAAI,kBAAkB;AAEtB,MAAI,WAAW;AACb,kBAAO,MAAM,4FAA4F;AAEzG,qBAAkB,MAAM,OAAO,QAAQ,EAAE,EAAE,UAAU;;AAGvD,QAAM,qBAAqB;AAE3B,SAAO;GAAC,MAAM,EAAC,iBAAgB;GAAE,SAAS;GAAK;UACxC,OAAO;AACd,iBAAO,MAAM,iEAAiE,MAAM;AAEpF,iBAAO,MAAM,uEAAuE;AAEpF,QAAM,qBAAqB;EAE3B,IAAIC;AACJ,MAAI,OAAO,UAAU,SACnB,gBAAe;WACN,iBAAiB,MAC1B,gBAAe,MAAM;MAErB,gBAAe,KAAK,UAAU,MAAM;AAGtC,SAAO;GACL,OAAO;GACP,SAAS;GACV;;;AAIL,4BAAe"}
@@ -1,6 +1,6 @@
1
1
  import thunderid_default from "./thunderid.js";
2
2
  import ThunderIDProvider_default from "./ThunderIDProvider.js";
3
- import thunderIDProxy_default from "./proxy/thunderIDProxy.js";
3
+ import thunderIDProxy_default, { removeChunkedCookieFromHeader, replaceChunkedCookieInHeader } from "./proxy/thunderIDProxy.js";
4
4
  import createRouteMatcher_default from "./proxy/createRouteMatcher.js";
5
5
 
6
- export { ThunderIDProvider_default as ThunderIDProvider, createRouteMatcher_default as createRouteMatcher, thunderIDProxy_default as thunderIDProxy, thunderid_default as thunderid };
6
+ export { ThunderIDProvider_default as ThunderIDProvider, createRouteMatcher_default as createRouteMatcher, removeChunkedCookieFromHeader, replaceChunkedCookieInHeader, thunderIDProxy_default as thunderIDProxy, thunderid_default as thunderid };
@@ -23,6 +23,19 @@ export interface ThunderIDProxyContext {
23
23
  }) => Promise<NextResponse | void>;
24
24
  }
25
25
  type ThunderIDProxyHandler = (thunderid: ThunderIDProxyContext, req: NextRequest) => Promise<NextResponse | void> | NextResponse | void;
26
+ /**
27
+ * Removes a cookie from a raw Cookie header string — the unchunked `name`
28
+ * entry and/or any numbered `${name}.0`, `${name}.1`, ... chunk entries.
29
+ */
30
+ export declare const removeChunkedCookieFromHeader: (cookieHeader: string, name: string) => string;
31
+ /**
32
+ * Replaces a cookie's value inside a raw Cookie header string, splitting it
33
+ * across numbered `${name}.0`, `${name}.1`, ... chunk entries once it would
34
+ * exceed the ~4KB per-cookie limit browsers enforce. Any entry the cookie
35
+ * doesn't appear in yet is appended; stale chunk entries a shrunk value no
36
+ * longer needs are dropped.
37
+ */
38
+ export declare const replaceChunkedCookieInHeader: (cookieHeader: string, name: string, value: string) => string;
26
39
  /**
27
40
  * ThunderID proxy that integrates authentication into your Next.js application.
28
41
  * Similar to Clerk's clerkMiddleware pattern.
@@ -1 +1 @@
1
- {"version":3,"file":"thunderIDProxy.d.ts","sourceRoot":"","sources":["../../../src/server/proxy/thunderIDProxy.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,WAAW,EAAE,YAAY,EAAC,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAC,mBAAmB,EAAC,MAAM,qBAAqB,CAAC;AAGxD,OAAuB,EAAC,mBAAmB,EAAC,MAAM,4BAA4B,CAAC;AAG/E,MAAM,MAAM,qBAAqB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAEjE,MAAM,WAAW,qBAAqB;IACpC,4DAA4D;IAC5D,UAAU,EAAE,MAAM,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAAC;IAC3D,kDAAkD;IAClD,YAAY,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACvC,iEAAiE;IACjE,UAAU,EAAE,MAAM,OAAO,CAAC;IAC1B;;;;;;;;OAQG;IACH,YAAY,EAAE,CAAC,YAAY,CAAC,EAAE;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAC,KAAK,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;CACpF;AAED,KAAK,qBAAqB,GAAG,CAC3B,SAAS,EAAE,qBAAqB,EAChC,GAAG,EAAE,WAAW,KACb,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,YAAY,GAAG,IAAI,CAAC;AA4CxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,QAAA,MAAM,cAAc,GAEhB,UAAU,qBAAqB,EAC/B,UAAU,qBAAqB,GAAG,CAAC,CAAC,GAAG,EAAE,WAAW,KAAK,qBAAqB,CAAC,KAC9E,CAAC,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,CAoMlD,CAAC;AAEJ,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"thunderIDProxy.d.ts","sourceRoot":"","sources":["../../../src/server/proxy/thunderIDProxy.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,WAAW,EAAE,YAAY,EAAC,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAC,mBAAmB,EAAC,MAAM,qBAAqB,CAAC;AAUxD,OAAuB,EAAC,mBAAmB,EAAC,MAAM,4BAA4B,CAAC;AAG/E,MAAM,MAAM,qBAAqB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAEjE,MAAM,WAAW,qBAAqB;IACpC,4DAA4D;IAC5D,UAAU,EAAE,MAAM,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAAC;IAC3D,kDAAkD;IAClD,YAAY,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACvC,iEAAiE;IACjE,UAAU,EAAE,MAAM,OAAO,CAAC;IAC1B;;;;;;;;OAQG;IACH,YAAY,EAAE,CAAC,YAAY,CAAC,EAAE;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAC,KAAK,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;CACpF;AAED,KAAK,qBAAqB,GAAG,CAC3B,SAAS,EAAE,qBAAqB,EAChC,GAAG,EAAE,WAAW,KACb,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,YAAY,GAAG,IAAI,CAAC;AAiBxD;;;GAGG;AACH,eAAO,MAAM,6BAA6B,GAAI,cAAc,MAAM,EAAE,MAAM,MAAM,KAAG,MAalF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,GAAI,cAAc,MAAM,EAAE,MAAM,MAAM,EAAE,OAAO,MAAM,KAAG,MAShG,CAAC;AAoBF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,QAAA,MAAM,cAAc,GAEhB,UAAU,qBAAqB,EAC/B,UAAU,qBAAqB,GAAG,CAAC,CAAC,GAAG,EAAE,WAAW,KAAK,qBAAqB,CAAC,KAC9E,CAAC,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,CAkNlD,CAAC;AAEJ,eAAe,cAAc,CAAC"}