@asgardeo/nextjs 0.3.9 → 0.3.11

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 (53) hide show
  1. package/dist/cjs/middleware.js +45 -0
  2. package/dist/cjs/middleware.js.map +7 -0
  3. package/dist/cjs/server/index.js +2 -10
  4. package/dist/cjs/server/index.js.map +2 -2
  5. package/dist/esm/client/contexts/Asgardeo/AsgardeoContext.js +2 -0
  6. package/dist/esm/client/contexts/Asgardeo/AsgardeoContext.js.map +1 -1
  7. package/dist/esm/client/contexts/Asgardeo/AsgardeoProvider.js +3 -1
  8. package/dist/esm/client/contexts/Asgardeo/AsgardeoProvider.js.map +1 -1
  9. package/dist/esm/constants/sessionConstants.js +49 -0
  10. package/dist/esm/constants/sessionConstants.js.map +1 -0
  11. package/dist/esm/middleware.js +35 -0
  12. package/dist/esm/middleware.js.map +1 -0
  13. package/dist/esm/server/AsgardeoProvider.js +4 -2
  14. package/dist/esm/server/AsgardeoProvider.js.map +1 -1
  15. package/dist/esm/server/actions/clearSession.js +49 -0
  16. package/dist/esm/server/actions/clearSession.js.map +1 -0
  17. package/dist/esm/server/actions/getAccessToken.js.map +1 -1
  18. package/dist/esm/server/actions/getSessionId.js.map +1 -1
  19. package/dist/esm/server/actions/getSessionPayload.js.map +1 -1
  20. package/dist/esm/server/actions/handleOAuthCallbackAction.js +6 -3
  21. package/dist/esm/server/actions/handleOAuthCallbackAction.js.map +1 -1
  22. package/dist/esm/server/actions/isSignedIn.js +11 -15
  23. package/dist/esm/server/actions/isSignedIn.js.map +1 -1
  24. package/dist/esm/server/actions/refreshToken.js +86 -0
  25. package/dist/esm/server/actions/refreshToken.js.map +1 -0
  26. package/dist/esm/server/actions/signInAction.js +13 -5
  27. package/dist/esm/server/actions/signInAction.js.map +1 -1
  28. package/dist/esm/server/actions/signOutAction.js.map +1 -1
  29. package/dist/esm/server/actions/switchOrganization.js +8 -9
  30. package/dist/esm/server/actions/switchOrganization.js.map +1 -1
  31. package/dist/esm/server/index.js +0 -3
  32. package/dist/esm/server/index.js.map +1 -1
  33. package/dist/esm/server/middleware/asgardeoMiddleware.js +182 -85
  34. package/dist/esm/server/middleware/asgardeoMiddleware.js.map +1 -1
  35. package/dist/esm/utils/SessionManager.js +54 -7
  36. package/dist/esm/utils/SessionManager.js.map +1 -1
  37. package/dist/esm/utils/decorateConfigWithNextEnv.js +5 -1
  38. package/dist/esm/utils/decorateConfigWithNextEnv.js.map +1 -1
  39. package/dist/esm/utils/handleRefreshToken.js +82 -0
  40. package/dist/esm/utils/handleRefreshToken.js.map +1 -0
  41. package/dist/types/client/contexts/Asgardeo/AsgardeoContext.d.ts +5 -1
  42. package/dist/types/client/contexts/Asgardeo/AsgardeoProvider.d.ts +3 -0
  43. package/dist/types/constants/sessionConstants.d.ts +48 -0
  44. package/dist/types/middleware.d.ts +34 -0
  45. package/dist/types/server/AsgardeoProvider.d.ts +14 -0
  46. package/dist/types/server/actions/clearSession.d.ts +39 -0
  47. package/dist/types/server/actions/isSignedIn.d.ts +8 -3
  48. package/dist/types/server/actions/refreshToken.d.ts +44 -0
  49. package/dist/types/server/index.d.ts +0 -3
  50. package/dist/types/server/middleware/asgardeoMiddleware.d.ts +20 -28
  51. package/dist/types/utils/SessionManager.d.ts +26 -5
  52. package/dist/types/utils/handleRefreshToken.d.ts +46 -0
  53. package/package.json +9 -3
@@ -19,6 +19,7 @@
19
19
  import { generateSessionId, EmbeddedSignInFlowStatus, isEmpty, } from '@asgardeo/node';
20
20
  import { cookies } from 'next/headers';
21
21
  import AsgardeoNextClient from '../../AsgardeoNextClient';
22
+ import logger from '../../utils/logger';
22
23
  import SessionManager from '../../utils/SessionManager';
