@tern-secure/nextjs 5.1.8 → 5.1.9

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 (329) hide show
  1. package/dist/cjs/__tests__/gemini_fnTernSecureNextHandler.bench.js +31 -0
  2. package/dist/cjs/__tests__/gemini_fnTernSecureNextHandler.bench.js.map +1 -0
  3. package/dist/cjs/app-router/admin/actions.js +62 -0
  4. package/dist/cjs/app-router/admin/actions.js.map +1 -0
  5. package/dist/cjs/app-router/admin/constants.js +29 -0
  6. package/dist/cjs/app-router/admin/constants.js.map +1 -0
  7. package/dist/cjs/app-router/admin/fnValidators.js +295 -0
  8. package/dist/cjs/app-router/admin/fnValidators.js.map +1 -0
  9. package/dist/cjs/app-router/admin/index.js +16 -3
  10. package/dist/cjs/app-router/admin/index.js.map +1 -1
  11. package/dist/cjs/app-router/admin/responses.js +120 -0
  12. package/dist/cjs/app-router/admin/responses.js.map +1 -0
  13. package/dist/cjs/app-router/admin/sessionHandlers.js +167 -0
  14. package/dist/cjs/app-router/admin/sessionHandlers.js.map +1 -0
  15. package/dist/cjs/app-router/admin/ternsecureNextjsHandler.js +84 -0
  16. package/dist/cjs/app-router/admin/ternsecureNextjsHandler.js.map +1 -0
  17. package/dist/cjs/app-router/admin/types.js +127 -0
  18. package/dist/cjs/app-router/admin/types.js.map +1 -0
  19. package/dist/cjs/app-router/admin/utils.js +107 -0
  20. package/dist/cjs/app-router/admin/utils.js.map +1 -0
  21. package/dist/cjs/app-router/admin/validators.js +217 -0
  22. package/dist/cjs/app-router/admin/validators.js.map +1 -0
  23. package/dist/cjs/app-router/client/TernSecureProvider.js +2 -6
  24. package/dist/cjs/app-router/client/TernSecureProvider.js.map +1 -1
  25. package/dist/cjs/app-router/server/auth.js +100 -0
  26. package/dist/cjs/app-router/server/auth.js.map +1 -0
  27. package/dist/cjs/app-router/server/utils.js +87 -0
  28. package/dist/cjs/app-router/server/utils.js.map +1 -0
  29. package/dist/cjs/boundary/components.js +4 -7
  30. package/dist/cjs/boundary/components.js.map +1 -1
  31. package/dist/cjs/{components/uiComponents.js → constants.js} +17 -18
  32. package/dist/cjs/constants.js.map +1 -0
  33. package/dist/cjs/errors.js.map +1 -1
  34. package/dist/cjs/index.js +4 -9
  35. package/dist/cjs/index.js.map +1 -1
  36. package/dist/cjs/server/constant.js +38 -0
  37. package/dist/cjs/server/constant.js.map +1 -0
  38. package/dist/cjs/server/edge-session.js +118 -24
  39. package/dist/cjs/server/edge-session.js.map +1 -1
  40. package/dist/cjs/server/headers-utils.js +70 -0
  41. package/dist/cjs/server/headers-utils.js.map +1 -0
  42. package/dist/cjs/server/index.js +8 -6
  43. package/dist/cjs/server/index.js.map +1 -1
  44. package/dist/cjs/server/jwt-edge.js +47 -19
  45. package/dist/cjs/server/jwt-edge.js.map +1 -1
  46. package/dist/cjs/server/jwt.js +11 -4
  47. package/dist/cjs/server/jwt.js.map +1 -1
  48. package/dist/cjs/server/nextErrors.js +131 -0
  49. package/dist/cjs/server/nextErrors.js.map +1 -0
  50. package/dist/cjs/server/nextFetcher.js +31 -0
  51. package/dist/cjs/server/nextFetcher.js.map +1 -0
  52. package/dist/cjs/server/node/SessionTernSecure.js +55 -0
  53. package/dist/cjs/server/node/SessionTernSecure.js.map +1 -0
  54. package/dist/cjs/server/{auth.js → node/auth.js} +11 -20
  55. package/dist/cjs/server/node/auth.js.map +1 -0
  56. package/dist/cjs/server/node/index.js +40 -0
  57. package/dist/cjs/server/node/index.js.map +1 -0
  58. package/dist/cjs/server/node/node-session.js +60 -0
  59. package/dist/cjs/server/node/node-session.js.map +1 -0
  60. package/dist/cjs/server/node/ternSecureNodeMiddleware.js +182 -0
  61. package/dist/cjs/server/node/ternSecureNodeMiddleware.js.map +1 -0
  62. package/dist/cjs/server/protect.js +90 -0
  63. package/dist/cjs/server/protect.js.map +1 -0
  64. package/dist/cjs/server/redirect.js +84 -0
  65. package/dist/cjs/server/redirect.js.map +1 -0
  66. package/dist/cjs/server/routeMatcher.js +36 -0
  67. package/dist/cjs/server/routeMatcher.js.map +1 -0
  68. package/dist/cjs/server/sdk-versions.js +43 -0
  69. package/dist/cjs/server/sdk-versions.js.map +1 -0
  70. package/dist/cjs/server/session-store.js.map +1 -1
  71. package/dist/cjs/server/ternSecureEdgeMiddleware.js +298 -0
  72. package/dist/cjs/server/ternSecureEdgeMiddleware.js.map +1 -0
  73. package/dist/cjs/server/ternSecureFireMiddleware.js +192 -0
  74. package/dist/cjs/server/ternSecureFireMiddleware.js.map +1 -0
  75. package/dist/cjs/server/types.js.map +1 -1
  76. package/dist/cjs/server/utils.js +115 -2
  77. package/dist/cjs/server/utils.js.map +1 -1
  78. package/dist/cjs/types.js.map +1 -1
  79. package/dist/cjs/utils/NextCookieAdapter.js +44 -0
  80. package/dist/cjs/utils/NextCookieAdapter.js.map +1 -0
  81. package/dist/cjs/utils/allNextProviderProps.js +10 -24
  82. package/dist/cjs/utils/allNextProviderProps.js.map +1 -1
  83. package/dist/cjs/utils/config.js +38 -2
  84. package/dist/cjs/utils/config.js.map +1 -1
  85. package/dist/cjs/utils/construct.js.map +1 -1
  86. package/dist/cjs/utils/fireconfig.js +38 -0
  87. package/dist/cjs/utils/fireconfig.js.map +1 -0
  88. package/dist/cjs/utils/logger.js +101 -0
  89. package/dist/cjs/utils/logger.js.map +1 -0
  90. package/dist/cjs/utils/redis.js +33 -0
  91. package/dist/cjs/utils/redis.js.map +1 -0
  92. package/dist/cjs/utils/response.js +38 -0
  93. package/dist/cjs/utils/response.js.map +1 -0
  94. package/dist/cjs/utils/serverRedirectAuth.js +39 -0
  95. package/dist/cjs/utils/serverRedirectAuth.js.map +1 -0
  96. package/dist/cjs/utils/ternsecure-sw.js +1 -1
  97. package/dist/cjs/utils/ternsecure-sw.js.map +1 -1
  98. package/dist/cjs/utils/withLogger.js +82 -0
  99. package/dist/cjs/utils/withLogger.js.map +1 -0
  100. package/dist/esm/__tests__/gemini_fnTernSecureNextHandler.bench.js +30 -0
  101. package/dist/esm/__tests__/gemini_fnTernSecureNextHandler.bench.js.map +1 -0
  102. package/dist/esm/app-router/admin/actions.js +40 -0
  103. package/dist/esm/app-router/admin/actions.js.map +1 -0
  104. package/dist/esm/app-router/admin/constants.js +5 -0
  105. package/dist/esm/app-router/admin/constants.js.map +1 -0
  106. package/dist/esm/app-router/admin/fnValidators.js +270 -0
  107. package/dist/esm/app-router/admin/fnValidators.js.map +1 -0
  108. package/dist/esm/app-router/admin/index.js +16 -2
  109. package/dist/esm/app-router/admin/index.js.map +1 -1
  110. package/dist/esm/app-router/admin/responses.js +93 -0
  111. package/dist/esm/app-router/admin/responses.js.map +1 -0
  112. package/dist/esm/app-router/admin/sessionHandlers.js +131 -0
  113. package/dist/esm/app-router/admin/sessionHandlers.js.map +1 -0
  114. package/dist/esm/app-router/admin/ternsecureNextjsHandler.js +62 -0
  115. package/dist/esm/app-router/admin/ternsecureNextjsHandler.js.map +1 -0
  116. package/dist/esm/app-router/admin/types.js +98 -0
  117. package/dist/esm/app-router/admin/types.js.map +1 -0
  118. package/dist/esm/app-router/admin/utils.js +80 -0
  119. package/dist/esm/app-router/admin/utils.js.map +1 -0
  120. package/dist/esm/app-router/admin/validators.js +189 -0
  121. package/dist/esm/app-router/admin/validators.js.map +1 -0
  122. package/dist/esm/app-router/client/TernSecureProvider.js +2 -6
  123. package/dist/esm/app-router/client/TernSecureProvider.js.map +1 -1
  124. package/dist/esm/app-router/server/auth.js +81 -0
  125. package/dist/esm/app-router/server/auth.js.map +1 -0
  126. package/dist/esm/app-router/server/utils.js +51 -0
  127. package/dist/esm/app-router/server/utils.js.map +1 -0
  128. package/dist/esm/boundary/components.js +4 -7
  129. package/dist/esm/boundary/components.js.map +1 -1
  130. package/dist/esm/constants.js +17 -0
  131. package/dist/esm/constants.js.map +1 -0
  132. package/dist/esm/errors.js.map +1 -1
  133. package/dist/esm/index.js +5 -11
  134. package/dist/esm/index.js.map +1 -1
  135. package/dist/esm/server/constant.js +11 -0
  136. package/dist/esm/server/constant.js.map +1 -0
  137. package/dist/esm/server/edge-session.js +113 -22
  138. package/dist/esm/server/edge-session.js.map +1 -1
  139. package/dist/esm/server/headers-utils.js +41 -0
  140. package/dist/esm/server/headers-utils.js.map +1 -0
  141. package/dist/esm/server/index.js +9 -3
  142. package/dist/esm/server/index.js.map +1 -1
  143. package/dist/esm/server/jwt-edge.js +48 -20
  144. package/dist/esm/server/jwt-edge.js.map +1 -1
  145. package/dist/esm/server/jwt.js +12 -5
  146. package/dist/esm/server/jwt.js.map +1 -1
  147. package/dist/esm/server/nextErrors.js +97 -0
  148. package/dist/esm/server/nextErrors.js.map +1 -0
  149. package/dist/esm/server/nextFetcher.js +7 -0
  150. package/dist/esm/server/nextFetcher.js.map +1 -0
  151. package/dist/esm/server/node/SessionTernSecure.js +31 -0
  152. package/dist/esm/server/node/SessionTernSecure.js.map +1 -0
  153. package/dist/esm/server/{auth.js → node/auth.js} +11 -20
  154. package/dist/esm/server/node/auth.js.map +1 -0
  155. package/dist/esm/server/node/index.js +19 -0
  156. package/dist/esm/server/node/index.js.map +1 -0
  157. package/dist/esm/server/node/node-session.js +36 -0
  158. package/dist/esm/server/node/node-session.js.map +1 -0
  159. package/dist/esm/server/node/ternSecureNodeMiddleware.js +165 -0
  160. package/dist/esm/server/node/ternSecureNodeMiddleware.js.map +1 -0
  161. package/dist/esm/server/protect.js +66 -0
  162. package/dist/esm/server/protect.js.map +1 -0
  163. package/dist/esm/server/redirect.js +60 -0
  164. package/dist/esm/server/redirect.js.map +1 -0
  165. package/dist/esm/server/routeMatcher.js +12 -0
  166. package/dist/esm/server/routeMatcher.js.map +1 -0
  167. package/dist/esm/server/sdk-versions.js +8 -0
  168. package/dist/esm/server/sdk-versions.js.map +1 -0
  169. package/dist/esm/server/session-store.js.map +1 -1
  170. package/dist/esm/server/ternSecureEdgeMiddleware.js +286 -0
  171. package/dist/esm/server/ternSecureEdgeMiddleware.js.map +1 -0
  172. package/dist/esm/server/ternSecureFireMiddleware.js +179 -0
  173. package/dist/esm/server/ternSecureFireMiddleware.js.map +1 -0
  174. package/dist/esm/server/utils.js +99 -1
  175. package/dist/esm/server/utils.js.map +1 -1
  176. package/dist/esm/types.js.map +1 -1
  177. package/dist/esm/utils/NextCookieAdapter.js +20 -0
  178. package/dist/esm/utils/NextCookieAdapter.js.map +1 -0
  179. package/dist/esm/utils/allNextProviderProps.js +10 -24
  180. package/dist/esm/utils/allNextProviderProps.js.map +1 -1
  181. package/dist/esm/utils/config.js +34 -1
  182. package/dist/esm/utils/config.js.map +1 -1
  183. package/dist/esm/utils/construct.js +1 -1
  184. package/dist/esm/utils/construct.js.map +1 -1
  185. package/dist/esm/utils/fireconfig.js +14 -0
  186. package/dist/esm/utils/fireconfig.js.map +1 -0
  187. package/dist/esm/utils/logger.js +74 -0
  188. package/dist/esm/utils/logger.js.map +1 -0
  189. package/dist/esm/utils/redis.js +9 -0
  190. package/dist/esm/utils/redis.js.map +1 -0
  191. package/dist/esm/utils/response.js +13 -0
  192. package/dist/esm/utils/response.js.map +1 -0
  193. package/dist/esm/utils/serverRedirectAuth.js +17 -0
  194. package/dist/esm/utils/serverRedirectAuth.js.map +1 -0
  195. package/dist/esm/utils/ternsecure-sw.js +1 -1
  196. package/dist/esm/utils/ternsecure-sw.js.map +1 -1
  197. package/dist/esm/utils/withLogger.js +57 -0
  198. package/dist/esm/utils/withLogger.js.map +1 -0
  199. package/dist/types/app-router/admin/actions.d.ts +19 -0
  200. package/dist/types/app-router/admin/actions.d.ts.map +1 -0
  201. package/dist/types/app-router/admin/constants.d.ts +2 -0
  202. package/dist/types/app-router/admin/constants.d.ts.map +1 -0
  203. package/dist/types/app-router/admin/fnValidators.d.ts +35 -0
  204. package/dist/types/app-router/admin/fnValidators.d.ts.map +1 -0
  205. package/dist/types/app-router/admin/index.d.ts +3 -1
  206. package/dist/types/app-router/admin/index.d.ts.map +1 -1
  207. package/dist/types/app-router/admin/responses.d.ts +28 -0
  208. package/dist/types/app-router/admin/responses.d.ts.map +1 -0
  209. package/dist/types/app-router/admin/sessionHandlers.d.ts +26 -0
  210. package/dist/types/app-router/admin/sessionHandlers.d.ts.map +1 -0
  211. package/dist/types/app-router/admin/ternsecureNextjsHandler.d.ts +7 -0
  212. package/dist/types/app-router/admin/ternsecureNextjsHandler.d.ts.map +1 -0
  213. package/dist/types/app-router/admin/types.d.ts +105 -0
  214. package/dist/types/app-router/admin/types.d.ts.map +1 -0
  215. package/dist/types/app-router/admin/utils.d.ts +53 -0
  216. package/dist/types/app-router/admin/utils.d.ts.map +1 -0
  217. package/dist/types/app-router/admin/validators.d.ts +46 -0
  218. package/dist/types/app-router/admin/validators.d.ts.map +1 -0
  219. package/dist/types/app-router/client/TernSecureProvider.d.ts.map +1 -1
  220. package/dist/types/app-router/server/auth.d.ts +26 -0
  221. package/dist/types/app-router/server/auth.d.ts.map +1 -0
  222. package/dist/types/app-router/server/utils.d.ts +5 -0
  223. package/dist/types/app-router/server/utils.d.ts.map +1 -0
  224. package/dist/types/boundary/components.d.ts +1 -1
  225. package/dist/types/boundary/components.d.ts.map +1 -1
  226. package/dist/types/constants.d.ts +11 -0
  227. package/dist/types/constants.d.ts.map +1 -0
  228. package/dist/types/errors.d.ts +1 -1
  229. package/dist/types/errors.d.ts.map +1 -1
  230. package/dist/types/index.d.ts +3 -3
  231. package/dist/types/index.d.ts.map +1 -1
  232. package/dist/types/server/constant.d.ts +5 -0
  233. package/dist/types/server/constant.d.ts.map +1 -0
  234. package/dist/types/server/edge-session.d.ts +13 -1
  235. package/dist/types/server/edge-session.d.ts.map +1 -1
  236. package/dist/types/server/headers-utils.d.ts +10 -0
  237. package/dist/types/server/headers-utils.d.ts.map +1 -0
  238. package/dist/types/server/index.d.ts +6 -3
  239. package/dist/types/server/index.d.ts.map +1 -1
  240. package/dist/types/server/jwt-edge.d.ts +12 -18
  241. package/dist/types/server/jwt-edge.d.ts.map +1 -1
  242. package/dist/types/server/jwt.d.ts +12 -18
  243. package/dist/types/server/jwt.d.ts.map +1 -1
  244. package/dist/types/server/nextErrors.d.ts +54 -0
  245. package/dist/types/server/nextErrors.d.ts.map +1 -0
  246. package/dist/types/server/nextFetcher.d.ts +26 -0
  247. package/dist/types/server/nextFetcher.d.ts.map +1 -0
  248. package/dist/types/server/node/SessionTernSecure.d.ts +3 -0
  249. package/dist/types/server/node/SessionTernSecure.d.ts.map +1 -0
  250. package/dist/types/server/{auth.d.ts → node/auth.d.ts} +5 -5
  251. package/dist/types/server/node/auth.d.ts.map +1 -0
  252. package/dist/types/server/node/index.d.ts +3 -0
  253. package/dist/types/server/node/index.d.ts.map +1 -0
  254. package/dist/types/server/node/node-session.d.ts +4 -0
  255. package/dist/types/server/node/node-session.d.ts.map +1 -0
  256. package/dist/types/server/node/ternSecureNodeMiddleware.d.ts +54 -0
  257. package/dist/types/server/node/ternSecureNodeMiddleware.d.ts.map +1 -0
  258. package/dist/types/server/protect.d.ts +26 -0
  259. package/dist/types/server/protect.d.ts.map +1 -0
  260. package/dist/types/server/redirect.d.ts +20 -0
  261. package/dist/types/server/redirect.d.ts.map +1 -0
  262. package/dist/types/server/routeMatcher.d.ts +13 -0
  263. package/dist/types/server/routeMatcher.d.ts.map +1 -0
  264. package/dist/types/server/sdk-versions.d.ts +8 -0
  265. package/dist/types/server/sdk-versions.d.ts.map +1 -0
  266. package/dist/types/server/session-store.d.ts.map +1 -1
  267. package/dist/types/server/ternSecureEdgeMiddleware.d.ts +47 -0
  268. package/dist/types/server/ternSecureEdgeMiddleware.d.ts.map +1 -0
  269. package/dist/types/server/ternSecureFireMiddleware.d.ts +47 -0
  270. package/dist/types/server/ternSecureFireMiddleware.d.ts.map +1 -0
  271. package/dist/types/server/types.d.ts +16 -2
  272. package/dist/types/server/types.d.ts.map +1 -1
  273. package/dist/types/server/utils.d.ts +7 -0
  274. package/dist/types/server/utils.d.ts.map +1 -1
  275. package/dist/types/types.d.ts +33 -1
  276. package/dist/types/types.d.ts.map +1 -1
  277. package/dist/types/utils/NextCookieAdapter.d.ts +9 -0
  278. package/dist/types/utils/NextCookieAdapter.d.ts.map +1 -0
  279. package/dist/types/utils/allNextProviderProps.d.ts +1 -1
  280. package/dist/types/utils/allNextProviderProps.d.ts.map +1 -1
  281. package/dist/types/utils/config.d.ts +17 -1
  282. package/dist/types/utils/config.d.ts.map +1 -1
  283. package/dist/types/utils/fireconfig.d.ts +4 -0
  284. package/dist/types/utils/fireconfig.d.ts.map +1 -0
  285. package/dist/types/utils/logger.d.ts +27 -0
  286. package/dist/types/utils/logger.d.ts.map +1 -0
  287. package/dist/types/utils/redis.d.ts +8 -0
  288. package/dist/types/utils/redis.d.ts.map +1 -0
  289. package/dist/types/utils/response.d.ts +3 -0
  290. package/dist/types/utils/response.d.ts.map +1 -0
  291. package/dist/types/utils/serverRedirectAuth.d.ts +6 -0
  292. package/dist/types/utils/serverRedirectAuth.d.ts.map +1 -0
  293. package/dist/types/utils/withLogger.d.ts +17 -0
  294. package/dist/types/utils/withLogger.d.ts.map +1 -0
  295. package/package.json +21 -7
  296. package/server/node/package.json +5 -0
  297. package/server/package.json +5 -0
  298. package/dist/cjs/app-router/admin/sessionHandler.js +0 -74
  299. package/dist/cjs/app-router/admin/sessionHandler.js.map +0 -1
  300. package/dist/cjs/app-router/client/actions.js +0 -4
  301. package/dist/cjs/app-router/client/actions.js.map +0 -1
  302. package/dist/cjs/components/uiComponents.js.map +0 -1
  303. package/dist/cjs/server/auth.js.map +0 -1
  304. package/dist/cjs/server/ternSecureMiddleware.js +0 -95
  305. package/dist/cjs/server/ternSecureMiddleware.js.map +0 -1
  306. package/dist/cjs/utils/tern-ui-script.js +0 -78
  307. package/dist/cjs/utils/tern-ui-script.js.map +0 -1
  308. package/dist/esm/app-router/admin/sessionHandler.js +0 -50
  309. package/dist/esm/app-router/admin/sessionHandler.js.map +0 -1
  310. package/dist/esm/app-router/client/actions.js +0 -3
  311. package/dist/esm/app-router/client/actions.js.map +0 -1
  312. package/dist/esm/components/uiComponents.js +0 -21
  313. package/dist/esm/components/uiComponents.js.map +0 -1
  314. package/dist/esm/server/auth.js.map +0 -1
  315. package/dist/esm/server/ternSecureMiddleware.js +0 -69
  316. package/dist/esm/server/ternSecureMiddleware.js.map +0 -1
  317. package/dist/esm/utils/tern-ui-script.js +0 -44
  318. package/dist/esm/utils/tern-ui-script.js.map +0 -1
  319. package/dist/types/app-router/admin/sessionHandler.d.ts +0 -3
  320. package/dist/types/app-router/admin/sessionHandler.d.ts.map +0 -1
  321. package/dist/types/app-router/client/actions.d.ts +0 -2
  322. package/dist/types/app-router/client/actions.d.ts.map +0 -1
  323. package/dist/types/components/uiComponents.d.ts +0 -6
  324. package/dist/types/components/uiComponents.d.ts.map +0 -1
  325. package/dist/types/server/auth.d.ts.map +0 -1
  326. package/dist/types/server/ternSecureMiddleware.d.ts +0 -20
  327. package/dist/types/server/ternSecureMiddleware.d.ts.map +0 -1
  328. package/dist/types/utils/tern-ui-script.d.ts +0 -9
  329. package/dist/types/utils/tern-ui-script.d.ts.map +0 -1
