@civic/auth 0.1.4-beta.7 → 0.1.5-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (275) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +11 -8
  3. package/dist/cjs/constants.d.ts +1 -2
  4. package/dist/cjs/constants.d.ts.map +1 -1
  5. package/dist/cjs/constants.js +1 -3
  6. package/dist/cjs/constants.js.map +1 -1
  7. package/dist/cjs/lib/oauth.d.ts.map +1 -1
  8. package/dist/cjs/lib/oauth.js +1 -0
  9. package/dist/cjs/lib/oauth.js.map +1 -1
  10. package/dist/cjs/nextjs/config.d.ts +3 -0
  11. package/dist/cjs/nextjs/config.d.ts.map +1 -1
  12. package/dist/cjs/nextjs/config.js +4 -0
  13. package/dist/cjs/nextjs/config.js.map +1 -1
  14. package/dist/cjs/nextjs/hooks/useUserCookie.d.ts.map +1 -1
  15. package/dist/cjs/nextjs/hooks/useUserCookie.js +2 -0
  16. package/dist/cjs/nextjs/hooks/useUserCookie.js.map +1 -1
  17. package/dist/cjs/nextjs/providers/NextAuthProvider.d.ts +2 -2
  18. package/dist/cjs/nextjs/providers/NextAuthProvider.d.ts.map +1 -1
  19. package/dist/cjs/nextjs/providers/NextAuthProvider.js +26 -26
  20. package/dist/cjs/nextjs/providers/NextAuthProvider.js.map +1 -1
  21. package/dist/cjs/nextjs/routeHandler.d.ts +2 -1
  22. package/dist/cjs/nextjs/routeHandler.d.ts.map +1 -1
  23. package/dist/cjs/nextjs/routeHandler.js +122 -38
  24. package/dist/cjs/nextjs/routeHandler.js.map +1 -1
  25. package/dist/cjs/reactjs/components/UserButton.d.ts +1 -3
  26. package/dist/cjs/reactjs/components/UserButton.d.ts.map +1 -1
  27. package/dist/cjs/reactjs/components/UserButton.js +3 -3
  28. package/dist/cjs/reactjs/components/UserButton.js.map +1 -1
  29. package/dist/cjs/reactjs/hooks/useClientTokenExchangeSession.d.ts +3 -0
  30. package/dist/cjs/reactjs/hooks/useClientTokenExchangeSession.d.ts.map +1 -0
  31. package/dist/cjs/reactjs/hooks/useClientTokenExchangeSession.js +16 -0
  32. package/dist/cjs/reactjs/hooks/useClientTokenExchangeSession.js.map +1 -0
  33. package/dist/cjs/reactjs/providers/AuthProvider.d.ts +11 -0
  34. package/dist/cjs/reactjs/providers/AuthProvider.d.ts.map +1 -0
  35. package/dist/cjs/reactjs/providers/AuthProvider.js +108 -0
  36. package/dist/cjs/reactjs/providers/AuthProvider.js.map +1 -0
  37. package/dist/cjs/reactjs/providers/CivicAuthProvider.d.ts +6 -0
  38. package/dist/cjs/reactjs/providers/CivicAuthProvider.d.ts.map +1 -0
  39. package/dist/cjs/reactjs/providers/CivicAuthProvider.js +38 -0
  40. package/dist/cjs/reactjs/providers/CivicAuthProvider.js.map +1 -0
  41. package/dist/cjs/reactjs/providers/ClientTokenExchangeSessionProvider.d.ts +17 -0
  42. package/dist/cjs/reactjs/providers/ClientTokenExchangeSessionProvider.d.ts.map +1 -0
  43. package/dist/cjs/reactjs/providers/ClientTokenExchangeSessionProvider.js +185 -0
  44. package/dist/cjs/reactjs/providers/ClientTokenExchangeSessionProvider.js.map +1 -0
  45. package/dist/cjs/reactjs/providers/index.d.ts +2 -2
  46. package/dist/cjs/reactjs/providers/index.d.ts.map +1 -1
  47. package/dist/cjs/reactjs/providers/index.js +2 -2
  48. package/dist/cjs/reactjs/providers/index.js.map +1 -1
  49. package/dist/cjs/server/ServerAuthenticationResolver.d.ts +1 -0
  50. package/dist/cjs/server/ServerAuthenticationResolver.d.ts.map +1 -1
  51. package/dist/cjs/server/ServerAuthenticationResolver.js +6 -0
  52. package/dist/cjs/server/ServerAuthenticationResolver.js.map +1 -1
  53. package/dist/cjs/services/AuthenticationService.d.ts +8 -2
  54. package/dist/cjs/services/AuthenticationService.d.ts.map +1 -1
  55. package/dist/cjs/services/AuthenticationService.js +90 -11
  56. package/dist/cjs/services/AuthenticationService.js.map +1 -1
  57. package/dist/cjs/services/types.d.ts +2 -1
  58. package/dist/cjs/services/types.d.ts.map +1 -1
  59. package/dist/cjs/services/types.js.map +1 -1
  60. package/dist/cjs/shared/components/CivicAuthIframe.d.ts +1 -0
  61. package/dist/cjs/shared/components/CivicAuthIframe.d.ts.map +1 -1
  62. package/dist/cjs/shared/components/CivicAuthIframe.js +2 -3
  63. package/dist/cjs/shared/components/CivicAuthIframe.js.map +1 -1
  64. package/dist/cjs/shared/components/CivicAuthIframeContainer.d.ts +4 -0
  65. package/dist/cjs/shared/components/CivicAuthIframeContainer.d.ts.map +1 -1
  66. package/dist/cjs/shared/components/CivicAuthIframeContainer.js +7 -6
  67. package/dist/cjs/shared/components/CivicAuthIframeContainer.js.map +1 -1
  68. package/dist/cjs/shared/components/CivicAuthLogoutIframeContainer.d.ts +7 -0
  69. package/dist/cjs/shared/components/CivicAuthLogoutIframeContainer.d.ts.map +1 -0
  70. package/dist/cjs/shared/components/CivicAuthLogoutIframeContainer.js +28 -0
  71. package/dist/cjs/shared/components/CivicAuthLogoutIframeContainer.js.map +1 -0
  72. package/dist/cjs/shared/components/IFrameAndLoading.d.ts +2 -1
  73. package/dist/cjs/shared/components/IFrameAndLoading.d.ts.map +1 -1
  74. package/dist/cjs/shared/components/IFrameAndLoading.js +7 -2
  75. package/dist/cjs/shared/components/IFrameAndLoading.js.map +1 -1
  76. package/dist/cjs/shared/hooks/index.d.ts +3 -1
  77. package/dist/cjs/shared/hooks/index.d.ts.map +1 -1
  78. package/dist/cjs/shared/hooks/index.js +6 -2
  79. package/dist/cjs/shared/hooks/index.js.map +1 -1
  80. package/dist/cjs/shared/hooks/useSignIn.d.ts +3 -2
  81. package/dist/cjs/shared/hooks/useSignIn.d.ts.map +1 -1
  82. package/dist/cjs/shared/hooks/useSignIn.js +69 -14
  83. package/dist/cjs/shared/hooks/useSignIn.js.map +1 -1
  84. package/dist/cjs/shared/hooks/useWindowFocused.d.ts +5 -0
  85. package/dist/cjs/shared/hooks/useWindowFocused.d.ts.map +1 -0
  86. package/dist/cjs/shared/hooks/useWindowFocused.js +24 -0
  87. package/dist/cjs/shared/hooks/useWindowFocused.js.map +1 -0
  88. package/dist/cjs/shared/index.d.ts +1 -0
  89. package/dist/cjs/shared/index.d.ts.map +1 -1
  90. package/dist/cjs/shared/index.js +5 -3
  91. package/dist/cjs/shared/index.js.map +1 -1
  92. package/dist/cjs/shared/lib/types.d.ts +1 -0
  93. package/dist/cjs/shared/lib/types.d.ts.map +1 -1
  94. package/dist/cjs/shared/lib/types.js.map +1 -1
  95. package/dist/cjs/shared/lib/util.d.ts +3 -2
  96. package/dist/cjs/shared/lib/util.d.ts.map +1 -1
  97. package/dist/cjs/shared/lib/util.js +7 -3
  98. package/dist/cjs/shared/lib/util.js.map +1 -1
  99. package/dist/cjs/shared/providers/AuthContext.d.ts +1 -0
  100. package/dist/cjs/shared/providers/AuthContext.d.ts.map +1 -1
  101. package/dist/cjs/shared/providers/AuthContext.js.map +1 -1
  102. package/dist/cjs/shared/providers/AuthProvider.d.ts +15 -4
  103. package/dist/cjs/shared/providers/AuthProvider.d.ts.map +1 -1
  104. package/dist/cjs/shared/providers/AuthProvider.js +12 -3
  105. package/dist/cjs/shared/providers/AuthProvider.js.map +1 -1
  106. package/dist/cjs/shared/providers/CivicAuthConfigContext.d.ts +3 -1
  107. package/dist/cjs/shared/providers/CivicAuthConfigContext.d.ts.map +1 -1
  108. package/dist/cjs/shared/providers/CivicAuthConfigContext.js +10 -1
  109. package/dist/cjs/shared/providers/CivicAuthConfigContext.js.map +1 -1
  110. package/dist/cjs/shared/providers/CivicAuthProvider.d.ts +1 -1
  111. package/dist/cjs/shared/providers/CivicAuthProvider.d.ts.map +1 -1
  112. package/dist/cjs/shared/providers/CivicAuthProvider.js +2 -2
  113. package/dist/cjs/shared/providers/CivicAuthProvider.js.map +1 -1
  114. package/dist/cjs/shared/providers/ClientTokenExchangeSessionProvider.d.ts.map +1 -1
  115. package/dist/cjs/shared/providers/ClientTokenExchangeSessionProvider.js +10 -25
  116. package/dist/cjs/shared/providers/ClientTokenExchangeSessionProvider.js.map +1 -1
  117. package/dist/cjs/shared/providers/IframeProvider.d.ts +3 -0
  118. package/dist/cjs/shared/providers/IframeProvider.d.ts.map +1 -1
  119. package/dist/cjs/shared/providers/IframeProvider.js +9 -3
  120. package/dist/cjs/shared/providers/IframeProvider.js.map +1 -1
  121. package/dist/cjs/shared/providers/UserProvider.d.ts +2 -1
  122. package/dist/cjs/shared/providers/UserProvider.d.ts.map +1 -1
  123. package/dist/cjs/shared/providers/UserProvider.js +2 -1
  124. package/dist/cjs/shared/providers/UserProvider.js.map +1 -1
  125. package/dist/cjs/shared/providers/types.d.ts +3 -1
  126. package/dist/cjs/shared/providers/types.d.ts.map +1 -1
  127. package/dist/cjs/shared/providers/types.js.map +1 -1
  128. package/dist/cjs/shared/version.d.ts +1 -1
  129. package/dist/cjs/shared/version.js +1 -1
  130. package/dist/cjs/shared/version.js.map +1 -1
  131. package/dist/cjs/types.d.ts +1 -0
  132. package/dist/cjs/types.d.ts.map +1 -1
  133. package/dist/cjs/types.js.map +1 -1
  134. package/dist/cjs/version.d.ts +2 -0
  135. package/dist/cjs/version.d.ts.map +1 -0
  136. package/dist/cjs/version.js +6 -0
  137. package/dist/cjs/version.js.map +1 -0
  138. package/dist/esm/constants.d.ts +1 -2
  139. package/dist/esm/constants.d.ts.map +1 -1
  140. package/dist/esm/constants.js +1 -2
  141. package/dist/esm/constants.js.map +1 -1
  142. package/dist/esm/lib/oauth.d.ts.map +1 -1
  143. package/dist/esm/lib/oauth.js +1 -0
  144. package/dist/esm/lib/oauth.js.map +1 -1
  145. package/dist/esm/nextjs/config.d.ts +3 -0
  146. package/dist/esm/nextjs/config.d.ts.map +1 -1
  147. package/dist/esm/nextjs/config.js +4 -0
  148. package/dist/esm/nextjs/config.js.map +1 -1
  149. package/dist/esm/nextjs/hooks/useUserCookie.d.ts.map +1 -1
  150. package/dist/esm/nextjs/hooks/useUserCookie.js +2 -0
  151. package/dist/esm/nextjs/hooks/useUserCookie.js.map +1 -1
  152. package/dist/esm/nextjs/providers/NextAuthProvider.d.ts +2 -2
  153. package/dist/esm/nextjs/providers/NextAuthProvider.d.ts.map +1 -1
  154. package/dist/esm/nextjs/providers/NextAuthProvider.js +26 -26
  155. package/dist/esm/nextjs/providers/NextAuthProvider.js.map +1 -1
  156. package/dist/esm/nextjs/routeHandler.d.ts +2 -1
  157. package/dist/esm/nextjs/routeHandler.d.ts.map +1 -1
  158. package/dist/esm/nextjs/routeHandler.js +123 -40
  159. package/dist/esm/nextjs/routeHandler.js.map +1 -1
  160. package/dist/esm/reactjs/components/UserButton.d.ts +1 -3
  161. package/dist/esm/reactjs/components/UserButton.d.ts.map +1 -1
  162. package/dist/esm/reactjs/components/UserButton.js +3 -3
  163. package/dist/esm/reactjs/components/UserButton.js.map +1 -1
  164. package/dist/esm/reactjs/hooks/useClientTokenExchangeSession.d.ts +3 -0
  165. package/dist/esm/reactjs/hooks/useClientTokenExchangeSession.d.ts.map +1 -0
  166. package/dist/esm/reactjs/hooks/useClientTokenExchangeSession.js +13 -0
  167. package/dist/esm/reactjs/hooks/useClientTokenExchangeSession.js.map +1 -0
  168. package/dist/esm/reactjs/providers/AuthProvider.d.ts +11 -0
  169. package/dist/esm/reactjs/providers/AuthProvider.d.ts.map +1 -0
  170. package/dist/esm/reactjs/providers/AuthProvider.js +72 -0
  171. package/dist/esm/reactjs/providers/AuthProvider.js.map +1 -0
  172. package/dist/esm/reactjs/providers/CivicAuthProvider.d.ts +6 -0
  173. package/dist/esm/reactjs/providers/CivicAuthProvider.d.ts.map +1 -0
  174. package/dist/esm/reactjs/providers/CivicAuthProvider.js +32 -0
  175. package/dist/esm/reactjs/providers/CivicAuthProvider.js.map +1 -0
  176. package/dist/esm/reactjs/providers/ClientTokenExchangeSessionProvider.d.ts +17 -0
  177. package/dist/esm/reactjs/providers/ClientTokenExchangeSessionProvider.d.ts.map +1 -0
  178. package/dist/esm/reactjs/providers/ClientTokenExchangeSessionProvider.js +148 -0
  179. package/dist/esm/reactjs/providers/ClientTokenExchangeSessionProvider.js.map +1 -0
  180. package/dist/esm/reactjs/providers/index.d.ts +2 -2
  181. package/dist/esm/reactjs/providers/index.d.ts.map +1 -1
  182. package/dist/esm/reactjs/providers/index.js +2 -2
  183. package/dist/esm/reactjs/providers/index.js.map +1 -1
  184. package/dist/esm/server/ServerAuthenticationResolver.d.ts +1 -0
  185. package/dist/esm/server/ServerAuthenticationResolver.d.ts.map +1 -1
  186. package/dist/esm/server/ServerAuthenticationResolver.js +6 -0
  187. package/dist/esm/server/ServerAuthenticationResolver.js.map +1 -1
  188. package/dist/esm/services/AuthenticationService.d.ts +8 -2
  189. package/dist/esm/services/AuthenticationService.d.ts.map +1 -1
  190. package/dist/esm/services/AuthenticationService.js +90 -11
  191. package/dist/esm/services/AuthenticationService.js.map +1 -1
  192. package/dist/esm/services/types.d.ts +2 -1
  193. package/dist/esm/services/types.d.ts.map +1 -1
  194. package/dist/esm/services/types.js.map +1 -1
  195. package/dist/esm/shared/components/CivicAuthIframe.d.ts +1 -0
  196. package/dist/esm/shared/components/CivicAuthIframe.d.ts.map +1 -1
  197. package/dist/esm/shared/components/CivicAuthIframe.js +2 -3
  198. package/dist/esm/shared/components/CivicAuthIframe.js.map +1 -1
  199. package/dist/esm/shared/components/CivicAuthIframeContainer.d.ts +4 -0
  200. package/dist/esm/shared/components/CivicAuthIframeContainer.d.ts.map +1 -1
  201. package/dist/esm/shared/components/CivicAuthIframeContainer.js +7 -7
  202. package/dist/esm/shared/components/CivicAuthIframeContainer.js.map +1 -1
  203. package/dist/esm/shared/components/CivicAuthLogoutIframeContainer.d.ts +7 -0
  204. package/dist/esm/shared/components/CivicAuthLogoutIframeContainer.d.ts.map +1 -0
  205. package/dist/esm/shared/components/CivicAuthLogoutIframeContainer.js +22 -0
  206. package/dist/esm/shared/components/CivicAuthLogoutIframeContainer.js.map +1 -0
  207. package/dist/esm/shared/components/IFrameAndLoading.d.ts +2 -1
  208. package/dist/esm/shared/components/IFrameAndLoading.d.ts.map +1 -1
  209. package/dist/esm/shared/components/IFrameAndLoading.js +7 -2
  210. package/dist/esm/shared/components/IFrameAndLoading.js.map +1 -1
  211. package/dist/esm/shared/hooks/index.d.ts +3 -1
  212. package/dist/esm/shared/hooks/index.d.ts.map +1 -1
  213. package/dist/esm/shared/hooks/index.js +3 -1
  214. package/dist/esm/shared/hooks/index.js.map +1 -1
  215. package/dist/esm/shared/hooks/useSignIn.d.ts +3 -2
  216. package/dist/esm/shared/hooks/useSignIn.d.ts.map +1 -1
  217. package/dist/esm/shared/hooks/useSignIn.js +70 -15
  218. package/dist/esm/shared/hooks/useSignIn.js.map +1 -1
  219. package/dist/esm/shared/hooks/useWindowFocused.d.ts +5 -0
  220. package/dist/esm/shared/hooks/useWindowFocused.d.ts.map +1 -0
  221. package/dist/esm/shared/hooks/useWindowFocused.js +21 -0
  222. package/dist/esm/shared/hooks/useWindowFocused.js.map +1 -0
  223. package/dist/esm/shared/index.d.ts +1 -0
  224. package/dist/esm/shared/index.d.ts.map +1 -1
  225. package/dist/esm/shared/index.js +3 -2
  226. package/dist/esm/shared/index.js.map +1 -1
  227. package/dist/esm/shared/lib/types.d.ts +1 -0
  228. package/dist/esm/shared/lib/types.d.ts.map +1 -1
  229. package/dist/esm/shared/lib/types.js.map +1 -1
  230. package/dist/esm/shared/lib/util.d.ts +3 -2
  231. package/dist/esm/shared/lib/util.d.ts.map +1 -1
  232. package/dist/esm/shared/lib/util.js +7 -3
  233. package/dist/esm/shared/lib/util.js.map +1 -1
  234. package/dist/esm/shared/providers/AuthContext.d.ts +1 -0
  235. package/dist/esm/shared/providers/AuthContext.d.ts.map +1 -1
  236. package/dist/esm/shared/providers/AuthContext.js.map +1 -1
  237. package/dist/esm/shared/providers/AuthProvider.d.ts +15 -4
  238. package/dist/esm/shared/providers/AuthProvider.d.ts.map +1 -1
  239. package/dist/esm/shared/providers/AuthProvider.js +12 -3
  240. package/dist/esm/shared/providers/AuthProvider.js.map +1 -1
  241. package/dist/esm/shared/providers/CivicAuthConfigContext.d.ts +3 -1
  242. package/dist/esm/shared/providers/CivicAuthConfigContext.d.ts.map +1 -1
  243. package/dist/esm/shared/providers/CivicAuthConfigContext.js +10 -1
  244. package/dist/esm/shared/providers/CivicAuthConfigContext.js.map +1 -1
  245. package/dist/esm/shared/providers/CivicAuthProvider.d.ts +1 -1
  246. package/dist/esm/shared/providers/CivicAuthProvider.d.ts.map +1 -1
  247. package/dist/esm/shared/providers/CivicAuthProvider.js +3 -3
  248. package/dist/esm/shared/providers/CivicAuthProvider.js.map +1 -1
  249. package/dist/esm/shared/providers/ClientTokenExchangeSessionProvider.d.ts.map +1 -1
  250. package/dist/esm/shared/providers/ClientTokenExchangeSessionProvider.js +8 -23
  251. package/dist/esm/shared/providers/ClientTokenExchangeSessionProvider.js.map +1 -1
  252. package/dist/esm/shared/providers/IframeProvider.d.ts +3 -0
  253. package/dist/esm/shared/providers/IframeProvider.d.ts.map +1 -1
  254. package/dist/esm/shared/providers/IframeProvider.js +9 -3
  255. package/dist/esm/shared/providers/IframeProvider.js.map +1 -1
  256. package/dist/esm/shared/providers/UserProvider.d.ts +2 -1
  257. package/dist/esm/shared/providers/UserProvider.d.ts.map +1 -1
  258. package/dist/esm/shared/providers/UserProvider.js +2 -1
  259. package/dist/esm/shared/providers/UserProvider.js.map +1 -1
  260. package/dist/esm/shared/providers/types.d.ts +3 -1
  261. package/dist/esm/shared/providers/types.d.ts.map +1 -1
  262. package/dist/esm/shared/providers/types.js.map +1 -1
  263. package/dist/esm/shared/version.d.ts +1 -1
  264. package/dist/esm/shared/version.js +1 -1
  265. package/dist/esm/shared/version.js.map +1 -1
  266. package/dist/esm/types.d.ts +1 -0
  267. package/dist/esm/types.d.ts.map +1 -1
  268. package/dist/esm/types.js.map +1 -1
  269. package/dist/esm/version.d.ts +2 -0
  270. package/dist/esm/version.d.ts.map +1 -0
  271. package/dist/esm/version.js +3 -0
  272. package/dist/esm/version.js.map +1 -0
  273. package/dist/tsconfig.cjs.tsbuildinfo +1 -1
  274. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  275. package/package.json +6 -6
