@civic/auth 0.2.1-beta.1 → 0.2.2-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 (114) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/dist/cjs/nextjs/index.d.ts +4 -2
  3. package/dist/cjs/nextjs/index.d.ts.map +1 -1
  4. package/dist/cjs/nextjs/index.js +16 -6
  5. package/dist/cjs/nextjs/index.js.map +1 -1
  6. package/dist/cjs/nextjs/providers/NextAuthProvider.d.ts.map +1 -1
  7. package/dist/cjs/nextjs/providers/NextAuthProvider.js +12 -19
  8. package/dist/cjs/nextjs/providers/NextAuthProvider.js.map +1 -1
  9. package/dist/cjs/nextjs/routeHandler.js +3 -3
  10. package/dist/cjs/nextjs/routeHandler.js.map +1 -1
  11. package/dist/cjs/reactjs/components/SignOutButton.d.ts.map +1 -1
  12. package/dist/cjs/reactjs/components/SignOutButton.js +3 -2
  13. package/dist/cjs/reactjs/components/SignOutButton.js.map +1 -1
  14. package/dist/cjs/reactjs/components/UserButton.d.ts.map +1 -1
  15. package/dist/cjs/reactjs/components/UserButton.js +4 -2
  16. package/dist/cjs/reactjs/components/UserButton.js.map +1 -1
  17. package/dist/cjs/reactjs/hooks/useSignIn.d.ts +6 -0
  18. package/dist/cjs/reactjs/hooks/useSignIn.d.ts.map +1 -0
  19. package/dist/cjs/reactjs/hooks/useSignIn.js +38 -0
  20. package/dist/cjs/reactjs/hooks/useSignIn.js.map +1 -0
  21. package/dist/cjs/reactjs/providers/AuthProvider.d.ts.map +1 -1
  22. package/dist/cjs/reactjs/providers/AuthProvider.js +3 -1
  23. package/dist/cjs/reactjs/providers/AuthProvider.js.map +1 -1
  24. package/dist/cjs/reactjs/providers/CivicAuthProvider.d.ts.map +1 -1
  25. package/dist/cjs/reactjs/providers/CivicAuthProvider.js +2 -2
  26. package/dist/cjs/reactjs/providers/CivicAuthProvider.js.map +1 -1
  27. package/dist/cjs/services/AuthenticationService.d.ts.map +1 -1
  28. package/dist/cjs/services/AuthenticationService.js +37 -15
  29. package/dist/cjs/services/AuthenticationService.js.map +1 -1
  30. package/dist/cjs/shared/components/IFrameAndLoading.d.ts.map +1 -1
  31. package/dist/cjs/shared/components/IFrameAndLoading.js +54 -6
  32. package/dist/cjs/shared/components/IFrameAndLoading.js.map +1 -1
  33. package/dist/cjs/shared/hooks/useSignIn.d.ts +1 -0
  34. package/dist/cjs/shared/hooks/useSignIn.d.ts.map +1 -1
  35. package/dist/cjs/shared/hooks/useSignIn.js +13 -3
  36. package/dist/cjs/shared/hooks/useSignIn.js.map +1 -1
  37. package/dist/cjs/shared/lib/UserSession.d.ts +7 -7
  38. package/dist/cjs/shared/lib/UserSession.d.ts.map +1 -1
  39. package/dist/cjs/shared/lib/UserSession.js.map +1 -1
  40. package/dist/cjs/shared/providers/AuthContext.d.ts +1 -0
  41. package/dist/cjs/shared/providers/AuthContext.d.ts.map +1 -1
  42. package/dist/cjs/shared/providers/AuthContext.js.map +1 -1
  43. package/dist/cjs/shared/providers/TokenProvider.d.ts +0 -1
  44. package/dist/cjs/shared/providers/TokenProvider.d.ts.map +1 -1
  45. package/dist/cjs/shared/providers/TokenProvider.js +0 -5
  46. package/dist/cjs/shared/providers/TokenProvider.js.map +1 -1
  47. package/dist/cjs/shared/providers/UserProvider.d.ts +7 -5
  48. package/dist/cjs/shared/providers/UserProvider.d.ts.map +1 -1
  49. package/dist/cjs/shared/providers/UserProvider.js +20 -11
  50. package/dist/cjs/shared/providers/UserProvider.js.map +1 -1
  51. package/dist/cjs/shared/version.d.ts +1 -1
  52. package/dist/cjs/shared/version.js +1 -1
  53. package/dist/cjs/shared/version.js.map +1 -1
  54. package/dist/cjs/types.d.ts +9 -0
  55. package/dist/cjs/types.d.ts.map +1 -1
  56. package/dist/cjs/types.js.map +1 -1
  57. package/dist/esm/nextjs/index.d.ts +4 -2
  58. package/dist/esm/nextjs/index.d.ts.map +1 -1
  59. package/dist/esm/nextjs/index.js +11 -2
  60. package/dist/esm/nextjs/index.js.map +1 -1
  61. package/dist/esm/nextjs/providers/NextAuthProvider.d.ts.map +1 -1
  62. package/dist/esm/nextjs/providers/NextAuthProvider.js +12 -19
  63. package/dist/esm/nextjs/providers/NextAuthProvider.js.map +1 -1
  64. package/dist/esm/nextjs/routeHandler.js +2 -2
  65. package/dist/esm/nextjs/routeHandler.js.map +1 -1
  66. package/dist/esm/reactjs/components/SignOutButton.d.ts.map +1 -1
  67. package/dist/esm/reactjs/components/SignOutButton.js +3 -2
  68. package/dist/esm/reactjs/components/SignOutButton.js.map +1 -1
  69. package/dist/esm/reactjs/components/UserButton.d.ts.map +1 -1
  70. package/dist/esm/reactjs/components/UserButton.js +4 -2
  71. package/dist/esm/reactjs/components/UserButton.js.map +1 -1
  72. package/dist/esm/reactjs/hooks/useSignIn.d.ts +6 -0
  73. package/dist/esm/reactjs/hooks/useSignIn.d.ts.map +1 -0
  74. package/dist/esm/reactjs/hooks/useSignIn.js +34 -0
  75. package/dist/esm/reactjs/hooks/useSignIn.js.map +1 -0
  76. package/dist/esm/reactjs/providers/AuthProvider.d.ts.map +1 -1
  77. package/dist/esm/reactjs/providers/AuthProvider.js +3 -1
  78. package/dist/esm/reactjs/providers/AuthProvider.js.map +1 -1
  79. package/dist/esm/reactjs/providers/CivicAuthProvider.d.ts.map +1 -1
  80. package/dist/esm/reactjs/providers/CivicAuthProvider.js +2 -2
  81. package/dist/esm/reactjs/providers/CivicAuthProvider.js.map +1 -1
  82. package/dist/esm/services/AuthenticationService.d.ts.map +1 -1
  83. package/dist/esm/services/AuthenticationService.js +37 -15
  84. package/dist/esm/services/AuthenticationService.js.map +1 -1
  85. package/dist/esm/shared/components/IFrameAndLoading.d.ts.map +1 -1
  86. package/dist/esm/shared/components/IFrameAndLoading.js +21 -3
  87. package/dist/esm/shared/components/IFrameAndLoading.js.map +1 -1
  88. package/dist/esm/shared/hooks/useSignIn.d.ts +1 -0
  89. package/dist/esm/shared/hooks/useSignIn.d.ts.map +1 -1
  90. package/dist/esm/shared/hooks/useSignIn.js +14 -4
  91. package/dist/esm/shared/hooks/useSignIn.js.map +1 -1
  92. package/dist/esm/shared/lib/UserSession.d.ts +7 -7
  93. package/dist/esm/shared/lib/UserSession.d.ts.map +1 -1
  94. package/dist/esm/shared/lib/UserSession.js.map +1 -1
  95. package/dist/esm/shared/providers/AuthContext.d.ts +1 -0
  96. package/dist/esm/shared/providers/AuthContext.d.ts.map +1 -1
  97. package/dist/esm/shared/providers/AuthContext.js.map +1 -1
  98. package/dist/esm/shared/providers/TokenProvider.d.ts +0 -1
  99. package/dist/esm/shared/providers/TokenProvider.d.ts.map +1 -1
  100. package/dist/esm/shared/providers/TokenProvider.js +1 -6
  101. package/dist/esm/shared/providers/TokenProvider.js.map +1 -1
  102. package/dist/esm/shared/providers/UserProvider.d.ts +7 -5
  103. package/dist/esm/shared/providers/UserProvider.d.ts.map +1 -1
  104. package/dist/esm/shared/providers/UserProvider.js +20 -11
  105. package/dist/esm/shared/providers/UserProvider.js.map +1 -1
  106. package/dist/esm/shared/version.d.ts +1 -1
  107. package/dist/esm/shared/version.js +1 -1
  108. package/dist/esm/shared/version.js.map +1 -1
  109. package/dist/esm/types.d.ts +9 -0
  110. package/dist/esm/types.d.ts.map +1 -1
  111. package/dist/esm/types.js.map +1 -1
  112. package/dist/tsconfig.cjs.tsbuildinfo +1 -1
  113. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  114. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AuthenticationService.js","sourceRoot":"","sources":["../../../src/services/AuthenticationService.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAS9E,OAAO,EACL,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,SAAS,EACT,cAAc,EACd,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EACzB,cAAc,EACd,WAAW,EACX,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAM3D,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAwBjE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,8BAA8B;IACjC,kBAAkB,GAA2C,IAAI,CAAC;IAEhE,MAAM,CAAuC;IAEhD,cAAc,CAAC,WAAwB;QAC5C,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,WAAW,CAAC;IACxC,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;IACjC,CAAC;IAED,IAAI,qBAAqB;QACvB,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,YAAY,8BAA8B,CAAC;IAC5E,CAAC;IACD,IAAI,KAAK;QACP,OAAO,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAC5E,CAAC;IACD,YAAY,MAA0B;QACpC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,yBAAyB,CAAC,WAAmB;QACjD,OAAO,CAAC,IAAI,CACV,qEAAqE,EACrE,WAAW,CACZ,CAAC;QACF,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,WAAW,CAAC;IACrC,CAAC;IAED,uGAAuG;IACvG,qEAAqE;IACrE,KAAK,CAAC,MAAM,CAAC,SAAmC;QAC9C,MAAM,GAAG,GAAG,MAAM,qBAAqB,CAAC;YACtC,GAAG,IAAI,CAAC,MAAM;YACd,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAC,CAAC;QAEH,IAAI,CAAC,kBAAkB,GAAG,CAAC,KAAmB,EAAE,EAAE;YAChD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC9C,IACE,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC;gBAClC,OAAO,CAAC,QAAQ,KAAK,WAAW,EAChC,CAAC;gBACD,IAAI,CAAC,2BAA2B,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACnE,OAAO;gBACT,CAAC;gBACD,MAAM,YAAY,GAAG,KAAK,CAAC,IAAwB,CAAC;gBACpD,IAAI,CAAC,yBAAyB,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACxD,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAE5D,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;YACzC,IAAI,CAAC,SAAS;gBACZ,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;YACpE,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;QAChD,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;YAC3C,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;QACxC,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YAC1C,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,QAAQ,CAAC,CAAC;gBAC1D,IAAI,CAAC,WAAW,EAAE,CAAC;oBACjB,MAAM,IAAI,UAAU,CAAC,6BAA6B,CAAC,CAAC;gBACtD,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;gBACpC,MAAM,IAAI,UAAU,CAClB,qDAAqD,CACtD,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,GAAG,CAAC;IACb,CAAC;IAES,qBAAqB,CAC7B,MAAyB,EACzB,WAAmB;QAEnB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,WAAW,GAAG,GAAG,EAAE;gBACvB,IAAI,CAAC;oBACH,6DAA6D;oBAC7D,MAAM,UAAU,GAAG,MAAM,CAAC,aAAa,EAAE,QAAQ,CAAC,IAAI,CAAC;oBACvD,IAAI,UAAU,EAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;wBACtC,aAAa,CAAC,QAAQ,CAAC,CAAC;wBACxB,OAAO,EAAE,CAAC;oBACZ,CAAC;gBACH,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,6BAA6B;oBAC7B,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC,CAAC,CAAC;gBACvC,CAAC;YACH,CAAC,CAAC;YAEF,MAAM,QAAQ,GAAG,WAAW,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;YAC/C,2BAA2B;YAC3B,UAAU,CAAC,GAAG,EAAE;gBACd,aAAa,CAAC,QAAQ,CAAC,CAAC;gBACxB,MAAM,CAAC,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC,CAAC;YAC7D,CAAC,EAAE,KAAK,CAAC,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CACX,OAA2B,EAC3B,SAAmC;QAEnC,IAAI,GAAG,CAAC;QACR,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,IAAI,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAC/B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;YACrE,CAAC;YACD,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC7D,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;YACvE,CAAC;YACD,GAAG,GAAG,MAAM,sBAAsB,CAAC;gBACjC,GAAG,IAAI,CAAC,MAAM;gBACd,OAAO;gBACP,KAAK;gBACL,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,iBAAiB;aAC3C,CAAC,CAAC;QACL,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;YACzC,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;YACpE,CAAC;YACD,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;YAE9C,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,qBAAqB,CAC9B,SAAS,EACT,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAC9B,CAAC;gBAEF,2CAA2C;gBAC3C,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC;oBAChC,MAAM,YAAY,GAAG,IAAI,mBAAmB,EAAE,CAAC;oBAC/C,MAAM,WAAW,CAAC,YAAY,CAAC,CAAC;oBAChC,MAAM,SAAS,CAAC,YAAY,CAAC,CAAC;oBAC9B,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAC9C,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;YAC3C,MAAM,YAAY,GAAG,IAAI,mBAAmB,EAAE,CAAC;YAC/C,YAAY,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;YACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;QACxC,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YAC1C,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,QAAQ,CAAC,CAAC;gBAC1D,IAAI,CAAC,WAAW,EAAE,CAAC;oBACjB,MAAM,IAAI,UAAU,CAAC,6BAA6B,CAAC,CAAC;gBACtD,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;gBACpC,MAAM,IAAI,UAAU,CAClB,qDAAqD,CACtD,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,GAAG,CAAC;IACb,CAAC;IAED,OAAO;QACL,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC5B,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,8BAA8B;IAC/B,MAAM,CAAuC;IAEvD,YAAY,MAA0B;QACpC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,uGAAuG;IACvG,4BAA4B;IAC5B,KAAK,CAAC,MAAM;QACV,OAAO,qBAAqB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAe;QAC3B,OAAO,sBAAsB,CAAC;YAC5B,GAAG,IAAI,CAAC,MAAM;YACd,OAAO;SACR,CAAC,CAAC;IACL,CAAC;CACF;AAaD;;;GAGG;AACH,MAAM,OAAO,4BAA6B,SAAQ,8BAA8B;IAQlE;IAPJ,YAAY,CAA2B;IACvC,SAAS,CAAwB;IAEzC,0EAA0E;IAC1E,YACE,MAAmC;IACnC,6FAA6F;IACnF,eAAe,IAAI,+BAA+B,EAAE;QAE9D,KAAK,CAAC;YACJ,GAAG,MAAM;YACT,yDAAyD;YACzD,YAAY,EAAE,YAAY;SAC3B,CAAC,CAAC;QANO,iBAAY,GAAZ,YAAY,CAAwC;IAOhE,CAAC;IAED,kFAAkF;IAClF,oGAAoG;IACpG,kDAAkD;IAClD,KAAK,CAAC,IAAI;QACR,uBAAuB;QACvB,IAAI,CAAC,SAAS,GAAG,MAAM,yBAAyB,CAC9C,IAAI,CAAC,MAAM,CAAC,WAAW,EACvB,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAC9B,CAAC;QACF,IAAI,CAAC,YAAY,GAAG,IAAI,YAAY,CAClC,IAAI,CAAC,MAAM,CAAC,QAAQ,EACpB,IAAI,CAAC,SAAS,CAAC,IAAI,EACnB,IAAI,CAAC,SAAS,CAAC,KAAK,EACpB;YACE,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW;SACrC,CACF,CAAC;QAEF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,wBAAwB;IACxB,uEAAuE;IACvE,uCAAuC;IACvC,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,MAAM,CAAC,WAAW,EACvB,IAAI,CAAC,SAAU,CAChB,CAAC;QACF,MAAM,aAAa,GAAG,IAAI,mBAAmB,EAAE,CAAC;QAChD,MAAM,WAAW,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC;QAC1C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,WAAW,GAAG,IAAI,kBAAkB,CAAC,aAAa,CAAC,CAAC;QAC1D,MAAM,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5B,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3C,uCAAuC;QACvC,MAAM,iBAAiB,GAAG,oBAAoB,CAC5C,KAAK,EACL,IAAI,CAAC,MAAM,CAAC,WAAW,CACxB,CAAC;QAEF,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;YACpC,yBAAyB;YACzB,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,GAAG,EAAE;gBAC3C,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;YAC1B,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC;QACD,8GAA8G;QAC9G,yBAAyB,CAAC,wBAAwB,CAAC,CAAC;QACpD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,0CAA0C;IAC1C,KAAK,CAAC,cAAc;QAClB,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,IAAI,mBAAmB,EAAE,CAAC,CAAC;QAEpE,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,KAAK,CAAC,uBAAuB;QAC3B,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAChD,IAAI,CAAC,WAAW,EAAE,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;gBACtD,MAAM,sBAAsB,GAAG,EAAE,GAAG,WAAW,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;gBACxE,gDAAgD;gBAChD,OAAO,sBAAsB,CAAC;YAChC,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,YAAY;gBAAE,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAE7D,4DAA4D;YAC5D,MAAM,oBAAoB,CACxB;gBACE,YAAY,EAAE,WAAW,CAAC,WAAW;gBACrC,QAAQ,EAAE,WAAW,CAAC,OAAO;gBAC7B,aAAa,EAAE,WAAW,CAAC,YAAY;aACxC,EACD,IAAI,CAAC,SAAU,EACf,IAAI,CAAC,YAAa,EAClB,IAAI,CAAC,MAAM,CAAC,WAAW,CACxB,CAAC;YACF,OAAO,WAAW,CAAC;QACrB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,oCAAoC,EAAE,KAAK,CAAC,CAAC;YAC1D,MAAM,sBAAsB,GAAG;gBAC7B,aAAa,EAAE,KAAK;aACrB,CAAC;YACF,MAAM,WAAW,CAAC,IAAI,mBAAmB,EAAE,CAAC,CAAC;YAC7C,OAAO,sBAAsB,CAAC;QAChC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,qBAAqB;QACzB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;IACpC,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,KAAK,CAChB,MAAmC;QAEnC,MAAM,QAAQ,GAAG,IAAI,4BAA4B,CAAC,MAAM,CAAC,CAAC;QAC1D,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEtB,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF","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\nexport type GenericAuthenticationInitiatorConfig = {\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\nexport type BrowserAuthenticationInitiatorConfig = Omit<\n GenericAuthenticationInitiatorConfig,\n \"state\"\n> & {\n logoutUrl?: string;\n logoutRedirectUrl: 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};\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: BrowserAuthenticationInitiatorConfig;\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: GenericAuthenticationInitiatorConfig;\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"]}
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 IframeAuthMessage,\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\nexport type GenericAuthenticationInitiatorConfig = {\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\nexport type BrowserAuthenticationInitiatorConfig = Omit<\n GenericAuthenticationInitiatorConfig,\n \"state\"\n> & {\n logoutUrl?: string;\n logoutRedirectUrl: 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};\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: BrowserAuthenticationInitiatorConfig;\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 let interval: NodeJS.Timeout | undefined = undefined;\n let timeout: NodeJS.Timeout | undefined = undefined;\n\n const messageHandler = (event: MessageEvent) => {\n if (event.source !== iframe.contentWindow) {\n // This message did not originate from the iframe. Ignore it.\n console.log(\n \"Message did not originate from the iframe. Ignoring it.\",\n );\n return;\n }\n\n const message = event.data as IframeAuthMessage;\n\n if (\n message.source === \"civicloginApp\" &&\n message.type === \"auth_error\"\n ) {\n clearInterval(interval);\n clearTimeout(timeout);\n return;\n }\n\n if (\n message.source === \"civicloginApp\" &&\n message.type === \"auth_error_try_again\"\n ) {\n clearInterval(interval);\n clearTimeout(timeout);\n window.removeEventListener(\"message\", messageHandler);\n reject(new Error(message.data.error || \"Authentication failed\"));\n return;\n }\n };\n\n window.addEventListener(\"message\", messageHandler);\n\n // Keep the existing URL check logic for success case\n const checkIframe = () => {\n try {\n const currentUrl = iframe.contentWindow?.location.href;\n if (currentUrl?.includes(expectedUrl)) {\n clearInterval(interval);\n window.removeEventListener(\"message\", messageHandler);\n resolve();\n }\n } catch (e) {\n // Ignore cross-origin errors\n console.log(\"Cross-origin error\", e);\n }\n };\n\n interval = setInterval(checkIframe, 100);\n\n // Timeout after 10 seconds\n timeout = setTimeout(() => {\n clearInterval(interval);\n window.removeEventListener(\"message\", messageHandler);\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 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 }\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: GenericAuthenticationInitiatorConfig;\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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"IFrameAndLoading.d.ts","sourceRoot":"","sources":["../../../../src/shared/components/IFrameAndLoading.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,QAAA,MAAM,gBAAgB,8CAInB;IACD,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,sBA2CA,CAAC;AACF,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"IFrameAndLoading.d.ts","sourceRoot":"","sources":["../../../../src/shared/components/IFrameAndLoading.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAQnD,QAAA,MAAM,gBAAgB,8CAInB;IACD,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,sBAuEA,CAAC;AACF,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
@@ -1,21 +1,39 @@
1
- import React from "react";
1
+ import React, { useEffect, useState } from "react";
2
2
  import { useIframe } from "../hooks/useIframe.js";
3
3
  import { useIsInIframe } from "../hooks/useIsInIframe.js";
4
4
  import { CivicAuthIframeContainer } from "./CivicAuthIframeContainer.js";
5
5
  import { BlockDisplay } from "./BlockDisplay.js";
6
6
  import { LoadingIcon } from "./LoadingIcon.js";
7
7
  import { CivicAuthLogoutIframeContainer } from "./CivicAuthLogoutIframeContainer.js";
8
- const IFrameAndLoading = ({ error, isLoading, showIframeOnLogout = true, }) => {
8
+ const IFrameAndLoading = ({ error, isLoading, showIframeOnLogout = false, }) => {
9
9
  const isInIframe = useIsInIframe();
10
+ const [logoutIframeLoading, setLogoutIframeLoading] = useState(true);
10
11
  const { renderIframe, iframeIsVisible, setIframeIsVisible, logoutIframeIsVisible, } = useIframe();
11
12
  const showLoadingOverlay = isInIframe || isLoading;
13
+ useEffect(() => {
14
+ const handleErrorMessage = (event) => {
15
+ const thisURL = new URL(window.location.href);
16
+ if (!(event.origin.endsWith("civic.com") || thisURL.hostname === "localhost")) {
17
+ return;
18
+ }
19
+ // The login app has thrown an error, so we need to show the logout iframe
20
+ if (event.data?.source === "civicloginApp" &&
21
+ event.data?.type === "auth_error") {
22
+ setLogoutIframeLoading(false);
23
+ return;
24
+ }
25
+ setLogoutIframeLoading(true);
26
+ };
27
+ window.addEventListener("message", handleErrorMessage);
28
+ return () => window.removeEventListener("message", handleErrorMessage);
29
+ }, []);
12
30
  return (React.createElement(React.Fragment, null,
13
31
  renderIframe && (React.createElement("div", { style: iframeIsVisible ? { display: "block" } : { display: "none" } },
14
32
  React.createElement(CivicAuthIframeContainer, { onClose: () => setIframeIsVisible(false) }))),
15
33
  React.createElement("div", { style: showIframeOnLogout && logoutIframeIsVisible
16
34
  ? { display: "block" }
17
35
  : { display: "none" } },
18
- React.createElement(CivicAuthLogoutIframeContainer, { isLoading: true })),
36
+ React.createElement(CivicAuthLogoutIframeContainer, { isLoading: logoutIframeLoading })),
19
37
  error && (React.createElement(BlockDisplay, null,
20
38
  React.createElement("div", null,
21
39
  "Error: ",
@@ -1 +1 @@
1
- {"version":3,"file":"IFrameAndLoading.js","sourceRoot":"","sources":["../../../../src/shared/components/IFrameAndLoading.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AAErF,MAAM,gBAAgB,GAAG,CAAC,EACxB,KAAK,EACL,SAAS,EACT,kBAAkB,GAAG,IAAI,GAK1B,EAAE,EAAE;IACH,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,EACJ,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,qBAAqB,GACtB,GAAG,SAAS,EAAE,CAAC;IAChB,MAAM,kBAAkB,GAAG,UAAU,IAAI,SAAS,CAAC;IAEnD,OAAO,CACL;QACG,YAAY,IAAI,CACf,6BACE,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE;YAEnE,oBAAC,wBAAwB,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,kBAAkB,CAAC,KAAK,CAAC,GAAI,CAClE,CACP;QAED,6BACE,KAAK,EACH,kBAAkB,IAAI,qBAAqB;gBACzC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE;gBACtB,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE;YAGzB,oBAAC,8BAA8B,IAAC,SAAS,EAAE,IAAI,GAAI,CAC/C;QAEL,KAAK,IAAI,CACR,oBAAC,YAAY;YACX;;gBAAa,KAAK,EAAE,OAAO,CAAO,CACrB,CAChB;QAEA,kBAAkB,IAAI,CAAC,KAAK,IAAI,CAC/B,oBAAC,YAAY;YACX,oBAAC,WAAW,OAAG,CACF,CAChB,CACA,CACJ,CAAC;AACJ,CAAC,CAAC;AACF,OAAO,EAAE,gBAAgB,EAAE,CAAC","sourcesContent":["import React from \"react\";\nimport { useIframe } from \"../hooks/useIframe.js\";\nimport { useIsInIframe } from \"../hooks/useIsInIframe.js\";\nimport { CivicAuthIframeContainer } from \"./CivicAuthIframeContainer.js\";\nimport { BlockDisplay } from \"./BlockDisplay.js\";\nimport { LoadingIcon } from \"./LoadingIcon.js\";\nimport { CivicAuthLogoutIframeContainer } from \"./CivicAuthLogoutIframeContainer.js\";\n\nconst IFrameAndLoading = ({\n error,\n isLoading,\n showIframeOnLogout = true,\n}: {\n error: Error | null;\n isLoading: boolean;\n showIframeOnLogout?: boolean;\n}) => {\n const isInIframe = useIsInIframe();\n const {\n renderIframe,\n iframeIsVisible,\n setIframeIsVisible,\n logoutIframeIsVisible,\n } = useIframe();\n const showLoadingOverlay = isInIframe || isLoading;\n\n return (\n <>\n {renderIframe && (\n <div\n style={iframeIsVisible ? { display: \"block\" } : { display: \"none\" }}\n >\n <CivicAuthIframeContainer onClose={() => setIframeIsVisible(false)} />\n </div>\n )}\n\n <div\n style={\n showIframeOnLogout && logoutIframeIsVisible\n ? { display: \"block\" }\n : { display: \"none\" }\n }\n >\n <CivicAuthLogoutIframeContainer isLoading={true} />\n </div>\n\n {error && (\n <BlockDisplay>\n <div>Error: {error?.message}</div>\n </BlockDisplay>\n )}\n\n {showLoadingOverlay && !error && (\n <BlockDisplay>\n <LoadingIcon />\n </BlockDisplay>\n )}\n </>\n );\n};\nexport { IFrameAndLoading };\n"]}
1
+ {"version":3,"file":"IFrameAndLoading.js","sourceRoot":"","sources":["../../../../src/shared/components/IFrameAndLoading.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AAErF,MAAM,gBAAgB,GAAG,CAAC,EACxB,KAAK,EACL,SAAS,EACT,kBAAkB,GAAG,KAAK,GAK3B,EAAE,EAAE;IACH,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACrE,MAAM,EACJ,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,qBAAqB,GACtB,GAAG,SAAS,EAAE,CAAC;IAChB,MAAM,kBAAkB,GAAG,UAAU,IAAI,SAAS,CAAC;IAEnD,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,kBAAkB,GAAG,CAAC,KAAmB,EAAE,EAAE;YACjD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC9C,IACE,CAAC,CACC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,QAAQ,KAAK,WAAW,CACvE,EACD,CAAC;gBACD,OAAO;YACT,CAAC;YAED,0EAA0E;YAC1E,IACE,KAAK,CAAC,IAAI,EAAE,MAAM,KAAK,eAAe;gBACtC,KAAK,CAAC,IAAI,EAAE,IAAI,KAAK,YAAY,EACjC,CAAC;gBACD,sBAAsB,CAAC,KAAK,CAAC,CAAC;gBAC9B,OAAO;YACT,CAAC;YAED,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC,CAAC;QAEF,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;QACvD,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;IACzE,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,CACL;QACG,YAAY,IAAI,CACf,6BACE,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE;YAEnE,oBAAC,wBAAwB,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,kBAAkB,CAAC,KAAK,CAAC,GAAI,CAClE,CACP;QAED,6BACE,KAAK,EACH,kBAAkB,IAAI,qBAAqB;gBACzC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE;gBACtB,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE;YAGzB,oBAAC,8BAA8B,IAAC,SAAS,EAAE,mBAAmB,GAAI,CAC9D;QAEL,KAAK,IAAI,CACR,oBAAC,YAAY;YACX;;gBAAa,KAAK,EAAE,OAAO,CAAO,CACrB,CAChB;QAEA,kBAAkB,IAAI,CAAC,KAAK,IAAI,CAC/B,oBAAC,YAAY;YACX,oBAAC,WAAW,OAAG,CACF,CAChB,CACA,CACJ,CAAC;AACJ,CAAC,CAAC;AACF,OAAO,EAAE,gBAAgB,EAAE,CAAC","sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport { useIframe } from \"../hooks/useIframe.js\";\nimport { useIsInIframe } from \"../hooks/useIsInIframe.js\";\nimport { CivicAuthIframeContainer } from \"./CivicAuthIframeContainer.js\";\nimport { BlockDisplay } from \"./BlockDisplay.js\";\nimport { LoadingIcon } from \"./LoadingIcon.js\";\nimport { CivicAuthLogoutIframeContainer } from \"./CivicAuthLogoutIframeContainer.js\";\n\nconst IFrameAndLoading = ({\n error,\n isLoading,\n showIframeOnLogout = false,\n}: {\n error: Error | null;\n isLoading: boolean;\n showIframeOnLogout?: boolean;\n}) => {\n const isInIframe = useIsInIframe();\n const [logoutIframeLoading, setLogoutIframeLoading] = useState(true);\n const {\n renderIframe,\n iframeIsVisible,\n setIframeIsVisible,\n logoutIframeIsVisible,\n } = useIframe();\n const showLoadingOverlay = isInIframe || isLoading;\n\n useEffect(() => {\n const handleErrorMessage = (event: MessageEvent) => {\n const thisURL = new URL(window.location.href);\n if (\n !(\n event.origin.endsWith(\"civic.com\") || thisURL.hostname === \"localhost\"\n )\n ) {\n return;\n }\n\n // The login app has thrown an error, so we need to show the logout iframe\n if (\n event.data?.source === \"civicloginApp\" &&\n event.data?.type === \"auth_error\"\n ) {\n setLogoutIframeLoading(false);\n return;\n }\n\n setLogoutIframeLoading(true);\n };\n\n window.addEventListener(\"message\", handleErrorMessage);\n return () => window.removeEventListener(\"message\", handleErrorMessage);\n }, []);\n\n return (\n <>\n {renderIframe && (\n <div\n style={iframeIsVisible ? { display: \"block\" } : { display: \"none\" }}\n >\n <CivicAuthIframeContainer onClose={() => setIframeIsVisible(false)} />\n </div>\n )}\n\n <div\n style={\n showIframeOnLogout && logoutIframeIsVisible\n ? { display: \"block\" }\n : { display: \"none\" }\n }\n >\n <CivicAuthLogoutIframeContainer isLoading={logoutIframeLoading} />\n </div>\n\n {error && (\n <BlockDisplay>\n <div>Error: {error?.message}</div>\n </BlockDisplay>\n )}\n\n {showLoadingOverlay && !error && (\n <BlockDisplay>\n <LoadingIcon />\n </BlockDisplay>\n )}\n </>\n );\n};\nexport { IFrameAndLoading };\n"]}
@@ -9,6 +9,7 @@ type SignInProps = {
9
9
  declare const useSignIn: ({ pkceConsumer, preSignOut, postSignOut, displayMode, }: SignInProps) => {
10
10
  signIn: () => Promise<void>;
11
11
  signOut: () => Promise<void>;
12
+ isSigningOut: boolean;
12
13
  displayMode: DisplayMode;
13
14
  };
14
15
  export { useSignIn };
@@ -1 +1 @@
1
- {"version":3,"file":"useSignIn.d.ts","sourceRoot":"","sources":["../../../../src/shared/hooks/useSignIn.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAKpE,KAAK,WAAW,GAAG;IACjB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,WAAW,EAAE,WAAW,CAAC;CAC1B,CAAC;AACF,QAAA,MAAM,SAAS,4DAKZ,WAAW;kBAkEyB,OAAO,CAAC,IAAI,CAAC;;;CAsEnD,CAAC;AACF,OAAO,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"useSignIn.d.ts","sourceRoot":"","sources":["../../../../src/shared/hooks/useSignIn.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAKpE,KAAK,WAAW,GAAG;IACjB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,WAAW,EAAE,WAAW,CAAC;CAC1B,CAAC;AACF,QAAA,MAAM,SAAS,4DAKZ,WAAW;kBAmEyB,OAAO,CAAC,IAAI,CAAC;;;;CAiFnD,CAAC;AACF,OAAO,EAAE,SAAS,EAAE,CAAC"}
@@ -2,7 +2,7 @@ import { BrowserAuthenticationInitiator } from "../../services/AuthenticationSer
2
2
  import { BrowserPublicClientPKCEProducer } from "../../services/PKCE.js";
3
3
  import { useCivicAuthConfig } from "../../shared/hooks/useCivicAuthConfig.js";
4
4
  import { useIframe } from "../../shared/hooks/useIframe.js";
5
- import { useCallback, useEffect, useMemo } from "react";
5
+ import { useCallback, useEffect, useMemo, useState } from "react";
6
6
  import { PopupError } from "../../services/types.js";
7
7
  import { useSession } from "./useSession.js";
8
8
  import { LocalStorageAdapter } from "../../browser/storage.js";
@@ -11,6 +11,7 @@ const useSignIn = ({ pkceConsumer, preSignOut, postSignOut, displayMode, }) => {
11
11
  const civicAuthConfig = useCivicAuthConfig();
12
12
  const { iframeRef, logoutIframeRef, setIframeIsVisible, setLogoutIframeIsVisible, } = useIframe();
13
13
  const { data: session } = useSession();
14
+ const [isSigningOut, setIsSigningOut] = useState(false);
14
15
  const authInitiator = useMemo(() => {
15
16
  if (!civicAuthConfig) {
16
17
  return null;
@@ -80,6 +81,7 @@ const useSignIn = ({ pkceConsumer, preSignOut, postSignOut, displayMode, }) => {
80
81
  const idToken = session?.idToken;
81
82
  if (!authInitiator)
82
83
  return;
84
+ setIsSigningOut(true);
83
85
  if (displayMode === "iframe") {
84
86
  setIframeIsVisible(false);
85
87
  setLogoutIframeIsVisible(true);
@@ -88,6 +90,7 @@ const useSignIn = ({ pkceConsumer, preSignOut, postSignOut, displayMode, }) => {
88
90
  await preSignOut?.();
89
91
  const useIframeRef = logoutIframeRef?.current || null;
90
92
  await authInitiator.signOut(idToken, useIframeRef).catch((error) => {
93
+ setIsSigningOut(false);
91
94
  console.log("signOut error", {
92
95
  error,
93
96
  isPopupError: error instanceof PopupError,
@@ -104,21 +107,28 @@ const useSignIn = ({ pkceConsumer, preSignOut, postSignOut, displayMode, }) => {
104
107
  catch (error) {
105
108
  console.error("Signout error:", error);
106
109
  }
107
- setLogoutIframeIsVisible(false);
108
- await postSignOut?.();
109
110
  }, [
110
111
  session?.idToken,
111
112
  authInitiator,
112
113
  displayMode,
113
114
  setLogoutIframeIsVisible,
114
- postSignOut,
115
115
  setIframeIsVisible,
116
116
  preSignOut,
117
117
  logoutIframeRef,
118
118
  ]);
119
+ // handle logout finished
120
+ useEffect(() => {
121
+ if (isSigningOut && !session?.authenticated) {
122
+ setIsSigningOut(false);
123
+ postSignOut?.().then(() => {
124
+ setLogoutIframeIsVisible(false);
125
+ });
126
+ }
127
+ }, [session, postSignOut, isSigningOut, setLogoutIframeIsVisible]);
119
128
  return {
120
129
  signIn,
121
130
  signOut,
131
+ isSigningOut,
122
132
  displayMode,
123
133
  };
124
134
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useSignIn.js","sourceRoot":"","sources":["../../../../src/shared/hooks/useSignIn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AACrF,OAAO,EAAE,+BAA+B,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAE1E,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACxD,OAAO,EAAE,UAAU,EAAqB,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAQxD,MAAM,SAAS,GAAG,CAAC,EACjB,YAAY,EACZ,UAAU,EACV,WAAW,EACX,WAAW,GACC,EAAE,EAAE;IAChB,MAAM,eAAe,GAAG,kBAAkB,EAAE,CAAC;IAC7C,MAAM,EACJ,SAAS,EACT,eAAe,EACf,kBAAkB,EAClB,wBAAwB,GACzB,GAAG,SAAS,EAAE,CAAC;IAChB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,CAAC;IAEvC,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE;QACjC,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,EACJ,QAAQ,EACR,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,KAAK,EACL,WAAW,EACX,SAAS,EACT,MAAM,GACP,GAAG,eAAe,CAAC;QACpB,OAAO,IAAI,8BAA8B,CAAC;YACxC,YAAY,EAAE,YAAY,IAAI,IAAI,+BAA+B,EAAE,EAAE,kDAAkD;YACvH,QAAQ;YACR,WAAW;YACX,SAAS;YACT,iBAAiB;YACjB,MAAM;YACN,WAAW;YACX,WAAW;YACX,iBAAiB,EAAE,SAAS;YAC5B,KAAK;SACN,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,eAAe,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC;IAEjD,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,GAAG,EAAE;YACV,IAAI,aAAa,EAAE,CAAC;gBAClB,aAAa,CAAC,OAAO,EAAE,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IAEpB,4FAA4F;IAC5F,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3D,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,YAAY,GAAG,IAAI,mBAAmB,EAAE,CAAC;QAC/C,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,iBAAiB,EAAE,EAAE;YAC1D,IAAI,KAAK,IAAI,KAAK,KAAK,iBAAiB,EAAE,CAAC;gBACzC,gBAAgB;gBAChB,WAAW,CAAC,YAAY,CAAC,CAAC;gBAC1B,SAAS,CAAC,YAAY,CAAC,CAAC;gBACxB,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAE5C,2BAA2B;gBAC3B,cAAc,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;gBAC1C,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBACpD,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,IAAmB,EAAE;QACnD,IAAI,CAAC,aAAa;YAAE,OAAO;QAE3B,aAAa,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAC1C,IAAI,WAAW,KAAK,QAAQ,EAAE,CAAC;YAC7B,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;QACD,MAAM,YAAY,GAAG,SAAS,EAAE,OAAO,IAAI,IAAI,CAAC;QAChD,MAAM,aAAa,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACvD,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE;gBAC1B,KAAK;gBACL,YAAY,EAAE,KAAK,YAAY,UAAU;aAC1C,CAAC,CAAC;YACH,mFAAmF;YACnF,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;gBAChC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,kBAAkB;gBAC7C,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC,wCAAwC;gBACjE,aAAa,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,0BAA0B;gBACpE,aAAa,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,oBAAoB;YAC1D,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAEhE,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACrC,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC;QACjC,IAAI,CAAC,aAAa;YAAE,OAAO;QAE3B,IAAI,WAAW,KAAK,QAAQ,EAAE,CAAC;YAC7B,kBAAkB,CAAC,KAAK,CAAC,CAAC;YAC1B,wBAAwB,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;QAED,IAAI,CAAC;YACH,MAAM,UAAU,EAAE,EAAE,CAAC;YAErB,MAAM,YAAY,GAAG,eAAe,EAAE,OAAO,IAAI,IAAI,CAAC;YACtD,MAAM,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBACjE,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE;oBAC3B,KAAK;oBACL,YAAY,EAAE,KAAK,YAAY,UAAU;iBAC1C,CAAC,CAAC;gBACH,gCAAgC;gBAChC,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;oBAChC,wBAAwB,CAAC,KAAK,CAAC,CAAC;oBAChC,aAAa,CAAC,OAAO,EAAE,CAAC;oBACxB,aAAa,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;oBACzC,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;gBAC/C,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;QACzC,CAAC;QACD,wBAAwB,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,WAAW,EAAE,EAAE,CAAC;IACxB,CAAC,EAAE;QACD,OAAO,EAAE,OAAO;QAChB,aAAa;QACb,WAAW;QACX,wBAAwB;QACxB,WAAW;QACX,kBAAkB;QAClB,UAAU;QACV,eAAe;KAChB,CAAC,CAAC;IAEH,OAAO;QACL,MAAM;QACN,OAAO;QACP,WAAW;KACZ,CAAC;AACJ,CAAC,CAAC;AACF,OAAO,EAAE,SAAS,EAAE,CAAC","sourcesContent":["import { BrowserAuthenticationInitiator } from \"@/services/AuthenticationService.js\";\nimport { BrowserPublicClientPKCEProducer } from \"@/services/PKCE.js\";\nimport { useCivicAuthConfig } from \"@/shared/hooks/useCivicAuthConfig.js\";\nimport type { DisplayMode } from \"@/types.js\";\nimport { useIframe } from \"@/shared/hooks/useIframe.js\";\nimport { useCallback, useEffect, useMemo } from \"react\";\nimport { PopupError, type PKCEConsumer } from \"@/services/types.js\";\nimport { useSession } from \"./useSession.js\";\nimport { LocalStorageAdapter } from \"@/browser/storage.js\";\nimport { clearTokens, clearUser } from \"../lib/util.js\";\n\ntype SignInProps = {\n pkceConsumer?: PKCEConsumer;\n preSignOut?: () => Promise<void>;\n postSignOut?: () => Promise<void>;\n displayMode: DisplayMode;\n};\nconst useSignIn = ({\n pkceConsumer,\n preSignOut,\n postSignOut,\n displayMode,\n}: SignInProps) => {\n const civicAuthConfig = useCivicAuthConfig();\n const {\n iframeRef,\n logoutIframeRef,\n setIframeIsVisible,\n setLogoutIframeIsVisible,\n } = useIframe();\n const { data: session } = useSession();\n\n const authInitiator = useMemo(() => {\n if (!civicAuthConfig) {\n return null;\n }\n const {\n clientId,\n redirectUrl,\n logoutUrl,\n logoutRedirectUrl,\n nonce,\n oauthServer,\n endpoints,\n scopes,\n } = civicAuthConfig;\n return new BrowserAuthenticationInitiator({\n pkceConsumer: pkceConsumer || new BrowserPublicClientPKCEProducer(), // generate and retrieve the challenge client-side\n clientId,\n redirectUrl,\n logoutUrl,\n logoutRedirectUrl,\n scopes,\n displayMode,\n oauthServer,\n endpointOverrides: endpoints,\n nonce,\n });\n }, [civicAuthConfig, displayMode, pkceConsumer]);\n\n useEffect(() => {\n return () => {\n if (authInitiator) {\n authInitiator.cleanup();\n }\n };\n }, [authInitiator]);\n\n // This effect is used to clear the tokens and user when the user signs out after a redirect\n useEffect(() => {\n const params = new URLSearchParams(window.location.search);\n const state = params.get(\"state\");\n const localStorage = new LocalStorageAdapter();\n localStorage.get(\"logout_state\").then((storedLogoutState) => {\n if (state && state === storedLogoutState) {\n // Clear storage\n clearTokens(localStorage);\n clearUser(localStorage);\n LocalStorageAdapter.emitter.emit(\"signOut\");\n\n // Clean up storage and URL\n sessionStorage.removeItem(\"logout_state\");\n const cleanUrl = window.location.href.split(\"?\")[0];\n window.history.replaceState({}, document.title, cleanUrl);\n }\n });\n }, []);\n\n const signIn = useCallback(async (): Promise<void> => {\n if (!authInitiator) return;\n\n authInitiator.setDisplayMode(displayMode);\n if (displayMode === \"iframe\") {\n setIframeIsVisible(true);\n }\n const useIframeRef = iframeRef?.current || null;\n await authInitiator.signIn(useIframeRef).catch((error) => {\n console.log(\"signIn error\", {\n error,\n isPopupError: error instanceof PopupError,\n });\n // if we've tried to open a popup and it has failed, then fallback to redirect mode\n if (error instanceof PopupError) {\n setIframeIsVisible(false); // hide the iframe\n authInitiator.cleanup(); // clear any event listeners from before\n authInitiator.setDisplayMode(\"redirect\"); // switch to redirect mode\n authInitiator.signIn(useIframeRef); // retry the sign in\n }\n });\n }, [authInitiator, displayMode, iframeRef, setIframeIsVisible]);\n\n const signOut = useCallback(async () => {\n const idToken = session?.idToken;\n if (!authInitiator) return;\n\n if (displayMode === \"iframe\") {\n setIframeIsVisible(false);\n setLogoutIframeIsVisible(true);\n }\n\n try {\n await preSignOut?.();\n\n const useIframeRef = logoutIframeRef?.current || null;\n await authInitiator.signOut(idToken, useIframeRef).catch((error) => {\n console.log(\"signOut error\", {\n error,\n isPopupError: error instanceof PopupError,\n });\n // Same popup fallback as signIn\n if (error instanceof PopupError) {\n setLogoutIframeIsVisible(false);\n authInitiator.cleanup();\n authInitiator.setDisplayMode(\"redirect\");\n authInitiator.signOut(idToken, useIframeRef);\n }\n });\n } catch (error) {\n console.error(\"Signout error:\", error);\n }\n setLogoutIframeIsVisible(false);\n await postSignOut?.();\n }, [\n session?.idToken,\n authInitiator,\n displayMode,\n setLogoutIframeIsVisible,\n postSignOut,\n setIframeIsVisible,\n preSignOut,\n logoutIframeRef,\n ]);\n\n return {\n signIn,\n signOut,\n displayMode,\n };\n};\nexport { useSignIn };\n"]}
1
+ {"version":3,"file":"useSignIn.js","sourceRoot":"","sources":["../../../../src/shared/hooks/useSignIn.ts"],"names":[],"mappings":"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","sourcesContent":["import { BrowserAuthenticationInitiator } from \"@/services/AuthenticationService.js\";\nimport { BrowserPublicClientPKCEProducer } from \"@/services/PKCE.js\";\nimport { useCivicAuthConfig } from \"@/shared/hooks/useCivicAuthConfig.js\";\nimport type { DisplayMode } from \"@/types.js\";\nimport { useIframe } from \"@/shared/hooks/useIframe.js\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { PopupError, type PKCEConsumer } from \"@/services/types.js\";\nimport { useSession } from \"./useSession.js\";\nimport { LocalStorageAdapter } from \"@/browser/storage.js\";\nimport { clearTokens, clearUser } from \"../lib/util.js\";\n\ntype SignInProps = {\n pkceConsumer?: PKCEConsumer;\n preSignOut?: () => Promise<void>;\n postSignOut?: () => Promise<void>;\n displayMode: DisplayMode;\n};\nconst useSignIn = ({\n pkceConsumer,\n preSignOut,\n postSignOut,\n displayMode,\n}: SignInProps) => {\n const civicAuthConfig = useCivicAuthConfig();\n const {\n iframeRef,\n logoutIframeRef,\n setIframeIsVisible,\n setLogoutIframeIsVisible,\n } = useIframe();\n const { data: session } = useSession();\n const [isSigningOut, setIsSigningOut] = useState(false);\n\n const authInitiator = useMemo(() => {\n if (!civicAuthConfig) {\n return null;\n }\n const {\n clientId,\n redirectUrl,\n logoutUrl,\n logoutRedirectUrl,\n nonce,\n oauthServer,\n endpoints,\n scopes,\n } = civicAuthConfig;\n return new BrowserAuthenticationInitiator({\n pkceConsumer: pkceConsumer || new BrowserPublicClientPKCEProducer(), // generate and retrieve the challenge client-side\n clientId,\n redirectUrl,\n logoutUrl,\n logoutRedirectUrl,\n scopes,\n displayMode,\n oauthServer,\n endpointOverrides: endpoints,\n nonce,\n });\n }, [civicAuthConfig, displayMode, pkceConsumer]);\n\n useEffect(() => {\n return () => {\n if (authInitiator) {\n authInitiator.cleanup();\n }\n };\n }, [authInitiator]);\n\n // This effect is used to clear the tokens and user when the user signs out after a redirect\n useEffect(() => {\n const params = new URLSearchParams(window.location.search);\n const state = params.get(\"state\");\n const localStorage = new LocalStorageAdapter();\n localStorage.get(\"logout_state\").then((storedLogoutState) => {\n if (state && state === storedLogoutState) {\n // Clear storage\n clearTokens(localStorage);\n clearUser(localStorage);\n LocalStorageAdapter.emitter.emit(\"signOut\");\n\n // Clean up storage and URL\n sessionStorage.removeItem(\"logout_state\");\n const cleanUrl = window.location.href.split(\"?\")[0];\n window.history.replaceState({}, document.title, cleanUrl);\n }\n });\n }, []);\n\n const signIn = useCallback(async (): Promise<void> => {\n if (!authInitiator) return;\n\n authInitiator.setDisplayMode(displayMode);\n if (displayMode === \"iframe\") {\n setIframeIsVisible(true);\n }\n const useIframeRef = iframeRef?.current || null;\n await authInitiator.signIn(useIframeRef).catch((error) => {\n console.log(\"signIn error\", {\n error,\n isPopupError: error instanceof PopupError,\n });\n // if we've tried to open a popup and it has failed, then fallback to redirect mode\n if (error instanceof PopupError) {\n setIframeIsVisible(false); // hide the iframe\n authInitiator.cleanup(); // clear any event listeners from before\n authInitiator.setDisplayMode(\"redirect\"); // switch to redirect mode\n authInitiator.signIn(useIframeRef); // retry the sign in\n }\n });\n }, [authInitiator, displayMode, iframeRef, setIframeIsVisible]);\n\n const signOut = useCallback(async () => {\n const idToken = session?.idToken;\n if (!authInitiator) return;\n\n setIsSigningOut(true);\n if (displayMode === \"iframe\") {\n setIframeIsVisible(false);\n setLogoutIframeIsVisible(true);\n }\n\n try {\n await preSignOut?.();\n\n const useIframeRef = logoutIframeRef?.current || null;\n await authInitiator.signOut(idToken, useIframeRef).catch((error) => {\n setIsSigningOut(false);\n console.log(\"signOut error\", {\n error,\n isPopupError: error instanceof PopupError,\n });\n\n // Same popup fallback as signIn\n if (error instanceof PopupError) {\n setLogoutIframeIsVisible(false);\n authInitiator.cleanup();\n authInitiator.setDisplayMode(\"redirect\");\n authInitiator.signOut(idToken, useIframeRef);\n }\n });\n } catch (error) {\n console.error(\"Signout error:\", error);\n }\n }, [\n session?.idToken,\n authInitiator,\n displayMode,\n setLogoutIframeIsVisible,\n setIframeIsVisible,\n preSignOut,\n logoutIframeRef,\n ]);\n\n // handle logout finished\n useEffect(() => {\n if (isSigningOut && !session?.authenticated) {\n setIsSigningOut(false);\n postSignOut?.().then(() => {\n setLogoutIframeIsVisible(false);\n });\n }\n }, [session, postSignOut, isSigningOut, setLogoutIframeIsVisible]);\n\n return {\n signIn,\n signOut,\n isSigningOut,\n displayMode,\n };\n};\nexport { useSignIn };\n"]}
@@ -1,12 +1,12 @@
1
- import type { AuthStorage, User } from "../../types.js";
2
- export interface UserSession {
3
- get(): Promise<User | null>;
4
- set(user: User): Promise<void>;
1
+ import type { AuthStorage, UnknownObject, User } from "../../types.js";
2
+ export interface UserSession<T extends UnknownObject> {
3
+ get(): Promise<User<T> | null>;
4
+ set(user: User<T>): Promise<void>;
5
5
  }
6
- export declare class GenericUserSession implements UserSession {
6
+ export declare class GenericUserSession<T extends UnknownObject> implements UserSession<T> {
7
7
  readonly storage: AuthStorage;
8
8
  constructor(storage: AuthStorage);
9
- get(): Promise<User | null>;
10
- set(user: User | null): Promise<void>;
9
+ get(): Promise<User<T> | null>;
10
+ set(user: User<T> | null): Promise<void>;
11
11
  }
12
12
  //# sourceMappingURL=UserSession.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"UserSession.d.ts","sourceRoot":"","sources":["../../../../src/shared/lib/UserSession.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAsB,IAAI,EAAE,MAAM,YAAY,CAAC;AAIxE,MAAM,WAAW,WAAW;IAC1B,GAAG,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAC5B,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAED,qBAAa,kBAAmB,YAAW,WAAW;IACxC,QAAQ,CAAC,OAAO,EAAE,WAAW;gBAApB,OAAO,EAAE,WAAW;IAEnC,GAAG,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAK3B,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CAO5C"}
1
+ {"version":3,"file":"UserSession.d.ts","sourceRoot":"","sources":["../../../../src/shared/lib/UserSession.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAEX,aAAa,EACb,IAAI,EACL,MAAM,YAAY,CAAC;AAIpB,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,aAAa;IAClD,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC/B,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC;AAED,qBAAa,kBAAkB,CAAC,CAAC,SAAS,aAAa,CACrD,YAAW,WAAW,CAAC,CAAC,CAAC;IAEb,QAAQ,CAAC,OAAO,EAAE,WAAW;gBAApB,OAAO,EAAE,WAAW;IAEnC,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAK9B,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CAO/C"}
@@ -1 +1 @@
1
- {"version":3,"file":"UserSession.js","sourceRoot":"","sources":["../../../../src/shared/lib/UserSession.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAO3D,MAAM,OAAO,kBAAkB;IACR;IAArB,YAAqB,OAAoB;QAApB,YAAO,GAAP,OAAO,CAAa;IAAG,CAAC;IAE7C,KAAK,CAAC,GAAG;QACP,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAiB;QACzB,MAAM,eAAe,GAAG,IAAI,EAAE,eAAe;YAC3C,CAAC,CAAC,2BAA2B,CAAC,IAAI,EAAE,eAAqC,CAAC;YAC1E,CAAC,CAAC,IAAI,CAAC;QACT,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC;CACF","sourcesContent":["import type { AuthStorage, ForwardedTokensJWT, User } from \"@/types.js\";\nimport { UserStorage } from \"@/shared/lib/types.js\";\nimport { convertForwardedTokenFormat } from \"@/lib/jwt.js\";\n\nexport interface UserSession {\n get(): Promise<User | null>;\n set(user: User): Promise<void>;\n}\n\nexport class GenericUserSession implements UserSession {\n constructor(readonly storage: AuthStorage) {}\n\n async get(): Promise<User | null> {\n const user = await this.storage.get(UserStorage.USER);\n return user ? JSON.parse(user) : null;\n }\n\n async set(user: User | null): Promise<void> {\n const forwardedTokens = user?.forwardedTokens\n ? convertForwardedTokenFormat(user?.forwardedTokens as ForwardedTokensJWT)\n : null;\n const value = user ? JSON.stringify({ ...user, forwardedTokens }) : \"\";\n await this.storage.set(UserStorage.USER, value);\n }\n}\n"]}
1
+ {"version":3,"file":"UserSession.js","sourceRoot":"","sources":["../../../../src/shared/lib/UserSession.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAO3D,MAAM,OAAO,kBAAkB;IAGR;IAArB,YAAqB,OAAoB;QAApB,YAAO,GAAP,OAAO,CAAa;IAAG,CAAC;IAE7C,KAAK,CAAC,GAAG;QACP,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAoB;QAC5B,MAAM,eAAe,GAAG,IAAI,EAAE,eAAe;YAC3C,CAAC,CAAC,2BAA2B,CAAC,IAAI,EAAE,eAAqC,CAAC;YAC1E,CAAC,CAAC,IAAI,CAAC;QACT,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC;CACF","sourcesContent":["import type {\n AuthStorage,\n ForwardedTokensJWT,\n UnknownObject,\n User,\n} from \"@/types.js\";\nimport { UserStorage } from \"@/shared/lib/types.js\";\nimport { convertForwardedTokenFormat } from \"@/lib/jwt.js\";\n\nexport interface UserSession<T extends UnknownObject> {\n get(): Promise<User<T> | null>;\n set(user: User<T>): Promise<void>;\n}\n\nexport class GenericUserSession<T extends UnknownObject>\n implements UserSession<T>\n{\n constructor(readonly storage: AuthStorage) {}\n\n async get(): Promise<User<T> | null> {\n const user = await this.storage.get(UserStorage.USER);\n return user ? JSON.parse(user) : null;\n }\n\n async set(user: User<T> | null): Promise<void> {\n const forwardedTokens = user?.forwardedTokens\n ? convertForwardedTokenFormat(user?.forwardedTokens as ForwardedTokensJWT)\n : null;\n const value = user ? JSON.stringify({ ...user, forwardedTokens }) : \"\";\n await this.storage.set(UserStorage.USER, value);\n }\n}\n"]}
@@ -5,6 +5,7 @@ export type AuthContextType = {
5
5
  isLoading: boolean;
6
6
  error: Error | null;
7
7
  signOut: () => Promise<void>;
8
+ isSigningOut: boolean;
8
9
  displayMode: DisplayMode;
9
10
  };
10
11
  export declare const AuthContext: import("react").Context<AuthContextType | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"AuthContext.d.ts","sourceRoot":"","sources":["../../../../src/shared/providers/AuthContext.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,WAAW,EAAE,WAAW,CAAC;CAC1B,CAAC;AACF,eAAO,MAAM,WAAW,iDAA8C,CAAC"}
1
+ {"version":3,"file":"AuthContext.d.ts","sourceRoot":"","sources":["../../../../src/shared/providers/AuthContext.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,WAAW,CAAC;CAC1B,CAAC;AACF,eAAO,MAAM,WAAW,iDAA8C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"AuthContext.js","sourceRoot":"","sources":["../../../../src/shared/providers/AuthContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAWtC,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAyB,IAAI,CAAC,CAAC","sourcesContent":["import { createContext } from \"react\";\nimport type { DisplayMode } from \"@/types.js\";\n\nexport type AuthContextType = {\n signIn: (displayMode?: DisplayMode) => Promise<void>;\n isAuthenticated: boolean;\n isLoading: boolean;\n error: Error | null;\n signOut: () => Promise<void>;\n displayMode: DisplayMode;\n};\nexport const AuthContext = createContext<AuthContextType | null>(null);\n"]}
1
+ {"version":3,"file":"AuthContext.js","sourceRoot":"","sources":["../../../../src/shared/providers/AuthContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAYtC,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAyB,IAAI,CAAC,CAAC","sourcesContent":["import { createContext } from \"react\";\nimport type { DisplayMode } from \"@/types.js\";\n\nexport type AuthContextType = {\n signIn: (displayMode?: DisplayMode) => Promise<void>;\n isAuthenticated: boolean;\n isLoading: boolean;\n error: Error | null;\n signOut: () => Promise<void>;\n isSigningOut: boolean;\n displayMode: DisplayMode;\n};\nexport const AuthContext = createContext<AuthContextType | null>(null);\n"]}
@@ -5,7 +5,6 @@ type TokenContextType = {
5
5
  accessToken: string | null;
6
6
  idToken: string | null;
7
7
  forwardedTokens: ForwardedTokens;
8
- refreshToken: () => Promise<void>;
9
8
  isLoading: boolean;
10
9
  error: Error | null;
11
10
  };
@@ -1 +1 @@
1
- {"version":3,"file":"TokenProvider.d.ts","sourceRoot":"","sources":["../../../../src/shared/providers/TokenProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAA8C,MAAM,OAAO,CAAC;AAEnE,OAAO,KAAK,EAAE,eAAe,EAAW,MAAM,YAAY,CAAC;AAI3D,KAAK,gBAAgB,GAAG;IACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;IACjC,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB,CAAC;AAEF,QAAA,MAAM,YAAY,6CAAyD,CAAC;AAE5E,QAAA,MAAM,aAAa,iBAAkB;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,sBA4C3D,CAAC;AAEF,YAAY,EAAE,gBAAgB,EAAE,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"TokenProvider.d.ts","sourceRoot":"","sources":["../../../../src/shared/providers/TokenProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAiC,MAAM,OAAO,CAAC;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAW,MAAM,YAAY,CAAC;AAI3D,KAAK,gBAAgB,GAAG;IACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB,CAAC;AAEF,QAAA,MAAM,YAAY,6CAAyD,CAAC;AAE5E,QAAA,MAAM,aAAa,iBAAkB;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,sBAsC3D,CAAC;AAEF,YAAY,EAAE,gBAAgB,EAAE,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import React, { createContext, useCallback, useMemo } from "react";
2
+ import React, { createContext, useMemo } from "react";
3
3
  import { useSession } from "../../shared/hooks/useSession.js";
4
4
  import { parseJWT } from "oslo/jwt";
5
5
  import { convertForwardedTokenFormat } from "../../lib/jwt.js";
@@ -7,9 +7,6 @@ const TokenContext = createContext(undefined);
7
7
  const TokenProvider = ({ children }) => {
8
8
  const { isLoading, error: authError } = useSession();
9
9
  const { data: session } = useSession();
10
- const refreshToken = useCallback(async () => {
11
- throw new Error("Not implemented");
12
- }, []);
13
10
  const decodeTokens = useMemo(() => {
14
11
  if (!session?.idToken)
15
12
  return null;
@@ -25,14 +22,12 @@ const TokenProvider = ({ children }) => {
25
22
  accessToken: session?.accessToken || null,
26
23
  idToken: session?.idToken || null,
27
24
  forwardedTokens: decodeTokens || {},
28
- refreshToken,
29
25
  isLoading,
30
26
  error: authError,
31
27
  }), [
32
28
  session?.accessToken,
33
29
  session?.idToken,
34
30
  decodeTokens,
35
- refreshToken,
36
31
  isLoading,
37
32
  authError,
38
33
  ]);
@@ -1 +1 @@
1
- {"version":3,"file":"TokenProvider.js","sourceRoot":"","sources":["../../../../src/shared/providers/TokenProvider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE1D,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAW3D,MAAM,YAAY,GAAG,aAAa,CAA+B,SAAS,CAAC,CAAC;AAE5E,MAAM,aAAa,GAAG,CAAC,EAAE,QAAQ,EAA2B,EAAE,EAAE;IAC9D,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,UAAU,EAAE,CAAC;IACrD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,CAAC;IAEvC,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC1C,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACrC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,EAAE;QAChC,IAAI,CAAC,OAAO,EAAE,OAAO;YAAE,OAAO,IAAI,CAAC;QAEnC,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAmB,CAAC;QAE9D,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QAE5B,MAAM,EAAE,eAAe,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC;QAE9C,OAAO,eAAe;YACpB,CAAC,CAAC,2BAA2B,CAAC,eAAe,CAAC;YAC9C,CAAC,CAAC,IAAI,CAAC;IACX,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAEvB,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,CAAC;QACL,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,IAAI;QACzC,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,IAAI;QACjC,eAAe,EAAE,YAAY,IAAI,EAAE;QACnC,YAAY;QACZ,SAAS;QACT,KAAK,EAAE,SAAyB;KACjC,CAAC,EACF;QACE,OAAO,EAAE,WAAW;QACpB,OAAO,EAAE,OAAO;QAChB,YAAY;QACZ,YAAY;QACZ,SAAS;QACT,SAAS;KACV,CACF,CAAC;IAEF,OAAO,CACL,oBAAC,YAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,IAAG,QAAQ,CAAyB,CACxE,CAAC;AACJ,CAAC,CAAC;AAGF,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC","sourcesContent":["\"use client\";\nimport type { ReactNode } from \"react\";\nimport React, { createContext, useCallback, useMemo } from \"react\";\nimport { useSession } from \"@/shared/hooks/useSession.js\";\nimport type { ForwardedTokens, IdToken } from \"@/types.js\";\nimport { parseJWT } from \"oslo/jwt\";\nimport { convertForwardedTokenFormat } from \"@/lib/jwt.js\";\n\ntype TokenContextType = {\n accessToken: string | null;\n idToken: string | null;\n forwardedTokens: ForwardedTokens;\n refreshToken: () => Promise<void>;\n isLoading: boolean;\n error: Error | null;\n};\n\nconst TokenContext = createContext<TokenContextType | undefined>(undefined);\n\nconst TokenProvider = ({ children }: { children: ReactNode }) => {\n const { isLoading, error: authError } = useSession();\n const { data: session } = useSession();\n\n const refreshToken = useCallback(async () => {\n throw new Error(\"Not implemented\");\n }, []);\n\n const decodeTokens = useMemo(() => {\n if (!session?.idToken) return null;\n\n const parsedJWT = parseJWT(session.idToken) as IdToken | null;\n\n if (!parsedJWT) return null;\n\n const { forwardedTokens } = parsedJWT.payload;\n\n return forwardedTokens\n ? convertForwardedTokenFormat(forwardedTokens)\n : null;\n }, [session?.idToken]);\n\n const value = useMemo(\n () => ({\n accessToken: session?.accessToken || null,\n idToken: session?.idToken || null,\n forwardedTokens: decodeTokens || {},\n refreshToken,\n isLoading,\n error: authError as Error | null,\n }),\n [\n session?.accessToken,\n session?.idToken,\n decodeTokens,\n refreshToken,\n isLoading,\n authError,\n ],\n );\n\n return (\n <TokenContext.Provider value={value}>{children}</TokenContext.Provider>\n );\n};\n\nexport type { TokenContextType };\nexport { TokenProvider, TokenContext };\n"]}
1
+ {"version":3,"file":"TokenProvider.js","sourceRoot":"","sources":["../../../../src/shared/providers/TokenProvider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE1D,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAU3D,MAAM,YAAY,GAAG,aAAa,CAA+B,SAAS,CAAC,CAAC;AAE5E,MAAM,aAAa,GAAG,CAAC,EAAE,QAAQ,EAA2B,EAAE,EAAE;IAC9D,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,UAAU,EAAE,CAAC;IACrD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,CAAC;IAEvC,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,EAAE;QAChC,IAAI,CAAC,OAAO,EAAE,OAAO;YAAE,OAAO,IAAI,CAAC;QAEnC,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAmB,CAAC;QAE9D,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QAE5B,MAAM,EAAE,eAAe,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC;QAE9C,OAAO,eAAe;YACpB,CAAC,CAAC,2BAA2B,CAAC,eAAe,CAAC;YAC9C,CAAC,CAAC,IAAI,CAAC;IACX,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAEvB,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,CAAC;QACL,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,IAAI;QACzC,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,IAAI;QACjC,eAAe,EAAE,YAAY,IAAI,EAAE;QACnC,SAAS;QACT,KAAK,EAAE,SAAyB;KACjC,CAAC,EACF;QACE,OAAO,EAAE,WAAW;QACpB,OAAO,EAAE,OAAO;QAChB,YAAY;QACZ,SAAS;QACT,SAAS;KACV,CACF,CAAC;IAEF,OAAO,CACL,oBAAC,YAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,IAAG,QAAQ,CAAyB,CACxE,CAAC;AACJ,CAAC,CAAC;AAGF,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC","sourcesContent":["\"use client\";\nimport type { ReactNode } from \"react\";\nimport React, { createContext, useMemo } from \"react\";\nimport { useSession } from \"@/shared/hooks/useSession.js\";\nimport type { ForwardedTokens, IdToken } from \"@/types.js\";\nimport { parseJWT } from \"oslo/jwt\";\nimport { convertForwardedTokenFormat } from \"@/lib/jwt.js\";\n\ntype TokenContextType = {\n accessToken: string | null;\n idToken: string | null;\n forwardedTokens: ForwardedTokens;\n isLoading: boolean;\n error: Error | null;\n};\n\nconst TokenContext = createContext<TokenContextType | undefined>(undefined);\n\nconst TokenProvider = ({ children }: { children: ReactNode }) => {\n const { isLoading, error: authError } = useSession();\n const { data: session } = useSession();\n\n const decodeTokens = useMemo(() => {\n if (!session?.idToken) return null;\n\n const parsedJWT = parseJWT(session.idToken) as IdToken | null;\n\n if (!parsedJWT) return null;\n\n const { forwardedTokens } = parsedJWT.payload;\n\n return forwardedTokens\n ? convertForwardedTokenFormat(forwardedTokens)\n : null;\n }, [session?.idToken]);\n\n const value = useMemo(\n () => ({\n accessToken: session?.accessToken || null,\n idToken: session?.idToken || null,\n forwardedTokens: decodeTokens || {},\n isLoading,\n error: authError as Error | null,\n }),\n [\n session?.accessToken,\n session?.idToken,\n decodeTokens,\n isLoading,\n authError,\n ],\n );\n\n return (\n <TokenContext.Provider value={value}>{children}</TokenContext.Provider>\n );\n};\n\nexport type { TokenContextType };\nexport { TokenProvider, TokenContext };\n"]}
@@ -1,21 +1,23 @@
1
1
  import React from "react";
2
2
  import type { ReactNode } from "react";
3
3
  import type { JWT } from "oslo/jwt";
4
- import type { AuthStorage, DisplayMode, EmptyObject, ForwardedTokens, User } from "../../types.js";
4
+ import type { AuthStorage, DisplayMode, ForwardedTokens, User } from "../../types.js";
5
5
  import type { AuthContextType } from "../../shared/providers/AuthContext.js";
6
- type UserContextType<T extends Record<string, unknown> & JWT["payload"] = Record<string, unknown> & JWT["payload"]> = {
6
+ type UserContent = Record<string, unknown> & JWT["payload"];
7
+ type UserContextType<T extends UserContent = UserContent> = {
7
8
  user: User<T> | null;
8
9
  } & {
9
10
  accessToken?: string | null;
10
11
  idToken?: string | null;
11
12
  forwardedTokens?: ForwardedTokens;
12
13
  } & Omit<AuthContextType, "isAuthenticated">;
13
- declare const UserContext: React.Context<UserContextType<Record<string, unknown> & object> | null>;
14
- declare const UserProvider: <T extends EmptyObject>({ children, storage, user: inputUser, signOut, signIn, displayMode, }: {
14
+ declare const UserContext: React.Context<UserContextType<UserContent> | null>;
15
+ declare const UserProvider: <T extends UserContent>({ children, storage, user: inputUser, signOut, isSigningOut, signIn, displayMode, }: {
15
16
  children: ReactNode;
16
17
  storage: AuthStorage;
17
- user?: User<T> | null;
18
+ user: User<T> | null;
18
19
  signOut: () => Promise<void>;
20
+ isSigningOut: boolean;
19
21
  signIn: (displayMode?: DisplayMode) => Promise<void>;
20
22
  displayMode: DisplayMode;
21
23
  }) => React.JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"UserProvider.d.ts","sourceRoot":"","sources":["../../../../src/shared/providers/UserProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA0D,MAAM,OAAO,CAAC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,eAAe,EACf,IAAI,EACL,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAIzE,KAAK,eAAe,CAClB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC1E,GAAG,CAAC,SAAS,CAAC,IACd;IACF,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;CACtB,GAAG;IACF,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC,GAAG,IAAI,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAC;AAE7C,QAAA,MAAM,WAAW,yEAA8C,CAAC;AAEhE,QAAA,MAAM,YAAY,GAAI,CAAC,SAAS,WAAW,yEAOxC;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,OAAO,EAAE,WAAW,CAAC;IACrB,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,WAAW,EAAE,WAAW,CAAC;CAC1B,sBAqDA,CAAC;AAEF,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"UserProvider.d.ts","sourceRoot":"","sources":["../../../../src/shared/providers/UserProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA0D,MAAM,OAAO,CAAC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,eAAe,EACf,IAAI,EACL,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAIzE,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;AAC5D,KAAK,eAAe,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAAI;IAC1D,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;CACtB,GAAG;IACF,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC,GAAG,IAAI,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAC;AAE7C,QAAA,MAAM,WAAW,oDAA8C,CAAC;AAEhE,QAAA,MAAM,YAAY,GAAI,CAAC,SAAS,WAAW,uFAQxC;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,OAAO,EAAE,WAAW,CAAC;IACrB,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,WAAW,EAAE,WAAW,CAAC;CAC1B,sBA8DA,CAAC;AAEF,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC"}
@@ -4,31 +4,31 @@ import { useSession } from "../../shared/hooks/useSession.js";
4
4
  import { GenericUserSession } from "../../shared/lib/UserSession.js";
5
5
  import { useToken } from "../hooks/useToken.js";
6
6
  const UserContext = createContext(null);
7
- const UserProvider = ({ children, storage, user: inputUser = null, signOut, signIn, displayMode, }) => {
7
+ const UserProvider = ({ children, storage, user: inputUser, signOut, isSigningOut, signIn, displayMode, }) => {
8
8
  const { error: authError, isLoading: authLoading } = useSession();
9
9
  const { data: session } = useSession();
10
10
  const tokens = useToken();
11
11
  const [userLoading, setUserLoading] = useState(false);
12
12
  const [userError, setUserError] = useState(null);
13
- const [user, setUser] = useState(null);
13
+ const [user, setUser] = useState(inputUser);
14
14
  const fetchUser = useCallback(async () => {
15
- if (!session?.idToken) {
15
+ if (!session?.idToken)
16
16
  return null;
17
- }
18
17
  const userSession = new GenericUserSession(storage);
19
18
  return userSession.get();
20
19
  }, [session?.idToken, storage]);
21
20
  useEffect(() => {
22
- if (!session?.idToken) {
23
- setUser(null);
24
- return;
25
- }
26
21
  if (session?.idToken) {
27
22
  setUserLoading(true);
28
23
  fetchUser()
29
24
  .then((user) => {
30
25
  setUserLoading(false);
31
- setUser(user);
26
+ setUser((prevUser) => {
27
+ // we only want to update the user if it's set - if a user is passed in, don't assume it is wrong here
28
+ // it could be just the fetchUser returned null for some other reason.
29
+ // TODO consider cleaning this up in general to avoid needing context here.
30
+ return user ?? prevUser;
31
+ });
32
32
  })
33
33
  .catch((error) => {
34
34
  setUserLoading(false);
@@ -37,14 +37,23 @@ const UserProvider = ({ children, storage, user: inputUser = null, signOut, sign
37
37
  }
38
38
  }, [fetchUser, session?.idToken]);
39
39
  const isLoading = authLoading || userLoading;
40
- const error = authError || userError;
40
+ const error = authError ?? userError;
41
+ // While we are passing a user as a prop _and_ storing it in state,
42
+ // there is the case where the user is not set in the state yet
43
+ // (setState is called but the rerender has not yet happened), but
44
+ // is passed as a prop. In this case, we want to use the prop value.
45
+ // A better solution is to avoid having multiple layers of context.
46
+ // If the user is passed in, we just use that.
47
+ // We should not split user state management across multiple contexts
48
+ const userValue = user ?? inputUser;
41
49
  return (React.createElement(UserContext.Provider, { value: {
42
50
  ...tokens,
43
- user: (inputUser || user) ?? null,
51
+ user: userValue,
44
52
  isLoading,
45
53
  error,
46
54
  signIn,
47
55
  signOut,
56
+ isSigningOut,
48
57
  displayMode: displayMode || "iframe",
49
58
  } }, children));
50
59
  };
@@ -1 +1 @@
1
- {"version":3,"file":"UserProvider.js","sourceRoot":"","sources":["../../../../src/shared/providers/UserProvider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAU/E,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAahD,MAAM,WAAW,GAAG,aAAa,CAAyB,IAAI,CAAC,CAAC;AAEhE,MAAM,YAAY,GAAG,CAAwB,EAC3C,QAAQ,EACR,OAAO,EACP,IAAI,EAAE,SAAS,GAAG,IAAI,EACtB,OAAO,EACP,MAAM,EACN,WAAW,GAQZ,EAAE,EAAE;IACH,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,UAAU,EAAE,CAAC;IAClE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,CAAC;IACvC,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC1B,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAC/D,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IAC/D,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAc,IAAI,CAAC,CAAC;IAEpD,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,IAA0B,EAAE;QAC7D,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,WAAW,GAAG,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACpD,OAAO,WAAW,CAAC,GAAG,EAAE,CAAC;IAC3B,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAEhC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,CAAC;YACd,OAAO;QACT,CAAC;QACD,IAAI,OAAO,EAAE,OAAO,EAAE,CAAC;YACrB,cAAc,CAAC,IAAI,CAAC,CAAC;YACrB,SAAS,EAAE;iBACR,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;gBACb,cAAc,CAAC,KAAK,CAAC,CAAC;gBACtB,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBACf,cAAc,CAAC,KAAK,CAAC,CAAC;gBACtB,YAAY,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC,CAAC,CAAC;QACP,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAElC,MAAM,SAAS,GAAG,WAAW,IAAI,WAAW,CAAC;IAC7C,MAAM,KAAK,GAAG,SAAS,IAAI,SAAS,CAAC;IAErC,OAAO,CACL,oBAAC,WAAW,CAAC,QAAQ,IACnB,KAAK,EAAE;YACL,GAAG,MAAM;YACT,IAAI,EAAE,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,IAAI;YACjC,SAAS;YACT,KAAK;YACL,MAAM;YACN,OAAO;YACP,WAAW,EAAE,WAAW,IAAI,QAAQ;SACrC,IAEA,QAAQ,CACY,CACxB,CAAC;AACJ,CAAC,CAAC;AAIF,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC","sourcesContent":["\"use client\";\n\nimport React, { createContext, useCallback, useEffect, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { JWT } from \"oslo/jwt\";\nimport type {\n AuthStorage,\n DisplayMode,\n EmptyObject,\n ForwardedTokens,\n User,\n} from \"@/types.js\";\nimport { useSession } from \"@/shared/hooks/useSession.js\";\nimport type { AuthContextType } from \"@/shared/providers/AuthContext.js\";\nimport { GenericUserSession } from \"@/shared/lib/UserSession.js\";\nimport { useToken } from \"../hooks/useToken.js\";\n\ntype UserContextType<\n T extends Record<string, unknown> & JWT[\"payload\"] = Record<string, unknown> &\n JWT[\"payload\"],\n> = {\n user: User<T> | null;\n} & {\n accessToken?: string | null;\n idToken?: string | null;\n forwardedTokens?: ForwardedTokens;\n} & Omit<AuthContextType, \"isAuthenticated\">;\n\nconst UserContext = createContext<UserContextType | null>(null);\n\nconst UserProvider = <T extends EmptyObject>({\n children,\n storage,\n user: inputUser = null,\n signOut,\n signIn,\n displayMode,\n}: {\n children: ReactNode;\n storage: AuthStorage;\n user?: User<T> | null;\n signOut: () => Promise<void>;\n signIn: (displayMode?: DisplayMode) => Promise<void>;\n displayMode: DisplayMode;\n}) => {\n const { error: authError, isLoading: authLoading } = useSession();\n const { data: session } = useSession();\n const tokens = useToken();\n const [userLoading, setUserLoading] = useState<boolean>(false);\n const [userError, setUserError] = useState<Error | null>(null);\n const [user, setUser] = useState<User | null>(null);\n\n const fetchUser = useCallback(async (): Promise<User | null> => {\n if (!session?.idToken) {\n return null;\n }\n const userSession = new GenericUserSession(storage);\n return userSession.get();\n }, [session?.idToken, storage]);\n\n useEffect(() => {\n if (!session?.idToken) {\n setUser(null);\n return;\n }\n if (session?.idToken) {\n setUserLoading(true);\n fetchUser()\n .then((user) => {\n setUserLoading(false);\n setUser(user);\n })\n .catch((error) => {\n setUserLoading(false);\n setUserError(error);\n });\n }\n }, [fetchUser, session?.idToken]);\n\n const isLoading = authLoading || userLoading;\n const error = authError || userError;\n\n return (\n <UserContext.Provider\n value={{\n ...tokens,\n user: (inputUser || user) ?? null,\n isLoading,\n error,\n signIn,\n signOut,\n displayMode: displayMode || \"iframe\",\n }}\n >\n {children}\n </UserContext.Provider>\n );\n};\n\nexport type { UserContextType };\n\nexport { UserProvider, UserContext };\n"]}
1
+ {"version":3,"file":"UserProvider.js","sourceRoot":"","sources":["../../../../src/shared/providers/UserProvider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAS/E,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAWhD,MAAM,WAAW,GAAG,aAAa,CAAyB,IAAI,CAAC,CAAC;AAEhE,MAAM,YAAY,GAAG,CAAwB,EAC3C,QAAQ,EACR,OAAO,EACP,IAAI,EAAE,SAAS,EACf,OAAO,EACP,YAAY,EACZ,MAAM,EACN,WAAW,GASZ,EAAE,EAAE;IACH,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,UAAU,EAAE,CAAC;IAClE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,CAAC;IACvC,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC1B,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAC/D,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IAC/D,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAiB,SAAS,CAAC,CAAC;IAE5D,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,IAA6B,EAAE;QAChE,IAAI,CAAC,OAAO,EAAE,OAAO;YAAE,OAAO,IAAI,CAAC;QACnC,MAAM,WAAW,GAAG,IAAI,kBAAkB,CAAI,OAAO,CAAC,CAAC;QACvD,OAAO,WAAW,CAAC,GAAG,EAAE,CAAC;IAC3B,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAEhC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO,EAAE,OAAO,EAAE,CAAC;YACrB,cAAc,CAAC,IAAI,CAAC,CAAC;YACrB,SAAS,EAAE;iBACR,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;gBACb,cAAc,CAAC,KAAK,CAAC,CAAC;gBACtB,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;oBACnB,sGAAsG;oBACtG,sEAAsE;oBACtE,2EAA2E;oBAC3E,OAAO,IAAI,IAAI,QAAQ,CAAC;gBAC1B,CAAC,CAAC,CAAC;YACL,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBACf,cAAc,CAAC,KAAK,CAAC,CAAC;gBACtB,YAAY,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC,CAAC,CAAC;QACP,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAElC,MAAM,SAAS,GAAG,WAAW,IAAI,WAAW,CAAC;IAC7C,MAAM,KAAK,GAAG,SAAS,IAAI,SAAS,CAAC;IAErC,mEAAmE;IACnE,+DAA+D;IAC/D,kEAAkE;IAClE,oEAAoE;IACpE,mEAAmE;IACnE,8CAA8C;IAC9C,qEAAqE;IACrE,MAAM,SAAS,GAAG,IAAI,IAAI,SAAS,CAAC;IAEpC,OAAO,CACL,oBAAC,WAAW,CAAC,QAAQ,IACnB,KAAK,EAAE;YACL,GAAG,MAAM;YACT,IAAI,EAAE,SAAS;YACf,SAAS;YACT,KAAK;YACL,MAAM;YACN,OAAO;YACP,YAAY;YACZ,WAAW,EAAE,WAAW,IAAI,QAAQ;SACrC,IAEA,QAAQ,CACY,CACxB,CAAC;AACJ,CAAC,CAAC;AAIF,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC","sourcesContent":["\"use client\";\n\nimport React, { createContext, useCallback, useEffect, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { JWT } from \"oslo/jwt\";\nimport type {\n AuthStorage,\n DisplayMode,\n ForwardedTokens,\n User,\n} from \"@/types.js\";\nimport { useSession } from \"@/shared/hooks/useSession.js\";\nimport type { AuthContextType } from \"@/shared/providers/AuthContext.js\";\nimport { GenericUserSession } from \"@/shared/lib/UserSession.js\";\nimport { useToken } from \"../hooks/useToken.js\";\n\ntype UserContent = Record<string, unknown> & JWT[\"payload\"];\ntype UserContextType<T extends UserContent = UserContent> = {\n user: User<T> | null;\n} & {\n accessToken?: string | null;\n idToken?: string | null;\n forwardedTokens?: ForwardedTokens;\n} & Omit<AuthContextType, \"isAuthenticated\">;\n\nconst UserContext = createContext<UserContextType | null>(null);\n\nconst UserProvider = <T extends UserContent>({\n children,\n storage,\n user: inputUser,\n signOut,\n isSigningOut,\n signIn,\n displayMode,\n}: {\n children: ReactNode;\n storage: AuthStorage;\n user: User<T> | null;\n signOut: () => Promise<void>;\n isSigningOut: boolean;\n signIn: (displayMode?: DisplayMode) => Promise<void>;\n displayMode: DisplayMode;\n}) => {\n const { error: authError, isLoading: authLoading } = useSession();\n const { data: session } = useSession();\n const tokens = useToken();\n const [userLoading, setUserLoading] = useState<boolean>(false);\n const [userError, setUserError] = useState<Error | null>(null);\n const [user, setUser] = useState<User<T> | null>(inputUser);\n\n const fetchUser = useCallback(async (): Promise<User<T> | null> => {\n if (!session?.idToken) return null;\n const userSession = new GenericUserSession<T>(storage);\n return userSession.get();\n }, [session?.idToken, storage]);\n\n useEffect(() => {\n if (session?.idToken) {\n setUserLoading(true);\n fetchUser()\n .then((user) => {\n setUserLoading(false);\n setUser((prevUser) => {\n // we only want to update the user if it's set - if a user is passed in, don't assume it is wrong here\n // it could be just the fetchUser returned null for some other reason.\n // TODO consider cleaning this up in general to avoid needing context here.\n return user ?? prevUser;\n });\n })\n .catch((error) => {\n setUserLoading(false);\n setUserError(error);\n });\n }\n }, [fetchUser, session?.idToken]);\n\n const isLoading = authLoading || userLoading;\n const error = authError ?? userError;\n\n // While we are passing a user as a prop _and_ storing it in state,\n // there is the case where the user is not set in the state yet\n // (setState is called but the rerender has not yet happened), but\n // is passed as a prop. In this case, we want to use the prop value.\n // A better solution is to avoid having multiple layers of context.\n // If the user is passed in, we just use that.\n // We should not split user state management across multiple contexts\n const userValue = user ?? inputUser;\n\n return (\n <UserContext.Provider\n value={{\n ...tokens,\n user: userValue,\n isLoading,\n error,\n signIn,\n signOut,\n isSigningOut,\n displayMode: displayMode || \"iframe\",\n }}\n >\n {children}\n </UserContext.Provider>\n );\n};\n\nexport type { UserContextType };\n\nexport { UserProvider, UserContext };\n"]}
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "@civic/auth:0.2.1-beta.1";
1
+ export declare const VERSION = "@civic/auth:0.2.2-beta.0";
2
2
  //# sourceMappingURL=version.d.ts.map