23
24
  /**
24
25
  * Server action for signing in a user.
@@ -74,13 +75,21 @@ const signInAction = async (payload, request) => {
74
75
  state: response?.authData?.state,
75
76
  }, {}, sessionId);
76
77
  if (signInResult) {
77
- const idToken = await client.getDecodedIdToken(sessionId);
78
+ const idToken = await client.getDecodedIdToken(sessionId, (signInResult['idToken'] || signInResult['id_token']));
78
79
  const userIdFromToken = (idToken['sub'] || signInResult['sub'] || sessionId);
79
80
  const { accessToken } = signInResult;
81
+ const refreshToken = signInResult['refreshToken'] ?? '';
80
82
  const scopes = signInResult['scope'];
81
83
  const organizationId = (idToken['user_org'] || idToken['organization_id']);
82
- const sessionToken = await SessionManager.createSessionToken(accessToken, userIdFromToken, sessionId, scopes, organizationId);
83
- cookieStore.set(SessionManager.getSessionCookieName(), sessionToken, SessionManager.getSessionCookieOptions());
84
+ const rawExpiresIn = signInResult['expiresIn'] ?? signInResult['expires_in'];
85
+ const expiresIn = Number(rawExpiresIn);
86
+ if (Number.isNaN(expiresIn)) {
87
+ throw new Error(`[signInAction] Invalid expiresIn value received: ${rawExpiresIn}`);
88
+ }
89
+ const config = await client.getConfiguration();
90
+ const sessionCookieExpiryTime = SessionManager.resolveSessionCookieExpiry(config.sessionCookieExpiryTime);
91
+ const sessionToken = await SessionManager.createSessionToken(accessToken, userIdFromToken, sessionId, scopes, expiresIn, refreshToken, organizationId);
92
+ cookieStore.set(SessionManager.getSessionCookieName(), sessionToken, SessionManager.getSessionCookieOptions(sessionCookieExpiryTime));
84
93
  cookieStore.delete(SessionManager.getTempSessionCookieName());
85
94
  }
86
95
  const afterSignInUrl = await (await client.getStorageManager()).getConfigDataParameter('afterSignInUrl');
@@ -89,8 +98,7 @@ const signInAction = async (payload, request) => {
89
98
  return { data: response, success: true };
90
99
  }
91
100
  catch (error) {
92
- // eslint-disable-next-line no-console
93
- console.error('[signInAction] Error during sign-in:', error);
101
+ logger.error(`[signInAction] Error during sign-in: ${error instanceof Error ? error.message : String(error)}`);
94
102
  return { error: String(error), success: false };
95
103
  }
96
104
  };
@@ -1 +1 @@
1
- {"version":3,"file":"signInAction.js","sourceRoot":"","sources":["../../../../src/server/actions/signInAction.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"signInAction.js","sourceRoot":"","sources":["../../../../src/server/actions/signInAction.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"signOutAction.js","sourceRoot":"","sources":["../../../../src/server/actions/signOutAction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,YAAY,CAAC;AAGb,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AACrC,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAC1C,OAAO,kBAAkB,MAAM,0BAA0B,CAAC;AAC1D,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,cAAc,MAAM,4BAA4B,CAAC;AAExD;;;;;GAKG;AACH,MAAM,aAAa,GAAG,KAAK,IAAqF,EAAE;IAChH,MAAM,CAAC,KAAK,CAAC,qEAAqE,CAAC,CAAC;IAEpF,MAAM,mBAAmB,GAAG,KAAK,IAAmB,EAAE;QACpD,MAAM,WAAW,GAA2B,MAAM,OAAO,EAAE,CAAC;QAE5D,WAAW,CAAC,MAAM,CAAC,cAAc,CAAC,oBAAoB,EAAE,CAAC,CAAC;QAC1D,WAAW,CAAC,MAAM,CAAC,cAAc,CAAC,wBAAwB,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,MAAM,GAAuB,kBAAkB,CAAC,WAAW,EAAE,CAAC;QACpE,MAAM,SAAS,GAAuB,MAAM,YAAY,EAAE,CAAC;QAE3D,IAAI,eAAe,GAAW,GAAG,CAAC;QAElC,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,CAAC,KAAK,CAAC,2FAA2F,CAAC,CAAC;YAE1G,eAAe,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,mBAAmB,EAAE,CAAC;QAE5B,OAAO,EAAC,IAAI,EAAE,EAAC,eAAe,EAAC,EAAE,OAAO,EAAE,IAAI,EAAC,CAAC;IAClD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,+DAA+D,EAAE,KAAK,CAAC,CAAC;QAErF,MAAM,CAAC,KAAK,CAAC,sEAAsE,CAAC,CAAC;QAErF,MAAM,mBAAmB,EAAE,CAAC;QAE5B,IAAI,YAAqB,CAAC;QAC1B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,YAAY,GAAG,KAAK,CAAC;QACvB,CAAC;aAAM,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAClC,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC;QAC/B,CAAC;aAAM,CAAC;YACN,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC;QAED,OAAO;YACL,KAAK,EAAE,YAAY;YACnB,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAEF,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"signOutAction.js","sourceRoot":"","sources":["../../../../src/server/actions/signOutAction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,YAAY,CAAC;AAEb,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AACrC,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAC1C,OAAO,kBAAkB,MAAM,0BAA0B,CAAC;AAC1D,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,cAAc,MAAM,4BAA4B,CAAC;AAIxD;;;;;GAKG;AACH,MAAM,aAAa,GAAG,KAAK,IAAqF,EAAE;IAChH,MAAM,CAAC,KAAK,CAAC,qEAAqE,CAAC,CAAC;IAEpF,MAAM,mBAAmB,GAAG,KAAK,IAAmB,EAAE;QACpD,MAAM,WAAW,GAAmB,MAAM,OAAO,EAAE,CAAC;QAEpD,WAAW,CAAC,MAAM,CAAC,cAAc,CAAC,oBAAoB,EAAE,CAAC,CAAC;QAC1D,WAAW,CAAC,MAAM,CAAC,cAAc,CAAC,wBAAwB,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,MAAM,GAAuB,kBAAkB,CAAC,WAAW,EAAE,CAAC;QACpE,MAAM,SAAS,GAAuB,MAAM,YAAY,EAAE,CAAC;QAE3D,IAAI,eAAe,GAAW,GAAG,CAAC;QAElC,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,CAAC,KAAK,CAAC,2FAA2F,CAAC,CAAC;YAE1G,eAAe,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,mBAAmB,EAAE,CAAC;QAE5B,OAAO,EAAC,IAAI,EAAE,EAAC,eAAe,EAAC,EAAE,OAAO,EAAE,IAAI,EAAC,CAAC;IAClD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,+DAA+D,EAAE,KAAK,CAAC,CAAC;QAErF,MAAM,CAAC,KAAK,CAAC,sEAAsE,CAAC,CAAC;QAErF,MAAM,mBAAmB,EAAE,CAAC;QAE5B,IAAI,YAAqB,CAAC;QAC1B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,YAAY,GAAG,KAAK,CAAC;QACvB,CAAC;aAAM,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAClC,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC;QAC/B,CAAC;aAAM,CAAC;YACN,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC;QAED,OAAO;YACL,KAAK,EAAE,YAAY;YACnB,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -31,20 +31,19 @@ const switchOrganization = async (organization, sessionId) => {
31
31
  const client = AsgardeoNextClient.getInstance();
32
32
  const resolvedSessionId = sessionId ?? (await getSessionId());
33
33
  const response = await client.switchOrganization(organization, resolvedSessionId);
34
- // After switching organization, we need to refresh the page to get updated session data
35
- // This is because server components don't maintain state between function calls
36
34
  const { revalidatePath } = await import('next/cache');
37
- // Revalidate the current path to refresh the component with new data
38
35
  revalidatePath('/');
39
- if (response) {
40
- const idToken = await client.getDecodedIdToken(resolvedSessionId, response.idToken);
36
+ if (response && response.accessToken) {
37
+ const tokenResponse = response;
38
+ const idToken = await client.getDecodedIdToken(resolvedSessionId, tokenResponse.idToken);
41
39
  const userIdFromToken = idToken['sub'];
42
- const { accessToken } = response;
43
- const scopes = response.scope;
44
40
  const organizationId = (idToken['user_org'] || idToken['organization_id']);
45
- const sessionToken = await SessionManager.createSessionToken(accessToken, userIdFromToken, resolvedSessionId, scopes, organizationId);
41
+ const config = await client.getConfiguration();
42
+ const sessionCookieExpiryTime = SessionManager.resolveSessionCookieExpiry(config.sessionCookieExpiryTime);
43
+ const expiresIn = parseInt(tokenResponse.expiresIn, 10);
44
+ const sessionToken = await SessionManager.createSessionToken(tokenResponse.accessToken, userIdFromToken, resolvedSessionId, tokenResponse.scope, expiresIn, tokenResponse.refreshToken ?? '', organizationId);
46
45
  logger.debug('[switchOrganization] Session token created successfully.');
47
- cookieStore.set(SessionManager.getSessionCookieName(), sessionToken, SessionManager.getSessionCookieOptions());
46
+ cookieStore.set(SessionManager.getSessionCookieName(), sessionToken, SessionManager.getSessionCookieOptions(sessionCookieExpiryTime));
48
47
  }
49
48
  return response;
50
49
  }
@@ -1 +1 @@
1
- {"version":3,"file":"switchOrganization.js","sourceRoot":"","sources":["../../../../src/server/actions/switchOrganization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,YAAY,CAAC;AAEb,OAAO,EAAe,gBAAgB,EAAyB,MAAM,gBAAgB,CAAC;AAEtF,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AACrC,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAC1C,OAAO,kBAAkB,MAAM,0BAA0B,CAAC;AAC1D,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,cAAc,MAAM,4BAA4B,CAAC;AAExD;;GAEG;AACH,MAAM,kBAAkB,GAAG,KAAK,EAC9B,YAA0B,EAC1B,SAA6B,EACM,EAAE;IACrC,IAAI,CAAC;QACH,MAAM,WAAW,GAA2B,MAAM,OAAO,EAAE,CAAC;QAC5D,MAAM,MAAM,GAAuB,kBAAkB,CAAC,WAAW,EAAE,CAAC;QACpE,MAAM,iBAAiB,GAAW,SAAS,IAAK,CAAC,MAAM,YAAY,EAAE,CAAY,CAAC;QAClF,MAAM,QAAQ,GAA6B,MAAM,MAAM,CAAC,kBAAkB,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC;QAE5G,wFAAwF;QACxF,gFAAgF;QAChF,MAAM,EAAC,cAAc,EAAC,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAEpD,qEAAqE;QACrE,cAAc,CAAC,GAAG,CAAC,CAAC;QAEpB,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,OAAO,GAAY,MAAM,MAAM,CAAC,iBAAiB,CAAC,iBAAiB,EAAG,QAA0B,CAAC,OAAO,CAAC,CAAC;YAChH,MAAM,eAAe,GAAW,OAAO,CAAC,KAAK,CAAW,CAAC;YACzD,MAAM,EAAC,WAAW,EAAC,GAA0B,QAAyB,CAAC;YACvE,MAAM,MAAM,GAAY,QAA0B,CAAC,KAAK,CAAC;YACzD,MAAM,cAAc,GAAuB,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAEhF,CAAC;YAEd,MAAM,YAAY,GAAW,MAAM,cAAc,CAAC,kBAAkB,CAClE,WAAW,EACX,eAAyB,EACzB,iBAA2B,EAC3B,MAAM,EACN,cAAc,CACf,CAAC;YAEF,MAAM,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;YAEzE,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC,oBAAoB,EAAE,EAAE,YAAY,EAAE,cAAc,CAAC,uBAAuB,EAAE,CAAC,CAAC;QACjH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,gBAAgB,CACxB,uCAAuC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAC/G,0CAA0C,EAC1C,QAAQ,EACR,KAAK,YAAY,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CACjE,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"switchOrganization.js","sourceRoot":"","sources":["../../../../src/server/actions/switchOrganization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,YAAY,CAAC;AAEb,OAAO,EAAe,gBAAgB,EAAyB,MAAM,gBAAgB,CAAC;AACtF,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AACrC,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAC1C,OAAO,kBAAkB,MAAM,0BAA0B,CAAC;AAE1D,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,cAAc,MAAM,4BAA4B,CAAC;AAIxD;;GAEG;AACH,MAAM,kBAAkB,GAAG,KAAK,EAC9B,YAA0B,EAC1B,SAA6B,EACM,EAAE;IACrC,IAAI,CAAC;QACH,MAAM,WAAW,GAAmB,MAAM,OAAO,EAAE,CAAC;QACpD,MAAM,MAAM,GAAuB,kBAAkB,CAAC,WAAW,EAAE,CAAC;QACpE,MAAM,iBAAiB,GAAW,SAAS,IAAK,CAAC,MAAM,YAAY,EAAE,CAAY,CAAC;QAClF,MAAM,QAAQ,GAA6B,MAAM,MAAM,CAAC,kBAAkB,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC;QAE5G,MAAM,EAAC,cAAc,EAAC,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QACpD,cAAc,CAAC,GAAG,CAAC,CAAC;QAEpB,IAAI,QAAQ,IAAK,QAA0B,CAAC,WAAW,EAAE,CAAC;YACxD,MAAM,aAAa,GAAkB,QAAyB,CAAC;YAC/D,MAAM,OAAO,GAAY,MAAM,MAAM,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;YAClG,MAAM,eAAe,GAAW,OAAO,CAAC,KAAK,CAAW,CAAC;YACzD,MAAM,cAAc,GAAuB,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAEhF,CAAC;YACd,MAAM,MAAM,GAAuB,MAAM,MAAM,CAAC,gBAAgB,EAAE,CAAC;YACnE,MAAM,uBAAuB,GAAW,cAAc,CAAC,0BAA0B,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC;YAClH,MAAM,SAAS,GAAW,QAAQ,CAAC,aAAa,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YAEhE,MAAM,YAAY,GAAW,MAAM,cAAc,CAAC,kBAAkB,CAClE,aAAa,CAAC,WAAW,EACzB,eAAe,EACf,iBAAiB,EACjB,aAAa,CAAC,KAAK,EACnB,SAAS,EACT,aAAa,CAAC,YAAY,IAAI,EAAE,EAChC,cAAc,CACf,CAAC;YAEF,MAAM,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;YAEzE,WAAW,CAAC,GAAG,CACb,cAAc,CAAC,oBAAoB,EAAE,EACrC,YAAY,EACZ,cAAc,CAAC,uBAAuB,CAAC,uBAAuB,CAAC,CAChE,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,gBAAgB,CACxB,uCAAuC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAC/G,0CAA0C,EAC1C,QAAQ,EACR,KAAK,YAAY,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CACjE,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -19,7 +19,4 @@
19
19
  export { default as asgardeo } from './asgardeo';
20
20
  export { default as AsgardeoProvider } from './AsgardeoProvider.js';
21
21
  export * from './AsgardeoProvider.js';
22
- export { default as asgardeoMiddleware } from './middleware/asgardeoMiddleware';
23
- export * from './middleware/asgardeoMiddleware';
24
- export { default as createRouteMatcher } from './middleware/createRouteMatcher';
25
22
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,mCAAmC;AAEnC,OAAO,EAAC,OAAO,IAAI,QAAQ,EAAC,MAAM,YAAY,CAAC;AAE/C,OAAO,EAAC,OAAO,IAAI,gBAAgB,EAAC,MAAM,uBAAuB,CAAC;AAClE,cAAc,uBAAuB,CAAC;AAEtC,OAAO,EAAC,OAAO,IAAI,kBAAkB,EAAC,MAAM,iCAAiC,CAAC;AAC9E,cAAc,iCAAiC,CAAC;AAEhD,OAAO,EAAC,OAAO,IAAI,kBAAkB,EAAC,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,mCAAmC;AAEnC,OAAO,EAAC,OAAO,IAAI,QAAQ,EAAC,MAAM,YAAY,CAAC;AAE/C,OAAO,EAAC,OAAO,IAAI,gBAAgB,EAAC,MAAM,uBAAuB,CAAC;AAClE,cAAc,uBAAuB,CAAC"}
@@ -16,44 +16,79 @@
16
16
  * under the License.
17
17
  */