@@ -0,0 +1,270 @@
1
+ import { NextResponse } from "next/server";
2
+ import { createApiErrorResponse } from "./responses";
3
+ function createRequestContext(request) {
4
+ const url = new URL(request.url);
5
+ const pathSegments = url.pathname.split("/").filter(Boolean);
6
+ return {
7
+ request,
8
+ origin: request.headers.get("origin"),
9
+ host: request.headers.get("host"),
10
+ referer: request.headers.get("referer"),
11
+ userAgent: request.headers.get("user-agent") || "",
12
+ method: request.method,
13
+ pathSegments
14
+ };
15
+ }
16
+ function createValidators(context) {
17
+ const { request, origin, host, referer, userAgent, method, pathSegments } = context;
18
+ async function validateCors(corsOptions) {
19
+ if (corsOptions.skipSameOrigin) {
20
+ if (!origin || host && origin.includes(host)) {
21
+ return null;
22
+ }
23
+ }
24
+ if (corsOptions.allowedOrigins !== "*") {
25
+ const isAllowed = corsOptions.allowedOrigins.some((allowedOrigin) => {
26
+ if (allowedOrigin.startsWith("*")) {
27
+ const domain = allowedOrigin.slice(1);
28
+ return origin?.endsWith(domain);
29
+ }
30
+ return origin === allowedOrigin;
31
+ });
32
+ if (!isAllowed) {
33
+ return createApiErrorResponse("CORS_ORIGIN_NOT_ALLOWED", "Origin not allowed", 403);
34
+ }
35
+ }
36
+ return null;
37
+ }
38
+ function createCorsOptionsResponse(corsOptions) {
39
+ const response = new NextResponse(null, { status: 204 });
40
+ if (corsOptions.allowedOrigins === "*") {
41
+ response.headers.set("Access-Control-Allow-Origin", "*");
42
+ } else {
43
+ response.headers.set("Access-Control-Allow-Origin", corsOptions.allowedOrigins.join(","));
44
+ }
45
+ response.headers.set(
46
+ "Access-Control-Allow-Methods",
47
+ corsOptions.allowedMethods?.join(",") || "GET,POST"
48
+ );
49
+ response.headers.set(
50
+ "Access-Control-Allow-Headers",
51
+ corsOptions.allowedHeaders?.join(",") || "Content-Type,Authorization"
52
+ );
53
+ if (corsOptions.allowCredentials) {
54
+ response.headers.set("Access-Control-Allow-Credentials", "true");
55
+ }
56
+ if (corsOptions.maxAge) {
57
+ response.headers.set("Access-Control-Max-Age", corsOptions.maxAge.toString());
58
+ }
59
+ return response;
60
+ }
61
+ async function validateSecurity(securityOptions) {
62
+ const csrfResult = validateCsrf(securityOptions);
63
+ if (csrfResult) return csrfResult;
64
+ const headersResult = validateRequiredHeaders(securityOptions);
65
+ if (headersResult) return headersResult;
66
+ const userAgentResult = validateUserAgent(securityOptions);
67
+ if (userAgentResult) return userAgentResult;
68
+ return null;
69
+ }
70
+ function validateCsrf(securityOptions) {
71
+ if (securityOptions.requireCSRF && origin && host && !origin.includes(host)) {
72
+ const hasCSRFHeader = request.headers.get("x-requested-with") === "XMLHttpRequest";
73
+ const hasValidReferer = referer && host && referer.includes(host);
74
+ if (!hasCSRFHeader && !hasValidReferer) {
75
+ const isAllowedReferer = securityOptions.allowedReferers?.some(
76
+ (allowedRef) => referer?.includes(allowedRef)
77
+ );
78
+ if (!isAllowedReferer) {
79
+ return createApiErrorResponse("CSRF_PROTECTION", "Access denied", 403);
80
+ }
81
+ }
82
+ }
83
+ return null;
84
+ }
85
+ function validateRequiredHeaders(securityOptions) {
86
+ if (securityOptions.requiredHeaders) {
87
+ for (const [headerName, expectedValue] of Object.entries(securityOptions.requiredHeaders)) {
88
+ const actualValue = request.headers.get(headerName);
89
+ if (actualValue !== expectedValue) {
90
+ return createApiErrorResponse(
91
+ "INVALID_HEADERS",
92
+ "Required header missing or invalid",
93
+ 400
94
+ );
95
+ }
96
+ }
97
+ }
98
+ return null;
99
+ }
100
+ function validateUserAgent(securityOptions) {
101
+ if (securityOptions.userAgent?.block?.length) {
102
+ const isBlocked = securityOptions.userAgent.block.some(
103
+ (blocked) => userAgent.toLowerCase().includes(blocked.toLowerCase())
104
+ );
105
+ if (isBlocked) {
106
+ return createApiErrorResponse("USER_AGENT_BLOCKED", "Access denied", 403);
107
+ }
108
+ }
109
+ if (securityOptions.userAgent?.allow?.length) {
110
+ const isAllowed = securityOptions.userAgent.allow.some(
111
+ (allowed) => userAgent.toLowerCase().includes(allowed.toLowerCase())
112
+ );
113
+ if (!isAllowed) {
114
+ return createApiErrorResponse("USER_AGENT_NOT_ALLOWED", "Access denied", 403);
115
+ }
116
+ }
117
+ return null;
118
+ }
119
+ function validateCsrfToken(csrfToken, csrfCookieValue) {
120
+ if (!csrfToken) {
121
+ return createApiErrorResponse("INVALID_CSRF_TOKEN", "CSRF token is required", 400);
122
+ }
123
+ if (!csrfCookieValue) {
124
+ return createApiErrorResponse("CSRF_COOKIE_MISSING", "CSRF token cookie not found", 403);
125
+ }
126
+ if (csrfToken !== csrfCookieValue) {
127
+ return createApiErrorResponse("CSRF_TOKEN_MISMATCH", "CSRF token mismatch", 403);
128
+ }
129
+ return null;
130
+ }
131
+ function validatePathStructure() {
132
+ if (pathSegments.length < 3) {
133
+ return createApiErrorResponse(
134
+ "INVALID_ROUTE",
135
+ "Invalid route structure. Expected: /api/auth/{endpoint}",
136
+ 404
137
+ );
138
+ }
139
+ return null;
140
+ }
141
+ function validateEndpoint(_endpoint, endpointConfig) {
142
+ if (!endpointConfig || !endpointConfig.enabled) {
143
+ return createApiErrorResponse("ENDPOINT_NOT_FOUND", "Endpoint not found", 404);
144
+ }
145
+ if (method !== "OPTIONS" && !endpointConfig.methods.includes(method)) {
146
+ return createApiErrorResponse("METHOD_NOT_ALLOWED", "Method not allowed", 405);
147
+ }
148
+ return null;
149
+ }
150
+ function validateSubEndpoint(subEndpoint, subEndpointConfig) {
151
+ if (!subEndpoint) {
152
+ return createApiErrorResponse("SUB_ENDPOINT_REQUIRED", "Session sub-endpoint required", 400);
153
+ }
154
+ if (!subEndpointConfig || !subEndpointConfig.enabled) {
155
+ return createApiErrorResponse("ENDPOINT_NOT_FOUND", "Endpoint not found", 404);
156
+ }
157
+ if (!subEndpointConfig.methods?.includes(method)) {
158
+ return createApiErrorResponse("METHOD_NOT_ALLOWED", "Method not allowed", 405);
159
+ }
160
+ return null;
161
+ }
162
+ async function validateSessionRequest() {
163
+ try {
164
+ const body = await request.json();
165
+ return { body, idToken: body.idToken, csrfToken: body.csrfToken };
166
+ } catch (error) {
167
+ return {
168
+ body: null,
169
+ error: createApiErrorResponse("INVALID_REQUEST_FORMAT", "Invalid request format", 400)
170
+ };
171
+ }
172
+ }
173
+ function validateIdToken(idToken) {
174
+ if (!idToken) {
175
+ return createApiErrorResponse(
176
+ "INVALID_TOKEN",
177
+ "ID token is required for creating session",
178
+ 400
179
+ );
180
+ }
181
+ return null;
182
+ }
183
+ async function validateRequest(config) {
184
+ if (method === "OPTIONS" && config.cors) {
185
+ return {
186
+ isValid: true,
187
+ corsResponse: createCorsOptionsResponse(config.cors)
188
+ };
189
+ }
190
+ const pathError = validatePathStructure();
191
+ if (pathError) {
192
+ return { isValid: false, error: pathError };
193
+ }
194
+ if (config.cors) {
195
+ const corsError = await validateCors(config.cors);
196
+ if (corsError) {
197
+ return { isValid: false, error: corsError };
198
+ }
199
+ }
200
+ if (config.security) {
201
+ const securityError = await validateSecurity(config.security);
202
+ if (securityError) {
203
+ return { isValid: false, error: securityError };
204
+ }
205
+ }
206
+ if (config.endpoint) {
207
+ const endpointError = validateEndpoint(config.endpoint.name, config.endpoint.config);
208
+ if (endpointError) {
209
+ return { isValid: false, error: endpointError };
210
+ }
211
+ }
212
+ if (config.subEndpoint) {
213
+ const subEndpointError = validateSubEndpoint(
214
+ config.subEndpoint.name,
215
+ config.subEndpoint.config
216
+ );
217
+ if (subEndpointError) {
218
+ return { isValid: false, error: subEndpointError };
219
+ }
220
+ }
221
+ let sessionData;
222
+ if (method === "POST" && (config.requireIdToken || config.requireCsrfToken)) {
223
+ const sessionResult = await validateSessionRequest();
224
+ if (sessionResult.error) {
225
+ return { isValid: false, error: sessionResult.error };
226
+ }
227
+ sessionData = sessionResult;
228
+ if (config.requireIdToken) {
229
+ const idTokenError = validateIdToken(sessionData.idToken);
230
+ if (idTokenError) {
231
+ return { isValid: false, error: idTokenError };
232
+ }
233
+ }
234
+ if (config.requireCsrfToken && sessionData.csrfToken) {
235
+ const csrfCookieValue = request.cookies.get("csrfToken")?.value;
236
+ const csrfError = validateCsrfToken(sessionData.csrfToken, csrfCookieValue);
237
+ if (csrfError) {
238
+ return { isValid: false, error: csrfError };
239
+ }
240
+ }
241
+ }
242
+ return {
243
+ isValid: true,
244
+ sessionData
245
+ };
246
+ }
247
+ function createValidationConfig(overrides = {}) {
248
+ return {
249
+ ...overrides
250
+ };
251
+ }
252
+ return {
253
+ createValidationConfig,
254
+ validateRequest,
255
+ validateCors,
256
+ validateSecurity,
257
+ validatePathStructure,
258
+ validateEndpoint,
259
+ validateSubEndpoint,
260
+ validateSessionRequest,
261
+ validateIdToken,
262
+ validateCsrfToken,
263
+ createCorsOptionsResponse
264
+ };
265
+ }
266
+ export {
267
+ createRequestContext,
268
+ createValidators
269
+ };
270
+ //# sourceMappingURL=fnValidators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/app-router/admin/fnValidators.ts"],"sourcesContent":["import { type NextRequest, NextResponse } from 'next/server';\n\nimport { createApiErrorResponse } from './responses';\nimport type {\n AuthEndpoint,\n ComprehensiveValidationResult,\n CorsOptions,\n EndpointConfig,\n SecurityOptions,\n SessionSubEndpoint,\n ValidationConfig,\n} from './types';\n\nexport interface RequestContext {\n request: NextRequest;\n origin: string | null;\n host: string | null;\n referer: string | null;\n userAgent: string;\n method: string;\n pathSegments: string[];\n}\n\nexport function createRequestContext(request: NextRequest): RequestContext {\n const url = new URL(request.url);\n const pathSegments = url.pathname.split('/').filter(Boolean);\n\n return {\n request,\n origin: request.headers.get('origin'),\n host: request.headers.get('host'),\n referer: request.headers.get('referer'),\n userAgent: request.headers.get('user-agent') || '',\n method: request.method,\n pathSegments,\n };\n}\n\n/**\n * Main validators factory function\n * Returns an object containing all validator functions and utilities\n */\nexport function createValidators(context: RequestContext) {\n const { request, origin, host, referer, userAgent, method, pathSegments } = context;\n\n async function validateCors(corsOptions: CorsOptions): Promise<NextResponse | null> {\n if (corsOptions.skipSameOrigin) {\n if (!origin || (host && origin.includes(host))) {\n return null;\n }\n }\n\n if (corsOptions.allowedOrigins !== '*') {\n const isAllowed = corsOptions.allowedOrigins.some(allowedOrigin => {\n if (allowedOrigin.startsWith('*')) {\n const domain = allowedOrigin.slice(1);\n return origin?.endsWith(domain);\n }\n return origin === allowedOrigin;\n });\n\n if (!isAllowed) {\n return createApiErrorResponse('CORS_ORIGIN_NOT_ALLOWED', 'Origin not allowed', 403);\n }\n }\n\n return null;\n }\n\n function createCorsOptionsResponse(corsOptions: CorsOptions): NextResponse {\n const response = new NextResponse(null, { status: 204 });\n\n if (corsOptions.allowedOrigins === '*') {\n response.headers.set('Access-Control-Allow-Origin', '*');\n } else {\n response.headers.set('Access-Control-Allow-Origin', corsOptions.allowedOrigins.join(','));\n }\n\n response.headers.set(\n 'Access-Control-Allow-Methods',\n corsOptions.allowedMethods?.join(',') || 'GET,POST',\n );\n response.headers.set(\n 'Access-Control-Allow-Headers',\n corsOptions.allowedHeaders?.join(',') || 'Content-Type,Authorization',\n );\n\n if (corsOptions.allowCredentials) {\n response.headers.set('Access-Control-Allow-Credentials', 'true');\n }\n\n if (corsOptions.maxAge) {\n response.headers.set('Access-Control-Max-Age', corsOptions.maxAge.toString());\n }\n\n return response;\n }\n\n async function validateSecurity(securityOptions: SecurityOptions): Promise<NextResponse | null> {\n const csrfResult = validateCsrf(securityOptions);\n if (csrfResult) return csrfResult;\n\n const headersResult = validateRequiredHeaders(securityOptions);\n if (headersResult) return headersResult;\n\n const userAgentResult = validateUserAgent(securityOptions);\n if (userAgentResult) return userAgentResult;\n\n return null;\n }\n\n function validateCsrf(securityOptions: SecurityOptions): NextResponse | null {\n if (securityOptions.requireCSRF && origin && host && !origin.includes(host)) {\n const hasCSRFHeader = request.headers.get('x-requested-with') === 'XMLHttpRequest';\n const hasValidReferer = referer && host && referer.includes(host);\n\n if (!hasCSRFHeader && !hasValidReferer) {\n const isAllowedReferer = securityOptions.allowedReferers?.some((allowedRef: string) =>\n referer?.includes(allowedRef),\n );\n\n if (!isAllowedReferer) {\n return createApiErrorResponse('CSRF_PROTECTION', 'Access denied', 403);\n }\n }\n }\n return null;\n }\n\n function validateRequiredHeaders(securityOptions: SecurityOptions): NextResponse | null {\n if (securityOptions.requiredHeaders) {\n for (const [headerName, expectedValue] of Object.entries(securityOptions.requiredHeaders)) {\n const actualValue = request.headers.get(headerName);\n if (actualValue !== expectedValue) {\n return createApiErrorResponse(\n 'INVALID_HEADERS',\n 'Required header missing or invalid',\n 400,\n );\n }\n }\n }\n return null;\n }\n\n function validateUserAgent(securityOptions: SecurityOptions): NextResponse | null {\n if (securityOptions.userAgent?.block?.length) {\n const isBlocked = securityOptions.userAgent.block.some((blocked: string) =>\n userAgent.toLowerCase().includes(blocked.toLowerCase()),\n );\n\n if (isBlocked) {\n return createApiErrorResponse('USER_AGENT_BLOCKED', 'Access denied', 403);\n }\n }\n\n if (securityOptions.userAgent?.allow?.length) {\n const isAllowed = securityOptions.userAgent.allow.some((allowed: string) =>\n userAgent.toLowerCase().includes(allowed.toLowerCase()),\n );\n\n if (!isAllowed) {\n return createApiErrorResponse('USER_AGENT_NOT_ALLOWED', 'Access denied', 403);\n }\n }\n\n return null;\n }\n\n function validateCsrfToken(\n csrfToken: string,\n csrfCookieValue: string | undefined,\n ): NextResponse | null {\n if (!csrfToken) {\n return createApiErrorResponse('INVALID_CSRF_TOKEN', 'CSRF token is required', 400);\n }\n\n if (!csrfCookieValue) {\n return createApiErrorResponse('CSRF_COOKIE_MISSING', 'CSRF token cookie not found', 403);\n }\n\n if (csrfToken !== csrfCookieValue) {\n return createApiErrorResponse('CSRF_TOKEN_MISMATCH', 'CSRF token mismatch', 403);\n }\n\n return null;\n }\n\n function validatePathStructure(): NextResponse | null {\n if (pathSegments.length < 3) {\n return createApiErrorResponse(\n 'INVALID_ROUTE',\n 'Invalid route structure. Expected: /api/auth/{endpoint}',\n 404,\n );\n }\n return null;\n }\n\n function validateEndpoint(\n _endpoint: AuthEndpoint,\n endpointConfig: EndpointConfig,\n ): NextResponse | null {\n if (!endpointConfig || !endpointConfig.enabled) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n if (method !== 'OPTIONS' && !endpointConfig.methods.includes(method as any)) {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n return null;\n }\n\n function validateSubEndpoint(\n subEndpoint: SessionSubEndpoint | undefined,\n subEndpointConfig: any,\n ): NextResponse | null {\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n if (!subEndpointConfig || !subEndpointConfig.enabled) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n if (!subEndpointConfig.methods?.includes(method as any)) {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n return null;\n }\n\n async function validateSessionRequest(): Promise<{\n body: any;\n idToken?: string;\n csrfToken?: string;\n error?: NextResponse;\n }> {\n try {\n const body = await request.json();\n return { body, idToken: body.idToken, csrfToken: body.csrfToken };\n } catch (error) {\n return {\n body: null,\n error: createApiErrorResponse('INVALID_REQUEST_FORMAT', 'Invalid request format', 400),\n };\n }\n }\n\n function validateIdToken(idToken: string | undefined): NextResponse | null {\n if (!idToken) {\n return createApiErrorResponse(\n 'INVALID_TOKEN',\n 'ID token is required for creating session',\n 400,\n );\n }\n return null;\n }\n\n /**\n * Main validation orchestrator function\n * Runs all configured validations in the correct order\n */\n async function validateRequest(config: ValidationConfig): Promise<ComprehensiveValidationResult> {\n if (method === 'OPTIONS' && config.cors) {\n return {\n isValid: true,\n corsResponse: createCorsOptionsResponse(config.cors),\n };\n }\n const pathError = validatePathStructure();\n if (pathError) {\n return { isValid: false, error: pathError };\n }\n\n if (config.cors) {\n const corsError = await validateCors(config.cors);\n if (corsError) {\n return { isValid: false, error: corsError };\n }\n }\n\n if (config.security) {\n const securityError = await validateSecurity(config.security);\n if (securityError) {\n return { isValid: false, error: securityError };\n }\n }\n\n if (config.endpoint) {\n const endpointError = validateEndpoint(config.endpoint.name, config.endpoint.config);\n if (endpointError) {\n return { isValid: false, error: endpointError };\n }\n }\n\n if (config.subEndpoint) {\n const subEndpointError = validateSubEndpoint(\n config.subEndpoint.name,\n config.subEndpoint.config,\n );\n if (subEndpointError) {\n return { isValid: false, error: subEndpointError };\n }\n }\n\n let sessionData;\n if (method === 'POST' && (config.requireIdToken || config.requireCsrfToken)) {\n const sessionResult = await validateSessionRequest();\n if (sessionResult.error) {\n return { isValid: false, error: sessionResult.error };\n }\n\n sessionData = sessionResult;\n\n if (config.requireIdToken) {\n const idTokenError = validateIdToken(sessionData.idToken);\n if (idTokenError) {\n return { isValid: false, error: idTokenError };\n }\n }\n\n if (config.requireCsrfToken && sessionData.csrfToken) {\n const csrfCookieValue = request.cookies.get('csrfToken')?.value;\n const csrfError = validateCsrfToken(sessionData.csrfToken, csrfCookieValue);\n if (csrfError) {\n return { isValid: false, error: csrfError };\n }\n }\n }\n\n return {\n isValid: true,\n sessionData,\n };\n }\n\n /**\n * Convenience function for quick validation setup\n */\n function createValidationConfig(overrides: Partial<ValidationConfig> = {}): ValidationConfig {\n return {\n ...overrides,\n };\n }\n\n return {\n createValidationConfig,\n\n validateRequest,\n\n validateCors,\n validateSecurity,\n validatePathStructure,\n validateEndpoint,\n validateSubEndpoint,\n validateSessionRequest,\n validateIdToken,\n validateCsrfToken,\n\n createCorsOptionsResponse,\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,5 +1,19 @@
1
- import { createSessionHandler } from "./sessionHandler";
1
+ import { createTernSecureNextJsHandler } from "./ternsecureNextjsHandler";
2
+ import {
3
+ clearSessionCookieServer,
4
+ clearNextSessionCookie,
5
+ createSessionCookieServer,
6
+ createNextSessionCookie,
7
+ setNextServerSession,
8
+ setNextServerToken
9
+ } from "./actions";
2
10
  export {
3
- createSessionHandler
11
+ clearNextSessionCookie,
12
+ clearSessionCookieServer,
13
+ createNextSessionCookie,
14
+ createSessionCookieServer,
15
+ createTernSecureNextJsHandler,
16
+ setNextServerSession,
17
+ setNextServerToken
4
18
  };