@@ -1,7 +1,7 @@
1
1
  export { UserProvider, UserContext, } from "../../shared/providers/UserProvider.js";
2
2
  export { TokenProvider, TokenContext, } from "../../shared/providers/TokenProvider.js";
3
- export { AuthProvider } from "../../shared/providers/AuthProvider.js";
3
+ export { AuthProvider } from "../../reactjs/providers/AuthProvider.js";
4
4
  export { SessionProvider, SessionContext, } from "../../shared/providers/SessionProvider.js";
5
- export { CivicAuthProvider, } from "../../shared/providers/CivicAuthProvider.js";
5
+ export { CivicAuthProvider, } from "../../reactjs/providers/CivicAuthProvider.js";
6
6
  export { AuthContext } from "../../shared/providers/AuthContext.js";
7
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/reactjs/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,WAAW,GAEZ,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EACL,aAAa,EACb,YAAY,GAEb,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAElE,OAAO,EACL,eAAe,EACf,cAAc,GAEf,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EACL,iBAAiB,GAElB,MAAM,yCAAyC,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC","sourcesContent":["export {\n UserProvider,\n UserContext,\n type UserContextType,\n} from \"@/shared/providers/UserProvider.js\";\n\nexport {\n TokenProvider,\n TokenContext,\n type TokenContextType,\n} from \"@/shared/providers/TokenProvider.js\";\n\nexport { AuthProvider } from \"@/shared/providers/AuthProvider.js\";\n\nexport {\n SessionProvider,\n SessionContext,\n type SessionContextType,\n} from \"@/shared/providers/SessionProvider.js\";\n\nexport {\n CivicAuthProvider,\n type CivicAuthProviderProps,\n} from \"@/shared/providers/CivicAuthProvider.js\";\n\nexport { AuthContext } from \"@/shared/providers/AuthContext.js\";\nexport type { AuthContextType } from \"@/shared/providers/AuthContext.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/reactjs/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,WAAW,GAEZ,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EACL,aAAa,EACb,YAAY,GAEb,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAEnE,OAAO,EACL,eAAe,EACf,cAAc,GAEf,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EACL,iBAAiB,GAElB,MAAM,0CAA0C,CAAC;AAElD,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC","sourcesContent":["export {\n UserProvider,\n UserContext,\n type UserContextType,\n} from \"@/shared/providers/UserProvider.js\";\n\nexport {\n TokenProvider,\n TokenContext,\n type TokenContextType,\n} from \"@/shared/providers/TokenProvider.js\";\n\nexport { AuthProvider } from \"@/reactjs/providers/AuthProvider.js\";\n\nexport {\n SessionProvider,\n SessionContext,\n type SessionContextType,\n} from \"@/shared/providers/SessionProvider.js\";\n\nexport {\n CivicAuthProvider,\n type CivicAuthProviderProps,\n} from \"@/reactjs/providers/CivicAuthProvider.js\";\n\nexport { AuthContext } from \"@/shared/providers/AuthContext.js\";\nexport type { AuthContextType } from \"@/shared/providers/AuthContext.js\";\n"]}
@@ -14,6 +14,7 @@ export declare class ServerAuthenticationResolver implements AuthenticationResol
14
14
  init(): Promise<this>;
15
15
  tokenExchange(code: string, state: string): Promise<OIDCTokenResponseBody>;
16
16
  getSessionData(): Promise<SessionData | null>;
17
+ getEndSessionEndpoint(): Promise<string | null>;
17
18
  static build(authConfig: AuthConfig, storage: AuthStorage, endpointOverrides?: Partial<Endpoints>): Promise<AuthenticationResolver>;
18
19
  }