18
18
  import { NextResponse } from 'next/server';
19
+ import { REFRESH_BUFFER_SECONDS } from '../../constants/sessionConstants';
20
+ import decorateConfigWithNextEnv from '../../utils/decorateConfigWithNextEnv';
21
+ import handleRefreshToken from '../../utils/handleRefreshToken';
19
22
  import SessionManager from '../../utils/SessionManager';
20
- import { hasValidSession as hasValidJWTSession, getSessionFromRequest, getSessionIdFromRequest, } from '../../utils/sessionUtils';
23
+ import { getSessionFromRequest, getSessionIdFromRequest } from '../../utils/sessionUtils';
21
24
  /**
22
- * Enhanced session validation that checks both JWT and legacy sessions
23
- *
24
- * @param request - The Next.js request object
25
- * @returns True if a valid session exists, false otherwise
25
+ * Removes a named cookie from a raw Cookie header string.
26
26
  */
27
- const hasValidSession = async (request) => {
28
- try {
29
- return await hasValidJWTSession(request);
30
- }
31
- catch {
32
- return Promise.resolve(false);
33
- }
34
- };
27
+ const removeCookieFromHeader = (cookieHeader, name) => cookieHeader
28
+ .split(';')
29
+ .map((p) => p.trim())
30
+ .filter((p) => {
31
+ const eqIdx = p.indexOf('=');
32
+ const partName = eqIdx === -1 ? p : p.slice(0, eqIdx).trim();
33
+ return partName !== name;
34
+ })
35
+ .join('; ');
35
36
  /**
36
- * Gets the session ID from the request cookies.
37
- * Supports both JWT and legacy session formats.
38
- *
39
- * @param request - The Next.js request object
40
- * @returns The session ID if it exists, undefined otherwise
37
+ * Replaces the value of a named cookie inside a raw Cookie header string.
38
+ * If the cookie does not already appear in the header it is appended.
41
39
  */