5
19
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/admin/index.ts"],"sourcesContent":["export { createSessionHandler } from './sessionHandler'"],"mappings":"AAAA,SAAS,4BAA4B;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/admin/index.ts"],"sourcesContent":["export { createTernSecureNextJsHandler } from './ternsecureNextjsHandler'\n\nexport { \n clearSessionCookieServer,\n clearNextSessionCookie,\n createSessionCookieServer,\n createNextSessionCookie,\n setNextServerSession,\n setNextServerToken\n} from './actions'\n\nexport type { TernSecureHandlerOptions } from './types'"],"mappings":"AAAA,SAAS,qCAAqC;AAE9C;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;","names":[]}
@@ -0,0 +1,93 @@
1
+ import { NextResponse } from "next/server";
2
+ function createApiErrorResponse(code, message, status) {
3
+ const errors = [
4
+ {
5
+ code,
6
+ message
7
+ }
8
+ ];
9
+ return NextResponse.json(
10
+ {
11
+ success: false,
12
+ message,
13
+ error: code,
14
+ errors
15
+ // Include both formats for compatibility
16
+ },
17
+ { status }
18
+ );
19
+ }
20
+ function createApiSuccessResponse(data, status = 200) {
21
+ return NextResponse.json(
22
+ {
23
+ success: true,
24
+ ...data
25
+ },
26
+ { status }
27
+ );
28
+ }
29
+ class SessionResponseHelper {
30
+ static createVerificationResponse(decodedSession) {
31
+ return createApiSuccessResponse({
32
+ valid: true,
33
+ uid: decodedSession.data?.payload?.sub,
34
+ exp: decodedSession.data?.payload?.exp
35
+ });
36
+ }
37
+ static createUnauthorizedResponse() {
38
+ return createApiErrorResponse("UNAUTHORIZED", "Authentication required", 401);
39
+ }
40
+ static createSessionCreationResponse(res) {
41
+ if (!res.success) {
42
+ console.error("[TernSecureAuthHandler] Error creating session:", {
43
+ error: res.error,
44
+ message: res.message,
45
+ cookieSet: res.cookieSet
46
+ });
47
+ }
48
+ const statusCode = res.success ? 200 : res.error === "INVALID_TOKEN" ? 400 : res.error === "EXPIRED_TOKEN" ? 401 : 500;
49
+ return NextResponse.json(res, { status: statusCode });
50
+ }
51
+ static createRefreshResponse(refreshRes) {
52
+ if (!refreshRes.success) {
53
+ console.error("[TernSecureAuthHandler] Error refreshing session:", {
54
+ error: refreshRes.error,
55
+ message: refreshRes.message
56
+ });
57
+ }
58
+ const statusCode = refreshRes.success ? 200 : 401;
59
+ return NextResponse.json(refreshRes, { status: statusCode });
60
+ }
61
+ static createRevokeResponse(res) {
62
+ if (!res.success) {
63
+ console.error("[TernSecureAuthHandler] Error revoking session:", {
64
+ error: res.error,
65
+ message: res.message
66
+ });
67
+ }
68
+ const statusCode = res.success ? 200 : 500;
69
+ return NextResponse.json(res, { status: statusCode });
70
+ }
71
+ }
72
+ class HttpResponseHelper {
73
+ static createMethodNotAllowedResponse() {
74
+ return createApiErrorResponse("METHOD_NOT_ALLOWED", "Method not allowed", 405);
75
+ }
76
+ static createNotFoundResponse() {
77
+ return createApiErrorResponse("NOT_FOUND", "Endpoint not found", 404);
78
+ }
79
+ static createSubEndpointNotSupportedResponse() {
80
+ return createApiErrorResponse(
81
+ "SUB_ENDPOINT_NOT_SUPPORTED",
82
+ "Sub-endpoint not supported for POST method",
83
+ 400
84
+ );
85
+ }
86
+ }
87
+ export {
88
+ HttpResponseHelper,
89
+ SessionResponseHelper,
90
+ createApiErrorResponse,
91
+ createApiSuccessResponse
92
+ };
93
+ //# sourceMappingURL=responses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/app-router/admin/responses.ts"],"sourcesContent":["import type { TernSecureApiErrorJSON } from '@tern-secure/types';\nimport { NextResponse } from 'next/server';\n\n/**\n * Standardized error response creation\n */\nexport function createApiErrorResponse(\n code: string,\n message: string,\n status: number,\n): NextResponse {\n const errors: TernSecureApiErrorJSON[] = [\n {\n code,\n message,\n },\n ];\n\n return NextResponse.json(\n {\n success: false,\n message,\n error: code,\n errors, // Include both formats for compatibility\n },\n { status },\n );\n}\n\n/**\n * Standardized success response creation\n */\nexport function createApiSuccessResponse<T>(data: T, status: number = 200): NextResponse {\n return NextResponse.json(\n {\n success: true,\n ...data,\n },\n { status },\n );\n}\n\n/**\n * Session verification response utilities\n */\nexport class SessionResponseHelper {\n static createVerificationResponse(decodedSession: any): NextResponse {\n return createApiSuccessResponse({\n valid: true,\n uid: decodedSession.data?.payload?.sub,\n exp: decodedSession.data?.payload?.exp,\n });\n }\n\n static createUnauthorizedResponse(): NextResponse {\n return createApiErrorResponse('UNAUTHORIZED', 'Authentication required', 401);\n }\n\n static createSessionCreationResponse(res: any): NextResponse {\n if (!res.success) {\n console.error('[TernSecureAuthHandler] Error creating session:', {\n error: res.error,\n message: res.message,\n cookieSet: res.cookieSet,\n });\n }\n\n const statusCode = res.success\n ? 200\n : res.error === 'INVALID_TOKEN'\n ? 400\n : res.error === 'EXPIRED_TOKEN'\n ? 401\n : 500;\n\n return NextResponse.json(res, { status: statusCode });\n }\n\n static createRefreshResponse(refreshRes: any): NextResponse {\n if (!refreshRes.success) {\n console.error('[TernSecureAuthHandler] Error refreshing session:', {\n error: refreshRes.error,\n message: refreshRes.message,\n });\n }\n\n const statusCode = refreshRes.success ? 200 : 401;\n return NextResponse.json(refreshRes, { status: statusCode });\n }\n\n static createRevokeResponse(res: any): NextResponse {\n if (!res.success) {\n console.error('[TernSecureAuthHandler] Error revoking session:', {\n error: res.error,\n message: res.message,\n });\n }\n const statusCode = res.success ? 200 : 500;\n return NextResponse.json(res, { status: statusCode });\n }\n}\n\n/**\n * HTTP method response utilities\n */\nexport class HttpResponseHelper {\n static createMethodNotAllowedResponse(): NextResponse {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n static createNotFoundResponse(): NextResponse {\n return createApiErrorResponse('NOT_FOUND', 'Endpoint not found', 404);\n }\n\n static createSubEndpointNotSupportedResponse(): NextResponse {\n return createApiErrorResponse(\n 'SUB_ENDPOINT_NOT_SUPPORTED',\n 'Sub-endpoint not supported for POST method',\n 400,\n );\n }\n}\n"],"mappings":"AACA,SAAS,oBAAoB;AAKtB,SAAS,uBACd,MACA,SACA,QACc;AACd,QAAM,SAAmC;AAAA,IACvC;AAAA,MACE;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,aAAa;AAAA,IAClB;AAAA,MACE,SAAS;AAAA,MACT;AAAA,MACA,OAAO;AAAA,MACP;AAAA;AAAA,IACF;AAAA,IACA,EAAE,OAAO;AAAA,EACX;AACF;AAKO,SAAS,yBAA4B,MAAS,SAAiB,KAAmB;AACvF,SAAO,aAAa;AAAA,IAClB;AAAA,MACE,SAAS;AAAA,MACT,GAAG;AAAA,IACL;AAAA,IACA,EAAE,OAAO;AAAA,EACX;AACF;AAKO,MAAM,sBAAsB;AAAA,EACjC,OAAO,2BAA2B,gBAAmC;AACnE,WAAO,yBAAyB;AAAA,MAC9B,OAAO;AAAA,MACP,KAAK,eAAe,MAAM,SAAS;AAAA,MACnC,KAAK,eAAe,MAAM,SAAS;AAAA,IACrC,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,6BAA2C;AAChD,WAAO,uBAAuB,gBAAgB,2BAA2B,GAAG;AAAA,EAC9E;AAAA,EAEA,OAAO,8BAA8B,KAAwB;AAC3D,QAAI,CAAC,IAAI,SAAS;AAChB,cAAQ,MAAM,mDAAmD;AAAA,QAC/D,OAAO,IAAI;AAAA,QACX,SAAS,IAAI;AAAA,QACb,WAAW,IAAI;AAAA,MACjB,CAAC;AAAA,IACH;AAEA,UAAM,aAAa,IAAI,UACnB,MACA,IAAI,UAAU,kBACZ,MACA,IAAI,UAAU,kBACZ,MACA;AAER,WAAO,aAAa,KAAK,KAAK,EAAE,QAAQ,WAAW,CAAC;AAAA,EACtD;AAAA,EAEA,OAAO,sBAAsB,YAA+B;AAC1D,QAAI,CAAC,WAAW,SAAS;AACvB,cAAQ,MAAM,qDAAqD;AAAA,QACjE,OAAO,WAAW;AAAA,QAClB,SAAS,WAAW;AAAA,MACtB,CAAC;AAAA,IACH;AAEA,UAAM,aAAa,WAAW,UAAU,MAAM;AAC9C,WAAO,aAAa,KAAK,YAAY,EAAE,QAAQ,WAAW,CAAC;AAAA,EAC7D;AAAA,EAEA,OAAO,qBAAqB,KAAwB;AAClD,QAAI,CAAC,IAAI,SAAS;AAChB,cAAQ,MAAM,mDAAmD;AAAA,QAC/D,OAAO,IAAI;AAAA,QACX,SAAS,IAAI;AAAA,MACf,CAAC;AAAA,IACH;AACA,UAAM,aAAa,IAAI,UAAU,MAAM;AACvC,WAAO,aAAa,KAAK,KAAK,EAAE,QAAQ,WAAW,CAAC;AAAA,EACtD;AACF;AAKO,MAAM,mBAAmB;AAAA,EAC9B,OAAO,iCAA+C;AACpD,WAAO,uBAAuB,sBAAsB,sBAAsB,GAAG;AAAA,EAC/E;AAAA,EAEA,OAAO,yBAAuC;AAC5C,WAAO,uBAAuB,aAAa,sBAAsB,GAAG;AAAA,EACtE;AAAA,EAEA,OAAO,wCAAsD;AAC3D,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,131 @@
1
+ import { clearSessionCookie, createSessionCookie } from "@tern-secure/backend/admin";
2
+ import { ternDecodeJwtUnguarded } from "@tern-secure/backend/jwt";
3
+ import { NextCookieStore } from "../../utils/NextCookieAdapter";
4
+ import { createApiErrorResponse, HttpResponseHelper, SessionResponseHelper } from "./responses";
5
+ import { CsrfValidator, RequestValidator } from "./validators";
6
+ class SessionGetHandler {
7
+ static async handle(request, subEndpoint, _config) {
8
+ switch (subEndpoint) {
9
+ case "verify":
10
+ return this.handleVerify(request);
11
+ default:
12
+ return HttpResponseHelper.createNotFoundResponse();
13
+ }
14
+ }
15
+ static async handleVerify(request) {
16
+ try {
17
+ const sessionCookie = request.cookies.get("_session_cookie")?.value;
18
+ if (!sessionCookie) {
19
+ return SessionResponseHelper.createUnauthorizedResponse();
20
+ }
21
+ const decodedSession = ternDecodeJwtUnguarded(sessionCookie);
22
+ if (decodedSession.errors) {
23
+ return SessionResponseHelper.createUnauthorizedResponse();
24
+ }
25
+ return SessionResponseHelper.createVerificationResponse(decodedSession);
26
+ } catch (error) {
27
+ return SessionResponseHelper.createUnauthorizedResponse();
28
+ }
29
+ }
30
+ }
31
+ class SessionPostHandler {
32
+ static async handle(request, subEndpoint, _config) {
33
+ const cookieStore = new NextCookieStore();
34
+ const { idToken, csrfToken, error } = await RequestValidator.validateSessionRequest(request);
35
+ if (error) return error;
36
+ const csrfCookieValue = request.cookies.get("_session_terncf")?.value;
37
+ const csrfValidationError = CsrfValidator.validate(csrfToken || "", csrfCookieValue);
38
+ if (csrfValidationError) return csrfValidationError;
39
+ const options = {
40
+ tenantId: _config.tenantId
41
+ };
42
+ switch (subEndpoint) {
43
+ case "createsession":
44
+ return this.handleCreateSession(options, idToken, cookieStore);
45
+ case "refresh":
46
+ return this.handleRefreshSession(request, cookieStore);
47
+ case "revoke":
48
+ return this.handleRevokeSession(cookieStore);
49
+ default:
50
+ return HttpResponseHelper.createSubEndpointNotSupportedResponse();
51
+ }
52
+ }
53
+ static async handleCreateSession(options, idToken, cookieStore) {
54
+ const validationError = RequestValidator.validateIdToken(idToken);
55
+ if (validationError) return validationError;
56
+ if (!idToken) {
57
+ return createApiErrorResponse("ID_TOKEN_REQUIRED", "ID token is required", 400);
58
+ }
59
+ try {
60
+ const res = await createSessionCookie(idToken, cookieStore, options);
61
+ return SessionResponseHelper.createSessionCreationResponse(res);
62
+ } catch (error) {
63
+ return createApiErrorResponse("SESSION_CREATION_FAILED", "Session creation failed", 500);
64
+ }
65
+ }
66
+ static async handleRefreshSession(request, cookieStore) {
67
+ const currentSessionCookie = request.cookies.get("__session")?.value;
68
+ if (!currentSessionCookie) {
69
+ return createApiErrorResponse("NO_SESSION", "No session to refresh", 401);
70
+ }
71
+ try {
72
+ const decodedSession = ternDecodeJwtUnguarded(currentSessionCookie);
73
+ if (decodedSession.errors) {
74
+ return createApiErrorResponse("INVALID_SESSION", "Invalid session for refresh", 401);
75
+ }
76
+ const refreshRes = await createSessionCookie(
77
+ decodedSession.data?.payload?.sub || "",
78
+ cookieStore
79
+ );
80
+ return SessionResponseHelper.createRefreshResponse(refreshRes);
81
+ } catch (error) {
82
+ return createApiErrorResponse("REFRESH_FAILED", "Session refresh failed", 500);
83
+ }
84
+ }
85
+ static async handleRevokeSession(cookieStore) {
86
+ const res = await clearSessionCookie(cookieStore);
87
+ return SessionResponseHelper.createRevokeResponse(res);
88
+ }
89
+ }
90
+ class SessionEndpointHandler {
91
+ static async handle(request, method, subEndpoint, config) {
92
+ const sessionsConfig = config.endpoints.sessions;
93
+ if (!subEndpoint) {
94
+ return createApiErrorResponse("SUB_ENDPOINT_REQUIRED", "Session sub-endpoint required", 400);
95
+ }
96
+ const subEndpointConfig = sessionsConfig?.subEndpoints?.[subEndpoint];
97
+ const subEndpointValidation = this.validateSubEndpoint(subEndpoint, subEndpointConfig, method);
98
+ if (subEndpointValidation) return subEndpointValidation;
99
+ if (subEndpointConfig?.security) {
100
+ const { SecurityValidator } = await import("./validators.js");
101
+ const securityResult = await SecurityValidator.validate(request, subEndpointConfig.security);
102
+ if (securityResult) return securityResult;
103
+ }
104
+ switch (method) {
105
+ case "GET":
106
+ return SessionGetHandler.handle(request, subEndpoint, config);
107
+ case "POST":
108
+ return SessionPostHandler.handle(request, subEndpoint, config);
109
+ default:
110
+ return HttpResponseHelper.createMethodNotAllowedResponse();
111
+ }
112
+ }
113
+ static validateSubEndpoint(subEndpoint, subEndpointConfig, method) {
114
+ if (!subEndpoint) {
115
+ return createApiErrorResponse("SUB_ENDPOINT_REQUIRED", "Session sub-endpoint required", 400);
116
+ }
117
+ if (!subEndpointConfig || !subEndpointConfig.enabled) {
118
+ return createApiErrorResponse("ENDPOINT_NOT_FOUND", "Endpoint not found", 404);
119
+ }
120
+ if (!subEndpointConfig.methods?.includes(method)) {
121
+ return createApiErrorResponse("METHOD_NOT_ALLOWED", "Method not allowed", 405);
122
+ }
123
+ return null;
124
+ }
125
+ }
126
+ export {
127
+ SessionEndpointHandler,
128
+ SessionGetHandler,
129
+ SessionPostHandler
130
+ };
131
+ //# sourceMappingURL=sessionHandlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/app-router/admin/sessionHandlers.ts"],"sourcesContent":["import type { RequestOptions } from '@tern-secure/backend';\nimport { clearSessionCookie, createSessionCookie } from '@tern-secure/backend/admin';\nimport { ternDecodeJwtUnguarded } from '@tern-secure/backend/jwt';\nimport type { NextRequest, NextResponse } from 'next/server';\n\nimport { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport { createApiErrorResponse, HttpResponseHelper, SessionResponseHelper } from './responses';\nimport type {\n SessionSubEndpoint,\n TernSecureHandlerOptions,\n TernSecureInternalHandlerConfig,\n} from './types';\nimport { CsrfValidator, RequestValidator } from './validators';\n\n/**\n * Session GET request handlers\n */\nexport class SessionGetHandler {\n static async handle(\n request: NextRequest,\n subEndpoint: SessionSubEndpoint,\n _config: Required<TernSecureHandlerOptions>,\n ): Promise<NextResponse> {\n switch (subEndpoint) {\n case 'verify':\n return this.handleVerify(request);\n default:\n return HttpResponseHelper.createNotFoundResponse();\n }\n }\n\n private static async handleVerify(request: NextRequest): Promise<NextResponse> {\n try {\n const sessionCookie = request.cookies.get('_session_cookie')?.value;\n if (!sessionCookie) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n\n const decodedSession = ternDecodeJwtUnguarded(sessionCookie);\n if (decodedSession.errors) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n\n return SessionResponseHelper.createVerificationResponse(decodedSession);\n } catch (error) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n }\n}\n\n/**\n * Session POST request handlers\n */\nexport class SessionPostHandler {\n static async handle(\n request: NextRequest,\n subEndpoint: SessionSubEndpoint,\n _config: TernSecureInternalHandlerConfig,\n ): Promise<NextResponse> {\n const cookieStore = new NextCookieStore();\n\n const { idToken, csrfToken, error } = await RequestValidator.validateSessionRequest(request);\n if (error) return error;\n\n const csrfCookieValue = request.cookies.get('_session_terncf')?.value;\n const csrfValidationError = CsrfValidator.validate(csrfToken || '', csrfCookieValue);\n if (csrfValidationError) return csrfValidationError;\n\n const options = {\n tenantId: _config.tenantId,\n };\n\n switch (subEndpoint) {\n case 'createsession':\n return this.handleCreateSession(options, idToken, cookieStore);\n case 'refresh':\n return this.handleRefreshSession(request, cookieStore);\n case 'revoke':\n return this.handleRevokeSession(cookieStore);\n default:\n return HttpResponseHelper.createSubEndpointNotSupportedResponse();\n }\n }\n\n private static async handleCreateSession(\n options: RequestOptions,\n idToken: string | undefined,\n cookieStore: NextCookieStore,\n ): Promise<NextResponse> {\n const validationError = RequestValidator.validateIdToken(idToken);\n if (validationError) return validationError;\n if (!idToken) {\n return createApiErrorResponse('ID_TOKEN_REQUIRED', 'ID token is required', 400);\n }\n\n try {\n const res = await createSessionCookie(idToken, cookieStore, options);\n return SessionResponseHelper.createSessionCreationResponse(res);\n } catch (error) {\n return createApiErrorResponse('SESSION_CREATION_FAILED', 'Session creation failed', 500);\n }\n }\n\n private static async handleRefreshSession(\n request: NextRequest,\n cookieStore: NextCookieStore,\n ): Promise<NextResponse> {\n const currentSessionCookie = request.cookies.get('__session')?.value;\n if (!currentSessionCookie) {\n return createApiErrorResponse('NO_SESSION', 'No session to refresh', 401);\n }\n\n try {\n const decodedSession = ternDecodeJwtUnguarded(currentSessionCookie);\n if (decodedSession.errors) {\n return createApiErrorResponse('INVALID_SESSION', 'Invalid session for refresh', 401);\n }\n\n const refreshRes = await createSessionCookie(\n decodedSession.data?.payload?.sub || '',\n cookieStore,\n );\n\n return SessionResponseHelper.createRefreshResponse(refreshRes);\n } catch (error) {\n return createApiErrorResponse('REFRESH_FAILED', 'Session refresh failed', 500);\n }\n }\n\n private static async handleRevokeSession(cookieStore: NextCookieStore): Promise<NextResponse> {\n const res = await clearSessionCookie(cookieStore);\n return SessionResponseHelper.createRevokeResponse(res);\n }\n}\n\n/**\n * Main session endpoint orchestrator\n */\nexport class SessionEndpointHandler {\n static async handle(\n request: NextRequest,\n method: string,\n subEndpoint: SessionSubEndpoint | undefined,\n config: Required<TernSecureHandlerOptions>,\n ): Promise<NextResponse> {\n const sessionsConfig = config.endpoints.sessions;\n\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n const subEndpointConfig = sessionsConfig?.subEndpoints?.[subEndpoint];\n\n const subEndpointValidation = this.validateSubEndpoint(subEndpoint, subEndpointConfig, method);\n if (subEndpointValidation) return subEndpointValidation;\n\n if (subEndpointConfig?.security) {\n const { SecurityValidator } = await import('./validators.js');\n const securityResult = await SecurityValidator.validate(request, subEndpointConfig.security);\n if (securityResult) return securityResult;\n }\n\n switch (method) {\n case 'GET':\n return SessionGetHandler.handle(request, subEndpoint, config);\n case 'POST':\n return SessionPostHandler.handle(request, subEndpoint, config);\n default:\n return HttpResponseHelper.createMethodNotAllowedResponse();\n }\n }\n\n private static validateSubEndpoint(\n subEndpoint: SessionSubEndpoint | undefined,\n subEndpointConfig: any,\n method: string,\n ): NextResponse | null {\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n if (!subEndpointConfig || !subEndpointConfig.enabled) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n if (!subEndpointConfig.methods?.includes(method as any)) {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n return null;\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,62 @@
1
+ import { TENANT_ID } from "./constants";
2
+ import { createRequestContext, createValidators } from "./fnValidators";
3
+ import { createApiErrorResponse } from "./responses";
4
+ import { SessionEndpointHandler } from "./sessionHandlers";
5
+ import {
6
+ DEFAULT_HANDLER_OPTIONS
7
+ } from "./types";
8
+ import { ConfigUtils, LoggingUtils } from "./utils";
9
+ async function applyGlobalValidations(config, context) {
10
+ const { validateCors, validateSecurity, createCorsOptionsResponse } = createValidators(context);
11
+ const corsError = await validateCors(config.cors);
12
+ if (corsError) return corsError;
13
+ if (context.method === "OPTIONS") {
14
+ return createCorsOptionsResponse(config.cors);
15
+ }
16
+ const securityError = await validateSecurity(config.security);
17
+ if (securityError) return securityError;
18
+ return null;
19
+ }
20
+ async function routeToEndpointHandler(request, endpoint, subEndpoint, config) {
21
+ switch (endpoint) {
22
+ case "sessions":
23
+ return SessionEndpointHandler.handle(request, request.method, subEndpoint, config);
24
+ default:
25
+ return createApiErrorResponse("ENDPOINT_NOT_FOUND", "Endpoint not found", 404);
26
+ }
27
+ }
28
+ function createTernSecureNextJsHandler(options) {
29
+ const baseConfig = ConfigUtils.mergeWithDefaults(
30
+ DEFAULT_HANDLER_OPTIONS,
31
+ options
32
+ );
33
+ const internalConfig = {
34
+ ...baseConfig,
35
+ tenantId: TENANT_ID
36
+ };
37
+ const handler = async (request) => {
38
+ const context = createRequestContext(request);
39
+ const { pathSegments } = context;
40
+ const endpoint = pathSegments[2];
41
+ const subEndpoint = pathSegments[3];
42
+ LoggingUtils.logRequest(request, "Handler");
43
+ try {
44
+ const validationResult = await applyGlobalValidations(internalConfig, context);
45
+ if (validationResult) {
46
+ return validationResult;
47
+ }
48
+ return await routeToEndpointHandler(request, endpoint, subEndpoint, internalConfig);
49
+ } catch (error) {
50
+ LoggingUtils.logError(error, "Handler");
51
+ return createApiErrorResponse("INTERNAL_SERVER_ERROR", "Internal server error", 500);
52
+ }
53
+ };
54
+ return {
55
+ GET: handler,
56
+ POST: handler
57
+ };
58
+ }
59
+ export {
60
+ createTernSecureNextJsHandler
61
+ };
62
+ //# sourceMappingURL=ternsecureNextjsHandler.js.map