19
20
  //# sourceMappingURL=ServerAuthenticationResolver.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ServerAuthenticationResolver.d.ts","sourceRoot":"","sources":["../../../src/server/ServerAuthenticationResolver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EACT,qBAAqB,EACrB,WAAW,EACZ,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAOrD,OAAO,KAAK,EAAE,sBAAsB,EAAgB,MAAM,qBAAqB,CAAC;AAGhF,qBAAa,4BAA6B,YAAW,sBAAsB;IAMvE,QAAQ,CAAC,UAAU,EAAE,UAAU;IAC/B,QAAQ,CAAC,OAAO,EAAE,WAAW;IAC7B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC;IAPjD,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO,CAAC,SAAS,CAAwB;IAEzC,OAAO;IAOP,uBAAuB,IAAI,OAAO,CAAC,WAAW,CAAC;IAI/C,IAAI,WAAW,IAAI,MAAM,CAExB;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkBrB,aAAa,CACjB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,qBAAqB,CAAC;IAoB3B,cAAc,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;WAatC,KAAK,CAChB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,WAAW,EACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GACrC,OAAO,CAAC,sBAAsB,CAAC;CAUnC"}
1
+ {"version":3,"file":"ServerAuthenticationResolver.d.ts","sourceRoot":"","sources":["../../../src/server/ServerAuthenticationResolver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EACT,qBAAqB,EACrB,WAAW,EACZ,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAOrD,OAAO,KAAK,EAAE,sBAAsB,EAAgB,MAAM,qBAAqB,CAAC;AAGhF,qBAAa,4BAA6B,YAAW,sBAAsB;IAMvE,QAAQ,CAAC,UAAU,EAAE,UAAU;IAC/B,QAAQ,CAAC,OAAO,EAAE,WAAW;IAC7B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC;IAPjD,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO,CAAC,SAAS,CAAwB;IAEzC,OAAO;IAOP,uBAAuB,IAAI,OAAO,CAAC,WAAW,CAAC;IAI/C,IAAI,WAAW,IAAI,MAAM,CAExB;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkBrB,aAAa,CACjB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,qBAAqB,CAAC;IAoB3B,cAAc,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAa7C,qBAAqB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;WAOxC,KAAK,CAChB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,WAAW,EACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GACrC,OAAO,CAAC,sBAAsB,CAAC;CAUnC"}
@@ -52,6 +52,12 @@ export class ServerAuthenticationResolver {
52
52
  refreshToken: storageData.refresh_token,
53
53
  };
54
54
  }