42
- const getSessionIdFromRequestMiddleware = async (request) => getSessionIdFromRequest(request);
40
+ const replaceCookieInHeader = (cookieHeader, name, value) => {
41
+ const parts = cookieHeader
42
+ .split(';')
43
+ .map((p) => p.trim())
44
+ .filter(Boolean);
45
+ let found = false;
46
+ const updated = parts.map((part) => {
47
+ const eqIdx = part.indexOf('=');
48
+ const partName = eqIdx === -1 ? part : part.slice(0, eqIdx).trim();
49
+ if (partName === name) {
50
+ found = true;
51
+ return `${name}=${value}`;
52
+ }
53
+ return part;
54
+ });
55
+ if (!found) {
56
+ updated.push(`${name}=${value}`);
57
+ }
58
+ return updated.join('; ');
59
+ };
43
60
  /**
44
61
  * Asgardeo middleware that integrates authentication into your Next.js application.
45
62
  * Similar to Clerk's clerkMiddleware pattern.
46
63
  *
64
+ * Proactively refreshes the access token when it is within REFRESH_BUFFER_SECONDS of
65
+ * expiry so that Server Components always receive a fresh session. The refresh also
66
+ * recovers expired tokens as long as a refresh token is present.
67
+ *
68
+ * The updated session cookie is written to:
69
+ * - The response → browser stores the new cookie for subsequent requests.
70
+ * - The forwarded request headers → the same-request Server Component render sees
71
+ * the fresh token immediately without waiting for the next navigation.
72
+ *
73
+ * Token refresh requires baseUrl, clientId, and clientSecret. These are resolved from
74
+ * the options argument first, then from the standard Asgardeo environment variables
75
+ * (NEXT_PUBLIC_ASGARDEO_BASE_URL, NEXT_PUBLIC_ASGARDEO_CLIENT_ID,
76
+ * ASGARDEO_CLIENT_SECRET). If none are available the refresh step is skipped silently.
77
+ *
47
78
  * @param handler - Optional handler function to customize middleware behavior
48
79
  * @param options - Configuration options for the middleware
49
80
  * @returns Next.js middleware function
50
81
  *
51
82
  * @example
52
83
  * ```typescript
53
- * // middleware.ts - Basic usage
84
+ * // middleware.ts - Basic usage (config read from env vars automatically)
54
85
  * import { asgardeoMiddleware } from '@asgardeo/nextjs';
55
86
  *
56
87
  * export default asgardeoMiddleware();
88
+ *
89
+ * export const config = {
90
+ * matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
91
+ * };
57
92
  * ```
58
93
  *
59
94
  * @example
@@ -69,82 +104,111 @@ const getSessionIdFromRequestMiddleware = async (request) => getSessionIdFromReq
69
104
  * }
70
105
  * });
71
106
  * ```
72
- *
73
- * @example
74
- * ```typescript
75
- * // Advanced usage with custom logic
76
- * import { asgardeoMiddleware, createRouteMatcher } from '@asgardeo/nextjs';
77
- *
78
- * const isProtectedRoute = createRouteMatcher(['/dashboard(.*)']);
79
- * const isAuthRoute = createRouteMatcher(['/sign-in', '/sign-up']);
80
- *
81
- * export default asgardeoMiddleware(async (asgardeo, req) => {
82
- * // Skip protection for auth routes
83
- * if (isAuthRoute(req)) return;
84
- *
85
- * // Protect specified routes
86
- * if (isProtectedRoute(req)) {
87
- * await asgardeo.protectRoute({ redirect: '/sign-in' });
88
- * }
89
- *
90
- * // Check authentication status
91
- * if (asgardeo.isSignedIn()) {
92
- * console.log('User is authenticated with session:', asgardeo.getSessionId());
93
- * }
94
- * }, {
95
- * defaultRedirect: '/sign-in'
96
- * });
97
- * ```
98
107
  */