55
+ async getEndSessionEndpoint() {
56
+ if (!this.endpoints) {
57
+ return null;
58
+ }
59
+ return this.endpoints.endsession;
60
+ }
55
61
  static async build(authConfig, storage, endpointOverrides) {
56
62
  const resolver = new ServerAuthenticationResolver(authConfig, storage, endpointOverrides);
57
63
  await resolver.init();
@@ -1 +1 @@
1
- {"version":3,"file":"ServerAuthenticationResolver.js","sourceRoot":"","sources":["../../../src/server/ServerAuthenticationResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQ3C,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,cAAc,EACd,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,OAAO,4BAA4B;IAM5B;IACA;IACA;IAPH,YAAY,CAAe;IAC3B,YAAY,CAA2B;IACvC,SAAS,CAAwB;IAEzC,YACW,UAAsB,EACtB,OAAoB,EACpB,iBAAsC;QAFtC,eAAU,GAAV,UAAU,CAAY;QACtB,YAAO,GAAP,OAAO,CAAa;QACpB,sBAAiB,GAAjB,iBAAiB,CAAqB;QAE/C,IAAI,CAAC,YAAY,GAAG,IAAI,+BAA+B,CAAC,OAAO,CAAC,CAAC;IACnE,CAAC;IACD,uBAAuB;QACrB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,UAAU,CAAC,WAAW,IAAI,mBAAmB,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,IAAI;QACR,uBAAuB;QACvB,IAAI,CAAC,SAAS,GAAG,MAAM,yBAAyB,CAC9C,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,iBAAiB,CACvB,CAAC;QACF,IAAI,CAAC,YAAY,GAAG,IAAI,YAAY,CAClC,IAAI,CAAC,UAAU,CAAC,QAAQ,EACxB,IAAI,CAAC,SAAS,CAAC,IAAI,EACnB,IAAI,CAAC,SAAS,CAAC,KAAK,EACpB;YACE,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,WAAW;SACzC,CACF,CAAC;QAEF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,IAAY,EACZ,KAAa;QAEb,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1C,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC;QAC/D,IAAI,CAAC,YAAY;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAEzE,gCAAgC;QAChC,MAAM,MAAM,GAAG,MAAM,cAAc,CACjC,IAAI,EACJ,KAAK,EACL,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,YAAa,EAAE,8CAA8C;QAClE,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,SAAU,CAChB,CAAC;QAEF,MAAM,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAExC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEvD,IAAI,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC;QAE9B,OAAO;YACL,aAAa,EAAE,CAAC,CAAC,WAAW,CAAC,QAAQ;YACrC,OAAO,EAAE,WAAW,CAAC,QAAQ;YAC7B,WAAW,EAAE,WAAW,CAAC,YAAY;YACrC,YAAY,EAAE,WAAW,CAAC,aAAa;SACxC,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,KAAK,CAChB,UAAsB,EACtB,OAAoB,EACpB,iBAAsC;QAEtC,MAAM,QAAQ,GAAG,IAAI,4BAA4B,CAC/C,UAAU,EACV,OAAO,EACP,iBAAiB,CAClB,CAAC;QACF,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEtB,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF","sourcesContent":["import { GenericPublicClientPKCEProducer } from \"@/services/PKCE.js\";\nimport { OAuth2Client } from \"oslo/oauth2\";\nimport type {\n AuthStorage,\n Endpoints,\n OIDCTokenResponseBody,\n SessionData,\n} from \"@/types.js\";\nimport type { AuthConfig } from \"@/server/config.js\";\nimport {\n exchangeTokens,\n getEndpointsWithOverrides,\n retrieveTokens,\n storeTokens,\n} from \"@/shared/lib/util.js\";\nimport type { AuthenticationResolver, PKCEProducer } from \"@/services/types.ts\";\nimport { DEFAULT_AUTH_SERVER } from \"@/constants.js\";\n\nexport class ServerAuthenticationResolver implements AuthenticationResolver {\n private pkceProducer: PKCEProducer;\n private oauth2client: OAuth2Client | undefined;\n private endpoints: Endpoints | undefined;\n\n private constructor(\n readonly authConfig: AuthConfig,\n readonly storage: AuthStorage,\n readonly endpointOverrides?: Partial<Endpoints>,\n ) {\n this.pkceProducer = new GenericPublicClientPKCEProducer(storage);\n }\n validateExistingSession(): Promise<SessionData> {\n throw new Error(\"Method not implemented.\");\n }\n\n get oauthServer(): string {\n return this.authConfig.oauthServer || DEFAULT_AUTH_SERVER;\n }\n\n async init(): Promise<this> {\n // resolve oauth config\n this.endpoints = await getEndpointsWithOverrides(\n this.oauthServer,\n this.endpointOverrides,\n );\n this.oauth2client = new OAuth2Client(\n this.authConfig.clientId,\n this.endpoints.auth,\n this.endpoints.token,\n {\n redirectURI: this.authConfig.redirectUrl,\n },\n );\n\n return this;\n }\n\n async tokenExchange(\n code: string,\n state: string,\n ): Promise<OIDCTokenResponseBody> {\n if (!this.oauth2client) await this.init();\n const codeVerifier = await this.pkceProducer.getCodeVerifier();\n if (!codeVerifier) throw new Error(\"Code verifier not found in storage\");\n\n // exchange auth code for tokens\n const tokens = await exchangeTokens(\n code,\n state,\n this.pkceProducer,\n this.oauth2client!, // clean up types here to avoid the ! operator\n this.oauthServer,\n this.endpoints!, // clean up types here to avoid the ! operator\n );\n\n await storeTokens(this.storage, tokens);\n\n return tokens;\n }\n\n async getSessionData(): Promise<SessionData | null> {\n const storageData = await retrieveTokens(this.storage);\n\n if (!storageData) return null;\n\n return {\n authenticated: !!storageData.id_token,\n idToken: storageData.id_token,\n accessToken: storageData.access_token,\n refreshToken: storageData.refresh_token,\n };\n }\n\n static async build(\n authConfig: AuthConfig,\n storage: AuthStorage,\n endpointOverrides?: Partial<Endpoints>,\n ): Promise<AuthenticationResolver> {\n const resolver = new ServerAuthenticationResolver(\n authConfig,\n storage,\n endpointOverrides,\n );\n await resolver.init();\n\n return resolver;\n }\n}\n"]}
1
+ {"version":3,"file":"ServerAuthenticationResolver.js","sourceRoot":"","sources":["../../../src/server/ServerAuthenticationResolver.ts"],"names":[],"mappings":"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","sourcesContent":["import { GenericPublicClientPKCEProducer } from \"@/services/PKCE.js\";\nimport { OAuth2Client } from \"oslo/oauth2\";\nimport type {\n AuthStorage,\n Endpoints,\n OIDCTokenResponseBody,\n SessionData,\n} from \"@/types.js\";\nimport type { AuthConfig } from \"@/server/config.js\";\nimport {\n exchangeTokens,\n getEndpointsWithOverrides,\n retrieveTokens,\n storeTokens,\n} from \"@/shared/lib/util.js\";\nimport type { AuthenticationResolver, PKCEProducer } from \"@/services/types.ts\";\nimport { DEFAULT_AUTH_SERVER } from \"@/constants.js\";\n\nexport class ServerAuthenticationResolver implements AuthenticationResolver {\n private pkceProducer: PKCEProducer;\n private oauth2client: OAuth2Client | undefined;\n private endpoints: Endpoints | undefined;\n\n private constructor(\n readonly authConfig: AuthConfig,\n readonly storage: AuthStorage,\n readonly endpointOverrides?: Partial<Endpoints>,\n ) {\n this.pkceProducer = new GenericPublicClientPKCEProducer(storage);\n }\n validateExistingSession(): Promise<SessionData> {\n throw new Error(\"Method not implemented.\");\n }\n\n get oauthServer(): string {\n return this.authConfig.oauthServer || DEFAULT_AUTH_SERVER;\n }\n\n async init(): Promise<this> {\n // resolve oauth config\n this.endpoints = await getEndpointsWithOverrides(\n this.oauthServer,\n this.endpointOverrides,\n );\n this.oauth2client = new OAuth2Client(\n this.authConfig.clientId,\n this.endpoints.auth,\n this.endpoints.token,\n {\n redirectURI: this.authConfig.redirectUrl,\n },\n );\n\n return this;\n }\n\n async tokenExchange(\n code: string,\n state: string,\n ): Promise<OIDCTokenResponseBody> {\n if (!this.oauth2client) await this.init();\n const codeVerifier = await this.pkceProducer.getCodeVerifier();\n if (!codeVerifier) throw new Error(\"Code verifier not found in storage\");\n\n // exchange auth code for tokens\n const tokens = await exchangeTokens(\n code,\n state,\n this.pkceProducer,\n this.oauth2client!, // clean up types here to avoid the ! operator\n this.oauthServer,\n this.endpoints!, // clean up types here to avoid the ! operator\n );\n\n await storeTokens(this.storage, tokens);\n\n return tokens;\n }\n\n async getSessionData(): Promise<SessionData | null> {\n const storageData = await retrieveTokens(this.storage);\n\n if (!storageData) return null;\n\n return {\n authenticated: !!storageData.id_token,\n idToken: storageData.id_token,\n accessToken: storageData.access_token,\n refreshToken: storageData.refresh_token,\n };\n }\n\n async getEndSessionEndpoint(): Promise<string | null> {\n if (!this.endpoints) {\n return null;\n }\n return this.endpoints.endsession;\n }\n\n static async build(\n authConfig: AuthConfig,\n storage: AuthStorage,\n endpointOverrides?: Partial<Endpoints>,\n ): Promise<AuthenticationResolver> {\n const resolver = new ServerAuthenticationResolver(\n authConfig,\n storage,\n endpointOverrides,\n );\n await resolver.init();\n\n return resolver;\n }\n}\n"]}
@@ -27,6 +27,8 @@ export declare class BrowserAuthenticationInitiator implements AuthenticationIni
27
27
  protected config: {
28
28
  clientId: string;
29
29
  redirectUrl: string;
30
+ logoutUrl?: string;
31
+ logoutRedirectUrl: string;
30
32
  scopes: string[];
31
33
  displayMode: DisplayMode;
32
34
  oauthServer: string;
@@ -41,7 +43,8 @@ export declare class BrowserAuthenticationInitiator implements AuthenticationIni
41
43
  constructor(config: typeof this.config);
42
44
  handleLoginAppPopupFailed(redirectUrl: string): Promise<void>;
43
45
  signIn(iframeRef: HTMLIFrameElement | null): Promise<URL>;
44
- signOut(): Promise<URL>;
46
+ protected handleIframeUrlChange(iframe: HTMLIFrameElement, expectedUrl: string): Promise<void>;
47
+ signOut(idToken: string | undefined, iframeRef: HTMLIFrameElement | null): Promise<URL>;
45
48
  cleanup(): void;
46
49
  }
47
50
  /** A general-purpose authentication initiator, that just generates urls, but lets
@@ -61,11 +64,13 @@ export declare class GenericAuthenticationInitiator implements AuthenticationIni
61
64
  };
62
65
  constructor(config: typeof this.config);
63
66
  signIn(): Promise<URL>;
64
- signOut(): Promise<URL>;
67
+ signOut(idToken: string): Promise<URL>;
65
68
  }
66
69
  type BrowserAuthenticationConfig = {
67
70
  clientId: string;
68
71
  redirectUrl: string;
72
+ logoutUrl?: string;
73
+ logoutRedirectUrl: string;
69
74
  scopes: string[];
70
75
  oauthServer: string;
71
76
  endpointOverrides?: Partial<Endpoints>;
@@ -84,6 +89,7 @@ export declare class BrowserAuthenticationService extends BrowserAuthenticationI
84
89
  tokenExchange(code: string, state: string): Promise<OIDCTokenResponseBody>;
85
90
  getSessionData(): Promise<SessionData | null>;
86
91
  validateExistingSession(): Promise<SessionData>;
92
+ getEndSessionEndpoint(): Promise<string | null>;
87
93
  static build(config: BrowserAuthenticationConfig): Promise<AuthenticationResolver>;
88
94
  }
89
95
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"AuthenticationService.d.ts","sourceRoot":"","sources":["../../../src/services/AuthenticationService.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EAET,qBAAqB,EACrB,WAAW,EACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,+BAA+B,EAEhC,MAAM,oBAAoB,CAAC;AAe5B,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACtB,YAAY,EACb,MAAM,qBAAqB,CAAC;AAQ7B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,8BAA+B,YAAW,uBAAuB;IAC5E,OAAO,CAAC,kBAAkB,CAAgD;IAE1E,SAAS,CAAC,MAAM,EAAE;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,EAAE,CAAC;QAEjB,WAAW,EAAE,WAAW,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;QAEpB,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QAEvC,YAAY,EAAE,YAAY,CAAC;QAE3B,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IAEK,cAAc,CAAC,WAAW,EAAE,WAAW;IAI9C,IAAI,WAAW,gBAEd;IAED,IAAI,qBAAqB,YAExB;IACD,IAAI,KAAK,WAER;gBACW,MAAM,EAAE,OAAO,IAAI,CAAC,MAAM;IAIhC,yBAAyB,CAAC,WAAW,EAAE,MAAM;IAU7C,MAAM,CAAC,SAAS,EAAE,iBAAiB,GAAG,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC;IAiDzD,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC;IAe7B,OAAO;CAKR;AAED;;;GAGG;AACH,qBAAa,8BAA+B,YAAW,uBAAuB;IAC5E,SAAS,CAAC,MAAM,EAAE;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QAEf,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QAEvC,YAAY,EAAE,YAAY,CAAC;KAC5B,CAAC;gBAEU,MAAM,EAAE,OAAO,IAAI,CAAC,MAAM;IAMhC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC;IAItB,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC;CAG9B;AAED,KAAK,2BAA2B,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IACvC,WAAW,EAAE,WAAW,CAAC;CAC1B,CAAC;AAEF;;;GAGG;AACH,qBAAa,4BAA6B,SAAQ,8BAA8B;IAQ5E,SAAS,CAAC,YAAY;IAPxB,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO,CAAC,SAAS,CAAwB;gBAIvC,MAAM,EAAE,2BAA2B,EAEzB,YAAY,kCAAwC;IAY1D,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBrB,aAAa,CACjB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,qBAAqB,CAAC;IA0C3B,cAAc,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAa7C,uBAAuB,IAAI,OAAO,CAAC,WAAW,CAAC;WAgCxC,KAAK,CAChB,MAAM,EAAE,2BAA2B,GAClC,OAAO,CAAC,sBAAsB,CAAC;CAMnC"}
1
+ {"version":3,"file":"AuthenticationService.d.ts","sourceRoot":"","sources":["../../../src/services/AuthenticationService.ts"],"names":[],"mappings":"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"}
@@ -94,17 +94,87 @@ export class BrowserAuthenticationInitiator {
94
94
  }
95
95
  return url;
96
96
  }
97
- async signOut() {
98
- // we only use local storage for the client-side token exchange
99
- if (!this.isServerTokenExchange) {
97
+ handleIframeUrlChange(iframe, expectedUrl) {
98
+ return new Promise((resolve, reject) => {
99
+ const checkIframe = () => {
100
+ try {
101
+ // Try to access iframe URL - this will throw if cross-origin
102
+ const currentUrl = iframe.contentWindow?.location.href;
103
+ if (currentUrl?.includes(expectedUrl)) {
104
+ clearInterval(interval);
105
+ resolve();
106
+ }
107
+ }
108
+ catch (e) {
109
+ // Ignore cross-origin errors
110
+ console.log("Cross-origin error", e);
111
+ }
112
+ };
113
+ const interval = setInterval(checkIframe, 100);
114
+ // Timeout after 10 seconds
115
+ setTimeout(() => {
116
+ clearInterval(interval);
117
+ reject(new Error("Timeout waiting for iframe URL change"));
118
+ }, 10000);
119
+ });
120
+ }
121
+ async signOut(idToken, iframeRef) {
122
+ let url;
123
+ const state = this.state;
124
+ if (this.isServerTokenExchange) {
125
+ if (!this.config.logoutUrl) {
126
+ throw new Error("logoutUrl is required for server token exchange");
127
+ }
128
+ url = new URL(this.config.logoutUrl, window.location.origin);
129
+ url.searchParams.append("state", state);
130
+ }
131
+ else {
132
+ if (!idToken) {
133
+ throw new Error("idToken is required for non-server token exchange");
134
+ }
135
+ url = await generateOauthLogoutUrl({
136
+ ...this.config,
137
+ idToken,
138
+ state,
139
+ redirectUrl: this.config.logoutRedirectUrl,
140
+ });
141
+ }
142
+ if (this.config.displayMode === "iframe") {
143
+ if (!iframeRef) {
144
+ throw new Error("iframeRef is required for displayMode 'iframe'");
145
+ }
146
+ iframeRef.setAttribute("src", url.toString());
147
+ try {
148
+ await this.handleIframeUrlChange(iframeRef, this.config.logoutRedirectUrl);
149
+ // Clear storage after successful detection
150
+ if (!this.isServerTokenExchange) {
151
+ const localStorage = new LocalStorageAdapter();
152
+ await clearTokens(localStorage);
153
+ await clearUser(localStorage);
154
+ LocalStorageAdapter.emitter.emit("signOut");
155
+ }
156
+ }
157
+ catch (error) {
158
+ console.error("Failed to detect logout URL in iframe:", error);
159
+ }
160
+ }
161
+ if (this.config.displayMode === "redirect") {
100
162
  const localStorage = new LocalStorageAdapter();
101
- await clearTokens(localStorage);
102
- await clearUser(localStorage);
103
- LocalStorageAdapter.emitter.emit("signOut");
163
+ localStorage.set("logout_state", state);
164
+ window.location.href = url.toString();
165
+ }
166
+ if (this.config.displayMode === "new_tab") {
167
+ try {
168
+ const popupWindow = window.open(url.toString(), "_blank");
169
+ if (!popupWindow) {
170
+ throw new PopupError("Failed to open popup window");
171
+ }
172
+ }
173
+ catch (error) {
174
+ console.error("popupWindow", error);
175
+ throw new PopupError("window.open has thrown: Failed to open popup window");
176
+ }
104
177
  }
105
- // TODO open the iframe or new tab etc: the logout URL is not currently
106
- // supported by on the oauth, so just clear state until then
107
- const url = await generateOauthLogoutUrl(this.config);
108
178
  return url;
109
179
  }
110
180
  cleanup() {
@@ -127,8 +197,11 @@ export class GenericAuthenticationInitiator {
127
197
  async signIn() {
128
198
  return generateOauthLoginUrl(this.config);
129
199
  }
130
- async signOut() {
131
- return generateOauthLogoutUrl(this.config);
200
+ async signOut(idToken) {
201
+ return generateOauthLogoutUrl({
202
+ ...this.config,
203
+ idToken,
204
+ });
132
205
  }
133
206
  }
134
207
  /**
@@ -234,6 +307,12 @@ export class BrowserAuthenticationService extends BrowserAuthenticationInitiator
234
307
  return unAuthenticatedSession;
235
308
  }
236
309
  }
310
+ async getEndSessionEndpoint() {
311
+ if (!this.endpoints) {
312
+ return null;
313
+ }
314
+ return this.endpoints?.endsession;
315
+ }
237
316
  static async build(config) {
238
317
  const resolver = new BrowserAuthenticationService(config);
239
318
  await resolver.init();
@@ -1 +1 @@
1
- {"version":3,"file":"AuthenticationService.js","sourceRoot":"","sources":["../../../src/services/AuthenticationService.ts"],"names":[],"mappings":"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","sourcesContent":["// Proposals for revised versions of the SessionService AKA AuthSessionService\n\nimport type {\n DisplayMode,\n Endpoints,\n LoginPostMessage,\n OIDCTokenResponseBody,\n SessionData,\n} from \"@/types.js\";\nimport {\n BrowserPublicClientPKCEProducer,\n ConfidentialClientPKCEConsumer,\n} from \"@/services/PKCE.js\";\nimport {\n clearTokens,\n clearUser,\n exchangeTokens,\n generateOauthLoginUrl,\n generateOauthLogoutUrl,\n getEndpointsWithOverrides,\n retrieveTokens,\n storeTokens,\n validateOauth2Tokens,\n} from \"@/shared/lib/util.js\";\nimport { displayModeFromState, generateState } from \"@/lib/oauth.js\";\nimport { OAuth2Client } from \"oslo/oauth2\";\nimport { LocalStorageAdapter } from \"@/browser/storage.js\";\nimport type {\n AuthenticationInitiator,\n AuthenticationResolver,\n PKCEConsumer,\n} from \"@/services/types.js\";\nimport { PopupError } from \"@/services/types.js\";\nimport { removeParamsWithoutReload } from \"@/lib/windowUtil.js\";\nimport { DEFAULT_OAUTH_GET_PARAMS } from \"@/constants.js\";\nimport { validateLoginAppPostMessage } from \"@/lib/postMessage.js\";\nimport { getUser } from \"@/shared/lib/session.js\";\nimport { GenericUserSession } from \"@/shared/lib/UserSession.js\";\n\n/**\n * An authentication initiator that works on a browser. Since this is just triggering\n * login and logout, session data is not stored here.\n * An associated AuthenticationResolver would be needed to get the session data.\n * Storage is needed for the code verifier, this is the domain of the PKCEConsumer\n * The storage used by the PKCEConsumer should be available to the AuthenticationResolver.\n *\n * Example usage:\n *\n * 1) Client-only SPA -eg a react app with no server:\n * new BrowserAuthenticationInitiator({\n * pkceConsumer: new BrowserPublicClientPKCEProducer(), // generate and retrieve the challenge client-side\n * ... other config\n * })\n *\n * 2) Client-side of a client/server app - eg a react app with a backend:\n * new BrowserAuthenticationInitiator({\n * pkceConsumer: new ConfidentialClientPKCEConsumer(\"https://myserver.com/pkce\"), // get the challenge from the server\n * ... other config\n * })\n */\nexport class BrowserAuthenticationInitiator implements AuthenticationInitiator {\n private postMessageHandler: null | ((event: MessageEvent) => void) = null;\n\n protected config: {\n clientId: string;\n redirectUrl: string;\n scopes: string[];\n // determines whether to trigger the login/logout in an iframe, a new browser window, or redirect the current one.\n displayMode: DisplayMode;\n oauthServer: string;\n // the endpoints to use for the login (if not obtained from the auth server\n endpointOverrides?: Partial<Endpoints>;\n // used to get the PKCE challenge\n pkceConsumer: PKCEConsumer;\n // the nonce to use for the login\n nonce?: string;\n };\n\n public setDisplayMode(displayMode: DisplayMode) {\n this.config.displayMode = displayMode;\n }\n\n get displayMode() {\n return this.config.displayMode;\n }\n\n get isServerTokenExchange() {\n return this.config.pkceConsumer instanceof ConfidentialClientPKCEConsumer;\n }\n get state() {\n return generateState(this.config.displayMode, this.isServerTokenExchange);\n }\n constructor(config: typeof this.config) {\n this.config = config;\n }\n\n async handleLoginAppPopupFailed(redirectUrl: string) {\n console.warn(\n \"Login app popup failed open a popup, using redirect mode instead...\",\n redirectUrl,\n );\n window.location.href = redirectUrl;\n }\n\n // Use the config (Client ID, scopes OAuth Server, Endpoints, PKCEConsumer) to generate a new login url\n // and then use the display mode to decide how to send the user there\n async signIn(iframeRef: HTMLIFrameElement | null): Promise<URL> {\n const url = await generateOauthLoginUrl({\n ...this.config,\n state: this.state,\n });\n\n this.postMessageHandler = (event: MessageEvent) => {\n const thisURL = new URL(window.location.href);\n if (\n event.origin.endsWith(\"civic.com\") ||\n thisURL.hostname === \"localhost\"\n ) {\n if (!validateLoginAppPostMessage(event.data, this.config.clientId)) {\n return;\n }\n const loginMessage = event.data as LoginPostMessage;\n this.handleLoginAppPopupFailed(loginMessage.data.url);\n }\n };\n\n window.addEventListener(\"message\", this.postMessageHandler);\n\n if (this.config.displayMode === \"iframe\") {\n if (!iframeRef)\n throw new Error(\"iframeRef is required for displayMode 'iframe'\");\n iframeRef.setAttribute(\"src\", url.toString());\n }\n\n if (this.config.displayMode === \"redirect\") {\n window.location.href = url.toString();\n }\n\n if (this.config.displayMode === \"new_tab\") {\n try {\n const popupWindow = window.open(url.toString(), \"_blank\");\n if (!popupWindow) {\n throw new PopupError(\"Failed to open popup window\");\n }\n } catch (error) {\n console.error(\"popupWindow\", error);\n throw new PopupError(\n \"window.open has thrown: Failed to open popup window\",\n );\n }\n }\n\n return url;\n }\n\n async signOut(): Promise<URL> {\n // we only use local storage for the client-side token exchange\n if (!this.isServerTokenExchange) {\n const localStorage = new LocalStorageAdapter();\n await clearTokens(localStorage);\n await clearUser(localStorage);\n LocalStorageAdapter.emitter.emit(\"signOut\");\n }\n // TODO open the iframe or new tab etc: the logout URL is not currently\n // supported by on the oauth, so just clear state until then\n const url = await generateOauthLogoutUrl(this.config);\n\n return url;\n }\n\n cleanup() {\n if (this.postMessageHandler) {\n window.removeEventListener(\"message\", this.postMessageHandler);\n }\n }\n}\n\n/** A general-purpose authentication initiator, that just generates urls, but lets\n * the caller decide how to use them. This is useful for server-side applications\n * that may serve this URL to their front-ends or just call them directly\n */\nexport class GenericAuthenticationInitiator implements AuthenticationInitiator {\n protected config: {\n clientId: string;\n redirectUrl: string;\n state: string;\n scopes: string[];\n oauthServer: string;\n nonce?: string;\n // the endpoints to use for the login (if not obtained from the auth server)\n endpointOverrides?: Partial<Endpoints>;\n // used to get the PKCE challenge\n pkceConsumer: PKCEConsumer;\n };\n\n constructor(config: typeof this.config) {\n this.config = config;\n }\n\n // Use the config (Client ID, scopes OAuth Server, Endpoints, PKCEConsumer) to generate a new login url\n // and simply return the url\n async signIn(): Promise<URL> {\n return generateOauthLoginUrl(this.config);\n }\n\n async signOut(): Promise<URL> {\n return generateOauthLogoutUrl(this.config);\n }\n}\n\ntype BrowserAuthenticationConfig = {\n clientId: string;\n redirectUrl: string;\n scopes: string[];\n oauthServer: string;\n endpointOverrides?: Partial<Endpoints>;\n displayMode: DisplayMode;\n};\n\n/**\n * An authentication resolver that can run on the browser (i.e. a public client)\n * It uses PKCE for security. PKCE and Session data are stored in local storage\n */\nexport class BrowserAuthenticationService extends BrowserAuthenticationInitiator {\n private oauth2client: OAuth2Client | undefined;\n private endpoints: Endpoints | undefined;\n\n // TODO WIP - perhaps we want to keep resolver and initiator separate here\n constructor(\n config: BrowserAuthenticationConfig,\n // Since we are running fully on the client, we produce as well as consume the PKCE challenge\n protected pkceProducer = new BrowserPublicClientPKCEProducer(),\n ) {\n super({\n ...config,\n // Store and retrieve the PKCE challenge in local storage\n pkceConsumer: pkceProducer,\n });\n }\n\n // TODO too much code duplication here between the browser and the server variant.\n // Suggestion for refactor: Standardise the config for AuthenticationResolvers and create a one-shot\n // function for generating an oauth2client from it\n async init(): Promise<this> {\n // resolve oauth config\n this.endpoints = await getEndpointsWithOverrides(\n this.config.oauthServer,\n this.config.endpointOverrides,\n );\n this.oauth2client = new OAuth2Client(\n this.config.clientId,\n this.endpoints.auth,\n this.endpoints.token,\n {\n redirectURI: this.config.redirectUrl,\n },\n );\n\n return this;\n }\n\n // Two responsibilities:\n // 1. resolve the auth code to get the tokens (should use library code)\n // 2. store the tokens in local storage\n async tokenExchange(\n code: string,\n state: string,\n ): Promise<OIDCTokenResponseBody> {\n if (!this.oauth2client) await this.init();\n const codeVerifier = await this.pkceProducer.getCodeVerifier();\n if (!codeVerifier) throw new Error(\"Code verifier not found in storage\");\n\n // exchange auth code for tokens\n const tokens = await exchangeTokens(\n code,\n state,\n this.pkceProducer,\n this.oauth2client!, // clean up types here to avoid the ! operator\n this.config.oauthServer,\n this.endpoints!, // clean up types here to avoid the ! operator\n );\n const clientStorage = new LocalStorageAdapter();\n await storeTokens(clientStorage, tokens);\n const user = await getUser(clientStorage);\n if (!user) {\n throw new Error(\"Failed to get user info\");\n }\n const userSession = new GenericUserSession(clientStorage);\n await userSession.set(user);\n LocalStorageAdapter.emitter.emit(\"signIn\");\n // cleanup the browser window if needed\n const parsedDisplayMode = displayModeFromState(\n state,\n this.config.displayMode,\n );\n\n if (parsedDisplayMode === \"new_tab\") {\n // Close the popup window\n window.addEventListener(\"beforeunload\", () => {\n window?.opener?.focus();\n });\n window.close();\n }\n // these are the default oAuth params that get added to the URL in redirect which we want to remove if present\n removeParamsWithoutReload(DEFAULT_OAUTH_GET_PARAMS);\n return tokens;\n }\n\n // Get the session data from local storage\n async getSessionData(): Promise<SessionData | null> {\n const storageData = await retrieveTokens(new LocalStorageAdapter());\n\n if (!storageData) return null;\n\n return {\n authenticated: !!storageData.id_token,\n idToken: storageData.id_token,\n accessToken: storageData.access_token,\n refreshToken: storageData.refresh_token,\n };\n }\n\n async validateExistingSession(): Promise<SessionData> {\n try {\n const sessionData = await this.getSessionData();\n if (!sessionData?.idToken || !sessionData.accessToken) {\n const unAuthenticatedSession = { ...sessionData, authenticated: false };\n // await clearTokens(new LocalStorageAdapter());\n return unAuthenticatedSession;\n }\n if (!this.endpoints || !this.oauth2client) await this.init();\n\n // this function will throw if any of the tokens are invalid\n await validateOauth2Tokens(\n {\n access_token: sessionData.accessToken,\n id_token: sessionData.idToken,\n refresh_token: sessionData.refreshToken,\n },\n this.endpoints!,\n this.oauth2client!,\n this.config.oauthServer,\n );\n return sessionData;\n } catch (error) {\n console.warn(\"Failed to validate existing tokens\", error);\n const unAuthenticatedSession = {\n authenticated: false,\n };\n await clearTokens(new LocalStorageAdapter());\n return unAuthenticatedSession;\n }\n }\n\n static async build(\n config: BrowserAuthenticationConfig,\n ): Promise<AuthenticationResolver> {\n const resolver = new BrowserAuthenticationService(config);\n await resolver.init();\n\n return resolver;\n }\n}\n"]}
1
+ {"version":3,"file":"AuthenticationService.js","sourceRoot":"","sources":["../../../src/services/AuthenticationService.ts"],"names":[],"mappings":"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","sourcesContent":["// Proposals for revised versions of the SessionService AKA AuthSessionService\n\nimport type {\n DisplayMode,\n Endpoints,\n LoginPostMessage,\n OIDCTokenResponseBody,\n SessionData,\n} from \"@/types.js\";\nimport {\n BrowserPublicClientPKCEProducer,\n ConfidentialClientPKCEConsumer,\n} from \"@/services/PKCE.js\";\nimport {\n clearTokens,\n clearUser,\n exchangeTokens,\n generateOauthLoginUrl,\n generateOauthLogoutUrl,\n getEndpointsWithOverrides,\n retrieveTokens,\n storeTokens,\n validateOauth2Tokens,\n} from \"@/shared/lib/util.js\";\nimport { displayModeFromState, generateState } from \"@/lib/oauth.js\";\nimport { OAuth2Client } from \"oslo/oauth2\";\nimport { LocalStorageAdapter } from \"@/browser/storage.js\";\nimport type {\n AuthenticationInitiator,\n AuthenticationResolver,\n PKCEConsumer,\n} from \"@/services/types.js\";\nimport { PopupError } from \"@/services/types.js\";\nimport { removeParamsWithoutReload } from \"@/lib/windowUtil.js\";\nimport { DEFAULT_OAUTH_GET_PARAMS } from \"@/constants.js\";\nimport { validateLoginAppPostMessage } from \"@/lib/postMessage.js\";\nimport { getUser } from \"@/shared/lib/session.js\";\nimport { GenericUserSession } from \"@/shared/lib/UserSession.js\";\n\n/**\n * An authentication initiator that works on a browser. Since this is just triggering\n * login and logout, session data is not stored here.\n * An associated AuthenticationResolver would be needed to get the session data.\n * Storage is needed for the code verifier, this is the domain of the PKCEConsumer\n * The storage used by the PKCEConsumer should be available to the AuthenticationResolver.\n *\n * Example usage:\n *\n * 1) Client-only SPA -eg a react app with no server:\n * new BrowserAuthenticationInitiator({\n * pkceConsumer: new BrowserPublicClientPKCEProducer(), // generate and retrieve the challenge client-side\n * ... other config\n * })\n *\n * 2) Client-side of a client/server app - eg a react app with a backend:\n * new BrowserAuthenticationInitiator({\n * pkceConsumer: new ConfidentialClientPKCEConsumer(\"https://myserver.com/pkce\"), // get the challenge from the server\n * ... other config\n * })\n */\nexport class BrowserAuthenticationInitiator implements AuthenticationInitiator {\n private postMessageHandler: null | ((event: MessageEvent) => void) = null;\n\n protected config: {\n clientId: string;\n redirectUrl: string;\n logoutUrl?: string;\n logoutRedirectUrl: string;\n scopes: string[];\n // determines whether to trigger the login/logout in an iframe, a new browser window, or redirect the current one.\n displayMode: DisplayMode;\n oauthServer: string;\n // the endpoints to use for the login (if not obtained from the auth server\n endpointOverrides?: Partial<Endpoints>;\n // used to get the PKCE challenge\n pkceConsumer: PKCEConsumer;\n // the nonce to use for the login\n nonce?: string;\n };\n\n public setDisplayMode(displayMode: DisplayMode) {\n this.config.displayMode = displayMode;\n }\n\n get displayMode() {\n return this.config.displayMode;\n }\n\n get isServerTokenExchange() {\n return this.config.pkceConsumer instanceof ConfidentialClientPKCEConsumer;\n }\n get state() {\n return generateState(this.config.displayMode, this.isServerTokenExchange);\n }\n constructor(config: typeof this.config) {\n this.config = config;\n }\n\n async handleLoginAppPopupFailed(redirectUrl: string) {\n console.warn(\n \"Login app popup failed open a popup, using redirect mode instead...\",\n redirectUrl,\n );\n window.location.href = redirectUrl;\n }\n\n // Use the config (Client ID, scopes OAuth Server, Endpoints, PKCEConsumer) to generate a new login url\n // and then use the display mode to decide how to send the user there\n async signIn(iframeRef: HTMLIFrameElement | null): Promise<URL> {\n const url = await generateOauthLoginUrl({\n ...this.config,\n state: this.state,\n });\n\n this.postMessageHandler = (event: MessageEvent) => {\n const thisURL = new URL(window.location.href);\n if (\n event.origin.endsWith(\"civic.com\") ||\n thisURL.hostname === \"localhost\"\n ) {\n if (!validateLoginAppPostMessage(event.data, this.config.clientId)) {\n return;\n }\n const loginMessage = event.data as LoginPostMessage;\n this.handleLoginAppPopupFailed(loginMessage.data.url);\n }\n };\n\n window.addEventListener(\"message\", this.postMessageHandler);\n\n if (this.config.displayMode === \"iframe\") {\n if (!iframeRef)\n throw new Error(\"iframeRef is required for displayMode 'iframe'\");\n iframeRef.setAttribute(\"src\", url.toString());\n }\n\n if (this.config.displayMode === \"redirect\") {\n window.location.href = url.toString();\n }\n\n if (this.config.displayMode === \"new_tab\") {\n try {\n const popupWindow = window.open(url.toString(), \"_blank\");\n if (!popupWindow) {\n throw new PopupError(\"Failed to open popup window\");\n }\n } catch (error) {\n console.error(\"popupWindow\", error);\n throw new PopupError(\n \"window.open has thrown: Failed to open popup window\",\n );\n }\n }\n\n return url;\n }\n\n protected handleIframeUrlChange(\n iframe: HTMLIFrameElement,\n expectedUrl: string,\n ): Promise<void> {\n return new Promise((resolve, reject) => {\n const checkIframe = () => {\n try {\n // Try to access iframe URL - this will throw if cross-origin\n const currentUrl = iframe.contentWindow?.location.href;\n if (currentUrl?.includes(expectedUrl)) {\n clearInterval(interval);\n resolve();\n }\n } catch (e) {\n // Ignore cross-origin errors\n console.log(\"Cross-origin error\", e);\n }\n };\n\n const interval = setInterval(checkIframe, 100);\n // Timeout after 10 seconds\n setTimeout(() => {\n clearInterval(interval);\n reject(new Error(\"Timeout waiting for iframe URL change\"));\n }, 10000);\n });\n }\n\n async signOut(\n idToken: string | undefined,\n iframeRef: HTMLIFrameElement | null,\n ): Promise<URL> {\n let url;\n const state = this.state;\n if (this.isServerTokenExchange) {\n if (!this.config.logoutUrl) {\n throw new Error(\"logoutUrl is required for server token exchange\");\n }\n url = new URL(this.config.logoutUrl, window.location.origin);\n url.searchParams.append(\"state\", state);\n } else {\n if (!idToken) {\n throw new Error(\"idToken is required for non-server token exchange\");\n }\n url = await generateOauthLogoutUrl({\n ...this.config,\n idToken,\n state,\n redirectUrl: this.config.logoutRedirectUrl,\n });\n }\n\n if (this.config.displayMode === \"iframe\") {\n if (!iframeRef) {\n throw new Error(\"iframeRef is required for displayMode 'iframe'\");\n }\n iframeRef.setAttribute(\"src\", url.toString());\n\n try {\n await this.handleIframeUrlChange(\n iframeRef,\n this.config.logoutRedirectUrl,\n );\n\n // Clear storage after successful detection\n if (!this.isServerTokenExchange) {\n const localStorage = new LocalStorageAdapter();\n await clearTokens(localStorage);\n await clearUser(localStorage);\n LocalStorageAdapter.emitter.emit(\"signOut\");\n }\n } catch (error) {\n console.error(\"Failed to detect logout URL in iframe:\", error);\n }\n }\n\n if (this.config.displayMode === \"redirect\") {\n const localStorage = new LocalStorageAdapter();\n localStorage.set(\"logout_state\", state);\n window.location.href = url.toString();\n }\n\n if (this.config.displayMode === \"new_tab\") {\n try {\n const popupWindow = window.open(url.toString(), \"_blank\");\n if (!popupWindow) {\n throw new PopupError(\"Failed to open popup window\");\n }\n } catch (error) {\n console.error(\"popupWindow\", error);\n throw new PopupError(\n \"window.open has thrown: Failed to open popup window\",\n );\n }\n }\n\n return url;\n }\n\n cleanup() {\n if (this.postMessageHandler) {\n window.removeEventListener(\"message\", this.postMessageHandler);\n }\n }\n}\n\n/** A general-purpose authentication initiator, that just generates urls, but lets\n * the caller decide how to use them. This is useful for server-side applications\n * that may serve this URL to their front-ends or just call them directly\n */\nexport class GenericAuthenticationInitiator implements AuthenticationInitiator {\n protected config: {\n clientId: string;\n redirectUrl: string;\n state: string;\n scopes: string[];\n oauthServer: string;\n nonce?: string;\n // the endpoints to use for the login (if not obtained from the auth server)\n endpointOverrides?: Partial<Endpoints>;\n // used to get the PKCE challenge\n pkceConsumer: PKCEConsumer;\n };\n\n constructor(config: typeof this.config) {\n this.config = config;\n }\n\n // Use the config (Client ID, scopes OAuth Server, Endpoints, PKCEConsumer) to generate a new login url\n // and simply return the url\n async signIn(): Promise<URL> {\n return generateOauthLoginUrl(this.config);\n }\n\n async signOut(idToken: string): Promise<URL> {\n return generateOauthLogoutUrl({\n ...this.config,\n idToken,\n });\n }\n}\n\ntype BrowserAuthenticationConfig = {\n clientId: string;\n redirectUrl: string;\n logoutUrl?: string;\n logoutRedirectUrl: string;\n scopes: string[];\n oauthServer: string;\n endpointOverrides?: Partial<Endpoints>;\n displayMode: DisplayMode;\n};\n\n/**\n * An authentication resolver that can run on the browser (i.e. a public client)\n * It uses PKCE for security. PKCE and Session data are stored in local storage\n */\nexport class BrowserAuthenticationService extends BrowserAuthenticationInitiator {\n private oauth2client: OAuth2Client | undefined;\n private endpoints: Endpoints | undefined;\n\n // TODO WIP - perhaps we want to keep resolver and initiator separate here\n constructor(\n config: BrowserAuthenticationConfig,\n // Since we are running fully on the client, we produce as well as consume the PKCE challenge\n protected pkceProducer = new BrowserPublicClientPKCEProducer(),\n ) {\n super({\n ...config,\n // Store and retrieve the PKCE challenge in local storage\n pkceConsumer: pkceProducer,\n });\n }\n\n // TODO too much code duplication here between the browser and the server variant.\n // Suggestion for refactor: Standardise the config for AuthenticationResolvers and create a one-shot\n // function for generating an oauth2client from it\n async init(): Promise<this> {\n // resolve oauth config\n this.endpoints = await getEndpointsWithOverrides(\n this.config.oauthServer,\n this.config.endpointOverrides,\n );\n this.oauth2client = new OAuth2Client(\n this.config.clientId,\n this.endpoints.auth,\n this.endpoints.token,\n {\n redirectURI: this.config.redirectUrl,\n },\n );\n\n return this;\n }\n\n // Two responsibilities:\n // 1. resolve the auth code to get the tokens (should use library code)\n // 2. store the tokens in local storage\n async tokenExchange(\n code: string,\n state: string,\n ): Promise<OIDCTokenResponseBody> {\n if (!this.oauth2client) await this.init();\n const codeVerifier = await this.pkceProducer.getCodeVerifier();\n if (!codeVerifier) throw new Error(\"Code verifier not found in storage\");\n\n // exchange auth code for tokens\n const tokens = await exchangeTokens(\n code,\n state,\n this.pkceProducer,\n this.oauth2client!, // clean up types here to avoid the ! operator\n this.config.oauthServer,\n this.endpoints!, // clean up types here to avoid the ! operator\n );\n const clientStorage = new LocalStorageAdapter();\n await storeTokens(clientStorage, tokens);\n const user = await getUser(clientStorage);\n if (!user) {\n throw new Error(\"Failed to get user info\");\n }\n const userSession = new GenericUserSession(clientStorage);\n await userSession.set(user);\n LocalStorageAdapter.emitter.emit(\"signIn\");\n // cleanup the browser window if needed\n const parsedDisplayMode = displayModeFromState(\n state,\n this.config.displayMode,\n );\n\n if (parsedDisplayMode === \"new_tab\") {\n // Close the popup window\n window.addEventListener(\"beforeunload\", () => {\n window?.opener?.focus();\n });\n window.close();\n }\n // these are the default oAuth params that get added to the URL in redirect which we want to remove if present\n removeParamsWithoutReload(DEFAULT_OAUTH_GET_PARAMS);\n return tokens;\n }\n\n // Get the session data from local storage\n async getSessionData(): Promise<SessionData | null> {\n const storageData = await retrieveTokens(new LocalStorageAdapter());\n\n if (!storageData) return null;\n\n return {\n authenticated: !!storageData.id_token,\n idToken: storageData.id_token,\n accessToken: storageData.access_token,\n refreshToken: storageData.refresh_token,\n };\n }\n\n async validateExistingSession(): Promise<SessionData> {\n try {\n const sessionData = await this.getSessionData();\n if (!sessionData?.idToken || !sessionData.accessToken) {\n const unAuthenticatedSession = { ...sessionData, authenticated: false };\n // await clearTokens(new LocalStorageAdapter());\n return unAuthenticatedSession;\n }\n if (!this.endpoints || !this.oauth2client) await this.init();\n\n // this function will throw if any of the tokens are invalid\n await validateOauth2Tokens(\n {\n access_token: sessionData.accessToken,\n id_token: sessionData.idToken,\n refresh_token: sessionData.refreshToken,\n },\n this.endpoints!,\n this.oauth2client!,\n this.config.oauthServer,\n );\n return sessionData;\n } catch (error) {\n console.warn(\"Failed to validate existing tokens\", error);\n const unAuthenticatedSession = {\n authenticated: false,\n };\n await clearTokens(new LocalStorageAdapter());\n return unAuthenticatedSession;\n }\n }\n\n async getEndSessionEndpoint(): Promise<string | null> {\n if (!this.endpoints) {\n return null;\n }\n return this.endpoints?.endsession;\n }\n\n static async build(\n config: BrowserAuthenticationConfig,\n ): Promise<AuthenticationResolver> {\n const resolver = new BrowserAuthenticationService(config);\n await resolver.init();\n\n return resolver;\n }\n}\n"]}
@@ -7,11 +7,12 @@ export interface PKCEProducer extends PKCEConsumer {
7
7
  }
8
8
  export interface AuthenticationInitiator {
9
9
  signIn(iframeRef: HTMLIFrameElement | null): Promise<URL>;
10
- signOut(): Promise<URL>;
10
+ signOut(idToken: string, iframeRef: HTMLIFrameElement | null): Promise<URL>;
11
11
  }
12
12
  export interface AuthenticationResolver {
13
13
  tokenExchange(code: string, state: string): Promise<OIDCTokenResponseBody>;
14
14
  getSessionData(): Promise<SessionData | null>;
15
+ getEndSessionEndpoint(): Promise<string | null>;
15
16
  validateExistingSession(): Promise<SessionData>;
16
17
  }
17
18
  export interface AuthenticationRefresher {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AASrE,MAAM,WAAW,YAAY;IAE3B,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACrC;AAGD,MAAM,WAAW,YAAa,SAAQ,YAAY;IAEhD,eAAe,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC3C;AAGD,MAAM,WAAW,uBAAuB;IAEtC,MAAM,CAAC,SAAS,EAAE,iBAAiB,GAAG,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAG1D,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC;CACzB;AAGD,MAAM,WAAW,sBAAsB;IAKrC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAG3E,cAAc,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAG9C,uBAAuB,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,MAAM,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACrD;AAED,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM;CAI5B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AASrE,MAAM,WAAW,YAAY;IAE3B,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACrC;AAGD,MAAM,WAAW,YAAa,SAAQ,YAAY;IAEhD,eAAe,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC3C;AAGD,MAAM,WAAW,uBAAuB;IAEtC,MAAM,CAAC,SAAS,EAAE,iBAAiB,GAAG,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAG1D,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,iBAAiB,GAAG,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;CAC7E;AAGD,MAAM,WAAW,sBAAsB;IAKrC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAG3E,cAAc,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAE9C,qBAAqB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAEhD,uBAAuB,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,MAAM,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACrD;AAED,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM;CAI5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/services/types.ts"],"names":[],"mappings":"AAgDA,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF","sourcesContent":["import type { OIDCTokenResponseBody, SessionData } from \"@/types.js\";\n\n// A PKCEConsumer can get a code challenge to use in the login process\n// A PKCEProducer can also generate and store verifiers. The producer must also be a consumer in order to get the challenge from an existing flow\n// Examples:\n// - Client-only SPA: The SPA generates the code challenge and verifier, stores the verifier in state and returns the code challenge\n// Note - The SPA should use PKCEProducer instead to do both\n// - Client-side of a client/server app: The client calls the backend to get the challenge.\n// - Server-side: The server should generate a new stored verifier and derive the challenge from it.\nexport interface PKCEConsumer {\n // Retrieve a new PKCE challenge\n getCodeChallenge(): Promise<string>;\n}\n\n// All producers are consumers, because the producer can get its own challenge\nexport interface PKCEProducer extends PKCEConsumer {\n // Retrieve the PKCE challenge from the session if one exists\n getCodeVerifier(): Promise<string | null>;\n}\n\n// A service that can initiate requests to login or log out\nexport interface AuthenticationInitiator {\n // trigger a new login\n signIn(iframeRef: HTMLIFrameElement | null): Promise<URL>;\n\n // trigger a new logout\n signOut(): Promise<URL>;\n}\n\n// A service that can resolve an authentication request according to the OAuth Auth Code grant types\nexport interface AuthenticationResolver {\n // Given an auth code, get the tokens from the auth server and store them. works in PKCE and non-PKCE environments\n // Note, if we choose later to implement other grants, this method would move into a subinterface specifically\n // for the authorization code grant type.\n // The return type is just for convenience and can be ignored, as the same data would be provided by getSessionData\n tokenExchange(code: string, state: string): Promise<OIDCTokenResponseBody>;\n\n // If the tokens have already been retrieved, return them\n getSessionData(): Promise<SessionData | null>;\n\n // If an existing session is found, validate it and return the session data\n validateExistingSession(): Promise<SessionData>;\n}\n\nexport interface AuthenticationRefresher {\n refreshTokens: () => Promise<OIDCTokenResponseBody>;\n}\n\nexport class PopupError extends Error {\n constructor(message: string) {\n super(message);\n Object.setPrototypeOf(this, PopupError.prototype);\n }\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/services/types.ts"],"names":[],"mappings":"AAiDA,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF","sourcesContent":["import type { OIDCTokenResponseBody, SessionData } from \"@/types.js\";\n\n// A PKCEConsumer can get a code challenge to use in the login process\n// A PKCEProducer can also generate and store verifiers. The producer must also be a consumer in order to get the challenge from an existing flow\n// Examples:\n// - Client-only SPA: The SPA generates the code challenge and verifier, stores the verifier in state and returns the code challenge\n// Note - The SPA should use PKCEProducer instead to do both\n// - Client-side of a client/server app: The client calls the backend to get the challenge.\n// - Server-side: The server should generate a new stored verifier and derive the challenge from it.\nexport interface PKCEConsumer {\n // Retrieve a new PKCE challenge\n getCodeChallenge(): Promise<string>;\n}\n\n// All producers are consumers, because the producer can get its own challenge\nexport interface PKCEProducer extends PKCEConsumer {\n // Retrieve the PKCE challenge from the session if one exists\n getCodeVerifier(): Promise<string | null>;\n}\n\n// A service that can initiate requests to login or log out\nexport interface AuthenticationInitiator {\n // trigger a new login\n signIn(iframeRef: HTMLIFrameElement | null): Promise<URL>;\n\n // trigger a new logout\n signOut(idToken: string, iframeRef: HTMLIFrameElement | null): Promise<URL>;\n}\n\n// A service that can resolve an authentication request according to the OAuth Auth Code grant types\nexport interface AuthenticationResolver {\n // Given an auth code, get the tokens from the auth server and store them. works in PKCE and non-PKCE environments\n // Note, if we choose later to implement other grants, this method would move into a subinterface specifically\n // for the authorization code grant type.\n // The return type is just for convenience and can be ignored, as the same data would be provided by getSessionData\n tokenExchange(code: string, state: string): Promise<OIDCTokenResponseBody>;\n\n // If the tokens have already been retrieved, return them\n getSessionData(): Promise<SessionData | null>;\n\n getEndSessionEndpoint(): Promise<string | null>;\n // If an existing session is found, validate it and return the session data\n validateExistingSession(): Promise<SessionData>;\n}\n\nexport interface AuthenticationRefresher {\n refreshTokens: () => Promise<OIDCTokenResponseBody>;\n}\n\nexport class PopupError extends Error {\n constructor(message: string) {\n super(message);\n Object.setPrototypeOf(this, PopupError.prototype);\n }\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
  type CivicAuthIframeProps = {
3
3
  onLoad?: () => void;
4
+ id: string;
4
5
  };
5
6
  declare const CivicAuthIframe: React.ForwardRefExoticComponent<CivicAuthIframeProps & React.RefAttributes<HTMLIFrameElement>>;
6
7
  export type { CivicAuthIframeProps };
@@ -1 +1 @@
1
- {"version":3,"file":"CivicAuthIframe.d.ts","sourceRoot":"","sources":["../../../../src/shared/components/CivicAuthIframe.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAE1C,KAAK,oBAAoB,GAAG;IAC1B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,QAAA,MAAM,eAAe,gGAWpB,CAAC;AAIF,YAAY,EAAE,oBAAoB,EAAE,CAAC;AAErC,OAAO,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"CivicAuthIframe.d.ts","sourceRoot":"","sources":["../../../../src/shared/components/CivicAuthIframe.tsx"],"names":[],"mappings":"AACA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAE1C,KAAK,oBAAoB,GAAG;IAC1B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,QAAA,MAAM,eAAe,gGAWpB,CAAC;AAIF,YAAY,EAAE,oBAAoB,EAAE,CAAC;AAErC,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -1,8 +1,7 @@
1
1
  "use client";
2
- import { IFRAME_ID } from "../../constants.js";
3
2
  import React, { forwardRef } from "react";
4
- const CivicAuthIframe = forwardRef(({ onLoad }, ref) => {
5
- return (React.createElement("iframe", { id: IFRAME_ID, ref: ref, style: { height: "28rem", width: "100%", border: "none" }, onLoad: onLoad }));
3
+ const CivicAuthIframe = forwardRef(({ onLoad, id }, ref) => {
4
+ return (React.createElement("iframe", { id: id, ref: ref, style: { height: "28rem", width: "100%", border: "none" }, onLoad: onLoad }));
6
5
  });
7
6
  CivicAuthIframe.displayName = "CivicAuthIframe";
8
7
  export { CivicAuthIframe };
@@ -1 +1 @@
1
- {"version":3,"file":"CivicAuthIframe.js","sourceRoot":"","sources":["../../../../src/shared/components/CivicAuthIframe.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAM1C,MAAM,eAAe,GAAG,UAAU,CAChC,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,EAAE;IAClB,OAAO,CACL,gCACE,EAAE,EAAE,SAAS,EACb,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EACzD,MAAM,EAAE,MAAM,GACd,CACH,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,eAAe,CAAC,WAAW,GAAG,iBAAiB,CAAC;AAIhD,OAAO,EAAE,eAAe,EAAE,CAAC","sourcesContent":["\"use client\";\nimport { IFRAME_ID } from \"@/constants.js\";\nimport React, { forwardRef } from \"react\";\n\ntype CivicAuthIframeProps = {\n onLoad?: () => void;\n};\n\nconst CivicAuthIframe = forwardRef<HTMLIFrameElement, CivicAuthIframeProps>(\n ({ onLoad }, ref) => {\n return (\n <iframe\n id={IFRAME_ID}\n ref={ref}\n style={{ height: \"28rem\", width: \"100%\", border: \"none\" }}\n onLoad={onLoad}\n />\n );\n },\n);\n\nCivicAuthIframe.displayName = \"CivicAuthIframe\";\n\nexport type { CivicAuthIframeProps };\n\nexport { CivicAuthIframe };\n"]}
1
+ {"version":3,"file":"CivicAuthIframe.js","sourceRoot":"","sources":["../../../../src/shared/components/CivicAuthIframe.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAO1C,MAAM,eAAe,GAAG,UAAU,CAChC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE;IACtB,OAAO,CACL,gCACE,EAAE,EAAE,EAAE,EACN,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EACzD,MAAM,EAAE,MAAM,GACd,CACH,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,eAAe,CAAC,WAAW,GAAG,iBAAiB,CAAC;AAIhD,OAAO,EAAE,eAAe,EAAE,CAAC","sourcesContent":["\"use client\";\nimport React, { forwardRef } from \"react\";\n\ntype CivicAuthIframeProps = {\n onLoad?: () => void;\n id: string;\n};\n\nconst CivicAuthIframe = forwardRef<HTMLIFrameElement, CivicAuthIframeProps>(\n ({ onLoad, id }, ref) => {\n return (\n <iframe\n id={id}\n ref={ref}\n style={{ height: \"28rem\", width: \"100%\", border: \"none\" }}\n onLoad={onLoad}\n />\n );\n },\n);\n\nCivicAuthIframe.displayName = \"CivicAuthIframe\";\n\nexport type { CivicAuthIframeProps };\n\nexport { CivicAuthIframe };\n"]}
@@ -3,6 +3,10 @@ type CivicAuthIframeContainerProps = {
3
3
  onClose?: () => void;
4
4
  closeOnRedirect?: boolean;
5
5
  };
6
+ export declare function IframeChrome({ children, onClose, }: {
7
+ children: React.ReactNode;
8
+ onClose?: () => void;
9
+ }): React.JSX.Element;
6
10
  declare const CivicAuthIframeContainer: ({ onClose, closeOnRedirect, }: CivicAuthIframeContainerProps) => React.JSX.Element;
7
11
  export type { CivicAuthIframeContainerProps };
8
12
  export { CivicAuthIframeContainer };
@@ -1 +1 @@
1
- {"version":3,"file":"CivicAuthIframeContainer.d.ts","sourceRoot":"","sources":["../../../../src/shared/components/CivicAuthIframeContainer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAUxE,KAAK,6BAA6B,GAAG;IACnC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAuEF,QAAA,MAAM,wBAAwB,kCAG3B,6BAA6B,sBA8G/B,CAAC;AAEF,YAAY,EAAE,6BAA6B,EAAE,CAAC;AAE9C,OAAO,EAAE,wBAAwB,EAAE,CAAC"}
1
+ {"version":3,"file":"CivicAuthIframeContainer.d.ts","sourceRoot":"","sources":["../../../../src/shared/components/CivicAuthIframeContainer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAUxE,KAAK,6BAA6B,GAAG;IACnC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAWF,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,OAAO,GACR,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,qBAsDA;AAED,QAAA,MAAM,wBAAwB,kCAG3B,6BAA6B,sBAiH/B,CAAC;AAEF,YAAY,EAAE,6BAA6B,EAAE,CAAC;AAE9C,OAAO,EAAE,wBAAwB,EAAE,CAAC"}
@@ -11,9 +11,9 @@ import { useSession } from "../../shared/hooks/index.js";
11
11
  function NoChrome({ children, }) {
12
12
  return React.createElement("div", { style: { position: "relative" } }, children);
13
13
  }
14
- function IframeChrome({ children, onClose, }) {
14
+ export function IframeChrome({ children, onClose, }) {
15
15
  return (React.createElement("div", { style: {
16
- position: "absolute",
16
+ position: "fixed", // Change to fixed to stay in viewport
17
17
  left: 0,
18
18
  top: 0,
19
19
  zIndex: 50,
@@ -23,7 +23,8 @@ function IframeChrome({ children, onClose, }) {
23
23
  minWidth: "18rem",
24
24
  alignItems: "center",
25
25
  justifyContent: "center",
26
- backgroundColor: "rgba(17, 24, 39, 0.5)",
26
+ backgroundColor: "rgba(17, 24, 39, 0.5)", // Semi-transparent dark background
27
+ backdropFilter: "blur(4px)", // Optional: adds slight blur to background
27
28
  }, onClick: onClose },
28
29
  React.createElement("div", { style: {
29
30
  position: "relative",
@@ -93,9 +94,8 @@ const CivicAuthIframeContainer = ({ onClose, closeOnRedirect = true, }) => {
93
94
  return true; // Successfully processed the URL
94
95
  }
95
96
  }
96
- catch {
97
- // If we get here, the iframe hasn't redirected to our origin yet
98
- console.log("Waiting for redirect...");
97
+ catch (e) {
98
+ console.log("Waiting for redirect...", e);
99
99
  }
100
100
  }
101
101
  return false; // Haven't processed the URL yet
@@ -132,7 +132,7 @@ const CivicAuthIframeContainer = ({ onClose, closeOnRedirect = true, }) => {
132
132
  backgroundColor: "white",
133
133
  } },
134
134
  React.createElement(LoadingIcon, null))) : null,
135
- React.createElement(CivicAuthIframe, { ref: iframeRef, onLoad: handleIframeLoad })));
135
+ React.createElement(CivicAuthIframe, { ref: iframeRef, id: "civic-auth-iframe", onLoad: handleIframeLoad })));
136
136
  };
137
137
  export { CivicAuthIframeContainer };
138
138
  //# sourceMappingURL=CivicAuthIframeContainer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CivicAuthIframeContainer.js","sourceRoot":"","sources":["../../../../src/shared/components/CivicAuthIframeContainer.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { LoadingIcon } from \"@/shared/components/LoadingIcon.js\";\nimport { CloseIcon } from \"@/shared/components/CloseIcon.js\";\nimport { CivicAuthIframe } from \"@/shared/components/CivicAuthIframe.js\";\nimport { useIframe } from \"@/shared/hooks/index.js\";\nimport { TOKEN_EXCHANGE_TRIGGER_TEXT } from \"@/constants.js\";\nimport { useCivicAuthConfig } from \"@/shared/hooks/index.js\";\nimport { useClientTokenExchangeSession } from \"@/shared/hooks/index.js\";\nimport { useSession } from \"@/shared/hooks/index.js\";\n\ntype CivicAuthIframeContainerProps = {\n onClose?: () => void;\n closeOnRedirect?: boolean;\n};\n\nfunction NoChrome({\n children,\n}: {\n children: React.ReactNode;\n onClose?: () => void;\n}) {\n return <div style={{ position: \"relative\" }}>{children}</div>;\n}\n\nfunction IframeChrome({\n children,\n onClose,\n}: {\n children: React.ReactNode;\n onClose?: () => void;\n}) {\n return (\n <div\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n zIndex: 50,\n display: \"flex\",\n height: \"100vh\",\n width: \"100vw\",\n minWidth: \"18rem\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"rgba(17, 24, 39, 0.5)\",\n }}\n onClick={onClose}\n >\n <div\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n borderRadius: \"1.5rem\",\n backgroundColor: \"white\",\n padding: \"1.5rem\",\n boxShadow:\n \"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)\",\n }}\n onClick={(e) => e.stopPropagation()}\n >\n <button\n style={{\n position: \"absolute\",\n right: \"1rem\",\n top: \"1rem\",\n display: \"flex\",\n cursor: \"pointer\",\n alignItems: \"center\",\n justifyContent: \"center\",\n border: \"none\",\n backgroundColor: \"transparent\",\n padding: \"0.25rem\",\n color: \"#9ca3af\",\n }}\n onClick={onClose}\n >\n <CloseIcon />\n </button>\n\n {children}\n </div>\n </div>\n );\n}\nconst CivicAuthIframeContainer = ({\n onClose,\n closeOnRedirect = true,\n}: CivicAuthIframeContainerProps) => {\n const [isLoading, setIsLoading] = useState(true);\n const { isLoading: isAuthLoading, data: session } = useSession();\n const config = useCivicAuthConfig();\n const [tokenExchangeUrl, setTokenExchangeUrl] = useState<string | null>(null);\n const { doTokenExchange } = useClientTokenExchangeSession();\n const { iframeRef, iframeMode } = useIframe();\n\n useEffect(() => {\n if (tokenExchangeUrl) {\n doTokenExchange?.(tokenExchangeUrl);\n }\n }, [doTokenExchange, tokenExchangeUrl]);\n\n const processIframeUrl = useCallback(() => {\n if (!config) return;\n if (iframeRef && iframeRef.current && iframeRef.current.contentWindow) {\n try {\n const iframeUrl = iframeRef.current.contentWindow.location.href;\n // we know that oauth has finished when the iframe redirects to our redirectUrl\n if (iframeUrl.startsWith(config.redirectUrl)) {\n // we still want to show the spinner during redirect\n setIsLoading(true);\n const iframeBody =\n iframeRef.current.contentWindow.document.body.innerHTML;\n\n // If we're doing a server token exchange, we need to call the server a second time\n // using a fetch so that we're on the same domain and cookies can be sent and read\n // The server will use the presence of the code_verifier cookie to determine whether to do a token exchange or not.\n // On the initial (3rd party) redirect from the auth server, the cookie won't be sent, so the server-side callback route will just render a blank page,\n // and we'll do the exchange request from here, which will include the cookies.\n if (iframeBody.includes(TOKEN_EXCHANGE_TRIGGER_TEXT)) {\n const params = new URL(iframeUrl).searchParams;\n const appUrl = globalThis.window?.location?.origin;\n fetch(\n `${config.redirectUrl}?${params.toString()}&appUrl=${appUrl}`,\n );\n } else {\n // if we're doing token-exchange in the client, we can just set the authResponseUrl\n // to be handled by the auth provider\n // iframeRef.current.setAttribute(\"src\", \"\");\n setTokenExchangeUrl(iframeUrl);\n }\n\n if (closeOnRedirect) onClose?.();\n return true; // Successfully processed the URL\n }\n } catch {\n // If we get here, the iframe hasn't redirected to our origin yet\n console.log(\"Waiting for redirect...\");\n }\n }\n return false; // Haven't processed the URL yet\n }, [closeOnRedirect, config, iframeRef, onClose]);\n\n const intervalId = useRef<NodeJS.Timeout>();\n\n const handleEscape = useCallback(\n (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n onClose?.();\n }\n },\n [onClose],\n );\n\n // handle Escape\n useEffect(() => {\n window.addEventListener(\"keydown\", handleEscape);\n\n return () => window.removeEventListener(\"keydown\", handleEscape);\n });\n\n const handleIframeLoad = useCallback(() => {\n setIsLoading(false);\n\n const iframeHasUrl = processIframeUrl();\n\n if (iframeHasUrl && intervalId.current) {\n clearInterval(intervalId.current);\n }\n }, [processIframeUrl, setIsLoading, intervalId]);\n\n // if we're already authenticated then we're waiting either for the iframe to be closed\n // or the page to redirect, so we want to show the loading icon\n const showLoadingIcon = session?.authenticated || isLoading || isAuthLoading;\n\n const WrapperComponent = iframeMode === \"embedded\" ? NoChrome : IframeChrome;\n\n return (\n <WrapperComponent onClose={onClose}>\n {showLoadingIcon ? (\n <div\n id=\"civic-auth-loading-icon-wrapper\"\n style={{\n position: \"absolute\",\n inset: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"white\",\n }}\n >\n <LoadingIcon />\n </div>\n ) : null}\n\n <CivicAuthIframe ref={iframeRef} onLoad={handleIframeLoad} />\n </WrapperComponent>\n );\n};\n\nexport type { CivicAuthIframeContainerProps };\n\nexport { CivicAuthIframeContainer };\n"]}
1
+ {"version":3,"file":"CivicAuthIframeContainer.js","sourceRoot":"","sources":["../../../../src/shared/components/CivicAuthIframeContainer.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { LoadingIcon } from \"@/shared/components/LoadingIcon.js\";\nimport { CloseIcon } from \"@/shared/components/CloseIcon.js\";\nimport { CivicAuthIframe } from \"@/shared/components/CivicAuthIframe.js\";\nimport { useIframe } from \"@/shared/hooks/index.js\";\nimport { TOKEN_EXCHANGE_TRIGGER_TEXT } from \"@/constants.js\";\nimport { useCivicAuthConfig } from \"@/shared/hooks/index.js\";\nimport { useClientTokenExchangeSession } from \"@/shared/hooks/index.js\";\nimport { useSession } from \"@/shared/hooks/index.js\";\n\ntype CivicAuthIframeContainerProps = {\n onClose?: () => void;\n closeOnRedirect?: boolean;\n};\n\nfunction NoChrome({\n children,\n}: {\n children: React.ReactNode;\n onClose?: () => void;\n}) {\n return <div style={{ position: \"relative\" }}>{children}</div>;\n}\n\nexport function IframeChrome({\n children,\n onClose,\n}: {\n children: React.ReactNode;\n onClose?: () => void;\n}) {\n return (\n <div\n style={{\n position: \"fixed\", // Change to fixed to stay in viewport\n left: 0,\n top: 0,\n zIndex: 50,\n display: \"flex\",\n height: \"100vh\",\n width: \"100vw\",\n minWidth: \"18rem\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"rgba(17, 24, 39, 0.5)\", // Semi-transparent dark background\n backdropFilter: \"blur(4px)\", // Optional: adds slight blur to background\n }}\n onClick={onClose}\n >\n <div\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n borderRadius: \"1.5rem\",\n backgroundColor: \"white\",\n padding: \"1.5rem\",\n boxShadow:\n \"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)\",\n }}\n onClick={(e) => e.stopPropagation()}\n >\n <button\n style={{\n position: \"absolute\",\n right: \"1rem\",\n top: \"1rem\",\n display: \"flex\",\n cursor: \"pointer\",\n alignItems: \"center\",\n justifyContent: \"center\",\n border: \"none\",\n backgroundColor: \"transparent\",\n padding: \"0.25rem\",\n color: \"#9ca3af\",\n }}\n onClick={onClose}\n >\n <CloseIcon />\n </button>\n\n {children}\n </div>\n </div>\n );\n}\n\nconst CivicAuthIframeContainer = ({\n onClose,\n closeOnRedirect = true,\n}: CivicAuthIframeContainerProps) => {\n const [isLoading, setIsLoading] = useState(true);\n const { isLoading: isAuthLoading, data: session } = useSession();\n const config = useCivicAuthConfig();\n const [tokenExchangeUrl, setTokenExchangeUrl] = useState<string | null>(null);\n const { doTokenExchange } = useClientTokenExchangeSession();\n const { iframeRef, iframeMode } = useIframe();\n\n useEffect(() => {\n if (tokenExchangeUrl) {\n doTokenExchange?.(tokenExchangeUrl);\n }\n }, [doTokenExchange, tokenExchangeUrl]);\n\n const processIframeUrl = useCallback(() => {\n if (!config) return;\n if (iframeRef && iframeRef.current && iframeRef.current.contentWindow) {\n try {\n const iframeUrl = iframeRef.current.contentWindow.location.href;\n // we know that oauth has finished when the iframe redirects to our redirectUrl\n if (iframeUrl.startsWith(config.redirectUrl)) {\n // we still want to show the spinner during redirect\n setIsLoading(true);\n const iframeBody =\n iframeRef.current.contentWindow.document.body.innerHTML;\n\n // If we're doing a server token exchange, we need to call the server a second time\n // using a fetch so that we're on the same domain and cookies can be sent and read\n // The server will use the presence of the code_verifier cookie to determine whether to do a token exchange or not.\n // On the initial (3rd party) redirect from the auth server, the cookie won't be sent, so the server-side callback route will just render a blank page,\n // and we'll do the exchange request from here, which will include the cookies.\n if (iframeBody.includes(TOKEN_EXCHANGE_TRIGGER_TEXT)) {\n const params = new URL(iframeUrl).searchParams;\n const appUrl = globalThis.window?.location?.origin;\n fetch(\n `${config.redirectUrl}?${params.toString()}&appUrl=${appUrl}`,\n );\n } else {\n // if we're doing token-exchange in the client, we can just set the authResponseUrl\n // to be handled by the auth provider\n // iframeRef.current.setAttribute(\"src\", \"\");\n setTokenExchangeUrl(iframeUrl);\n }\n\n if (closeOnRedirect) onClose?.();\n return true; // Successfully processed the URL\n }\n } catch (e) {\n console.log(\"Waiting for redirect...\", e);\n }\n }\n return false; // Haven't processed the URL yet\n }, [closeOnRedirect, config, iframeRef, onClose]);\n\n const intervalId = useRef<NodeJS.Timeout>();\n\n const handleEscape = useCallback(\n (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n onClose?.();\n }\n },\n [onClose],\n );\n\n // handle Escape\n useEffect(() => {\n window.addEventListener(\"keydown\", handleEscape);\n\n return () => window.removeEventListener(\"keydown\", handleEscape);\n });\n\n const handleIframeLoad = useCallback(() => {\n setIsLoading(false);\n\n const iframeHasUrl = processIframeUrl();\n\n if (iframeHasUrl && intervalId.current) {\n clearInterval(intervalId.current);\n }\n }, [processIframeUrl, setIsLoading, intervalId]);\n\n // if we're already authenticated then we're waiting either for the iframe to be closed\n // or the page to redirect, so we want to show the loading icon\n const showLoadingIcon = session?.authenticated || isLoading || isAuthLoading;\n\n const WrapperComponent = iframeMode === \"embedded\" ? NoChrome : IframeChrome;\n\n return (\n <WrapperComponent onClose={onClose}>\n {showLoadingIcon ? (\n <div\n id=\"civic-auth-loading-icon-wrapper\"\n style={{\n position: \"absolute\",\n inset: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"white\",\n }}\n >\n <LoadingIcon />\n </div>\n ) : null}\n\n <CivicAuthIframe\n ref={iframeRef}\n id={\"civic-auth-iframe\"}\n onLoad={handleIframeLoad}\n />\n </WrapperComponent>\n );\n};\n\nexport type { CivicAuthIframeContainerProps };\n\nexport { CivicAuthIframeContainer };\n"]}
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ type CivicAuthLogoutIframeContainerProps = {
3
+ isLoading?: boolean;
4
+ };
5
+ declare const CivicAuthLogoutIframeContainer: ({ isLoading, }: CivicAuthLogoutIframeContainerProps) => React.JSX.Element;
6
+ export { CivicAuthLogoutIframeContainer };
7
+ //# sourceMappingURL=CivicAuthLogoutIframeContainer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CivicAuthLogoutIframeContainer.d.ts","sourceRoot":"","sources":["../../../../src/shared/components/CivicAuthLogoutIframeContainer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,KAAK,mCAAmC,GAAG;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,QAAA,MAAM,8BAA8B,mBAEjC,mCAAmC,sBA2BrC,CAAC;AAEF,OAAO,EAAE,8BAA8B,EAAE,CAAC"}
@@ -0,0 +1,22 @@
1
+ "use client";
2
+ import React from "react";
3
+ import { CivicAuthIframe } from "../../shared/components/CivicAuthIframe.js";
4
+ import { useIframe } from "../../shared/hooks/index.js";
5
+ import { LoadingIcon } from "./LoadingIcon.js";
6
+ import { IframeChrome } from "./CivicAuthIframeContainer.js";
7
+ const CivicAuthLogoutIframeContainer = ({ isLoading = false, }) => {
8
+ const { logoutIframeRef } = useIframe();
9
+ return (React.createElement(IframeChrome, null,
10
+ isLoading ? (React.createElement("div", { id: "civic-auth-loading-icon-wrapper", style: {
11
+ position: "absolute",
12
+ inset: 0,
13
+ display: "flex",
14
+ alignItems: "center",
15
+ justifyContent: "center",
16
+ backgroundColor: "white",
17
+ } },
18
+ React.createElement(LoadingIcon, null))) : null,
19
+ React.createElement(CivicAuthIframe, { ref: logoutIframeRef, id: "civic-auth-logout-iframe", onLoad: () => { } })));
20
+ };
21
+ export { CivicAuthLogoutIframeContainer };
22
+ //# sourceMappingURL=CivicAuthLogoutIframeContainer.js.map