99
108
  const asgardeoMiddleware = (handler, options) => async (request) => {
100
109
  const resolvedOptions = typeof options === 'function' ? options(request) : options || {};
110
+ // Resolve full config from passed options + environment variable fallbacks.
111
+ const resolvedConfig = decorateConfigWithNextEnv(resolvedOptions);
112
+ // ── OAuth callback detection ──────────────────────────────────────────────
101
113
  const url = new URL(request.url);
102
114
  const hasCallbackParams = url.searchParams.has('code') && url.searchParams.has('state');
103
115
  let isValidOAuthCallback = false;
104
- if (hasCallbackParams) {
105
- // OAuth callbacks should not contain error parameters that indicate failed auth
106
- const hasError = url.searchParams.has('error');
107
- if (!hasError) {
108
- // Validate that there's a temporary session that initiated this OAuth flow
109
- const tempSessionToken = request.cookies.get(SessionManager.getTempSessionCookieName())?.value;
110
- if (tempSessionToken) {
111
- try {
112
- // Verify the temporary session exists and is valid
113
- await SessionManager.verifyTempSession(tempSessionToken);
114
- isValidOAuthCallback = true;
115
- }
116
- catch {
117
- // Invalid temp session - this is not a legitimate OAuth callback
118
- isValidOAuthCallback = false;
119
- }
116
+ if (hasCallbackParams && !url.searchParams.has('error')) {
117
+ const tempSessionToken = request.cookies.get(SessionManager.getTempSessionCookieName())?.value;
118
+ if (tempSessionToken) {
119
+ try {
120
+ await SessionManager.verifyTempSession(tempSessionToken);
121
+ isValidOAuthCallback = true;
122
+ }
123
+ catch {
124
+ isValidOAuthCallback = false;
120
125
  }
121
126
  }
122
127
  }
123
- const sessionId = await getSessionIdFromRequestMiddleware(request);
124
- const isAuthenticated = await hasValidSession(request);
125
- const asgardeo = {
126
- getSession: async () => {
128
+ // ── Session resolution ────────────────────────────────────────────────────
129
+ // Step 1: Attempt to get a fully verified (signature + expiry) session.
130
+ const verifiedSession = await getSessionFromRequest(request);
131
+ // Step 2: If no verified session exists, verify the raw cookie's signature
132
+ // without enforcing expiry. This allows the middleware to recover from an
133
+ // expired access token as long as the JWT is authentic and a refresh token
134
+ // is present. Skipping the signature check here would let a tampered cookie
135
+ // drive identity-confusion attacks since handleRefreshToken reuses `sub`,
136
+ // `sessionId`, and `organizationId` from the input payload when minting the
137
+ // new session JWT.
138
+ let expiredSession;
139
+ if (!verifiedSession) {
140
+ const rawToken = request.cookies.get(SessionManager.getSessionCookieName())?.value;
141
+ if (rawToken) {
127
142
  try {
128
- return await getSessionFromRequest(request);
143
+ const decoded = await SessionManager.verifySessionTokenForRefresh(rawToken);
144
+ if (decoded.refreshToken) {
145
+ expiredSession = decoded;
146
+ }
129
147
  }
130
148
  catch {
131
- return undefined;
149
+ // Forged, tampered, wrong type, or malformed — ignore.
132
150
  }
133
- },
151
+ }
152
+ }
153
+ // ── Token refresh ─────────────────────────────────────────────────────────
154
+ const now = Math.floor(Date.now() / 1000);
155
+ const candidateSession = verifiedSession ?? expiredSession;
156
+ // Config is required to call the token endpoint.
157
+ const hasRefreshConfig = !!(resolvedConfig.baseUrl &&
158
+ resolvedConfig.clientId &&
159
+ resolvedConfig.clientSecret);
160
+ // Refresh when:
161
+ // a) Token is verified but within the proactive buffer window, OR
162
+ // b) Token has already expired but a refresh token is available.
163
+ const needsRefresh = !isValidOAuthCallback &&
164
+ hasRefreshConfig &&
165
+ !!candidateSession?.refreshToken &&
166
+ ((!!verifiedSession && verifiedSession.exp <= now + REFRESH_BUFFER_SECONDS) || !!expiredSession);
167
+ let activeSession = verifiedSession;
168
+ let refreshCookieUpdate;
169
+ if (needsRefresh && candidateSession) {
170
+ try {
171
+ const { newSessionToken, sessionCookieExpiryTime } = await handleRefreshToken(candidateSession, {
172
+ baseUrl: resolvedConfig.baseUrl,
173
+ clientId: resolvedConfig.clientId,
174
+ clientSecret: resolvedConfig.clientSecret,
175
+ sessionCookieExpiryTime: resolvedConfig.sessionCookieExpiryTime,
176
+ });
177
+ // Verify the newly minted token so activeSession reflects fresh claims.
178
+ activeSession = await SessionManager.verifySessionToken(newSessionToken);
179
+ refreshCookieUpdate = { expiry: sessionCookieExpiryTime, token: newSessionToken };
180
+ }
181
+ catch {
182
+ // Refresh failed — clear the irrecoverable session.
183
+ activeSession = undefined;
184
+ }
185
+ }
186
+ // ── Session cleanup detection ─────────────────────────────────────────────
187
+ // Mark stale cookies for deletion when the session is irrecoverable. Skipped
188
+ // during OAuth callbacks where a session cookie may not exist yet.
189
+ const rawSessionCookie = request.cookies.get(SessionManager.getSessionCookieName())?.value;
190
+ let shouldClearCookie = false;
191
+ if (!isValidOAuthCallback && rawSessionCookie && !activeSession && !refreshCookieUpdate) {
192
+ // A cookie was present but all resolution paths (verify, decode, refresh)
193
+ // failed — the session is dead and cannot be recovered.
194
+ shouldClearCookie = true;
195
+ }
196
+ const sessionId = activeSession?.sessionId ?? (await getSessionIdFromRequest(request));
197
+ const isAuthenticated = !!activeSession;
198
+ // ── Middleware context ────────────────────────────────────────────────────
199
+ const asgardeo = {
200
+ getSession: async () => activeSession,
134
201
  getSessionId: () => sessionId,
135
202
  isSignedIn: () => isAuthenticated,
136
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
137
203
  protectRoute: async (routeOptions) => {
138
- // Skip protection if this is a validated OAuth callback - let the callback handler process it first
139
- // This prevents race conditions where middleware redirects before OAuth callback completes
204
+ // Skip during a valid OAuth callback to avoid redirecting before the
205
+ // callback action has had a chance to complete.
140
206
  if (isValidOAuthCallback) {
141
207
  return undefined;
142
208
  }
143
209
  if (!isAuthenticated) {
144
210
  const referer = request.headers.get('referer');
145
- // TODO: Make this configurable or call the signIn() from here.
146
211
  let fallbackRedirect = '/';
147
- // If referer exists and is from the same origin, use it as fallback
148
212
  if (referer) {
149
213
  try {
150
214
  const refererUrl = new URL(referer);
@@ -153,25 +217,58 @@ const asgardeoMiddleware = (handler, options) => async (request) => {
153
217
  fallbackRedirect = refererUrl.pathname + refererUrl.search;
154
218
  }
155
219
  }
156
- catch (error) {
157
- // Invalid referer URL, ignore it
220
+ catch {
221
+ // Invalid referer ignore.
158
222
  }
159
223
  }
160
- // Fallback chain: options.redirect -> resolvedOptions.signInUrl -> resolvedOptions.defaultRedirect -> referer (same origin only)
161
- const redirectUrl = resolvedOptions?.signInUrl || fallbackRedirect;
162
- const signInUrl = new URL(redirectUrl, request.url);
163
- return NextResponse.redirect(signInUrl);
224
+ const redirectUrl = routeOptions?.redirect ?? resolvedConfig.signInUrl ?? fallbackRedirect;
225
+ return NextResponse.redirect(new URL(redirectUrl, request.url));
164
226
  }
165
227
  return undefined;
166
228
  },
167
229
  };
168
- if (handler) {
169
- const result = await handler(asgardeo, request);
170
- if (result) {
171
- return result;
230
+ // ── Handler ───────────────────────────────────────────────────────────────
231
+ const handlerResponse = handler ? await handler(asgardeo, request) : undefined;
232
+ // ── Build final response ──────────────────────────────────────────────────
233
+ if (shouldClearCookie) {
234
+ const cookieName = SessionManager.getSessionCookieName();
235
+ if (handlerResponse) {
236
+ // Handler returned a response (e.g. a redirect from protectRoute).
237
+ // Attach the deletion so the browser discards the stale cookie.
238
+ handlerResponse.cookies.delete(cookieName);
239
+ return handlerResponse;
172
240
  }
241
+ // Pass-through: strip the dead cookie from the forwarded request headers
242
+ // so the same-request Server Component render sees no session at all.
243
+ const requestHeaders = new Headers(request.headers);
244
+ requestHeaders.set('cookie', removeCookieFromHeader(request.headers.get('cookie') ?? '', cookieName));
245
+ const cleanResponse = NextResponse.next({ request: { headers: requestHeaders } });
246
+ cleanResponse.cookies.delete(cookieName);
247
+ return cleanResponse;
248
+ }
249
+ if (!refreshCookieUpdate) {
250
+ return handlerResponse ?? NextResponse.next();
251
+ }
252
+ // A token refresh occurred — the new session cookie must be applied to:
253
+ // 1. The HTTP response so the browser stores the updated cookie.
254
+ // 2. The forwarded request headers so the same-request Server Component
255
+ // render reads the fresh session token instead of the expired one.
256
+ const cookieName = SessionManager.getSessionCookieName();
257
+ const cookieOptions = SessionManager.getSessionCookieOptions(refreshCookieUpdate.expiry);
258
+ if (handlerResponse) {
259
+ // Handler returned a response (e.g. a redirect from protectRoute).
260
+ // Attach the refresh cookie so the browser receives it even on redirects.
261
+ handlerResponse.cookies.set(cookieName, refreshCookieUpdate.token, cookieOptions);
262
+ return handlerResponse;
173
263
  }
174
- return NextResponse.next();
264
+ // Default pass-through: update both the response cookie and the request
265
+ // Cookie header so the downstream Server Component render is not stale.
266
+ const requestHeaders = new Headers(request.headers);
267
+ const updatedCookieHeader = replaceCookieInHeader(request.headers.get('cookie') ?? '', cookieName, refreshCookieUpdate.token);
268
+ requestHeaders.set('cookie', updatedCookieHeader);
269
+ const response = NextResponse.next({ request: { headers: requestHeaders } });
270
+ response.cookies.set(cookieName, refreshCookieUpdate.token, cookieOptions);
271
+ return response;
175
272
  };
176
273
  export default asgardeoMiddleware;
177
274
  //# sourceMappingURL=asgardeoMiddleware.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"asgardeoMiddleware.js","sourceRoot":"","sources":["../../../../src/server/middleware/asgardeoMiddleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAc,YAAY,EAAC,MAAM,aAAa,CAAC;AAEtD,OAAO,cAAqC,MAAM,4BAA4B,CAAC;AAC/E,OAAO,EACL,eAAe,IAAI,kBAAkB,EACrC,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AA4BlC;;;;;GAKG;AACH,MAAM,eAAe,GAAG,KAAK,EAAE,OAAoB,EAAoB,EAAE;IACvE,IAAI,CAAC;QACH,OAAO,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;AACH,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,iCAAiC,GAAG,KAAK,EAAE,OAAoB,EAA+B,EAAE,CACpG,uBAAuB,CAAC,OAAO,CAAC,CAAC;AAEnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,MAAM,kBAAkB,GACtB,CACE,OAAmC,EACnC,OAAuF,EACpC,EAAE,CACvD,KAAK,EAAE,OAAoB,EAAyB,EAAE;IACpD,MAAM,eAAe,GAA8B,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC;IAEpH,MAAM,GAAG,GAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,iBAAiB,GAAY,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAEjG,IAAI,oBAAoB,GAAY,KAAK,CAAC;IAC1C,IAAI,iBAAiB,EAAE,CAAC;QACtB,gFAAgF;QAChF,MAAM,QAAQ,GAAY,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAExD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,2EAA2E;YAC3E,MAAM,gBAAgB,GAAuB,OAAO,CAAC,OAAO,CAAC,GAAG,CAC9D,cAAc,CAAC,wBAAwB,EAAE,CAC1C,EAAE,KAAK,CAAC;YACT,IAAI,gBAAgB,EAAE,CAAC;gBACrB,IAAI,CAAC;oBACH,mDAAmD;oBACnD,MAAM,cAAc,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;oBACzD,oBAAoB,GAAG,IAAI,CAAC;gBAC9B,CAAC;gBAAC,MAAM,CAAC;oBACP,iEAAiE;oBACjE,oBAAoB,GAAG,KAAK,CAAC;gBAC/B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAuB,MAAM,iCAAiC,CAAC,OAAO,CAAC,CAAC;IACvF,MAAM,eAAe,GAAY,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC;IAEhE,MAAM,QAAQ,GAA8B;QAC1C,UAAU,EAAE,KAAK,IAA8C,EAAE;YAC/D,IAAI,CAAC;gBACH,OAAO,MAAM,qBAAqB,CAAC,OAAO,CAAC,CAAC;YAC9C,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,SAAS,CAAC;YACnB,CAAC;QACH,CAAC;QACD,YAAY,EAAE,GAAuB,EAAE,CAAC,SAAS;QACjD,UAAU,EAAE,GAAY,EAAE,CAAC,eAAe;QAC1C,6DAA6D;QAC7D,YAAY,EAAE,KAAK,EAAE,YAAkC,EAAgC,EAAE;YACvF,oGAAoG;YACpG,2FAA2F;YAC3F,IAAI,oBAAoB,EAAE,CAAC;gBACzB,OAAO,SAAS,CAAC;YACnB,CAAC;YAED,IAAI,CAAC,eAAe,EAAE,CAAC;gBACrB,MAAM,OAAO,GAAkB,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAC9D,+DAA+D;gBAC/D,IAAI,gBAAgB,GAAW,GAAG,CAAC;gBAEnC,oEAAoE;gBACpE,IAAI,OAAO,EAAE,CAAC;oBACZ,IAAI,CAAC;wBACH,MAAM,UAAU,GAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;wBACzC,MAAM,UAAU,GAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;wBAE7C,IAAI,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC,MAAM,EAAE,CAAC;4BAC5C,gBAAgB,GAAG,UAAU,CAAC,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC;wBAC7D,CAAC;oBACH,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,iCAAiC;oBACnC,CAAC;gBACH,CAAC;gBAED,iIAAiI;gBACjI,MAAM,WAAW,GAAY,eAAe,EAAE,SAAoB,IAAI,gBAAgB,CAAC;gBAEvF,MAAM,SAAS,GAAQ,IAAI,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;gBAEzD,OAAO,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YAC1C,CAAC;YAED,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC;IAEF,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,MAAM,GAAwB,MAAM,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACrE,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IAED,OAAO,YAAY,CAAC,IAAI,EAAE,CAAC;AAC7B,CAAC,CAAC;AAEJ,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"asgardeoMiddleware.js","sourceRoot":"","sources":["../../../../src/server/middleware/asgardeoMiddleware.ts"],"names":[],"mappings":"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"}
@@ -16,12 +16,12 @@
16
16
  * under the License.
17
17
  */
18
18
  import { AsgardeoRuntimeError, CookieConfig } from '@asgardeo/node';
19
- import { SignJWT, jwtVerify } from 'jose';
19
+ import { SignJWT, jwtVerify, compactVerify } from 'jose';
20
+ import { DEFAULT_SESSION_COOKIE_EXPIRY_TIME } from '../constants/sessionConstants';
20
21
  /**
21
22
  * Session management utility class for JWT-based session cookies
22
23
  */
23
24
  class SessionManager {
24
- static DEFAULT_EXPIRY_SECONDS = 3600;
25
25
  /**
26
26
  * Get the signing secret from environment variable
27
27
  * Throws error in production if not set
@@ -55,13 +55,32 @@ class SessionManager {
55
55
  return jwt;
56
56
  }
57
57
  /**
58
- * Create a session cookie with user information
58
+ * Resolve the session cookie expiry time in seconds.
59
+ *
60
+ * Resolution order (first defined value wins):
61
+ * 1. `configuredExpiry` — value from `AsgardeoNodeConfig.sessionCookieExpiryTime`
62
+ * 2. `ASGARDEO_SESSION_COOKIE_EXPIRY_TIME` environment variable
63
+ * 3. `DEFAULT_SESSION_COOKIE_EXPIRY_TIME` (24 hours)
59
64
  */
60
- static async createSessionToken(accessToken, userId, sessionId, scopes, organizationId, expirySeconds = this.DEFAULT_EXPIRY_SECONDS) {
65
+ static resolveSessionCookieExpiry(configuredExpiry) {
66
+ if (configuredExpiry != null && configuredExpiry > 0) {
67
+ return configuredExpiry;
68
+ }
69
+ const envValue = process.env['ASGARDEO_SESSION_COOKIE_EXPIRY_TIME'];
70
+ if (envValue) {
71
+ const parsed = parseInt(envValue, 10);
72
+ if (!Number.isNaN(parsed) && parsed > 0) {
73
+ return parsed;
74
+ }
75
+ }
76
+ return DEFAULT_SESSION_COOKIE_EXPIRY_TIME;
77
+ }
78
+ static async createSessionToken(accessToken, userId, sessionId, scopes, accessTokenTtlSeconds, refreshToken, organizationId) {
61
79
  const secret = this.getSecret();
62
80
  const jwt = await new SignJWT({
63
81
  accessToken,
64
82
  organizationId,
83
+ refreshToken,
65
84
  scopes,
66
85
  sessionId,
67
86
  type: 'session',
@@ -69,7 +88,7 @@ class SessionManager {
69
88
  .setProtectedHeader({ alg: 'HS256' })
70
89
  .setSubject(userId)
71
90
  .setIssuedAt()
72
- .setExpirationTime(Date.now() / 1000 + expirySeconds)
91
+ .setExpirationTime(Math.floor(Date.now() / 1000) + accessTokenTtlSeconds)
73
92
  .sign(secret);
74
93
  return jwt;
75
94
  }
@@ -80,12 +99,40 @@ class SessionManager {
80
99
  try {
81
100
  const secret = this.getSecret();
82
101
  const { payload } = await jwtVerify(token, secret);
102
+ if (payload['type'] !== 'session') {
103
+ throw new Error('Invalid token type');
104
+ }
83
105
  return payload;
84
106
  }
85
107
  catch (error) {
86
108
  throw new AsgardeoRuntimeError(`Invalid session token: ${error instanceof Error ? error.message : 'Unknown error'}`, 'invalid-session-token', 'nextjs', 'Session token verification failed');
87
109
  }
88
110
  }
111
+ /**
112
+ * Verify a session token for refresh. Validates the HMAC signature and the
113
+ * `type === 'session'` discriminant but intentionally skips the `exp` check
114
+ * so an expired access token can still be exchanged for a new one.
115
+ *
116
+ * Session lifetime is still bounded — the cookie's `maxAge` is set from
117
+ * `sessionCookieExpiryTime`, so the browser drops an over-age session regardless
118
+ * of the access-token exp embedded in the JWT.
119
+ *
120
+ * Never use the returned payload for authorization.
121
+ */
122
+ static async verifySessionTokenForRefresh(token) {
123
+ try {
124
+ const secret = this.getSecret();
125
+ const { payload: rawPayload } = await compactVerify(token, secret);
126
+ const payload = JSON.parse(new TextDecoder().decode(rawPayload));
127
+ if (payload.type !== 'session') {
128
+ throw new Error('Invalid token type');
129
+ }
130
+ return payload;
131
+ }
132
+ catch (error) {
133
+ throw new AsgardeoRuntimeError(`Invalid session token: ${error instanceof Error ? error.message : 'Unknown error'}`, 'invalid-session-token-for-refresh', 'nextjs', 'Session token signature or type check failed during refresh');
134
+ }
135
+ }
89
136
  /**
90
137
  * Verify and decode a temporary session token
91
138
  */
@@ -105,10 +152,10 @@ class SessionManager {
105
152
  /**
106
153
  * Get session cookie options
107
154
  */
108
- static getSessionCookieOptions() {
155
+ static getSessionCookieOptions(maxAge) {
109
156
  return {
110
157
  httpOnly: true,
111
- maxAge: this.DEFAULT_EXPIRY_SECONDS,
158
+ maxAge,
112
159
  path: '/',
113
160
  sameSite: 'lax',
114
161
  secure: process.env['NODE_ENV'] === 'production',