@strivacity/sdk-core 4.0.0-beta.0 → 4.0.0-beta.2

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 (97) hide show
  1. package/README.md +228 -86
  2. package/dist/assets/oidc.cjs +1 -1
  3. package/dist/assets/oidc.cjs.map +1 -1
  4. package/dist/assets/oidc.mjs +1 -1
  5. package/dist/assets/oidc.mjs.map +1 -1
  6. package/dist/assets/server.cjs +1 -1
  7. package/dist/assets/server.cjs.map +1 -1
  8. package/dist/assets/server.mjs +1 -1
  9. package/dist/assets/server.mjs.map +1 -1
  10. package/dist/flows/base.cjs +1 -1
  11. package/dist/flows/base.cjs.map +1 -1
  12. package/dist/flows/base.d.ts +4 -2
  13. package/dist/flows/base.mjs +1 -1
  14. package/dist/flows/base.mjs.map +1 -1
  15. package/dist/flows/popup.cjs +1 -1
  16. package/dist/flows/popup.cjs.map +1 -1
  17. package/dist/flows/popup.mjs +1 -1
  18. package/dist/flows/popup.mjs.map +1 -1
  19. package/dist/index.cjs +1 -1
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.ts +6 -2
  22. package/dist/index.mjs +1 -1
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/server/base.cjs +1 -1
  25. package/dist/server/base.cjs.map +1 -1
  26. package/dist/server/base.d.ts +2 -4
  27. package/dist/server/base.mjs +1 -1
  28. package/dist/server/base.mjs.map +1 -1
  29. package/dist/server/index.cjs +1 -1
  30. package/dist/server/index.mjs +1 -1
  31. package/dist/storages/cache.cjs.map +1 -1
  32. package/dist/storages/cache.d.ts +1 -1
  33. package/dist/storages/cache.mjs.map +1 -1
  34. package/dist/storages/index.cjs +1 -1
  35. package/dist/storages/index.mjs +1 -1
  36. package/dist/storages/server.cjs +1 -1
  37. package/dist/storages/server.d.ts +29 -1
  38. package/dist/storages/server.mjs +1 -1
  39. package/dist/storages/worker.cjs.map +1 -1
  40. package/dist/storages/worker.d.ts +1 -1
  41. package/dist/storages/worker.mjs.map +1 -1
  42. package/dist/types/native.d.ts +67 -2
  43. package/dist/types/oidc.cjs.map +1 -1
  44. package/dist/types/oidc.d.ts +47 -6
  45. package/dist/types/oidc.mjs.map +1 -1
  46. package/dist/types/popup.d.ts +1 -1
  47. package/dist/types/server.d.ts +21 -9
  48. package/dist/utils/index.cjs +1 -1
  49. package/dist/utils/index.d.ts +1 -0
  50. package/dist/utils/index.mjs +1 -1
  51. package/dist/utils/native-login.cjs +2 -0
  52. package/dist/utils/native-login.cjs.map +1 -0
  53. package/dist/utils/native-login.d.ts +13 -0
  54. package/dist/utils/native-login.mjs +2 -0
  55. package/dist/utils/native-login.mjs.map +1 -0
  56. package/dist/utils/oidc.d.ts +3 -4
  57. package/dist/utils/path.cjs +2 -0
  58. package/dist/utils/path.cjs.map +1 -0
  59. package/dist/utils/path.d.ts +16 -0
  60. package/dist/utils/path.mjs +2 -0
  61. package/dist/utils/path.mjs.map +1 -0
  62. package/dist/utils/server.d.ts +5 -4
  63. package/dist/utils/session.cjs +1 -1
  64. package/dist/utils/session.cjs.map +1 -1
  65. package/dist/utils/session.d.ts +10 -1
  66. package/dist/utils/session.mjs +1 -1
  67. package/dist/utils/session.mjs.map +1 -1
  68. package/package.json +1 -1
  69. package/testing/tests/flows/base.spec.ts +0 -1030
  70. package/testing/tests/flows/embedded.spec.ts +0 -443
  71. package/testing/tests/flows/index.spec.ts +0 -8
  72. package/testing/tests/flows/native.spec.ts +0 -487
  73. package/testing/tests/flows/popup.spec.ts +0 -400
  74. package/testing/tests/flows/redirect.spec.ts +0 -369
  75. package/testing/tests/handlers/embedded.spec.ts +0 -199
  76. package/testing/tests/handlers/index.spec.ts +0 -8
  77. package/testing/tests/handlers/native.spec.ts +0 -283
  78. package/testing/tests/handlers/popup.spec.ts +0 -206
  79. package/testing/tests/handlers/redirect.spec.ts +0 -70
  80. package/testing/tests/index.spec.ts +0 -78
  81. package/testing/tests/server/base.spec.ts +0 -846
  82. package/testing/tests/server/index.spec.ts +0 -15
  83. package/testing/tests/storages/cache.spec.ts +0 -107
  84. package/testing/tests/storages/index.spec.ts +0 -22
  85. package/testing/tests/storages/indexeddb.spec.ts +0 -113
  86. package/testing/tests/storages/local.spec.ts +0 -46
  87. package/testing/tests/storages/memory.spec.ts +0 -51
  88. package/testing/tests/storages/server.spec.ts +0 -435
  89. package/testing/tests/storages/session.spec.ts +0 -46
  90. package/testing/tests/storages/worker.spec.ts +0 -106
  91. package/testing/tests/utils/common.spec.ts +0 -77
  92. package/testing/tests/utils/credentials.spec.ts +0 -195
  93. package/testing/tests/utils/dom.spec.ts +0 -37
  94. package/testing/tests/utils/index.spec.ts +0 -71
  95. package/testing/tests/utils/logging.spec.ts +0 -82
  96. package/testing/tests/utils/oidc.spec.ts +0 -744
  97. package/testing/tests/utils/server.spec.ts +0 -235
@@ -1,2 +1,2 @@
1
- const e=require("../utils/errors.cjs"),t=require("./oidc.cjs"),n=require("../utils/crypto.cjs");var r=`strivacity-session-v1`,i=3900;function a(){return globalThis.sty??={},globalThis.sty.storage??=new Map,{async get(e){return Promise.resolve(globalThis.sty.storage?.get(e)??null)},async set(e,t){return globalThis.sty.storage?.set(e,t),Promise.resolve()},async delete(e){return globalThis.sty.storage?.delete(e),Promise.resolve()}}}function o(){return globalThis.sty??={},globalThis.sty.storage=new Map,{get:e=>Promise.resolve(globalThis.sty.storage.get(e)??null),set:(e,t)=>(globalThis.sty.storage.set(e,t),Promise.resolve()),delete:e=>(globalThis.sty.storage.delete(e),Promise.resolve()),deleteByLogoutToken:e=>{for(let[t,n]of globalThis.sty.storage){let r=JSON.parse(n)?.claims;(e.sid&&r?.sid===e.sid||e.sub&&r?.sub===e.sub)&&globalThis.sty.storage.delete(t)}return Promise.resolve()}}}function s(e,t,n){let r={httpOnly:!0,secure:!0,sameSite:`lax`,path:`/`,...n?.defaultCookieOptions};return e.getSessionId||=async(t,n)=>n?h((await e.toRequest(n)).headers.get(`cookie`))[t]:null,{async get(n,r){let i=await e.getSessionId(n,r);return i?await t.get(i):null},async set(i,a,o){let s=await e.getSessionId(i,o);s||(s=n?.uuidGenerator?.()??globalThis.crypto.randomUUID(),_(o,g(i,s,r))),await t.set(s,a)},async delete(n,i){let a=await e.getSessionId(n,i);a&&await t.delete(a),_(i,g(n,``,{...r,expires:new Date(0)}))},async deleteByLogoutToken(e){await t.deleteByLogoutToken?.(e)}}}function c(e,t,a){let o={httpOnly:!0,secure:!0,sameSite:`lax`,path:`/`,...a?.defaultCookieOptions};async function s(e,n){return e?h((await t.toRequest(e)).headers.get(`cookie`))[n]:void 0}let c={async get(t,i){let a=await s(i,t);if(a)return await n.decryptString(a,e,r);let o=[];for(let e=0;;e++){let n=await s(i,`${t}.${e}`);if(!n)break;o.push(n)}return o.length===0?null:await n.decryptString(o.join(``),e,r)},async set(t,a,s){await c.delete(t,s);let l=await n.encryptString(a,e,r);if(l.length<=3900)_(s,g(t,l,o));else for(let e=0;e*i<l.length;e++)_(s,g(`${t}.${e}`,l.slice(e*i,(e+1)*i),o))},async delete(e,t){let n={...o,expires:new Date(0)};_(t,g(e,``,n));for(let r=0;await s(t,`${e}.${r}`);r++)_(t,g(`${e}.${r}`,``,n))}};return c}var l=new Set([`transfer-encoding`,`connection`,`keep-alive`,`content-encoding`]),u=`sty.returnTo`,d=`http://schemas.openid.net/event/backchannel-logout`,f=2592e3,p=new WeakMap;function m(n,r){if(r.postLoginRedirectUri??=new URL(r.redirectUri).origin,r.postLogoutRedirectUri??=new URL(r.redirectUri).origin,r.cookieMaxAge??=f,!r.storage){if(!r.secret)throw new e.ConfigurationError(`Missing SDK option: secret`);r.storage=c(r.secret,n,{defaultCookieOptions:{maxAge:r.cookieMaxAge}})}return r.stateStorage??=a(),r.urlHandler??=async()=>Promise.resolve(void 0),r.authUrlPrefix??=`/auth`,r.loginUri??=`/login`,r.serverSessionUri===void 0&&(r.serverSessionUri??=`${r.authUrlPrefix}/login`),t.m(r)}function h(e){let t={};if(!e)return t;for(let n of e.split(`;`)){let e=n.indexOf(`=`);if(e===-1)continue;let r=n.slice(0,e).trim(),i=n.slice(e+1).trim();if(r)try{t[r]=decodeURIComponent(i)}catch{t[r]=i}}return t}function g(e,t,n={}){let r=[`${e}=${encodeURIComponent(t)}`];return typeof n.maxAge==`number`&&r.push(`Max-Age=${Math.floor(n.maxAge)}`),n.expires&&r.push(`Expires=${n.expires.toUTCString()}`),r.push(`Path=${n.path??`/`}`),n.domain&&r.push(`Domain=${n.domain}`),n.sameSite&&r.push(`SameSite=${n.sameSite.charAt(0).toUpperCase()}${n.sameSite.slice(1)}`),n.secure&&r.push(`Secure`),n.httpOnly&&r.push(`HttpOnly`),r.join(`; `)}function _(t,n){if(typeof t!=`object`||!t)throw new e.InternalError(`Server adapter events must be objects to track outgoing cookies`);let r=p.get(t)??[];r.push(n),p.set(t,r)}function v(t,n){if(typeof t!=`object`||!t)throw new e.InternalError(`Server adapter events must be objects to track outgoing cookies`);let r=p.get(t);if(r?.length){for(let e of r)n.headers.append(`set-cookie`,e);p.delete(t)}return n}function y(e){let t=new Headers;for(let[n,r]of e.headers.entries())n.toLowerCase()!==`set-cookie`&&(l.has(n.toLowerCase())||t.set(n,r));let n=e.headers.get(`set-cookie`)?.split(`,`).map(e=>e.trim());return n?.length&&t.set(`set-cookie`,n.join(`, `)),new Response(e.body,{status:e.status,statusText:e.statusText,headers:t})}function b(e,t){let n;if(!e)return null;try{n=new URL(e.startsWith(`/`)?e.slice(1):e,t&&!t.endsWith(`/`)?`${t}/`:t)}catch{return null}return n.origin===new URL(t).origin?n.toString():null}Object.defineProperty(exports,"_",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"f",{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,"g",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"h",{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,"m",{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,"p",{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return g}});
1
+ const e=require("../utils/errors.cjs"),t=require("./oidc.cjs"),n=require("../utils/crypto.cjs");var r=`strivacity-session-v1`,i=3900;function a(){return globalThis.sty??={},globalThis.sty.storage??=new Map,{async get(e){return Promise.resolve(globalThis.sty.storage?.get(e)??null)},async set(e,t){return globalThis.sty.storage?.set(e,t),Promise.resolve()},async delete(e){return globalThis.sty.storage?.delete(e),Promise.resolve()}}}function o(){return globalThis.sty??={},globalThis.sty.storage=new Map,{get:e=>Promise.resolve(globalThis.sty.storage.get(e)??null),set:(e,t)=>(globalThis.sty.storage.set(e,t),Promise.resolve()),delete:e=>(globalThis.sty.storage.delete(e),Promise.resolve()),deleteByLogoutToken:e=>{for(let[t,n]of globalThis.sty.storage){let r=JSON.parse(n)?.claims;(e.sid&&r?.sid===e.sid||e.sub&&r?.sub===e.sub)&&globalThis.sty.storage.delete(t)}return Promise.resolve()}}}function s(e,t,n){let r={httpOnly:!0,secure:!0,sameSite:`lax`,path:`/`,...n?.defaultCookieOptions};e.getSessionId||=async(t,n)=>n?v((await e.toRequest(n)).headers.get(`cookie`))[t]:null;let i={async get(n,r){let i=await e.getSessionId(n,r);return i?await t.get(i):null},async set(i,a,o){let s=await e.getSessionId(i,o);s||(s=n?.uuidGenerator?.()??globalThis.crypto.randomUUID(),b(o,y(i,s,r))),await t.set(s,a)},async delete(n,i){let a=await e.getSessionId(n,i);a&&await t.delete(a),b(i,y(n,``,{...r,maxAge:0}))}};return t.deleteByLogoutToken&&(i.deleteByLogoutToken=e=>t.deleteByLogoutToken(e)),i}function c(e,t,n){let r={httpOnly:!0,secure:!0,sameSite:`lax`,path:`/`,...n?.defaultCookieOptions},i={...r,maxAge:0};function a(e){return{get:async n=>e?v((await t.toRequest(e)).headers.get(`cookie`))[n]:void 0,set:(t,n,r)=>b(e,y(t,n,r)),delete:t=>b(e,y(t,``,i))}}return{get:(t,n)=>l(a(n),t,e),set:(t,n,i)=>u(a(i),t,n,e,r),delete:(e,t)=>d(a(t),e,r)}}async function l(e,t,i){let a=await e.get(t);if(a)return await n.decryptString(a,i,r);let o=[];for(let n=0;;n++){let r=await e.get(`${t}.${n}`);if(!r)break;o.push(r)}return o.length>0?await n.decryptString(o.join(``),i,r):null}async function u(e,t,a,o,s){await d(e,t,s);let c=await n.encryptString(a,o,r);if(c.length<=3900){await e.set(t,c,s);return}for(let n=0;n*i<c.length;n++)await e.set(`${t}.${n}`,c.slice(n*i,(n+1)*i),s)}async function d(e,t,n){await e.delete(t,n);for(let r=0;await e.get(`${t}.${r}`);r++)await e.delete(`${t}.${r}`,n)}var f=new Set([`transfer-encoding`,`connection`,`keep-alive`,`content-encoding`]),p=`sty.returnTo`,m=`http://schemas.openid.net/event/backchannel-logout`,h=2592e3,g=new WeakMap;function _(n,r){let i={...r};if(i.postLoginRedirectUri??=new URL(i.redirectUri).origin,i.postLogoutRedirectUri??=new URL(i.redirectUri).origin,i.cookieMaxAge??=h,!i.storage){if(!i.secret)throw new e.ConfigurationError(`Missing SDK option: secret`);i.storage=c(i.secret,n,{defaultCookieOptions:{maxAge:i.cookieMaxAge}})}return i.stateStorage??=a(),i.urlHandler??=async()=>Promise.resolve(void 0),i.authUrlPrefix??=`/auth`,i.loginUri??=`/login`,i.serverSessionUri===void 0&&(i.serverSessionUri??=`${i.authUrlPrefix}/login`),t.m(i)}function v(e){let t={};if(!e)return t;for(let n of e.split(`;`)){let e=n.indexOf(`=`);if(e===-1)continue;let r=n.slice(0,e).trim(),i=n.slice(e+1).trim();if(r)try{t[r]=decodeURIComponent(i)}catch{t[r]=i}}return t}function y(e,t,n={}){let r=[`${e}=${encodeURIComponent(t)}`];return typeof n.maxAge==`number`&&r.push(`Max-Age=${Math.floor(n.maxAge)}`),n.expires&&r.push(`Expires=${n.expires.toUTCString()}`),r.push(`Path=${n.path??`/`}`),n.domain&&r.push(`Domain=${n.domain}`),n.sameSite&&r.push(`SameSite=${n.sameSite.charAt(0).toUpperCase()}${n.sameSite.slice(1)}`),n.secure&&r.push(`Secure`),n.httpOnly&&r.push(`HttpOnly`),r.join(`; `)}function b(t,n){if(typeof t!=`object`||!t)throw new e.InternalError(`Server adapter events must be objects to track outgoing cookies`);let r=g.get(t)??[];r.push(n),g.set(t,r)}function x(t,n){if(typeof t!=`object`||!t)throw new e.InternalError(`Server adapter events must be objects to track outgoing cookies`);let r=g.get(t);if(r?.length){for(let e of r)n.headers.append(`set-cookie`,e);g.delete(t)}return n}function S(e){let t=new Headers;for(let[n,r]of e.headers.entries())n.toLowerCase()!==`set-cookie`&&(f.has(n.toLowerCase())||t.set(n,r));let n=e.headers.get(`set-cookie`)?.split(`,`).map(e=>e.trim());return n?.length&&t.set(`set-cookie`,n.join(`, `)),new Response(e.body,{status:e.status,statusText:e.statusText,headers:t})}function C(e,t){let n;if(!e)return null;try{n=new URL(e.startsWith(`/`)?e.slice(1):e,t&&!t.endsWith(`/`)?`${t}/`:t)}catch{return null}return n.origin===new URL(t).origin?n.toString():null}Object.defineProperty(exports,"_",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,"b",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,"f",{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,"g",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"h",{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"m",{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,"p",{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,"v",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"y",{enumerable:!0,get:function(){return l}});
2
2
  //# sourceMappingURL=server.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.cjs","names":[],"sources":["../../src/storages/server.ts","../../src/utils/server.ts"],"sourcesContent":["import type { SDKStorage } from '../types/common';\nimport type { EncryptedCookieStorageOptions, ServerAdapter, ServerCookieOptions, ServerStorage, SessionIdCookieStorageOptions } from '../types/server';\nimport { encryptString, decryptString } from '../utils/crypto';\nimport { parseCookieHeader, pushSetCookie, serializeCookie } from '../utils/server';\n\nexport const COOKIE_CONTEXT = 'strivacity-session-v1';\nexport const COOKIE_CHUNK_SIZE = 3900;\n\n/**\n * Creates a simple in-memory state storage implementation, shared across all server adapters.\n *\n * @returns {SDKStorage} An object implementing the SDKStorage interface.\n */\nexport function createServerStateStorage(): SDKStorage {\n\tglobalThis.sty ??= {} as typeof globalThis.sty;\n\tglobalThis.sty.storage ??= new Map<string, string>();\n\n\treturn {\n\t\tasync get(key) {\n\t\t\treturn Promise.resolve(globalThis.sty.storage?.get(key) ?? null);\n\t\t},\n\t\tasync set(key, value) {\n\t\t\tglobalThis.sty.storage?.set(key, value);\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t\tasync delete(key) {\n\t\t\tglobalThis.sty.storage?.delete(key);\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t};\n}\n\n/**\n * In-memory global storage adapter for session data.\n * Not recommended for production use, as session data will be lost on server restart.\n *\n * @returns {ServerStorage} An object implementing the ServerStorage interface.\n */\nexport function createServerMemoryStorage(): ServerStorage {\n\tglobalThis.sty ??= {} as typeof globalThis.sty;\n\tglobalThis.sty.storage = new Map<string, string>();\n\n\treturn {\n\t\tget: (key) => {\n\t\t\treturn Promise.resolve(globalThis.sty.storage!.get(key) ?? null);\n\t\t},\n\t\tset: (key, value) => {\n\t\t\tglobalThis.sty.storage!.set(key, value);\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t\tdelete: (key) => {\n\t\t\tglobalThis.sty.storage!.delete(key);\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t\tdeleteByLogoutToken: (logoutToken) => {\n\t\t\tfor (const [mapKey, raw] of globalThis.sty.storage!) {\n\t\t\t\tconst claims = JSON.parse(raw)?.claims;\n\n\t\t\t\tif ((logoutToken.sid && claims?.sid === logoutToken.sid) || (logoutToken.sub && claims?.sub === logoutToken.sub)) {\n\t\t\t\t\tglobalThis.sty.storage!.delete(mapKey);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t};\n}\n\n/**\n * Creates a session storage that puts a session-id value cookie on the client and keeping the actual session data in the given `storage`.\n *\n * @param {ServerAdapter<TEvent>} adapter - The framework adapter used to read the incoming request.\n * @param {ServerStorage<TEvent>} storage - The storage used to persist session data, keyed by a randomly generated session id.\n * @param {SessionIdCookieStorageOptions} [options] - Options for the session ID cookie, including default cookie attributes and a UUID generator function.\n * @param {Partial<ServerCookieOptions>} [options.defaultCookieOptions] - Default cookie attributes for the session ID cookie.\n * @param {() => string} [options.uuidGenerator] - Function to generate a new UUID for the session ID. Defaults to `() => crypto.randomUUID()`.\n * @returns {ServerStorage<TEvent>} An object implementing the `ServerStorage` interface for managing sessions indexed by a session-id cookie.\n */\nexport function createSessionIdCookieStorage<TEvent = unknown>(\n\tadapter: ServerAdapter<TEvent>,\n\tstorage: ServerStorage,\n\toptions?: SessionIdCookieStorageOptions,\n): ServerStorage<TEvent> {\n\tconst defaultCookieOptions: ServerCookieOptions = {\n\t\thttpOnly: true,\n\t\tsecure: true,\n\t\tsameSite: 'lax',\n\t\tpath: '/',\n\t\t...options?.defaultCookieOptions,\n\t};\n\n\tif (!adapter.getSessionId) {\n\t\tadapter.getSessionId = async (key: string, event?: TEvent) => {\n\t\t\tif (!event) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst request = await adapter.toRequest(event);\n\t\t\tconst cookies = parseCookieHeader(request.headers.get('cookie'));\n\n\t\t\treturn cookies[key];\n\t\t};\n\t}\n\n\treturn {\n\t\tasync get(key, event) {\n\t\t\tconst id = await adapter.getSessionId!(key, event);\n\n\t\t\treturn id ? await storage.get(id) : null;\n\t\t},\n\t\tasync set(key, value, event) {\n\t\t\tlet id = await adapter.getSessionId!(key, event);\n\n\t\t\tif (!id) {\n\t\t\t\tid = options?.uuidGenerator?.() ?? globalThis.crypto.randomUUID();\n\t\t\t\tpushSetCookie(event, serializeCookie(key, id, defaultCookieOptions));\n\t\t\t}\n\n\t\t\tawait storage.set(id, value);\n\t\t},\n\t\tasync delete(key, event) {\n\t\t\tconst id = await adapter.getSessionId!(key, event);\n\n\t\t\tif (id) {\n\t\t\t\tawait storage.delete(id);\n\t\t\t}\n\n\t\t\tpushSetCookie(event, serializeCookie(key, '', { ...defaultCookieOptions, expires: new Date(0) }));\n\t\t},\n\t\tasync deleteByLogoutToken(token) {\n\t\t\tawait storage.deleteByLogoutToken?.(token);\n\t\t},\n\t};\n}\n\n/**\n * Creates an encrypted session storage backed by cookies.\n * Built entirely on top of `adapter.toRequest`'s `Request` (reading the `cookie` header) and the outgoing cookie jar (writing `set-cookie` headers).\n *\n * @param {string} secret - The secret key used for encryption and decryption.\n * @param {ServerAdapter<TEvent>} adapter - The framework adapter used to read the incoming request.\n * @param {EncryptedCookieStorageOptions} [options] - Cookie attributes (maxAge, sameSite, etc.). `path` defaults to `'/'`.\n * @param {Partial<ServerCookieOptions>} [options.defaultCookieOptions] - Default cookie attributes for the session ID cookie.\n * @returns {ServerStorage<TEvent>} An object implementing the `ServerStorage` interface for managing encrypted session cookies.\n */\nexport function createEncryptedCookieStorage<TEvent = unknown>(\n\tsecret: string,\n\tadapter: ServerAdapter<TEvent>,\n\toptions?: EncryptedCookieStorageOptions,\n): ServerStorage<TEvent> {\n\tconst defaultCookieOptions: ServerCookieOptions = {\n\t\thttpOnly: true,\n\t\tsecure: true,\n\t\tsameSite: 'lax',\n\t\tpath: '/',\n\t\t...options?.defaultCookieOptions,\n\t};\n\n\tasync function getIncomingCookie(event: TEvent | undefined, name: string): Promise<string | undefined> {\n\t\tif (!event) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst cookies = parseCookieHeader(request.headers.get('cookie'));\n\n\t\treturn cookies[name];\n\t}\n\n\tconst storage: ServerStorage<TEvent> = {\n\t\tasync get(key, event) {\n\t\t\tconst cookie = await getIncomingCookie(event, key);\n\n\t\t\tif (cookie) {\n\t\t\t\t// NOTE: If the cookie is present, we can decrypt it directly without checking for chunks.\n\t\t\t\treturn await decryptString(cookie, secret, COOKIE_CONTEXT);\n\t\t\t}\n\n\t\t\t// NOTE: If the cookie is not present, we check for chunked cookies (e.g., `key.0`, `key.1`, etc.) and concatenate them before decryption.\n\t\t\tconst cookieChunks: Array<string> = [];\n\n\t\t\tfor (let i = 0; ; i++) {\n\t\t\t\tconst chunk = await getIncomingCookie(event, `${key}.${i}`);\n\n\t\t\t\tif (!chunk) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcookieChunks.push(chunk);\n\t\t\t}\n\n\t\t\tif (cookieChunks.length === 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn await decryptString(cookieChunks.join(''), secret, COOKIE_CONTEXT);\n\t\t},\n\n\t\tasync set(key, value, event) {\n\t\t\t// NOTE: Delete existing cookie(s) first to avoid leaving old chunks behind\n\t\t\tawait storage.delete(key, event);\n\n\t\t\tconst encrypted = await encryptString(value, secret, COOKIE_CONTEXT);\n\n\t\t\tif (encrypted.length <= COOKIE_CHUNK_SIZE) {\n\t\t\t\tpushSetCookie(event, serializeCookie(key, encrypted, defaultCookieOptions));\n\t\t\t} else {\n\t\t\t\tfor (let i = 0; i * COOKIE_CHUNK_SIZE < encrypted.length; i++) {\n\t\t\t\t\tpushSetCookie(event, serializeCookie(`${key}.${i}`, encrypted.slice(i * COOKIE_CHUNK_SIZE, (i + 1) * COOKIE_CHUNK_SIZE), defaultCookieOptions));\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tasync delete(key, event) {\n\t\t\tconst expiredOptions = { ...defaultCookieOptions, expires: new Date(0) };\n\n\t\t\tpushSetCookie(event, serializeCookie(key, '', expiredOptions));\n\n\t\t\tfor (let i = 0; await getIncomingCookie(event, `${key}.${i}`); i++) {\n\t\t\t\tpushSetCookie(event, serializeCookie(`${key}.${i}`, '', expiredOptions));\n\t\t\t}\n\t\t},\n\t};\n\n\treturn storage;\n}\n","import type { HttpClientResponse, SDKStorage, ServerCookieOptions, ServerAdapter, ServerSDKOptions, ServerStorage } from '../types';\nimport { getSDKOptions } from './oidc';\nimport { createServerStateStorage, createEncryptedCookieStorage } from '../storages/server';\nimport { ConfigurationError, InternalError } from './errors';\n\n/**\n * Disallowed headers that should not be proxied from the SDK to the client, as they may interfere with the response handling.\n */\nexport const DISALLOWED_PROXY_HEADERS = new Set(['transfer-encoding', 'connection', 'keep-alive', 'content-encoding']);\n\n/**\n * Returns with the returnTo cookie name used for storing the returnTo URL in the server SDK.\n */\nexport const RETURN_TO_COOKIE = 'sty.returnTo';\n\n/**\n * Backchannel logout event name used for identifying backchannel logout requests in the server SDK.\n */\nexport const BACKCHANNEL_LOGOUT_EVENT = 'http://schemas.openid.net/event/backchannel-logout';\n\n/**\n * Default cookie max age in seconds (30 days).\n */\nexport const DEFAULT_COOKIE_MAX_AGE = 30 * 24 * 60 * 60;\n\n/**\n * A WeakMap to store cookies for each request event, allowing for proper cookie management in server-side environments.\n */\nconst cookieJars = new WeakMap<object, Array<string>>();\n\n/**\n * Returns with the server SDK options merged with the provided options.\n *\n * @param {SDKInitConfig} options - The SDK initialization configuration.\n * @template InitOptions - The type of the SDK initialization configuration.\n * @template Options - The type of the SDK options.\n * @returns {Options} The merged SDK options.\n */\nexport function getServerSDKOptions<\n\tTEvent = unknown,\n\tStorage extends ServerStorage<TEvent> = ServerStorage<TEvent>,\n\tStateStorage extends SDKStorage = SDKStorage,\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n>(adapter: ServerAdapter<TEvent>, options: any): ServerSDKOptions<TEvent, Storage, StateStorage> {\n\toptions.postLoginRedirectUri ??= new URL(options.redirectUri).origin;\n\toptions.postLogoutRedirectUri ??= new URL(options.redirectUri).origin;\n\toptions.cookieMaxAge ??= DEFAULT_COOKIE_MAX_AGE;\n\n\tif (!options.storage) {\n\t\tif (!options.secret) {\n\t\t\tthrow new ConfigurationError('Missing SDK option: secret');\n\t\t}\n\n\t\toptions.storage = createEncryptedCookieStorage<TEvent>(options.secret, adapter, { defaultCookieOptions: { maxAge: options.cookieMaxAge } });\n\t}\n\n\toptions.stateStorage ??= createServerStateStorage();\n\toptions.urlHandler ??= async () => Promise.resolve(undefined);\n\toptions.authUrlPrefix ??= '/auth';\n\toptions.loginUri ??= '/login';\n\n\tif (typeof options.serverSessionUri === 'undefined') {\n\t\toptions.serverSessionUri ??= `${options.authUrlPrefix}/login`;\n\t}\n\n\treturn getSDKOptions(options);\n}\n\n/**\n * Parses a `Cookie` request header into a plain name/value map.\n *\n * @param {string | null | undefined} header - The raw `Cookie` header value.\n * @returns {Record<string, string>} The parsed cookies.\n */\nexport function parseCookieHeader(header: string | null | undefined): Record<string, string> {\n\tconst cookies: Record<string, string> = {};\n\n\tif (!header) {\n\t\treturn cookies;\n\t}\n\n\tfor (const part of header.split(';')) {\n\t\tconst index = part.indexOf('=');\n\n\t\tif (index === -1) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst name = part.slice(0, index).trim();\n\t\tconst value = part.slice(index + 1).trim();\n\n\t\tif (name) {\n\t\t\ttry {\n\t\t\t\tcookies[name] = decodeURIComponent(value);\n\t\t\t} catch {\n\t\t\t\tcookies[name] = value;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn cookies;\n}\n\n/**\n * Serializes a name/value pair into a `Set-Cookie` header value.\n *\n * @param {string} name - The cookie name.\n * @param {string} value - The cookie value.\n * @param {ServerCookieOptions} [options] - The cookie attributes.\n * @returns {string} The serialized `Set-Cookie` header value.\n */\nexport function serializeCookie(name: string, value: string, options: ServerCookieOptions = {}): string {\n\tconst segments = [`${name}=${encodeURIComponent(value)}`];\n\n\tif (typeof options.maxAge === 'number') {\n\t\tsegments.push(`Max-Age=${Math.floor(options.maxAge)}`);\n\t}\n\tif (options.expires) {\n\t\tsegments.push(`Expires=${options.expires.toUTCString()}`);\n\t}\n\n\tsegments.push(`Path=${options.path ?? '/'}`);\n\n\tif (options.domain) {\n\t\tsegments.push(`Domain=${options.domain}`);\n\t}\n\tif (options.sameSite) {\n\t\tsegments.push(`SameSite=${options.sameSite.charAt(0).toUpperCase()}${options.sameSite.slice(1)}`);\n\t}\n\tif (options.secure) {\n\t\tsegments.push('Secure');\n\t}\n\tif (options.httpOnly) {\n\t\tsegments.push('HttpOnly');\n\t}\n\n\treturn segments.join('; ');\n}\n\n/**\n * Pushes a `Set-Cookie` header value into the cookie jar for the given event.\n *\n * @param {unknown} event - The framework-native request event.\n * @param {string} header - The `Set-Cookie` header value to push.\n */\nexport function pushSetCookie(event: unknown, header: string): void {\n\tif (event === null || typeof event !== 'object') {\n\t\tthrow new InternalError('Server adapter events must be objects to track outgoing cookies');\n\t}\n\n\tconst jar = cookieJars.get(event) ?? [];\n\tjar.push(header);\n\tcookieJars.set(event, jar);\n}\n\n/**\n * Flushes the accumulated `Set-Cookie` headers from the cookie jar into the provided `Response`.\n *\n * @param {unknown} event - The framework-native request event.\n * @param {Response} response - The `Response` object to append the `Set-Cookie` headers to.\n * @returns {Response} The modified `Response` with the appended `Set-Cookie` headers.\n */\nexport function flushSetCookies(event: unknown, response: Response): Response {\n\tif (event === null || typeof event !== 'object') {\n\t\tthrow new InternalError('Server adapter events must be objects to track outgoing cookies');\n\t}\n\n\tconst jar = cookieJars.get(event);\n\n\tif (jar?.length) {\n\t\tfor (const header of jar) {\n\t\t\tresponse.headers.append('set-cookie', header);\n\t\t}\n\n\t\tcookieJars.delete(event);\n\t}\n\n\treturn response;\n}\n\n/**\n * Proxies an `HttpClientResponse` to a Web `Response`, preserving headers and status code.\n *\n * @param {HttpClientResponse<T>} response - The `HttpClientResponse` to proxy.\n * @returns {Response} A `Response` object representing the proxied response.\n */\nexport function proxyResponse<T = unknown>(response: HttpClientResponse<T>): Response {\n\tconst proxyHeaders = new Headers();\n\n\tfor (const [key, value] of response.headers.entries()) {\n\t\tif (key.toLowerCase() === 'set-cookie') {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!DISALLOWED_PROXY_HEADERS.has(key.toLowerCase())) {\n\t\t\tproxyHeaders.set(key, value);\n\t\t}\n\t}\n\n\tconst proxyCookies = response.headers\n\t\t.get('set-cookie')\n\t\t?.split(',')\n\t\t.map((cookie) => cookie.trim());\n\n\tif (proxyCookies?.length) {\n\t\tproxyHeaders.set('set-cookie', proxyCookies.join(', '));\n\t}\n\n\treturn new Response(response.body, {\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\theaders: proxyHeaders,\n\t});\n}\n\n/**\n * Returns a safe absolute redirect URL only if it shares the same origin as `safeBaseUrl`, preventing open redirects.\n *\n * @param {string | undefined | null} dangerousRedirect - The untrusted redirect path or URL.\n * @param {string} safeBaseUrl - The trusted base URL whose origin is used as the allowed origin.\n * @returns {string | null} The resolved URL string if safe, or `null`.\n */\nexport function toSafeRedirect(dangerousRedirect: string | undefined | null, safeBaseUrl: string): string | null {\n\tlet url: URL;\n\n\tif (!dangerousRedirect) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\turl = new URL(\n\t\t\tdangerousRedirect.startsWith('/') ? dangerousRedirect.slice(1) : dangerousRedirect,\n\t\t\tsafeBaseUrl && !safeBaseUrl.endsWith('/') ? `${safeBaseUrl}/` : safeBaseUrl,\n\t\t);\n\t} catch {\n\t\treturn null;\n\t}\n\n\tif (url.origin === new URL(safeBaseUrl).origin) {\n\t\treturn url.toString();\n\t}\n\n\treturn null;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"server.cjs","names":[],"sources":["../../src/storages/server.ts","../../src/utils/server.ts"],"sourcesContent":["import type { SDKStorage } from '../types/common';\nimport type {\n\tCookieJar,\n\tEncryptedCookieStorageOptions,\n\tServerAdapter,\n\tServerCookieOptions,\n\tServerStorage,\n\tSessionIdCookieStorageOptions,\n} from '../types/server';\nimport { encryptString, decryptString } from '../utils/crypto';\nimport { parseCookieHeader, pushSetCookie, serializeCookie } from '../utils/server';\n\nexport const COOKIE_CONTEXT = 'strivacity-session-v1';\nexport const COOKIE_CHUNK_SIZE = 3900;\n\n/**\n * Creates a simple in-memory state storage implementation, shared across all server adapters.\n *\n * @returns {SDKStorage} An object implementing the SDKStorage interface.\n */\nexport function createServerStateStorage(): SDKStorage {\n\tglobalThis.sty ??= {} as typeof globalThis.sty;\n\tglobalThis.sty.storage ??= new Map<string, string>();\n\n\treturn {\n\t\tasync get(key) {\n\t\t\treturn Promise.resolve(globalThis.sty.storage?.get(key) ?? null);\n\t\t},\n\t\tasync set(key, value) {\n\t\t\tglobalThis.sty.storage?.set(key, value);\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t\tasync delete(key) {\n\t\t\tglobalThis.sty.storage?.delete(key);\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t};\n}\n\n/**\n * In-memory global storage adapter for session data.\n * Not recommended for production use, as session data will be lost on server restart.\n *\n * @returns {ServerStorage} An object implementing the ServerStorage interface.\n */\nexport function createServerMemoryStorage(): ServerStorage {\n\tglobalThis.sty ??= {} as typeof globalThis.sty;\n\tglobalThis.sty.storage = new Map<string, string>();\n\n\treturn {\n\t\tget: (key) => {\n\t\t\treturn Promise.resolve(globalThis.sty.storage!.get(key) ?? null);\n\t\t},\n\t\tset: (key, value) => {\n\t\t\tglobalThis.sty.storage!.set(key, value);\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t\tdelete: (key) => {\n\t\t\tglobalThis.sty.storage!.delete(key);\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t\tdeleteByLogoutToken: (logoutToken) => {\n\t\t\tfor (const [mapKey, raw] of globalThis.sty.storage!) {\n\t\t\t\tconst claims = JSON.parse(raw)?.claims;\n\n\t\t\t\tif ((logoutToken.sid && claims?.sid === logoutToken.sid) || (logoutToken.sub && claims?.sub === logoutToken.sub)) {\n\t\t\t\t\tglobalThis.sty.storage!.delete(mapKey);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t};\n}\n\n/**\n * Creates a session storage that puts a session-id value cookie on the client and keeping the actual session data in the given `storage`.\n *\n * @param {ServerAdapter<TEvent>} adapter - The framework adapter used to read the incoming request.\n * @param {ServerStorage<TEvent>} storage - The storage used to persist session data, keyed by a randomly generated session id.\n * @param {SessionIdCookieStorageOptions} [options] - Options for the session ID cookie, including default cookie attributes and a UUID generator function.\n * @param {Partial<ServerCookieOptions>} [options.defaultCookieOptions] - Default cookie attributes for the session ID cookie.\n * @param {() => string} [options.uuidGenerator] - Function to generate a new UUID for the session ID. Defaults to `() => crypto.randomUUID()`.\n * @returns {ServerStorage<TEvent>} An object implementing the `ServerStorage` interface for managing sessions indexed by a session-id cookie.\n */\nexport function createSessionIdCookieStorage<TEvent = unknown>(\n\tadapter: ServerAdapter<TEvent>,\n\tstorage: ServerStorage,\n\toptions?: SessionIdCookieStorageOptions,\n): ServerStorage<TEvent> {\n\tconst defaultCookieOptions: ServerCookieOptions = {\n\t\thttpOnly: true,\n\t\tsecure: true,\n\t\tsameSite: 'lax',\n\t\tpath: '/',\n\t\t...options?.defaultCookieOptions,\n\t};\n\n\tif (!adapter.getSessionId) {\n\t\tadapter.getSessionId = async (key: string, event?: TEvent) => {\n\t\t\tif (!event) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst request = await adapter.toRequest(event);\n\t\t\tconst cookies = parseCookieHeader(request.headers.get('cookie'));\n\n\t\t\treturn cookies[key];\n\t\t};\n\t}\n\n\tconst sessionIdStorage: ServerStorage<TEvent> = {\n\t\tasync get(key, event) {\n\t\t\tconst id = await adapter.getSessionId!(key, event);\n\n\t\t\treturn id ? await storage.get(id) : null;\n\t\t},\n\t\tasync set(key, value, event) {\n\t\t\tlet id = await adapter.getSessionId!(key, event);\n\n\t\t\tif (!id) {\n\t\t\t\tid = options?.uuidGenerator?.() ?? globalThis.crypto.randomUUID();\n\t\t\t\tpushSetCookie(event, serializeCookie(key, id, defaultCookieOptions));\n\t\t\t}\n\n\t\t\tawait storage.set(id, value);\n\t\t},\n\t\tasync delete(key, event) {\n\t\t\tconst id = await adapter.getSessionId!(key, event);\n\n\t\t\tif (id) {\n\t\t\t\tawait storage.delete(id);\n\t\t\t}\n\n\t\t\tpushSetCookie(event, serializeCookie(key, '', { ...defaultCookieOptions, maxAge: 0 }));\n\t\t},\n\t};\n\n\t// NOTE: only when the inner storage can do it, so the back-channel logout route answers 501 instead of a silent 200\n\tif (storage.deleteByLogoutToken) {\n\t\tsessionIdStorage.deleteByLogoutToken = (token) => storage.deleteByLogoutToken!(token);\n\t}\n\n\treturn sessionIdStorage;\n}\n\n/**\n * Creates an encrypted session storage backed by cookies.\n * Built entirely on top of `adapter.toRequest`'s `Request` (reading the `cookie` header) and the outgoing cookie jar (writing `set-cookie` headers).\n *\n * @param {string} secret - The secret key used for encryption and decryption.\n * @param {ServerAdapter<TEvent>} adapter - The framework adapter used to read the incoming request.\n * @param {EncryptedCookieStorageOptions} [options] - Cookie attributes (maxAge, sameSite, etc.). `path` defaults to `'/'`.\n * @param {Partial<ServerCookieOptions>} [options.defaultCookieOptions] - Default cookie attributes for the session ID cookie.\n * @returns {ServerStorage<TEvent>} An object implementing the `ServerStorage` interface for managing encrypted session cookies.\n */\nexport function createEncryptedCookieStorage<TEvent = unknown>(\n\tsecret: string,\n\tadapter: ServerAdapter<TEvent>,\n\toptions?: EncryptedCookieStorageOptions,\n): ServerStorage<TEvent> {\n\tconst defaultCookieOptions: ServerCookieOptions = {\n\t\thttpOnly: true,\n\t\tsecure: true,\n\t\tsameSite: 'lax',\n\t\tpath: '/',\n\t\t...options?.defaultCookieOptions,\n\t};\n\n\tconst expiredCookieOptions = { ...defaultCookieOptions, maxAge: 0 };\n\n\tfunction createJar(event: TEvent | undefined): CookieJar {\n\t\treturn {\n\t\t\tget: async (name) => {\n\t\t\t\tif (!event) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tconst request = await adapter.toRequest(event);\n\n\t\t\t\treturn parseCookieHeader(request.headers.get('cookie'))[name];\n\t\t\t},\n\t\t\tset: (name, value, cookieOptions) => pushSetCookie(event, serializeCookie(name, value, cookieOptions)),\n\t\t\tdelete: (name) => pushSetCookie(event, serializeCookie(name, '', expiredCookieOptions)),\n\t\t};\n\t}\n\n\treturn {\n\t\tget: (key, event) => readEncryptedCookie(createJar(event), key, secret),\n\t\tset: (key, value, event) => writeEncryptedCookie(createJar(event), key, value, secret, defaultCookieOptions),\n\t\tdelete: (key, event) => deleteEncryptedCookie(createJar(event), key, defaultCookieOptions),\n\t};\n}\n\n/**\n * Reads and decrypts a session written by `writeEncryptedCookie`: a single `key` cookie, or chunks `key.0`, `key.1`, ... joined in order.\n *\n * @param {CookieJar} jar - Access to the request's cookies.\n * @param {string} key - The cookie name.\n * @param {string} secret - The encryption secret.\n * @returns {Promise<string | null>} The decrypted value, or `null` when there is no cookie.\n */\nexport async function readEncryptedCookie<TOptions>(jar: CookieJar<TOptions>, key: string, secret: string): Promise<string | null> {\n\tconst cookie = await jar.get(key);\n\n\tif (cookie) {\n\t\treturn await decryptString(cookie, secret, COOKIE_CONTEXT);\n\t}\n\n\tconst chunks: Array<string> = [];\n\n\tfor (let i = 0; ; i++) {\n\t\tconst chunk = await jar.get(`${key}.${i}`);\n\n\t\tif (!chunk) {\n\t\t\tbreak;\n\t\t}\n\n\t\tchunks.push(chunk);\n\t}\n\n\treturn chunks.length > 0 ? await decryptString(chunks.join(''), secret, COOKIE_CONTEXT) : null;\n}\n\n/**\n * Encrypts a value and writes it as a single `key` cookie, or as `COOKIE_CHUNK_SIZE` chunks (`key.0`, `key.1`, ...) when it is too\n * large for one cookie. The previous cookie and all of its chunks from the request are deleted first, so no stale chunk is left behind.\n *\n * @param {CookieJar} jar - Access to the request's and the response's cookies.\n * @param {string} key - The cookie name.\n * @param {string} value - The plain value.\n * @param {string} secret - The encryption secret.\n * @param {TOptions} options - Cookie attributes for the written cookies (and for deleting the old ones).\n */\nexport async function writeEncryptedCookie<TOptions>(jar: CookieJar<TOptions>, key: string, value: string, secret: string, options: TOptions): Promise<void> {\n\tawait deleteEncryptedCookie(jar, key, options);\n\n\tconst encrypted = await encryptString(value, secret, COOKIE_CONTEXT);\n\n\tif (encrypted.length <= COOKIE_CHUNK_SIZE) {\n\t\tawait jar.set(key, encrypted, options);\n\t\treturn;\n\t}\n\n\tfor (let i = 0; i * COOKIE_CHUNK_SIZE < encrypted.length; i++) {\n\t\tawait jar.set(`${key}.${i}`, encrypted.slice(i * COOKIE_CHUNK_SIZE, (i + 1) * COOKIE_CHUNK_SIZE), options);\n\t}\n}\n\n/**\n * Deletes a session written by `writeEncryptedCookie`: the `key` cookie and every `key.N` chunk present in the request.\n *\n * @param {CookieJar} jar - Access to the request's and the response's cookies.\n * @param {string} key - The cookie name.\n * @param {TOptions} options - Cookie attributes (`path`, `domain`) of the cookies to delete.\n */\nexport async function deleteEncryptedCookie<TOptions>(jar: CookieJar<TOptions>, key: string, options: TOptions): Promise<void> {\n\tawait jar.delete(key, options);\n\n\tfor (let i = 0; await jar.get(`${key}.${i}`); i++) {\n\t\tawait jar.delete(`${key}.${i}`, options);\n\t}\n}\n","import type { HttpClientResponse, SDKStorage, ServerCookieOptions, ServerAdapter, ServerSDKOptions, ServerStorage } from '../types';\nimport { getSDKOptions } from './oidc';\nimport { createServerStateStorage, createEncryptedCookieStorage } from '../storages/server';\nimport { ConfigurationError, InternalError } from './errors';\n\n/**\n * Disallowed headers that should not be proxied from the SDK to the client, as they may interfere with the response handling.\n */\nexport const DISALLOWED_PROXY_HEADERS = new Set(['transfer-encoding', 'connection', 'keep-alive', 'content-encoding']);\n\n/**\n * Returns with the returnTo cookie name used for storing the returnTo URL in the server SDK.\n */\nexport const RETURN_TO_COOKIE = 'sty.returnTo';\n\n/**\n * Backchannel logout event name used for identifying backchannel logout requests in the server SDK.\n */\nexport const BACKCHANNEL_LOGOUT_EVENT = 'http://schemas.openid.net/event/backchannel-logout';\n\n/**\n * Default cookie max age in seconds (30 days).\n */\nexport const DEFAULT_COOKIE_MAX_AGE = 30 * 24 * 60 * 60;\n\n/**\n * A WeakMap to store cookies for each request event, allowing for proper cookie management in server-side environments.\n */\nconst cookieJars = new WeakMap<object, Array<string>>();\n\n/**\n * Returns with the server SDK options merged with the provided options.\n *\n * @param {SDKInitConfig} initOptions - The SDK initialization configuration.\n * @template TEvent - The type of the server request event.\n * @template Storage - The type of the server storage.\n * @template StateStorage - The type of the state storage.\n * @returns {Options} The merged SDK options.\n */\nexport function getServerSDKOptions<\n\tTEvent = unknown,\n\tStorage extends ServerStorage<TEvent> = ServerStorage<TEvent>,\n\tStateStorage extends SDKStorage = SDKStorage,\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n>(adapter: ServerAdapter<TEvent>, initOptions: any): ServerSDKOptions<TEvent, Storage, StateStorage> {\n\tconst options = { ...initOptions };\n\n\toptions.postLoginRedirectUri ??= new URL(options.redirectUri).origin;\n\toptions.postLogoutRedirectUri ??= new URL(options.redirectUri).origin;\n\toptions.cookieMaxAge ??= DEFAULT_COOKIE_MAX_AGE;\n\n\tif (!options.storage) {\n\t\tif (!options.secret) {\n\t\t\tthrow new ConfigurationError('Missing SDK option: secret');\n\t\t}\n\n\t\toptions.storage = createEncryptedCookieStorage<TEvent>(options.secret, adapter, { defaultCookieOptions: { maxAge: options.cookieMaxAge } });\n\t}\n\n\toptions.stateStorage ??= createServerStateStorage();\n\toptions.urlHandler ??= async () => Promise.resolve(undefined);\n\toptions.authUrlPrefix ??= '/auth';\n\toptions.loginUri ??= '/login';\n\n\tif (typeof options.serverSessionUri === 'undefined') {\n\t\toptions.serverSessionUri ??= `${options.authUrlPrefix}/login`;\n\t}\n\n\treturn getSDKOptions(options);\n}\n\n/**\n * Parses a `Cookie` request header into a plain name/value map.\n *\n * @param {string | null | undefined} header - The raw `Cookie` header value.\n * @returns {Record<string, string>} The parsed cookies.\n */\nexport function parseCookieHeader(header: string | null | undefined): Record<string, string> {\n\tconst cookies: Record<string, string> = {};\n\n\tif (!header) {\n\t\treturn cookies;\n\t}\n\n\tfor (const part of header.split(';')) {\n\t\tconst index = part.indexOf('=');\n\n\t\tif (index === -1) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst name = part.slice(0, index).trim();\n\t\tconst value = part.slice(index + 1).trim();\n\n\t\tif (name) {\n\t\t\ttry {\n\t\t\t\tcookies[name] = decodeURIComponent(value);\n\t\t\t} catch {\n\t\t\t\tcookies[name] = value;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn cookies;\n}\n\n/**\n * Serializes a name/value pair into a `Set-Cookie` header value.\n *\n * @param {string} name - The cookie name.\n * @param {string} value - The cookie value.\n * @param {ServerCookieOptions} [options] - The cookie attributes.\n * @returns {string} The serialized `Set-Cookie` header value.\n */\nexport function serializeCookie(name: string, value: string, options: ServerCookieOptions = {}): string {\n\tconst segments = [`${name}=${encodeURIComponent(value)}`];\n\n\tif (typeof options.maxAge === 'number') {\n\t\tsegments.push(`Max-Age=${Math.floor(options.maxAge)}`);\n\t}\n\tif (options.expires) {\n\t\tsegments.push(`Expires=${options.expires.toUTCString()}`);\n\t}\n\n\tsegments.push(`Path=${options.path ?? '/'}`);\n\n\tif (options.domain) {\n\t\tsegments.push(`Domain=${options.domain}`);\n\t}\n\tif (options.sameSite) {\n\t\tsegments.push(`SameSite=${options.sameSite.charAt(0).toUpperCase()}${options.sameSite.slice(1)}`);\n\t}\n\tif (options.secure) {\n\t\tsegments.push('Secure');\n\t}\n\tif (options.httpOnly) {\n\t\tsegments.push('HttpOnly');\n\t}\n\n\treturn segments.join('; ');\n}\n\n/**\n * Pushes a `Set-Cookie` header value into the cookie jar for the given event.\n *\n * @param {unknown} event - The framework-native request event.\n * @param {string} header - The `Set-Cookie` header value to push.\n */\nexport function pushSetCookie(event: unknown, header: string): void {\n\tif (event === null || typeof event !== 'object') {\n\t\tthrow new InternalError('Server adapter events must be objects to track outgoing cookies');\n\t}\n\n\tconst jar = cookieJars.get(event) ?? [];\n\tjar.push(header);\n\tcookieJars.set(event, jar);\n}\n\n/**\n * Flushes the accumulated `Set-Cookie` headers from the cookie jar into the provided `Response`.\n *\n * @param {unknown} event - The framework-native request event.\n * @param {Response} response - The `Response` object to append the `Set-Cookie` headers to.\n * @returns {Response} The modified `Response` with the appended `Set-Cookie` headers.\n */\nexport function flushSetCookies(event: unknown, response: Response): Response {\n\tif (event === null || typeof event !== 'object') {\n\t\tthrow new InternalError('Server adapter events must be objects to track outgoing cookies');\n\t}\n\n\tconst jar = cookieJars.get(event);\n\n\tif (jar?.length) {\n\t\tfor (const header of jar) {\n\t\t\tresponse.headers.append('set-cookie', header);\n\t\t}\n\n\t\tcookieJars.delete(event);\n\t}\n\n\treturn response;\n}\n\n/**\n * Proxies an `HttpClientResponse` to a Web `Response`, preserving headers and status code.\n *\n * @param {HttpClientResponse<T>} response - The `HttpClientResponse` to proxy.\n * @returns {Response} A `Response` object representing the proxied response.\n */\nexport function proxyResponse<T = unknown>(response: HttpClientResponse<T>): Response {\n\tconst proxyHeaders = new Headers();\n\n\tfor (const [key, value] of response.headers.entries()) {\n\t\tif (key.toLowerCase() === 'set-cookie') {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!DISALLOWED_PROXY_HEADERS.has(key.toLowerCase())) {\n\t\t\tproxyHeaders.set(key, value);\n\t\t}\n\t}\n\n\tconst proxyCookies = response.headers\n\t\t.get('set-cookie')\n\t\t?.split(',')\n\t\t.map((cookie) => cookie.trim());\n\n\tif (proxyCookies?.length) {\n\t\tproxyHeaders.set('set-cookie', proxyCookies.join(', '));\n\t}\n\n\treturn new Response(response.body, {\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\theaders: proxyHeaders,\n\t});\n}\n\n/**\n * Returns a safe absolute redirect URL only if it shares the same origin as `safeBaseUrl`, preventing open redirects.\n *\n * @param {string | undefined | null} dangerousRedirect - The untrusted redirect path or URL.\n * @param {string} safeBaseUrl - The trusted base URL whose origin is used as the allowed origin.\n * @returns {string | null} The resolved URL string if safe, or `null`.\n */\nexport function toSafeRedirect(dangerousRedirect: string | undefined | null, safeBaseUrl: string): string | null {\n\tlet url: URL;\n\n\tif (!dangerousRedirect) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\turl = new URL(\n\t\t\tdangerousRedirect.startsWith('/') ? dangerousRedirect.slice(1) : dangerousRedirect,\n\t\t\tsafeBaseUrl && !safeBaseUrl.endsWith('/') ? `${safeBaseUrl}/` : safeBaseUrl,\n\t\t);\n\t} catch {\n\t\treturn null;\n\t}\n\n\tif (url.origin === new URL(safeBaseUrl).origin) {\n\t\treturn url.toString();\n\t}\n\n\treturn null;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{ConfigurationError as e,InternalError as t}from"../utils/errors.mjs";import{m as n}from"./oidc.mjs";import{decryptString as r,encryptString as i}from"../utils/crypto.mjs";var a=`strivacity-session-v1`,o=3900;function s(){return globalThis.sty??={},globalThis.sty.storage??=new Map,{async get(e){return Promise.resolve(globalThis.sty.storage?.get(e)??null)},async set(e,t){return globalThis.sty.storage?.set(e,t),Promise.resolve()},async delete(e){return globalThis.sty.storage?.delete(e),Promise.resolve()}}}function c(){return globalThis.sty??={},globalThis.sty.storage=new Map,{get:e=>Promise.resolve(globalThis.sty.storage.get(e)??null),set:(e,t)=>(globalThis.sty.storage.set(e,t),Promise.resolve()),delete:e=>(globalThis.sty.storage.delete(e),Promise.resolve()),deleteByLogoutToken:e=>{for(let[t,n]of globalThis.sty.storage){let r=JSON.parse(n)?.claims;(e.sid&&r?.sid===e.sid||e.sub&&r?.sub===e.sub)&&globalThis.sty.storage.delete(t)}return Promise.resolve()}}}function l(e,t,n){let r={httpOnly:!0,secure:!0,sameSite:`lax`,path:`/`,...n?.defaultCookieOptions};return e.getSessionId||=async(t,n)=>n?_((await e.toRequest(n)).headers.get(`cookie`))[t]:null,{async get(n,r){let i=await e.getSessionId(n,r);return i?await t.get(i):null},async set(i,a,o){let s=await e.getSessionId(i,o);s||(s=n?.uuidGenerator?.()??globalThis.crypto.randomUUID(),y(o,v(i,s,r))),await t.set(s,a)},async delete(n,i){let a=await e.getSessionId(n,i);a&&await t.delete(a),y(i,v(n,``,{...r,expires:new Date(0)}))},async deleteByLogoutToken(e){await t.deleteByLogoutToken?.(e)}}}function u(e,t,n){let s={httpOnly:!0,secure:!0,sameSite:`lax`,path:`/`,...n?.defaultCookieOptions};async function c(e,n){return e?_((await t.toRequest(e)).headers.get(`cookie`))[n]:void 0}let l={async get(t,n){let i=await c(n,t);if(i)return await r(i,e,a);let o=[];for(let e=0;;e++){let r=await c(n,`${t}.${e}`);if(!r)break;o.push(r)}return o.length===0?null:await r(o.join(``),e,a)},async set(t,n,r){await l.delete(t,r);let c=await i(n,e,a);if(c.length<=3900)y(r,v(t,c,s));else for(let e=0;e*o<c.length;e++)y(r,v(`${t}.${e}`,c.slice(e*o,(e+1)*o),s))},async delete(e,t){let n={...s,expires:new Date(0)};y(t,v(e,``,n));for(let r=0;await c(t,`${e}.${r}`);r++)y(t,v(`${e}.${r}`,``,n))}};return l}var d=new Set([`transfer-encoding`,`connection`,`keep-alive`,`content-encoding`]),f=`sty.returnTo`,p=`http://schemas.openid.net/event/backchannel-logout`,m=2592e3,h=new WeakMap;function g(t,r){if(r.postLoginRedirectUri??=new URL(r.redirectUri).origin,r.postLogoutRedirectUri??=new URL(r.redirectUri).origin,r.cookieMaxAge??=m,!r.storage){if(!r.secret)throw new e(`Missing SDK option: secret`);r.storage=u(r.secret,t,{defaultCookieOptions:{maxAge:r.cookieMaxAge}})}return r.stateStorage??=s(),r.urlHandler??=async()=>Promise.resolve(void 0),r.authUrlPrefix??=`/auth`,r.loginUri??=`/login`,r.serverSessionUri===void 0&&(r.serverSessionUri??=`${r.authUrlPrefix}/login`),n(r)}function _(e){let t={};if(!e)return t;for(let n of e.split(`;`)){let e=n.indexOf(`=`);if(e===-1)continue;let r=n.slice(0,e).trim(),i=n.slice(e+1).trim();if(r)try{t[r]=decodeURIComponent(i)}catch{t[r]=i}}return t}function v(e,t,n={}){let r=[`${e}=${encodeURIComponent(t)}`];return typeof n.maxAge==`number`&&r.push(`Max-Age=${Math.floor(n.maxAge)}`),n.expires&&r.push(`Expires=${n.expires.toUTCString()}`),r.push(`Path=${n.path??`/`}`),n.domain&&r.push(`Domain=${n.domain}`),n.sameSite&&r.push(`SameSite=${n.sameSite.charAt(0).toUpperCase()}${n.sameSite.slice(1)}`),n.secure&&r.push(`Secure`),n.httpOnly&&r.push(`HttpOnly`),r.join(`; `)}function y(e,n){if(typeof e!=`object`||!e)throw new t(`Server adapter events must be objects to track outgoing cookies`);let r=h.get(e)??[];r.push(n),h.set(e,r)}function b(e,n){if(typeof e!=`object`||!e)throw new t(`Server adapter events must be objects to track outgoing cookies`);let r=h.get(e);if(r?.length){for(let e of r)n.headers.append(`set-cookie`,e);h.delete(e)}return n}function x(e){let t=new Headers;for(let[n,r]of e.headers.entries())n.toLowerCase()!==`set-cookie`&&(d.has(n.toLowerCase())||t.set(n,r));let n=e.headers.get(`set-cookie`)?.split(`,`).map(e=>e.trim());return n?.length&&t.set(`set-cookie`,n.join(`, `)),new Response(e.body,{status:e.status,statusText:e.statusText,headers:t})}function S(e,t){let n;if(!e)return null;try{n=new URL(e.startsWith(`/`)?e.slice(1):e,t&&!t.endsWith(`/`)?`${t}/`:t)}catch{return null}return n.origin===new URL(t).origin?n.toString():null}export{l as _,b as a,x as c,S as d,o as f,s as g,c as h,f as i,y as l,u as m,m as n,g as o,a as p,d as r,_ as s,p as t,v as u};
1
+ import{ConfigurationError as e,InternalError as t}from"../utils/errors.mjs";import{m as n}from"./oidc.mjs";import{decryptString as r,encryptString as i}from"../utils/crypto.mjs";var a=`strivacity-session-v1`,o=3900;function s(){return globalThis.sty??={},globalThis.sty.storage??=new Map,{async get(e){return Promise.resolve(globalThis.sty.storage?.get(e)??null)},async set(e,t){return globalThis.sty.storage?.set(e,t),Promise.resolve()},async delete(e){return globalThis.sty.storage?.delete(e),Promise.resolve()}}}function c(){return globalThis.sty??={},globalThis.sty.storage=new Map,{get:e=>Promise.resolve(globalThis.sty.storage.get(e)??null),set:(e,t)=>(globalThis.sty.storage.set(e,t),Promise.resolve()),delete:e=>(globalThis.sty.storage.delete(e),Promise.resolve()),deleteByLogoutToken:e=>{for(let[t,n]of globalThis.sty.storage){let r=JSON.parse(n)?.claims;(e.sid&&r?.sid===e.sid||e.sub&&r?.sub===e.sub)&&globalThis.sty.storage.delete(t)}return Promise.resolve()}}}function l(e,t,n){let r={httpOnly:!0,secure:!0,sameSite:`lax`,path:`/`,...n?.defaultCookieOptions};e.getSessionId||=async(t,n)=>n?b((await e.toRequest(n)).headers.get(`cookie`))[t]:null;let i={async get(n,r){let i=await e.getSessionId(n,r);return i?await t.get(i):null},async set(i,a,o){let s=await e.getSessionId(i,o);s||(s=n?.uuidGenerator?.()??globalThis.crypto.randomUUID(),S(o,x(i,s,r))),await t.set(s,a)},async delete(n,i){let a=await e.getSessionId(n,i);a&&await t.delete(a),S(i,x(n,``,{...r,maxAge:0}))}};return t.deleteByLogoutToken&&(i.deleteByLogoutToken=e=>t.deleteByLogoutToken(e)),i}function u(e,t,n){let r={httpOnly:!0,secure:!0,sameSite:`lax`,path:`/`,...n?.defaultCookieOptions},i={...r,maxAge:0};function a(e){return{get:async n=>e?b((await t.toRequest(e)).headers.get(`cookie`))[n]:void 0,set:(t,n,r)=>S(e,x(t,n,r)),delete:t=>S(e,x(t,``,i))}}return{get:(t,n)=>d(a(n),t,e),set:(t,n,i)=>f(a(i),t,n,e,r),delete:(e,t)=>p(a(t),e,r)}}async function d(e,t,n){let i=await e.get(t);if(i)return await r(i,n,a);let o=[];for(let n=0;;n++){let r=await e.get(`${t}.${n}`);if(!r)break;o.push(r)}return o.length>0?await r(o.join(``),n,a):null}async function f(e,t,n,r,s){await p(e,t,s);let c=await i(n,r,a);if(c.length<=3900){await e.set(t,c,s);return}for(let n=0;n*o<c.length;n++)await e.set(`${t}.${n}`,c.slice(n*o,(n+1)*o),s)}async function p(e,t,n){await e.delete(t,n);for(let r=0;await e.get(`${t}.${r}`);r++)await e.delete(`${t}.${r}`,n)}var m=new Set([`transfer-encoding`,`connection`,`keep-alive`,`content-encoding`]),h=`sty.returnTo`,g=`http://schemas.openid.net/event/backchannel-logout`,_=2592e3,v=new WeakMap;function y(t,r){let i={...r};if(i.postLoginRedirectUri??=new URL(i.redirectUri).origin,i.postLogoutRedirectUri??=new URL(i.redirectUri).origin,i.cookieMaxAge??=_,!i.storage){if(!i.secret)throw new e(`Missing SDK option: secret`);i.storage=u(i.secret,t,{defaultCookieOptions:{maxAge:i.cookieMaxAge}})}return i.stateStorage??=s(),i.urlHandler??=async()=>Promise.resolve(void 0),i.authUrlPrefix??=`/auth`,i.loginUri??=`/login`,i.serverSessionUri===void 0&&(i.serverSessionUri??=`${i.authUrlPrefix}/login`),n(i)}function b(e){let t={};if(!e)return t;for(let n of e.split(`;`)){let e=n.indexOf(`=`);if(e===-1)continue;let r=n.slice(0,e).trim(),i=n.slice(e+1).trim();if(r)try{t[r]=decodeURIComponent(i)}catch{t[r]=i}}return t}function x(e,t,n={}){let r=[`${e}=${encodeURIComponent(t)}`];return typeof n.maxAge==`number`&&r.push(`Max-Age=${Math.floor(n.maxAge)}`),n.expires&&r.push(`Expires=${n.expires.toUTCString()}`),r.push(`Path=${n.path??`/`}`),n.domain&&r.push(`Domain=${n.domain}`),n.sameSite&&r.push(`SameSite=${n.sameSite.charAt(0).toUpperCase()}${n.sameSite.slice(1)}`),n.secure&&r.push(`Secure`),n.httpOnly&&r.push(`HttpOnly`),r.join(`; `)}function S(e,n){if(typeof e!=`object`||!e)throw new t(`Server adapter events must be objects to track outgoing cookies`);let r=v.get(e)??[];r.push(n),v.set(e,r)}function C(e,n){if(typeof e!=`object`||!e)throw new t(`Server adapter events must be objects to track outgoing cookies`);let r=v.get(e);if(r?.length){for(let e of r)n.headers.append(`set-cookie`,e);v.delete(e)}return n}function w(e){let t=new Headers;for(let[n,r]of e.headers.entries())n.toLowerCase()!==`set-cookie`&&(m.has(n.toLowerCase())||t.set(n,r));let n=e.headers.get(`set-cookie`)?.split(`,`).map(e=>e.trim());return n?.length&&t.set(`set-cookie`,n.join(`, `)),new Response(e.body,{status:e.status,statusText:e.statusText,headers:t})}function T(e,t){let n;if(!e)return null;try{n=new URL(e.startsWith(`/`)?e.slice(1):e,t&&!t.endsWith(`/`)?`${t}/`:t)}catch{return null}return n.origin===new URL(t).origin?n.toString():null}export{l as _,C as a,f as b,w as c,T as d,o as f,s as g,c as h,h as i,S as l,u as m,_ as n,y as o,a as p,m as r,b as s,g as t,x as u,p as v,d as y};
2
2
  //# sourceMappingURL=server.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.mjs","names":[],"sources":["../../src/storages/server.ts","../../src/utils/server.ts"],"sourcesContent":["import type { SDKStorage } from '../types/common';\nimport type { EncryptedCookieStorageOptions, ServerAdapter, ServerCookieOptions, ServerStorage, SessionIdCookieStorageOptions } from '../types/server';\nimport { encryptString, decryptString } from '../utils/crypto';\nimport { parseCookieHeader, pushSetCookie, serializeCookie } from '../utils/server';\n\nexport const COOKIE_CONTEXT = 'strivacity-session-v1';\nexport const COOKIE_CHUNK_SIZE = 3900;\n\n/**\n * Creates a simple in-memory state storage implementation, shared across all server adapters.\n *\n * @returns {SDKStorage} An object implementing the SDKStorage interface.\n */\nexport function createServerStateStorage(): SDKStorage {\n\tglobalThis.sty ??= {} as typeof globalThis.sty;\n\tglobalThis.sty.storage ??= new Map<string, string>();\n\n\treturn {\n\t\tasync get(key) {\n\t\t\treturn Promise.resolve(globalThis.sty.storage?.get(key) ?? null);\n\t\t},\n\t\tasync set(key, value) {\n\t\t\tglobalThis.sty.storage?.set(key, value);\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t\tasync delete(key) {\n\t\t\tglobalThis.sty.storage?.delete(key);\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t};\n}\n\n/**\n * In-memory global storage adapter for session data.\n * Not recommended for production use, as session data will be lost on server restart.\n *\n * @returns {ServerStorage} An object implementing the ServerStorage interface.\n */\nexport function createServerMemoryStorage(): ServerStorage {\n\tglobalThis.sty ??= {} as typeof globalThis.sty;\n\tglobalThis.sty.storage = new Map<string, string>();\n\n\treturn {\n\t\tget: (key) => {\n\t\t\treturn Promise.resolve(globalThis.sty.storage!.get(key) ?? null);\n\t\t},\n\t\tset: (key, value) => {\n\t\t\tglobalThis.sty.storage!.set(key, value);\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t\tdelete: (key) => {\n\t\t\tglobalThis.sty.storage!.delete(key);\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t\tdeleteByLogoutToken: (logoutToken) => {\n\t\t\tfor (const [mapKey, raw] of globalThis.sty.storage!) {\n\t\t\t\tconst claims = JSON.parse(raw)?.claims;\n\n\t\t\t\tif ((logoutToken.sid && claims?.sid === logoutToken.sid) || (logoutToken.sub && claims?.sub === logoutToken.sub)) {\n\t\t\t\t\tglobalThis.sty.storage!.delete(mapKey);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t};\n}\n\n/**\n * Creates a session storage that puts a session-id value cookie on the client and keeping the actual session data in the given `storage`.\n *\n * @param {ServerAdapter<TEvent>} adapter - The framework adapter used to read the incoming request.\n * @param {ServerStorage<TEvent>} storage - The storage used to persist session data, keyed by a randomly generated session id.\n * @param {SessionIdCookieStorageOptions} [options] - Options for the session ID cookie, including default cookie attributes and a UUID generator function.\n * @param {Partial<ServerCookieOptions>} [options.defaultCookieOptions] - Default cookie attributes for the session ID cookie.\n * @param {() => string} [options.uuidGenerator] - Function to generate a new UUID for the session ID. Defaults to `() => crypto.randomUUID()`.\n * @returns {ServerStorage<TEvent>} An object implementing the `ServerStorage` interface for managing sessions indexed by a session-id cookie.\n */\nexport function createSessionIdCookieStorage<TEvent = unknown>(\n\tadapter: ServerAdapter<TEvent>,\n\tstorage: ServerStorage,\n\toptions?: SessionIdCookieStorageOptions,\n): ServerStorage<TEvent> {\n\tconst defaultCookieOptions: ServerCookieOptions = {\n\t\thttpOnly: true,\n\t\tsecure: true,\n\t\tsameSite: 'lax',\n\t\tpath: '/',\n\t\t...options?.defaultCookieOptions,\n\t};\n\n\tif (!adapter.getSessionId) {\n\t\tadapter.getSessionId = async (key: string, event?: TEvent) => {\n\t\t\tif (!event) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst request = await adapter.toRequest(event);\n\t\t\tconst cookies = parseCookieHeader(request.headers.get('cookie'));\n\n\t\t\treturn cookies[key];\n\t\t};\n\t}\n\n\treturn {\n\t\tasync get(key, event) {\n\t\t\tconst id = await adapter.getSessionId!(key, event);\n\n\t\t\treturn id ? await storage.get(id) : null;\n\t\t},\n\t\tasync set(key, value, event) {\n\t\t\tlet id = await adapter.getSessionId!(key, event);\n\n\t\t\tif (!id) {\n\t\t\t\tid = options?.uuidGenerator?.() ?? globalThis.crypto.randomUUID();\n\t\t\t\tpushSetCookie(event, serializeCookie(key, id, defaultCookieOptions));\n\t\t\t}\n\n\t\t\tawait storage.set(id, value);\n\t\t},\n\t\tasync delete(key, event) {\n\t\t\tconst id = await adapter.getSessionId!(key, event);\n\n\t\t\tif (id) {\n\t\t\t\tawait storage.delete(id);\n\t\t\t}\n\n\t\t\tpushSetCookie(event, serializeCookie(key, '', { ...defaultCookieOptions, expires: new Date(0) }));\n\t\t},\n\t\tasync deleteByLogoutToken(token) {\n\t\t\tawait storage.deleteByLogoutToken?.(token);\n\t\t},\n\t};\n}\n\n/**\n * Creates an encrypted session storage backed by cookies.\n * Built entirely on top of `adapter.toRequest`'s `Request` (reading the `cookie` header) and the outgoing cookie jar (writing `set-cookie` headers).\n *\n * @param {string} secret - The secret key used for encryption and decryption.\n * @param {ServerAdapter<TEvent>} adapter - The framework adapter used to read the incoming request.\n * @param {EncryptedCookieStorageOptions} [options] - Cookie attributes (maxAge, sameSite, etc.). `path` defaults to `'/'`.\n * @param {Partial<ServerCookieOptions>} [options.defaultCookieOptions] - Default cookie attributes for the session ID cookie.\n * @returns {ServerStorage<TEvent>} An object implementing the `ServerStorage` interface for managing encrypted session cookies.\n */\nexport function createEncryptedCookieStorage<TEvent = unknown>(\n\tsecret: string,\n\tadapter: ServerAdapter<TEvent>,\n\toptions?: EncryptedCookieStorageOptions,\n): ServerStorage<TEvent> {\n\tconst defaultCookieOptions: ServerCookieOptions = {\n\t\thttpOnly: true,\n\t\tsecure: true,\n\t\tsameSite: 'lax',\n\t\tpath: '/',\n\t\t...options?.defaultCookieOptions,\n\t};\n\n\tasync function getIncomingCookie(event: TEvent | undefined, name: string): Promise<string | undefined> {\n\t\tif (!event) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst cookies = parseCookieHeader(request.headers.get('cookie'));\n\n\t\treturn cookies[name];\n\t}\n\n\tconst storage: ServerStorage<TEvent> = {\n\t\tasync get(key, event) {\n\t\t\tconst cookie = await getIncomingCookie(event, key);\n\n\t\t\tif (cookie) {\n\t\t\t\t// NOTE: If the cookie is present, we can decrypt it directly without checking for chunks.\n\t\t\t\treturn await decryptString(cookie, secret, COOKIE_CONTEXT);\n\t\t\t}\n\n\t\t\t// NOTE: If the cookie is not present, we check for chunked cookies (e.g., `key.0`, `key.1`, etc.) and concatenate them before decryption.\n\t\t\tconst cookieChunks: Array<string> = [];\n\n\t\t\tfor (let i = 0; ; i++) {\n\t\t\t\tconst chunk = await getIncomingCookie(event, `${key}.${i}`);\n\n\t\t\t\tif (!chunk) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcookieChunks.push(chunk);\n\t\t\t}\n\n\t\t\tif (cookieChunks.length === 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn await decryptString(cookieChunks.join(''), secret, COOKIE_CONTEXT);\n\t\t},\n\n\t\tasync set(key, value, event) {\n\t\t\t// NOTE: Delete existing cookie(s) first to avoid leaving old chunks behind\n\t\t\tawait storage.delete(key, event);\n\n\t\t\tconst encrypted = await encryptString(value, secret, COOKIE_CONTEXT);\n\n\t\t\tif (encrypted.length <= COOKIE_CHUNK_SIZE) {\n\t\t\t\tpushSetCookie(event, serializeCookie(key, encrypted, defaultCookieOptions));\n\t\t\t} else {\n\t\t\t\tfor (let i = 0; i * COOKIE_CHUNK_SIZE < encrypted.length; i++) {\n\t\t\t\t\tpushSetCookie(event, serializeCookie(`${key}.${i}`, encrypted.slice(i * COOKIE_CHUNK_SIZE, (i + 1) * COOKIE_CHUNK_SIZE), defaultCookieOptions));\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tasync delete(key, event) {\n\t\t\tconst expiredOptions = { ...defaultCookieOptions, expires: new Date(0) };\n\n\t\t\tpushSetCookie(event, serializeCookie(key, '', expiredOptions));\n\n\t\t\tfor (let i = 0; await getIncomingCookie(event, `${key}.${i}`); i++) {\n\t\t\t\tpushSetCookie(event, serializeCookie(`${key}.${i}`, '', expiredOptions));\n\t\t\t}\n\t\t},\n\t};\n\n\treturn storage;\n}\n","import type { HttpClientResponse, SDKStorage, ServerCookieOptions, ServerAdapter, ServerSDKOptions, ServerStorage } from '../types';\nimport { getSDKOptions } from './oidc';\nimport { createServerStateStorage, createEncryptedCookieStorage } from '../storages/server';\nimport { ConfigurationError, InternalError } from './errors';\n\n/**\n * Disallowed headers that should not be proxied from the SDK to the client, as they may interfere with the response handling.\n */\nexport const DISALLOWED_PROXY_HEADERS = new Set(['transfer-encoding', 'connection', 'keep-alive', 'content-encoding']);\n\n/**\n * Returns with the returnTo cookie name used for storing the returnTo URL in the server SDK.\n */\nexport const RETURN_TO_COOKIE = 'sty.returnTo';\n\n/**\n * Backchannel logout event name used for identifying backchannel logout requests in the server SDK.\n */\nexport const BACKCHANNEL_LOGOUT_EVENT = 'http://schemas.openid.net/event/backchannel-logout';\n\n/**\n * Default cookie max age in seconds (30 days).\n */\nexport const DEFAULT_COOKIE_MAX_AGE = 30 * 24 * 60 * 60;\n\n/**\n * A WeakMap to store cookies for each request event, allowing for proper cookie management in server-side environments.\n */\nconst cookieJars = new WeakMap<object, Array<string>>();\n\n/**\n * Returns with the server SDK options merged with the provided options.\n *\n * @param {SDKInitConfig} options - The SDK initialization configuration.\n * @template InitOptions - The type of the SDK initialization configuration.\n * @template Options - The type of the SDK options.\n * @returns {Options} The merged SDK options.\n */\nexport function getServerSDKOptions<\n\tTEvent = unknown,\n\tStorage extends ServerStorage<TEvent> = ServerStorage<TEvent>,\n\tStateStorage extends SDKStorage = SDKStorage,\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n>(adapter: ServerAdapter<TEvent>, options: any): ServerSDKOptions<TEvent, Storage, StateStorage> {\n\toptions.postLoginRedirectUri ??= new URL(options.redirectUri).origin;\n\toptions.postLogoutRedirectUri ??= new URL(options.redirectUri).origin;\n\toptions.cookieMaxAge ??= DEFAULT_COOKIE_MAX_AGE;\n\n\tif (!options.storage) {\n\t\tif (!options.secret) {\n\t\t\tthrow new ConfigurationError('Missing SDK option: secret');\n\t\t}\n\n\t\toptions.storage = createEncryptedCookieStorage<TEvent>(options.secret, adapter, { defaultCookieOptions: { maxAge: options.cookieMaxAge } });\n\t}\n\n\toptions.stateStorage ??= createServerStateStorage();\n\toptions.urlHandler ??= async () => Promise.resolve(undefined);\n\toptions.authUrlPrefix ??= '/auth';\n\toptions.loginUri ??= '/login';\n\n\tif (typeof options.serverSessionUri === 'undefined') {\n\t\toptions.serverSessionUri ??= `${options.authUrlPrefix}/login`;\n\t}\n\n\treturn getSDKOptions(options);\n}\n\n/**\n * Parses a `Cookie` request header into a plain name/value map.\n *\n * @param {string | null | undefined} header - The raw `Cookie` header value.\n * @returns {Record<string, string>} The parsed cookies.\n */\nexport function parseCookieHeader(header: string | null | undefined): Record<string, string> {\n\tconst cookies: Record<string, string> = {};\n\n\tif (!header) {\n\t\treturn cookies;\n\t}\n\n\tfor (const part of header.split(';')) {\n\t\tconst index = part.indexOf('=');\n\n\t\tif (index === -1) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst name = part.slice(0, index).trim();\n\t\tconst value = part.slice(index + 1).trim();\n\n\t\tif (name) {\n\t\t\ttry {\n\t\t\t\tcookies[name] = decodeURIComponent(value);\n\t\t\t} catch {\n\t\t\t\tcookies[name] = value;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn cookies;\n}\n\n/**\n * Serializes a name/value pair into a `Set-Cookie` header value.\n *\n * @param {string} name - The cookie name.\n * @param {string} value - The cookie value.\n * @param {ServerCookieOptions} [options] - The cookie attributes.\n * @returns {string} The serialized `Set-Cookie` header value.\n */\nexport function serializeCookie(name: string, value: string, options: ServerCookieOptions = {}): string {\n\tconst segments = [`${name}=${encodeURIComponent(value)}`];\n\n\tif (typeof options.maxAge === 'number') {\n\t\tsegments.push(`Max-Age=${Math.floor(options.maxAge)}`);\n\t}\n\tif (options.expires) {\n\t\tsegments.push(`Expires=${options.expires.toUTCString()}`);\n\t}\n\n\tsegments.push(`Path=${options.path ?? '/'}`);\n\n\tif (options.domain) {\n\t\tsegments.push(`Domain=${options.domain}`);\n\t}\n\tif (options.sameSite) {\n\t\tsegments.push(`SameSite=${options.sameSite.charAt(0).toUpperCase()}${options.sameSite.slice(1)}`);\n\t}\n\tif (options.secure) {\n\t\tsegments.push('Secure');\n\t}\n\tif (options.httpOnly) {\n\t\tsegments.push('HttpOnly');\n\t}\n\n\treturn segments.join('; ');\n}\n\n/**\n * Pushes a `Set-Cookie` header value into the cookie jar for the given event.\n *\n * @param {unknown} event - The framework-native request event.\n * @param {string} header - The `Set-Cookie` header value to push.\n */\nexport function pushSetCookie(event: unknown, header: string): void {\n\tif (event === null || typeof event !== 'object') {\n\t\tthrow new InternalError('Server adapter events must be objects to track outgoing cookies');\n\t}\n\n\tconst jar = cookieJars.get(event) ?? [];\n\tjar.push(header);\n\tcookieJars.set(event, jar);\n}\n\n/**\n * Flushes the accumulated `Set-Cookie` headers from the cookie jar into the provided `Response`.\n *\n * @param {unknown} event - The framework-native request event.\n * @param {Response} response - The `Response` object to append the `Set-Cookie` headers to.\n * @returns {Response} The modified `Response` with the appended `Set-Cookie` headers.\n */\nexport function flushSetCookies(event: unknown, response: Response): Response {\n\tif (event === null || typeof event !== 'object') {\n\t\tthrow new InternalError('Server adapter events must be objects to track outgoing cookies');\n\t}\n\n\tconst jar = cookieJars.get(event);\n\n\tif (jar?.length) {\n\t\tfor (const header of jar) {\n\t\t\tresponse.headers.append('set-cookie', header);\n\t\t}\n\n\t\tcookieJars.delete(event);\n\t}\n\n\treturn response;\n}\n\n/**\n * Proxies an `HttpClientResponse` to a Web `Response`, preserving headers and status code.\n *\n * @param {HttpClientResponse<T>} response - The `HttpClientResponse` to proxy.\n * @returns {Response} A `Response` object representing the proxied response.\n */\nexport function proxyResponse<T = unknown>(response: HttpClientResponse<T>): Response {\n\tconst proxyHeaders = new Headers();\n\n\tfor (const [key, value] of response.headers.entries()) {\n\t\tif (key.toLowerCase() === 'set-cookie') {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!DISALLOWED_PROXY_HEADERS.has(key.toLowerCase())) {\n\t\t\tproxyHeaders.set(key, value);\n\t\t}\n\t}\n\n\tconst proxyCookies = response.headers\n\t\t.get('set-cookie')\n\t\t?.split(',')\n\t\t.map((cookie) => cookie.trim());\n\n\tif (proxyCookies?.length) {\n\t\tproxyHeaders.set('set-cookie', proxyCookies.join(', '));\n\t}\n\n\treturn new Response(response.body, {\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\theaders: proxyHeaders,\n\t});\n}\n\n/**\n * Returns a safe absolute redirect URL only if it shares the same origin as `safeBaseUrl`, preventing open redirects.\n *\n * @param {string | undefined | null} dangerousRedirect - The untrusted redirect path or URL.\n * @param {string} safeBaseUrl - The trusted base URL whose origin is used as the allowed origin.\n * @returns {string | null} The resolved URL string if safe, or `null`.\n */\nexport function toSafeRedirect(dangerousRedirect: string | undefined | null, safeBaseUrl: string): string | null {\n\tlet url: URL;\n\n\tif (!dangerousRedirect) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\turl = new URL(\n\t\t\tdangerousRedirect.startsWith('/') ? dangerousRedirect.slice(1) : dangerousRedirect,\n\t\t\tsafeBaseUrl && !safeBaseUrl.endsWith('/') ? `${safeBaseUrl}/` : safeBaseUrl,\n\t\t);\n\t} catch {\n\t\treturn null;\n\t}\n\n\tif (url.origin === new URL(safeBaseUrl).origin) {\n\t\treturn url.toString();\n\t}\n\n\treturn null;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"server.mjs","names":[],"sources":["../../src/storages/server.ts","../../src/utils/server.ts"],"sourcesContent":["import type { SDKStorage } from '../types/common';\nimport type {\n\tCookieJar,\n\tEncryptedCookieStorageOptions,\n\tServerAdapter,\n\tServerCookieOptions,\n\tServerStorage,\n\tSessionIdCookieStorageOptions,\n} from '../types/server';\nimport { encryptString, decryptString } from '../utils/crypto';\nimport { parseCookieHeader, pushSetCookie, serializeCookie } from '../utils/server';\n\nexport const COOKIE_CONTEXT = 'strivacity-session-v1';\nexport const COOKIE_CHUNK_SIZE = 3900;\n\n/**\n * Creates a simple in-memory state storage implementation, shared across all server adapters.\n *\n * @returns {SDKStorage} An object implementing the SDKStorage interface.\n */\nexport function createServerStateStorage(): SDKStorage {\n\tglobalThis.sty ??= {} as typeof globalThis.sty;\n\tglobalThis.sty.storage ??= new Map<string, string>();\n\n\treturn {\n\t\tasync get(key) {\n\t\t\treturn Promise.resolve(globalThis.sty.storage?.get(key) ?? null);\n\t\t},\n\t\tasync set(key, value) {\n\t\t\tglobalThis.sty.storage?.set(key, value);\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t\tasync delete(key) {\n\t\t\tglobalThis.sty.storage?.delete(key);\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t};\n}\n\n/**\n * In-memory global storage adapter for session data.\n * Not recommended for production use, as session data will be lost on server restart.\n *\n * @returns {ServerStorage} An object implementing the ServerStorage interface.\n */\nexport function createServerMemoryStorage(): ServerStorage {\n\tglobalThis.sty ??= {} as typeof globalThis.sty;\n\tglobalThis.sty.storage = new Map<string, string>();\n\n\treturn {\n\t\tget: (key) => {\n\t\t\treturn Promise.resolve(globalThis.sty.storage!.get(key) ?? null);\n\t\t},\n\t\tset: (key, value) => {\n\t\t\tglobalThis.sty.storage!.set(key, value);\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t\tdelete: (key) => {\n\t\t\tglobalThis.sty.storage!.delete(key);\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t\tdeleteByLogoutToken: (logoutToken) => {\n\t\t\tfor (const [mapKey, raw] of globalThis.sty.storage!) {\n\t\t\t\tconst claims = JSON.parse(raw)?.claims;\n\n\t\t\t\tif ((logoutToken.sid && claims?.sid === logoutToken.sid) || (logoutToken.sub && claims?.sub === logoutToken.sub)) {\n\t\t\t\t\tglobalThis.sty.storage!.delete(mapKey);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t};\n}\n\n/**\n * Creates a session storage that puts a session-id value cookie on the client and keeping the actual session data in the given `storage`.\n *\n * @param {ServerAdapter<TEvent>} adapter - The framework adapter used to read the incoming request.\n * @param {ServerStorage<TEvent>} storage - The storage used to persist session data, keyed by a randomly generated session id.\n * @param {SessionIdCookieStorageOptions} [options] - Options for the session ID cookie, including default cookie attributes and a UUID generator function.\n * @param {Partial<ServerCookieOptions>} [options.defaultCookieOptions] - Default cookie attributes for the session ID cookie.\n * @param {() => string} [options.uuidGenerator] - Function to generate a new UUID for the session ID. Defaults to `() => crypto.randomUUID()`.\n * @returns {ServerStorage<TEvent>} An object implementing the `ServerStorage` interface for managing sessions indexed by a session-id cookie.\n */\nexport function createSessionIdCookieStorage<TEvent = unknown>(\n\tadapter: ServerAdapter<TEvent>,\n\tstorage: ServerStorage,\n\toptions?: SessionIdCookieStorageOptions,\n): ServerStorage<TEvent> {\n\tconst defaultCookieOptions: ServerCookieOptions = {\n\t\thttpOnly: true,\n\t\tsecure: true,\n\t\tsameSite: 'lax',\n\t\tpath: '/',\n\t\t...options?.defaultCookieOptions,\n\t};\n\n\tif (!adapter.getSessionId) {\n\t\tadapter.getSessionId = async (key: string, event?: TEvent) => {\n\t\t\tif (!event) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst request = await adapter.toRequest(event);\n\t\t\tconst cookies = parseCookieHeader(request.headers.get('cookie'));\n\n\t\t\treturn cookies[key];\n\t\t};\n\t}\n\n\tconst sessionIdStorage: ServerStorage<TEvent> = {\n\t\tasync get(key, event) {\n\t\t\tconst id = await adapter.getSessionId!(key, event);\n\n\t\t\treturn id ? await storage.get(id) : null;\n\t\t},\n\t\tasync set(key, value, event) {\n\t\t\tlet id = await adapter.getSessionId!(key, event);\n\n\t\t\tif (!id) {\n\t\t\t\tid = options?.uuidGenerator?.() ?? globalThis.crypto.randomUUID();\n\t\t\t\tpushSetCookie(event, serializeCookie(key, id, defaultCookieOptions));\n\t\t\t}\n\n\t\t\tawait storage.set(id, value);\n\t\t},\n\t\tasync delete(key, event) {\n\t\t\tconst id = await adapter.getSessionId!(key, event);\n\n\t\t\tif (id) {\n\t\t\t\tawait storage.delete(id);\n\t\t\t}\n\n\t\t\tpushSetCookie(event, serializeCookie(key, '', { ...defaultCookieOptions, maxAge: 0 }));\n\t\t},\n\t};\n\n\t// NOTE: only when the inner storage can do it, so the back-channel logout route answers 501 instead of a silent 200\n\tif (storage.deleteByLogoutToken) {\n\t\tsessionIdStorage.deleteByLogoutToken = (token) => storage.deleteByLogoutToken!(token);\n\t}\n\n\treturn sessionIdStorage;\n}\n\n/**\n * Creates an encrypted session storage backed by cookies.\n * Built entirely on top of `adapter.toRequest`'s `Request` (reading the `cookie` header) and the outgoing cookie jar (writing `set-cookie` headers).\n *\n * @param {string} secret - The secret key used for encryption and decryption.\n * @param {ServerAdapter<TEvent>} adapter - The framework adapter used to read the incoming request.\n * @param {EncryptedCookieStorageOptions} [options] - Cookie attributes (maxAge, sameSite, etc.). `path` defaults to `'/'`.\n * @param {Partial<ServerCookieOptions>} [options.defaultCookieOptions] - Default cookie attributes for the session ID cookie.\n * @returns {ServerStorage<TEvent>} An object implementing the `ServerStorage` interface for managing encrypted session cookies.\n */\nexport function createEncryptedCookieStorage<TEvent = unknown>(\n\tsecret: string,\n\tadapter: ServerAdapter<TEvent>,\n\toptions?: EncryptedCookieStorageOptions,\n): ServerStorage<TEvent> {\n\tconst defaultCookieOptions: ServerCookieOptions = {\n\t\thttpOnly: true,\n\t\tsecure: true,\n\t\tsameSite: 'lax',\n\t\tpath: '/',\n\t\t...options?.defaultCookieOptions,\n\t};\n\n\tconst expiredCookieOptions = { ...defaultCookieOptions, maxAge: 0 };\n\n\tfunction createJar(event: TEvent | undefined): CookieJar {\n\t\treturn {\n\t\t\tget: async (name) => {\n\t\t\t\tif (!event) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tconst request = await adapter.toRequest(event);\n\n\t\t\t\treturn parseCookieHeader(request.headers.get('cookie'))[name];\n\t\t\t},\n\t\t\tset: (name, value, cookieOptions) => pushSetCookie(event, serializeCookie(name, value, cookieOptions)),\n\t\t\tdelete: (name) => pushSetCookie(event, serializeCookie(name, '', expiredCookieOptions)),\n\t\t};\n\t}\n\n\treturn {\n\t\tget: (key, event) => readEncryptedCookie(createJar(event), key, secret),\n\t\tset: (key, value, event) => writeEncryptedCookie(createJar(event), key, value, secret, defaultCookieOptions),\n\t\tdelete: (key, event) => deleteEncryptedCookie(createJar(event), key, defaultCookieOptions),\n\t};\n}\n\n/**\n * Reads and decrypts a session written by `writeEncryptedCookie`: a single `key` cookie, or chunks `key.0`, `key.1`, ... joined in order.\n *\n * @param {CookieJar} jar - Access to the request's cookies.\n * @param {string} key - The cookie name.\n * @param {string} secret - The encryption secret.\n * @returns {Promise<string | null>} The decrypted value, or `null` when there is no cookie.\n */\nexport async function readEncryptedCookie<TOptions>(jar: CookieJar<TOptions>, key: string, secret: string): Promise<string | null> {\n\tconst cookie = await jar.get(key);\n\n\tif (cookie) {\n\t\treturn await decryptString(cookie, secret, COOKIE_CONTEXT);\n\t}\n\n\tconst chunks: Array<string> = [];\n\n\tfor (let i = 0; ; i++) {\n\t\tconst chunk = await jar.get(`${key}.${i}`);\n\n\t\tif (!chunk) {\n\t\t\tbreak;\n\t\t}\n\n\t\tchunks.push(chunk);\n\t}\n\n\treturn chunks.length > 0 ? await decryptString(chunks.join(''), secret, COOKIE_CONTEXT) : null;\n}\n\n/**\n * Encrypts a value and writes it as a single `key` cookie, or as `COOKIE_CHUNK_SIZE` chunks (`key.0`, `key.1`, ...) when it is too\n * large for one cookie. The previous cookie and all of its chunks from the request are deleted first, so no stale chunk is left behind.\n *\n * @param {CookieJar} jar - Access to the request's and the response's cookies.\n * @param {string} key - The cookie name.\n * @param {string} value - The plain value.\n * @param {string} secret - The encryption secret.\n * @param {TOptions} options - Cookie attributes for the written cookies (and for deleting the old ones).\n */\nexport async function writeEncryptedCookie<TOptions>(jar: CookieJar<TOptions>, key: string, value: string, secret: string, options: TOptions): Promise<void> {\n\tawait deleteEncryptedCookie(jar, key, options);\n\n\tconst encrypted = await encryptString(value, secret, COOKIE_CONTEXT);\n\n\tif (encrypted.length <= COOKIE_CHUNK_SIZE) {\n\t\tawait jar.set(key, encrypted, options);\n\t\treturn;\n\t}\n\n\tfor (let i = 0; i * COOKIE_CHUNK_SIZE < encrypted.length; i++) {\n\t\tawait jar.set(`${key}.${i}`, encrypted.slice(i * COOKIE_CHUNK_SIZE, (i + 1) * COOKIE_CHUNK_SIZE), options);\n\t}\n}\n\n/**\n * Deletes a session written by `writeEncryptedCookie`: the `key` cookie and every `key.N` chunk present in the request.\n *\n * @param {CookieJar} jar - Access to the request's and the response's cookies.\n * @param {string} key - The cookie name.\n * @param {TOptions} options - Cookie attributes (`path`, `domain`) of the cookies to delete.\n */\nexport async function deleteEncryptedCookie<TOptions>(jar: CookieJar<TOptions>, key: string, options: TOptions): Promise<void> {\n\tawait jar.delete(key, options);\n\n\tfor (let i = 0; await jar.get(`${key}.${i}`); i++) {\n\t\tawait jar.delete(`${key}.${i}`, options);\n\t}\n}\n","import type { HttpClientResponse, SDKStorage, ServerCookieOptions, ServerAdapter, ServerSDKOptions, ServerStorage } from '../types';\nimport { getSDKOptions } from './oidc';\nimport { createServerStateStorage, createEncryptedCookieStorage } from '../storages/server';\nimport { ConfigurationError, InternalError } from './errors';\n\n/**\n * Disallowed headers that should not be proxied from the SDK to the client, as they may interfere with the response handling.\n */\nexport const DISALLOWED_PROXY_HEADERS = new Set(['transfer-encoding', 'connection', 'keep-alive', 'content-encoding']);\n\n/**\n * Returns with the returnTo cookie name used for storing the returnTo URL in the server SDK.\n */\nexport const RETURN_TO_COOKIE = 'sty.returnTo';\n\n/**\n * Backchannel logout event name used for identifying backchannel logout requests in the server SDK.\n */\nexport const BACKCHANNEL_LOGOUT_EVENT = 'http://schemas.openid.net/event/backchannel-logout';\n\n/**\n * Default cookie max age in seconds (30 days).\n */\nexport const DEFAULT_COOKIE_MAX_AGE = 30 * 24 * 60 * 60;\n\n/**\n * A WeakMap to store cookies for each request event, allowing for proper cookie management in server-side environments.\n */\nconst cookieJars = new WeakMap<object, Array<string>>();\n\n/**\n * Returns with the server SDK options merged with the provided options.\n *\n * @param {SDKInitConfig} initOptions - The SDK initialization configuration.\n * @template TEvent - The type of the server request event.\n * @template Storage - The type of the server storage.\n * @template StateStorage - The type of the state storage.\n * @returns {Options} The merged SDK options.\n */\nexport function getServerSDKOptions<\n\tTEvent = unknown,\n\tStorage extends ServerStorage<TEvent> = ServerStorage<TEvent>,\n\tStateStorage extends SDKStorage = SDKStorage,\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n>(adapter: ServerAdapter<TEvent>, initOptions: any): ServerSDKOptions<TEvent, Storage, StateStorage> {\n\tconst options = { ...initOptions };\n\n\toptions.postLoginRedirectUri ??= new URL(options.redirectUri).origin;\n\toptions.postLogoutRedirectUri ??= new URL(options.redirectUri).origin;\n\toptions.cookieMaxAge ??= DEFAULT_COOKIE_MAX_AGE;\n\n\tif (!options.storage) {\n\t\tif (!options.secret) {\n\t\t\tthrow new ConfigurationError('Missing SDK option: secret');\n\t\t}\n\n\t\toptions.storage = createEncryptedCookieStorage<TEvent>(options.secret, adapter, { defaultCookieOptions: { maxAge: options.cookieMaxAge } });\n\t}\n\n\toptions.stateStorage ??= createServerStateStorage();\n\toptions.urlHandler ??= async () => Promise.resolve(undefined);\n\toptions.authUrlPrefix ??= '/auth';\n\toptions.loginUri ??= '/login';\n\n\tif (typeof options.serverSessionUri === 'undefined') {\n\t\toptions.serverSessionUri ??= `${options.authUrlPrefix}/login`;\n\t}\n\n\treturn getSDKOptions(options);\n}\n\n/**\n * Parses a `Cookie` request header into a plain name/value map.\n *\n * @param {string | null | undefined} header - The raw `Cookie` header value.\n * @returns {Record<string, string>} The parsed cookies.\n */\nexport function parseCookieHeader(header: string | null | undefined): Record<string, string> {\n\tconst cookies: Record<string, string> = {};\n\n\tif (!header) {\n\t\treturn cookies;\n\t}\n\n\tfor (const part of header.split(';')) {\n\t\tconst index = part.indexOf('=');\n\n\t\tif (index === -1) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst name = part.slice(0, index).trim();\n\t\tconst value = part.slice(index + 1).trim();\n\n\t\tif (name) {\n\t\t\ttry {\n\t\t\t\tcookies[name] = decodeURIComponent(value);\n\t\t\t} catch {\n\t\t\t\tcookies[name] = value;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn cookies;\n}\n\n/**\n * Serializes a name/value pair into a `Set-Cookie` header value.\n *\n * @param {string} name - The cookie name.\n * @param {string} value - The cookie value.\n * @param {ServerCookieOptions} [options] - The cookie attributes.\n * @returns {string} The serialized `Set-Cookie` header value.\n */\nexport function serializeCookie(name: string, value: string, options: ServerCookieOptions = {}): string {\n\tconst segments = [`${name}=${encodeURIComponent(value)}`];\n\n\tif (typeof options.maxAge === 'number') {\n\t\tsegments.push(`Max-Age=${Math.floor(options.maxAge)}`);\n\t}\n\tif (options.expires) {\n\t\tsegments.push(`Expires=${options.expires.toUTCString()}`);\n\t}\n\n\tsegments.push(`Path=${options.path ?? '/'}`);\n\n\tif (options.domain) {\n\t\tsegments.push(`Domain=${options.domain}`);\n\t}\n\tif (options.sameSite) {\n\t\tsegments.push(`SameSite=${options.sameSite.charAt(0).toUpperCase()}${options.sameSite.slice(1)}`);\n\t}\n\tif (options.secure) {\n\t\tsegments.push('Secure');\n\t}\n\tif (options.httpOnly) {\n\t\tsegments.push('HttpOnly');\n\t}\n\n\treturn segments.join('; ');\n}\n\n/**\n * Pushes a `Set-Cookie` header value into the cookie jar for the given event.\n *\n * @param {unknown} event - The framework-native request event.\n * @param {string} header - The `Set-Cookie` header value to push.\n */\nexport function pushSetCookie(event: unknown, header: string): void {\n\tif (event === null || typeof event !== 'object') {\n\t\tthrow new InternalError('Server adapter events must be objects to track outgoing cookies');\n\t}\n\n\tconst jar = cookieJars.get(event) ?? [];\n\tjar.push(header);\n\tcookieJars.set(event, jar);\n}\n\n/**\n * Flushes the accumulated `Set-Cookie` headers from the cookie jar into the provided `Response`.\n *\n * @param {unknown} event - The framework-native request event.\n * @param {Response} response - The `Response` object to append the `Set-Cookie` headers to.\n * @returns {Response} The modified `Response` with the appended `Set-Cookie` headers.\n */\nexport function flushSetCookies(event: unknown, response: Response): Response {\n\tif (event === null || typeof event !== 'object') {\n\t\tthrow new InternalError('Server adapter events must be objects to track outgoing cookies');\n\t}\n\n\tconst jar = cookieJars.get(event);\n\n\tif (jar?.length) {\n\t\tfor (const header of jar) {\n\t\t\tresponse.headers.append('set-cookie', header);\n\t\t}\n\n\t\tcookieJars.delete(event);\n\t}\n\n\treturn response;\n}\n\n/**\n * Proxies an `HttpClientResponse` to a Web `Response`, preserving headers and status code.\n *\n * @param {HttpClientResponse<T>} response - The `HttpClientResponse` to proxy.\n * @returns {Response} A `Response` object representing the proxied response.\n */\nexport function proxyResponse<T = unknown>(response: HttpClientResponse<T>): Response {\n\tconst proxyHeaders = new Headers();\n\n\tfor (const [key, value] of response.headers.entries()) {\n\t\tif (key.toLowerCase() === 'set-cookie') {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!DISALLOWED_PROXY_HEADERS.has(key.toLowerCase())) {\n\t\t\tproxyHeaders.set(key, value);\n\t\t}\n\t}\n\n\tconst proxyCookies = response.headers\n\t\t.get('set-cookie')\n\t\t?.split(',')\n\t\t.map((cookie) => cookie.trim());\n\n\tif (proxyCookies?.length) {\n\t\tproxyHeaders.set('set-cookie', proxyCookies.join(', '));\n\t}\n\n\treturn new Response(response.body, {\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\theaders: proxyHeaders,\n\t});\n}\n\n/**\n * Returns a safe absolute redirect URL only if it shares the same origin as `safeBaseUrl`, preventing open redirects.\n *\n * @param {string | undefined | null} dangerousRedirect - The untrusted redirect path or URL.\n * @param {string} safeBaseUrl - The trusted base URL whose origin is used as the allowed origin.\n * @returns {string | null} The resolved URL string if safe, or `null`.\n */\nexport function toSafeRedirect(dangerousRedirect: string | undefined | null, safeBaseUrl: string): string | null {\n\tlet url: URL;\n\n\tif (!dangerousRedirect) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\turl = new URL(\n\t\t\tdangerousRedirect.startsWith('/') ? dangerousRedirect.slice(1) : dangerousRedirect,\n\t\t\tsafeBaseUrl && !safeBaseUrl.endsWith('/') ? `${safeBaseUrl}/` : safeBaseUrl,\n\t\t);\n\t} catch {\n\t\treturn null;\n\t}\n\n\tif (url.origin === new URL(safeBaseUrl).origin) {\n\t\treturn url.toString();\n\t}\n\n\treturn null;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../utils/errors.cjs"),t=require("../utils/session.cjs"),n=require("../assets/oidc.cjs");function r(r,i){let a={init:null,refresh:null,revoke:null,logout:null,tokenExchange:new Map},o={accessTokenExpired:new Set,init:new Set,loggedIn:new Set,sessionUpdated:new Set,sessionCleared:new Set,loginInitiated:new Set,flowInitiated:new Set,logoutInitiated:new Set,sessionLoaded:new Set,tokenRefreshed:new Set,tokenRefreshFailed:new Set,tokenRevoked:new Set,tokenRevokeFailed:new Set};function s(e,t){for(let n of o[e])n(...t)}function c(e,t){return o[e].add(t),{dispose:()=>o[e].delete(t)}}function l(e){for(let t in o)o[t].add(e);return{dispose:()=>{for(let t in o)o[t].delete(e)}}}async function u(){return await m(),r.session}async function d(e){await m(),e.id_token&&!e.claims&&(e.claims=await n.v({idToken:e.id_token,options:i})),i.serverSessionUri||await i.storage.set(i.storageTokenName,t.serializeSession(e)),r.session=e,s(`sessionUpdated`,[{idToken:r.session.id_token,accessToken:r.session.access_token,refreshToken:r.session.refresh_token,claims:r.session.claims}])}async function f(){await m(),i.serverSessionUri||await i.storage.delete(i.storageTokenName),r.session=null,s(`sessionCleared`,[])}async function p(e={autoRefresh:i.autoRefresh}){if(r.session?.access_token&&!t.isSessionExpired(r.session))return!0;if(e?.autoRefresh&&r.session?.refresh_token)try{await _()}catch{return!1}return!t.isSessionExpired(r.session)}async function m(){if(!r.initialized)return a.init||=(async()=>{try{if(!i.issuer){let t=new e.ConfigurationError(`Missing option: issuer`);throw i.logging?.error(`Required option missing`,t),t}if(!i.clientId){let t=new e.ConfigurationError(`Missing option: clientId`);throw i.logging?.error(`Required option missing`,t),t}if(!i.redirectUri){let t=new e.ConfigurationError(`Missing option: redirectUri`);throw i.logging?.error(`Required option missing`,t),t}if(i.scopes&&!Array.isArray(i.scopes)){let t=new e.ConfigurationError(`Invalid option: scopes`);throw i.logging?.error(`Invalid option provided`,t),t}i.serverSessionUri||(r.session=t.loadSession(await i.storage.get(i.storageTokenName))),r.initialized=!0,s(`init`,[]),i.logging?.debug(`SDK initialized`),!r.session&&!i.serverSessionUri&&i.logging?.debug(`No session found in storage`),r.session?.access_token&&(s(`sessionLoaded`,[{idToken:r.session.id_token,accessToken:r.session.access_token,refreshToken:r.session.refresh_token,claims:r.session.claims}]),i.logging?.debug(`Session loaded from storage`)),r.session?.access_token&&t.isSessionExpired(r.session)&&(s(`accessTokenExpired`,[{accessToken:r.session.access_token,refreshToken:r.session.refresh_token}]),i.logging?.debug(`Access token has expired`))}finally{a.init=null}})(),a.init}async function h(t={}){await m();let r=t.state??``,o=a.tokenExchange.get(r);if(o)return o;let c=(async()=>{i.logging?.debug(`Exchanging authorization code for tokens`);try{let r=await n.a({params:t,options:i});if(!r.access_token)throw new e.ProtocolError(`Missing access_token`);await d(r),i.logging?.debug(`Token exchange successful`),s(`loggedIn`,[{idToken:r.id_token,accessToken:r.access_token,refreshToken:r.refresh_token,claims:r.claims}]),i.logging&&(i.logging.xEventId=void 0,i.logging.info(`Login successful`))}catch(e){throw i.logging?.error(`Token exchange failed`,e),e}finally{a.tokenExchange.delete(r)}})();return a.tokenExchange.set(r,c),c}async function g(e){await m();let t=e??globalThis.window?.location.href;await h(await i.callbackHandler(t,i.responseMode))}async function _(){if(await m(),a.refresh)return a.refresh;if(a.revoke)try{await a.revoke}catch{}if(a.logout)try{await a.logout}catch{}if(i.logging?.debug(`Attempting to refresh session`),typeof r.session?.refresh_token!=`string`){i.logging?.debug(`Refresh called without refresh token`);return}return a.refresh=(async()=>{try{await d(await n.h({refreshToken:r.session.refresh_token,options:i,expectedSub:r.session?.claims?.sub})),s(`tokenRefreshed`,[{idToken:r.session?.id_token,accessToken:r.session?.access_token,refreshToken:r.session?.refresh_token,claims:r.session?.claims}]),i.logging?.debug(`Session refresh successful`)}catch(t){let n=r.session?.refresh_token;throw!(t instanceof e.NetworkError)&&!(t instanceof e.ServerError)&&await f(),s(`tokenRefreshFailed`,[{refreshToken:n}]),i.logging?.error(`Session refresh failed`,t),t}finally{a.refresh=null}})(),a.refresh}async function v(){if(await m(),a.revoke)return a.revoke;if(a.refresh)try{await a.refresh}catch{}if(a.logout)try{await a.logout}catch{}return a.revoke=(async()=>{try{r.session?.refresh_token?i.logging?.debug(`Attempting to revoke refresh token`):r.session?.access_token&&i.logging?.debug(`Attempting to revoke access token`);let e=r.session;if(await f(),!e?.access_token&&!e?.refresh_token){i.logging?.debug(`Revoke called without session`);return}let t=e.refresh_token?`refresh_token`:`access_token`,a=t===`refresh_token`?e.refresh_token:e.access_token;try{await n.g({tokenTypeHint:t,token:a,options:i}),t===`refresh_token`?(s(`tokenRevoked`,[{token:e.refresh_token,tokenTypeHint:`refresh_token`}]),i.logging?.info(`Refresh token successfully revoked`)):(s(`tokenRevoked`,[{token:e.access_token,tokenTypeHint:`access_token`}]),i.logging?.info(`Access token successfully revoked`))}catch(n){throw t===`refresh_token`?s(`tokenRevokeFailed`,[{token:e.refresh_token,tokenTypeHint:`refresh_token`}]):s(`tokenRevokeFailed`,[{token:e.access_token,tokenTypeHint:`access_token`}]),i.logging?.error(`Token revocation failed`,n),n}}finally{a.revoke=null}})(),a.revoke}async function y(e){if(await m(),a.logout)return a.logout;if(a.revoke)try{await a.revoke}catch{}if(a.refresh)try{await a.refresh}catch{}return a.logout=(async()=>{try{i.logging?.debug(`Attempting to logout`);let t=r.session;if(await f(),s(`logoutInitiated`,[{idToken:t?.id_token,claims:t?.claims}]),i.logging?.debug(`Logout initiated`),!t?.id_token){i.logging?.debug(`Logout called without id token`);return}try{let r=await n.p(i),a=n.n({url:r.end_session_endpoint,idToken:t.id_token,postLogoutRedirectUri:e?.postLogoutRedirectUri});await i.urlHandler(a,e)}catch(e){i.logging?.error(`Unable to redirect to the end-session endpoint`,e)}}finally{a.logout=null}})(),a.logout}return{dispatchEvent:s,subscribeToEvent:c,subscribeToAllEvents:l,getSession:u,updateSession:d,cleanupSession:f,checkAuthentication:p,init:m,tokenExchange:h,handleCallback:g,refresh:_,revoke:v,logout:y}}exports.createBaseFlow=r;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../utils/errors.cjs"),t=require("../utils/session.cjs"),n=require("../assets/oidc.cjs"),r=require("../handlers/redirect.cjs"),i=require("../utils/path.cjs");function a(a,o){let s={init:null,refresh:null,revoke:null,logout:null,tokenExchange:new Map},c=Promise.resolve(),l={accessTokenExpired:new Set,init:new Set,loggedIn:new Set,sessionUpdated:new Set,sessionCleared:new Set,loginInitiated:new Set,flowInitiated:new Set,logoutInitiated:new Set,sessionLoaded:new Set,tokenRefreshed:new Set,tokenRefreshFailed:new Set,tokenRevoked:new Set,tokenRevokeFailed:new Set};function u(e,t){for(let n of l[e])n(...t)}function d(e,t){return l[e].add(t),{dispose:()=>l[e].delete(t)}}function f(e){for(let t in l)l[t].add(e);return{dispose:()=>{for(let t in l)l[t].delete(e)}}}function p(e){let t=globalThis.window?globalThis.navigator?.locks:void 0;if(t)return t.request(`strivacity.session.${o.clientId}.${o.storageTokenName}`,e);let n=c.then(e);return c=n.catch(()=>{}),n}async function m(){return await y(),a.session}async function h(){return o.serverSessionUri?null:t.loadSession(await o.storage.get(o.storageTokenName))}async function g(e){await y(),e.id_token&&!e.claims&&(e.claims=await n.v({idToken:e.id_token,options:o})),o.serverSessionUri||await o.storage.set(o.storageTokenName,t.serializeSession(e)),a.session=e,u(`sessionUpdated`,[{idToken:a.session.id_token,accessToken:a.session.access_token,refreshToken:a.session.refresh_token,claims:a.session.claims}])}async function _(){await y(),o.serverSessionUri||await o.storage.delete(o.storageTokenName),a.session=null,u(`sessionCleared`,[])}async function v(e={autoRefresh:o.autoRefresh}){if(await y(),a.session?.access_token&&!t.isSessionExpired(a.session,o.refreshSkew))return!0;if(e?.autoRefresh&&a.session?.refresh_token&&!o.serverSessionUri)try{await S()}catch{return!1}return!t.isSessionExpired(a.session)}async function y(){if(!a.initialized)return s.init||=(async()=>{try{if(!o.issuer){let t=new e.ConfigurationError(`Missing option: issuer`);throw o.logging?.error(`Required option missing`,t),t}if(!o.clientId){let t=new e.ConfigurationError(`Missing option: clientId`);throw o.logging?.error(`Required option missing`,t),t}if(!o.redirectUri){let t=new e.ConfigurationError(`Missing option: redirectUri`);throw o.logging?.error(`Required option missing`,t),t}if(o.scopes&&!Array.isArray(o.scopes)){let t=new e.ConfigurationError(`Invalid option: scopes`);throw o.logging?.error(`Invalid option provided`,t),t}o.serverSessionUri||(a.session=t.loadSession(await o.storage.get(o.storageTokenName))),a.initialized=!0,u(`init`,[]),o.logging?.debug(`SDK initialized`),!a.session&&!o.serverSessionUri&&o.logging?.debug(`No session found in storage`),a.session?.access_token&&(u(`sessionLoaded`,[{idToken:a.session.id_token,accessToken:a.session.access_token,refreshToken:a.session.refresh_token,claims:a.session.claims}]),o.logging?.debug(`Session loaded from storage`)),a.session?.access_token&&t.isSessionExpired(a.session)&&(u(`accessTokenExpired`,[{accessToken:a.session.access_token,refreshToken:a.session.refresh_token}]),o.logging?.debug(`Access token has expired`))}finally{s.init=null}})(),s.init}async function b(t={}){await y();let r=t.state??``,i=s.tokenExchange.get(r);if(i)return i;let a=(async()=>{o.logging?.debug(`Exchanging authorization code for tokens`);try{let r=await n.a({params:t,options:o});if(!r.access_token)throw new e.ProtocolError(`Missing access_token`);await g(r),o.logging?.debug(`Token exchange successful`),u(`loggedIn`,[{idToken:r.id_token,accessToken:r.access_token,refreshToken:r.refresh_token,claims:r.claims}]),o.logging&&(o.logging.xEventId=void 0,o.logging.info(`Login successful`))}catch(e){throw o.logging?.error(`Token exchange failed`,e),e}finally{s.tokenExchange.delete(r)}})();return s.tokenExchange.set(r,a),a}async function x(e){await y();let t=e??globalThis.window?.location.href,r=await o.callbackHandler(t,o.responseMode),i=r.state?await o.stateStorage.get(`sty.${r.state}`):null,a;try{a=i?n.x(i).metadata?.returnTo:void 0}catch{}return await b(r),typeof a==`string`&&a?{returnTo:a}:{}}async function S(c){if(await y(),s.refresh)return s.refresh;if(o.logging?.debug(`Attempting to refresh session`),o.serverSessionUri){await r.redirectUrlHandler(i.appendReturnTo(`${o.authUrlPrefix}/refresh`,c?.returnTo));return}if(typeof a.session?.refresh_token!=`string`){o.logging?.debug(`Refresh called without refresh token`);return}return s.refresh=p(async()=>{let r=await h();if(!r&&!o.serverSessionUri){a.session&&(o.logging?.debug(`Session was cleared by another tab`),a.session=null,u(`sessionCleared`,[]));return}if(r?.access_token&&r.access_token!==a.session?.access_token&&(o.logging?.debug(`Using the session refreshed by another tab`),a.session=r,!t.isSessionExpired(r,o.refreshSkew))){u(`tokenRefreshed`,[{idToken:r.id_token,accessToken:r.access_token,refreshToken:r.refresh_token,claims:r.claims}]);return}if(typeof a.session?.refresh_token==`string`)try{await g(await n.h({refreshToken:a.session.refresh_token,options:o,expectedSub:a.session?.claims?.sub})),u(`tokenRefreshed`,[{idToken:a.session?.id_token,accessToken:a.session?.access_token,refreshToken:a.session?.refresh_token,claims:a.session?.claims}]),o.logging?.debug(`Session refresh successful`)}catch(t){let n=a.session?.refresh_token;throw!(t instanceof e.NetworkError)&&!(t instanceof e.ServerError)&&await _(),u(`tokenRefreshFailed`,[{refreshToken:n}]),o.logging?.error(`Session refresh failed`,t),t}}).finally(()=>{s.refresh=null}),s.refresh}async function C(){return await y(),s.revoke||=(async()=>{try{a.session?.refresh_token?o.logging?.debug(`Attempting to revoke refresh token`):a.session?.access_token&&o.logging?.debug(`Attempting to revoke access token`);let e=await p(async()=>{let e=await h()??a.session;return await _(),e});if(!e?.access_token&&!e?.refresh_token){o.logging?.debug(`Revoke called without session`);return}let t=e.refresh_token?`refresh_token`:`access_token`,r=t===`refresh_token`?e.refresh_token:e.access_token;try{await n.g({tokenTypeHint:t,token:r,options:o}),t===`refresh_token`?(u(`tokenRevoked`,[{token:e.refresh_token,tokenTypeHint:`refresh_token`}]),o.logging?.info(`Refresh token successfully revoked`)):(u(`tokenRevoked`,[{token:e.access_token,tokenTypeHint:`access_token`}]),o.logging?.info(`Access token successfully revoked`))}catch(n){throw t===`refresh_token`?u(`tokenRevokeFailed`,[{token:e.refresh_token,tokenTypeHint:`refresh_token`}]):u(`tokenRevokeFailed`,[{token:e.access_token,tokenTypeHint:`access_token`}]),o.logging?.error(`Token revocation failed`,n),n}}finally{s.revoke=null}})(),s.revoke}async function w(e,t){return await y(),s.logout||=(async()=>{try{o.logging?.debug(`Attempting to logout`);let r=await p(async()=>{let e=await h()??a.session;return await _(),e});if(u(`logoutInitiated`,[{idToken:r?.id_token,claims:r?.claims}]),o.logging?.debug(`Logout initiated`),!r?.id_token){o.logging?.debug(`Logout called without id token`);return}try{let i=await n.p(o),a=n.n({url:i.end_session_endpoint,idToken:r.id_token,postLogoutRedirectUri:e?.postLogoutRedirectUri});await(t??o.urlHandler)(a,e)}catch(e){o.logging?.error(`Unable to redirect to the end-session endpoint`,e)}}finally{s.logout=null}})(),s.logout}return{dispatchEvent:u,subscribeToEvent:d,subscribeToAllEvents:f,getSession:m,updateSession:g,cleanupSession:_,checkAuthentication:v,init:y,tokenExchange:b,handleCallback:x,refresh:S,revoke:C,logout:w}}exports.createBaseFlow=a;
2
2
  //# sourceMappingURL=base.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"base.cjs","names":[],"sources":["../../src/flows/base.ts"],"sourcesContent":["import type { EventFunctions, ExtraRequestArgs, FlowState, SDK, SDKOptions, SessionData } from '../types/oidc';\nimport { buildEndSessionUrl, exchangeCode, getDiscoveryDocument, refreshToken, revokeToken, verifyIdToken } from '../utils/oidc';\nimport { loadSession, serializeSession, isSessionExpired } from '../utils/session';\nimport { ConfigurationError, NetworkError, ProtocolError, ServerError } from '../utils/errors';\n\n/**\n * Creates a base flow for the Strivacity SDK, providing common functionality for managing authentication sessions.\n *\n * @param flowState - The initial state of the flow, including session data and initialization status.\n * @param options - The SDK options, including issuer, clientId, redirectUri, scopes, and storage configuration.\n * @template URLHandlerParams - The type of additional request arguments for URL handling.\n * @returns An object implementing the SDK interface, with methods for initializing the flow, managing sessions, and handling authentication events.\n */\nexport function createBaseFlow<URLHandlerParams extends ExtraRequestArgs = ExtraRequestArgs>(flowState: FlowState, options: SDKOptions) {\n\tconst promises: Record<'init' | 'refresh' | 'revoke' | 'logout', Promise<void> | null> & { tokenExchange: Map<string, Promise<void>> } = {\n\t\tinit: null,\n\t\trefresh: null,\n\t\trevoke: null,\n\t\tlogout: null,\n\t\ttokenExchange: new Map(),\n\t};\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tconst eventCallbacks: Record<keyof EventFunctions, Set<(...args: Array<any>) => Promise<void> | void>> = {\n\t\taccessTokenExpired: new Set(),\n\t\tinit: new Set(),\n\t\tloggedIn: new Set(),\n\t\tsessionUpdated: new Set(),\n\t\tsessionCleared: new Set(),\n\t\tloginInitiated: new Set(),\n\t\tflowInitiated: new Set(),\n\t\tlogoutInitiated: new Set(),\n\t\tsessionLoaded: new Set(),\n\t\ttokenRefreshed: new Set(),\n\t\ttokenRefreshFailed: new Set(),\n\t\ttokenRevoked: new Set(),\n\t\ttokenRevokeFailed: new Set(),\n\t};\n\n\tfunction dispatchEvent<T extends keyof EventFunctions>(eventName: T, args: Parameters<EventFunctions[T]>): void {\n\t\tfor (const fn of eventCallbacks[eventName]) {\n\t\t\tvoid fn(...args);\n\t\t}\n\t}\n\n\tfunction subscribeToEvent<T extends keyof EventFunctions>(\n\t\teventName: T,\n\t\tcallbackFn: (...params: Parameters<EventFunctions[T]>) => Promise<void> | void,\n\t): ReturnType<SDK<URLHandlerParams>['subscribeToEvent']> {\n\t\teventCallbacks[eventName].add(callbackFn);\n\t\treturn { dispose: () => eventCallbacks[eventName].delete(callbackFn) };\n\t}\n\n\tfunction subscribeToAllEvents(callbackFn: (...params: Array<unknown>) => Promise<void> | void): ReturnType<SDK<URLHandlerParams>['subscribeToAllEvents']> {\n\t\tfor (const eventName in eventCallbacks) {\n\t\t\teventCallbacks[eventName as keyof EventFunctions].add(callbackFn);\n\t\t}\n\n\t\treturn {\n\t\t\tdispose: () => {\n\t\t\t\tfor (const eventName in eventCallbacks) {\n\t\t\t\t\teventCallbacks[eventName as keyof EventFunctions].delete(callbackFn);\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tasync function getSession(): Promise<SessionData | null> {\n\t\tawait init();\n\n\t\treturn flowState.session;\n\t}\n\n\tasync function updateSession(newData: SessionData): ReturnType<SDK<URLHandlerParams>['updateSession']> {\n\t\tawait init();\n\n\t\t// NOTE: only unverified callers (e.g. direct API use) need validating here\n\t\tif (newData.id_token && !newData.claims) {\n\t\t\tnewData.claims = await verifyIdToken({ idToken: newData.id_token, options });\n\t\t}\n\n\t\tif (!options.serverSessionUri) {\n\t\t\tawait options.storage.set(options.storageTokenName, serializeSession(newData));\n\t\t}\n\n\t\tflowState.session = newData;\n\n\t\tdispatchEvent('sessionUpdated', [\n\t\t\t{\n\t\t\t\tidToken: flowState.session.id_token,\n\t\t\t\taccessToken: flowState.session.access_token,\n\t\t\t\trefreshToken: flowState.session.refresh_token,\n\t\t\t\tclaims: flowState.session.claims,\n\t\t\t},\n\t\t]);\n\t}\n\n\tasync function cleanupSession(): ReturnType<SDK<URLHandlerParams>['cleanupSession']> {\n\t\tawait init();\n\n\t\tif (!options.serverSessionUri) {\n\t\t\tawait options.storage.delete(options.storageTokenName);\n\t\t}\n\n\t\tflowState.session = null;\n\n\t\tdispatchEvent('sessionCleared', []);\n\t}\n\n\tasync function checkAuthentication(\n\t\tparams: { autoRefresh: boolean } = { autoRefresh: options.autoRefresh },\n\t): ReturnType<SDK<URLHandlerParams>['checkAuthentication']> {\n\t\tif (flowState.session?.access_token && !isSessionExpired(flowState.session)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (params?.autoRefresh && flowState.session?.refresh_token) {\n\t\t\ttry {\n\t\t\t\tawait refresh();\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn !isSessionExpired(flowState.session);\n\t}\n\n\tasync function init(): ReturnType<SDK<URLHandlerParams>['init']> {\n\t\tif (flowState.initialized) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (promises.init) {\n\t\t\treturn promises.init;\n\t\t}\n\n\t\tpromises.init = (async () => {\n\t\t\ttry {\n\t\t\t\tif (!options.issuer) {\n\t\t\t\t\tconst error = new ConfigurationError('Missing option: issuer');\n\t\t\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tif (!options.clientId) {\n\t\t\t\t\tconst error = new ConfigurationError('Missing option: clientId');\n\t\t\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tif (!options.redirectUri) {\n\t\t\t\t\tconst error = new ConfigurationError('Missing option: redirectUri');\n\t\t\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tif (options.scopes && !Array.isArray(options.scopes)) {\n\t\t\t\t\tconst error = new ConfigurationError('Invalid option: scopes');\n\t\t\t\t\toptions.logging?.error('Invalid option provided', error);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\n\t\t\t\tif (!options.serverSessionUri) {\n\t\t\t\t\tflowState.session = loadSession(await options.storage.get(options.storageTokenName));\n\t\t\t\t}\n\n\t\t\t\tflowState.initialized = true;\n\n\t\t\t\tdispatchEvent('init', []);\n\t\t\t\toptions.logging?.debug('SDK initialized');\n\n\t\t\t\tif (!flowState.session && !options.serverSessionUri) {\n\t\t\t\t\toptions.logging?.debug('No session found in storage');\n\t\t\t\t}\n\n\t\t\t\tif (flowState.session?.access_token) {\n\t\t\t\t\tdispatchEvent('sessionLoaded', [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tidToken: flowState.session.id_token,\n\t\t\t\t\t\t\taccessToken: flowState.session.access_token,\n\t\t\t\t\t\t\trefreshToken: flowState.session.refresh_token,\n\t\t\t\t\t\t\tclaims: flowState.session.claims,\n\t\t\t\t\t\t},\n\t\t\t\t\t]);\n\t\t\t\t\toptions.logging?.debug('Session loaded from storage');\n\t\t\t\t}\n\n\t\t\t\tif (flowState.session?.access_token && isSessionExpired(flowState.session)) {\n\t\t\t\t\tdispatchEvent('accessTokenExpired', [{ accessToken: flowState.session.access_token, refreshToken: flowState.session.refresh_token }]);\n\t\t\t\t\toptions.logging?.debug('Access token has expired');\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tpromises.init = null;\n\t\t\t}\n\t\t})();\n\n\t\treturn promises.init;\n\t}\n\n\tasync function tokenExchange(params: Parameters<SDK<URLHandlerParams>['tokenExchange']>[0] = {}): ReturnType<SDK<URLHandlerParams>['tokenExchange']> {\n\t\tawait init();\n\n\t\tconst exchangeKey = params.state ?? '';\n\t\tconst inFlight = promises.tokenExchange.get(exchangeKey);\n\n\t\tif (inFlight) {\n\t\t\treturn inFlight;\n\t\t}\n\n\t\tconst exchangePromise = (async () => {\n\t\t\toptions.logging?.debug('Exchanging authorization code for tokens');\n\n\t\t\ttry {\n\t\t\t\tconst session = await exchangeCode({ params, options });\n\n\t\t\t\tif (!session.access_token) {\n\t\t\t\t\tthrow new ProtocolError('Missing access_token');\n\t\t\t\t}\n\n\t\t\t\tawait updateSession(session);\n\n\t\t\t\toptions.logging?.debug('Token exchange successful');\n\n\t\t\t\tdispatchEvent('loggedIn', [\n\t\t\t\t\t{ idToken: session.id_token, accessToken: session.access_token, refreshToken: session.refresh_token, claims: session.claims },\n\t\t\t\t]);\n\n\t\t\t\tif (options.logging) {\n\t\t\t\t\toptions.logging.xEventId = undefined;\n\t\t\t\t\toptions.logging.info('Login successful');\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\toptions.logging?.error('Token exchange failed', error);\n\t\t\t\tthrow error;\n\t\t\t} finally {\n\t\t\t\tpromises.tokenExchange.delete(exchangeKey);\n\t\t\t}\n\t\t})();\n\n\t\tpromises.tokenExchange.set(exchangeKey, exchangePromise);\n\n\t\treturn exchangePromise;\n\t}\n\n\tasync function handleCallback(url?: string | URL): ReturnType<SDK<URLHandlerParams>['handleCallback']> {\n\t\tawait init();\n\n\t\tconst callbackUrl = url ?? globalThis.window?.location.href;\n\t\tconst params = (await options.callbackHandler(callbackUrl, options.responseMode)) as Record<string, string>;\n\n\t\tawait tokenExchange(params);\n\t}\n\n\tasync function refresh(): ReturnType<SDK<URLHandlerParams>['refresh']> {\n\t\tawait init();\n\n\t\tif (promises.refresh) {\n\t\t\treturn promises.refresh;\n\t\t}\n\n\t\tif (promises.revoke) {\n\t\t\ttry {\n\t\t\t\tawait promises.revoke;\n\t\t\t} catch {}\n\t\t}\n\n\t\tif (promises.logout) {\n\t\t\ttry {\n\t\t\t\tawait promises.logout;\n\t\t\t} catch {}\n\t\t}\n\n\t\toptions.logging?.debug('Attempting to refresh session');\n\n\t\tif (typeof flowState.session?.refresh_token !== 'string') {\n\t\t\toptions.logging?.debug('Refresh called without refresh token');\n\t\t\treturn;\n\t\t}\n\n\t\tpromises.refresh = (async () => {\n\t\t\ttry {\n\t\t\t\tconst session = await refreshToken({ refreshToken: flowState.session!.refresh_token!, options, expectedSub: flowState.session?.claims?.sub });\n\t\t\t\tawait updateSession(session);\n\n\t\t\t\tdispatchEvent('tokenRefreshed', [\n\t\t\t\t\t{\n\t\t\t\t\t\tidToken: flowState.session?.id_token,\n\t\t\t\t\t\taccessToken: flowState.session?.access_token,\n\t\t\t\t\t\trefreshToken: flowState.session?.refresh_token,\n\t\t\t\t\t\tclaims: flowState.session?.claims,\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t\toptions.logging?.debug('Session refresh successful');\n\t\t\t} catch (error) {\n\t\t\t\tconst failedRefreshToken = flowState.session?.refresh_token;\n\n\t\t\t\t// NOTE: Transient Network/Server failures must not destroy a session that could still be refreshed later.\n\t\t\t\tif (!(error instanceof NetworkError) && !(error instanceof ServerError)) {\n\t\t\t\t\tawait cleanupSession();\n\t\t\t\t}\n\n\t\t\t\tdispatchEvent('tokenRefreshFailed', [{ refreshToken: failedRefreshToken }]);\n\t\t\t\toptions.logging?.error('Session refresh failed', error);\n\n\t\t\t\tthrow error;\n\t\t\t} finally {\n\t\t\t\tpromises.refresh = null;\n\t\t\t}\n\t\t})();\n\n\t\treturn promises.refresh;\n\t}\n\n\tasync function revoke(): ReturnType<SDK<URLHandlerParams>['revoke']> {\n\t\tawait init();\n\n\t\tif (promises.revoke) {\n\t\t\treturn promises.revoke;\n\t\t}\n\n\t\tif (promises.refresh) {\n\t\t\ttry {\n\t\t\t\tawait promises.refresh;\n\t\t\t} catch {}\n\t\t}\n\n\t\tif (promises.logout) {\n\t\t\ttry {\n\t\t\t\tawait promises.logout;\n\t\t\t} catch {}\n\t\t}\n\n\t\tpromises.revoke = (async () => {\n\t\t\ttry {\n\t\t\t\tif (flowState.session?.refresh_token) {\n\t\t\t\t\toptions.logging?.debug('Attempting to revoke refresh token');\n\t\t\t\t} else if (flowState.session?.access_token) {\n\t\t\t\t\toptions.logging?.debug('Attempting to revoke access token');\n\t\t\t\t}\n\n\t\t\t\t// NOTE: Cleanup session before revocation\n\t\t\t\tconst currentSession = flowState.session;\n\t\t\t\tawait cleanupSession();\n\n\t\t\t\tif (!currentSession?.access_token && !currentSession?.refresh_token) {\n\t\t\t\t\toptions.logging?.debug('Revoke called without session');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst tokenTypeHint = currentSession.refresh_token ? 'refresh_token' : 'access_token';\n\t\t\t\tconst token = (tokenTypeHint === 'refresh_token' ? currentSession.refresh_token : currentSession.access_token)!;\n\n\t\t\t\ttry {\n\t\t\t\t\tawait revokeToken({ tokenTypeHint, token, options });\n\n\t\t\t\t\tif (tokenTypeHint === 'refresh_token') {\n\t\t\t\t\t\tdispatchEvent('tokenRevoked', [{ token: currentSession.refresh_token, tokenTypeHint: 'refresh_token' }]);\n\t\t\t\t\t\toptions.logging?.info('Refresh token successfully revoked');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdispatchEvent('tokenRevoked', [{ token: currentSession.access_token, tokenTypeHint: 'access_token' }]);\n\t\t\t\t\t\toptions.logging?.info('Access token successfully revoked');\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (tokenTypeHint === 'refresh_token') {\n\t\t\t\t\t\tdispatchEvent('tokenRevokeFailed', [{ token: currentSession.refresh_token, tokenTypeHint: 'refresh_token' }]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdispatchEvent('tokenRevokeFailed', [{ token: currentSession.access_token, tokenTypeHint: 'access_token' }]);\n\t\t\t\t\t}\n\n\t\t\t\t\toptions.logging?.error('Token revocation failed', error);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tpromises.revoke = null;\n\t\t\t}\n\t\t})();\n\n\t\treturn promises.revoke;\n\t}\n\n\tasync function logout(params?: Parameters<SDK<URLHandlerParams>['logout']>[0]): ReturnType<SDK<URLHandlerParams>['logout']> {\n\t\tawait init();\n\n\t\tif (promises.logout) {\n\t\t\treturn promises.logout;\n\t\t}\n\n\t\tif (promises.revoke) {\n\t\t\ttry {\n\t\t\t\tawait promises.revoke;\n\t\t\t} catch {}\n\t\t}\n\n\t\tif (promises.refresh) {\n\t\t\ttry {\n\t\t\t\tawait promises.refresh;\n\t\t\t} catch {}\n\t\t}\n\n\t\tpromises.logout = (async () => {\n\t\t\ttry {\n\t\t\t\toptions.logging?.debug('Attempting to logout');\n\n\t\t\t\t// NOTE: Cleanup session before logout\n\t\t\t\tconst currentSession = flowState.session;\n\t\t\t\tawait cleanupSession();\n\n\t\t\t\tdispatchEvent('logoutInitiated', [{ idToken: currentSession?.id_token, claims: currentSession?.claims }]);\n\t\t\t\toptions.logging?.debug('Logout initiated');\n\n\t\t\t\tif (!currentSession?.id_token) {\n\t\t\t\t\toptions.logging?.debug('Logout called without id token');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst metadata = await getDiscoveryDocument(options);\n\t\t\t\t\tconst logoutUrl = buildEndSessionUrl({\n\t\t\t\t\t\turl: metadata.end_session_endpoint,\n\t\t\t\t\t\tidToken: currentSession.id_token,\n\t\t\t\t\t\tpostLogoutRedirectUri: params?.postLogoutRedirectUri,\n\t\t\t\t\t});\n\n\t\t\t\t\tawait options.urlHandler(logoutUrl, params);\n\t\t\t\t} catch (error) {\n\t\t\t\t\toptions.logging?.error('Unable to redirect to the end-session endpoint', error);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tpromises.logout = null;\n\t\t\t}\n\t\t})();\n\n\t\treturn promises.logout;\n\t}\n\n\treturn {\n\t\tdispatchEvent,\n\t\tsubscribeToEvent,\n\t\tsubscribeToAllEvents,\n\t\tgetSession,\n\t\tupdateSession,\n\t\tcleanupSession,\n\t\tcheckAuthentication,\n\t\tinit,\n\t\ttokenExchange,\n\t\thandleCallback,\n\t\trefresh,\n\t\trevoke,\n\t\tlogout,\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"base.cjs","names":[],"sources":["../../src/flows/base.ts"],"sourcesContent":["import type { EventFunctions, ExtraRequestArgs, FlowState, SDK, SDKOptions, SessionData } from '../types/oidc';\nimport { buildEndSessionUrl, exchangeCode, getDiscoveryDocument, refreshToken, revokeToken, verifyIdToken } from '../utils/oidc';\nimport { loadSession, serializeSession, isSessionExpired } from '../utils/session';\nimport { parseState } from '../utils/state';\nimport { appendReturnTo } from '../utils/path';\nimport { ConfigurationError, NetworkError, ProtocolError, ServerError } from '../utils/errors';\nimport { redirectUrlHandler } from '../handlers/redirect';\n\n/**\n * Creates a base flow for the Strivacity SDK, providing common functionality for managing authentication sessions.\n *\n * @param flowState - The initial state of the flow, including session data and initialization status.\n * @param options - The SDK options, including issuer, clientId, redirectUri, scopes, and storage configuration.\n * @template URLHandlerParams - The type of additional request arguments for URL handling.\n * @returns An object implementing the SDK interface, with methods for initializing the flow, managing sessions, and handling authentication events.\n */\nexport function createBaseFlow<URLHandlerParams extends ExtraRequestArgs = ExtraRequestArgs>(flowState: FlowState, options: SDKOptions) {\n\tconst promises: Record<'init' | 'refresh' | 'revoke' | 'logout', Promise<void> | null> & { tokenExchange: Map<string, Promise<void>> } = {\n\t\tinit: null,\n\t\trefresh: null,\n\t\trevoke: null,\n\t\tlogout: null,\n\t\ttokenExchange: new Map(),\n\t};\n\tlet localSessionLock: Promise<unknown> = Promise.resolve();\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tconst eventCallbacks: Record<keyof EventFunctions, Set<(...args: Array<any>) => Promise<void> | void>> = {\n\t\taccessTokenExpired: new Set(),\n\t\tinit: new Set(),\n\t\tloggedIn: new Set(),\n\t\tsessionUpdated: new Set(),\n\t\tsessionCleared: new Set(),\n\t\tloginInitiated: new Set(),\n\t\tflowInitiated: new Set(),\n\t\tlogoutInitiated: new Set(),\n\t\tsessionLoaded: new Set(),\n\t\ttokenRefreshed: new Set(),\n\t\ttokenRefreshFailed: new Set(),\n\t\ttokenRevoked: new Set(),\n\t\ttokenRevokeFailed: new Set(),\n\t};\n\n\tfunction dispatchEvent<T extends keyof EventFunctions>(eventName: T, args: Parameters<EventFunctions[T]>): void {\n\t\tfor (const fn of eventCallbacks[eventName]) {\n\t\t\tvoid fn(...args);\n\t\t}\n\t}\n\n\tfunction subscribeToEvent<T extends keyof EventFunctions>(\n\t\teventName: T,\n\t\tcallbackFn: (...params: Parameters<EventFunctions[T]>) => Promise<void> | void,\n\t): ReturnType<SDK<URLHandlerParams>['subscribeToEvent']> {\n\t\teventCallbacks[eventName].add(callbackFn);\n\t\treturn { dispose: () => eventCallbacks[eventName].delete(callbackFn) };\n\t}\n\n\tfunction subscribeToAllEvents(callbackFn: (...params: Array<unknown>) => Promise<void> | void): ReturnType<SDK<URLHandlerParams>['subscribeToAllEvents']> {\n\t\tfor (const eventName in eventCallbacks) {\n\t\t\teventCallbacks[eventName as keyof EventFunctions].add(callbackFn);\n\t\t}\n\n\t\treturn {\n\t\t\tdispose: () => {\n\t\t\t\tfor (const eventName in eventCallbacks) {\n\t\t\t\t\teventCallbacks[eventName as keyof EventFunctions].delete(callbackFn);\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tfunction withSessionLock<T>(fn: () => Promise<T>): Promise<T> {\n\t\tconst locks = globalThis.window ? (globalThis.navigator as Navigator | undefined)?.locks : undefined;\n\n\t\tif (locks) {\n\t\t\treturn locks.request(`strivacity.session.${options.clientId}.${options.storageTokenName}`, fn);\n\t\t}\n\n\t\t// NOTE: in-process fallback of the session lock where the Web Locks API is not available\n\t\tconst result = localSessionLock.then(fn);\n\t\tlocalSessionLock = result.catch(() => {});\n\n\t\treturn result;\n\t}\n\n\tasync function getSession(): Promise<SessionData | null> {\n\t\tawait init();\n\n\t\treturn flowState.session;\n\t}\n\n\tasync function loadStoredSession(): Promise<SessionData | null> {\n\t\tif (options.serverSessionUri) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn loadSession(await options.storage.get(options.storageTokenName));\n\t}\n\n\tasync function updateSession(newData: SessionData): ReturnType<SDK<URLHandlerParams>['updateSession']> {\n\t\tawait init();\n\n\t\t// NOTE: only unverified callers (e.g. direct API use) need validating here\n\t\tif (newData.id_token && !newData.claims) {\n\t\t\tnewData.claims = await verifyIdToken({ idToken: newData.id_token, options });\n\t\t}\n\n\t\tif (!options.serverSessionUri) {\n\t\t\tawait options.storage.set(options.storageTokenName, serializeSession(newData));\n\t\t}\n\n\t\tflowState.session = newData;\n\n\t\tdispatchEvent('sessionUpdated', [\n\t\t\t{\n\t\t\t\tidToken: flowState.session.id_token,\n\t\t\t\taccessToken: flowState.session.access_token,\n\t\t\t\trefreshToken: flowState.session.refresh_token,\n\t\t\t\tclaims: flowState.session.claims,\n\t\t\t},\n\t\t]);\n\t}\n\n\tasync function cleanupSession(): ReturnType<SDK<URLHandlerParams>['cleanupSession']> {\n\t\tawait init();\n\n\t\tif (!options.serverSessionUri) {\n\t\t\tawait options.storage.delete(options.storageTokenName);\n\t\t}\n\n\t\tflowState.session = null;\n\n\t\tdispatchEvent('sessionCleared', []);\n\t}\n\n\tasync function checkAuthentication(\n\t\tparams: { autoRefresh: boolean } = { autoRefresh: options.autoRefresh },\n\t): ReturnType<SDK<URLHandlerParams>['checkAuthentication']> {\n\t\tawait init();\n\n\t\tif (flowState.session?.access_token && !isSessionExpired(flowState.session, options.refreshSkew)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (params?.autoRefresh && flowState.session?.refresh_token && !options.serverSessionUri) {\n\t\t\ttry {\n\t\t\t\tawait refresh();\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn !isSessionExpired(flowState.session);\n\t}\n\n\tasync function init(): ReturnType<SDK<URLHandlerParams>['init']> {\n\t\tif (flowState.initialized) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (promises.init) {\n\t\t\treturn promises.init;\n\t\t}\n\n\t\tpromises.init = (async () => {\n\t\t\ttry {\n\t\t\t\tif (!options.issuer) {\n\t\t\t\t\tconst error = new ConfigurationError('Missing option: issuer');\n\t\t\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tif (!options.clientId) {\n\t\t\t\t\tconst error = new ConfigurationError('Missing option: clientId');\n\t\t\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tif (!options.redirectUri) {\n\t\t\t\t\tconst error = new ConfigurationError('Missing option: redirectUri');\n\t\t\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tif (options.scopes && !Array.isArray(options.scopes)) {\n\t\t\t\t\tconst error = new ConfigurationError('Invalid option: scopes');\n\t\t\t\t\toptions.logging?.error('Invalid option provided', error);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\n\t\t\t\tif (!options.serverSessionUri) {\n\t\t\t\t\tflowState.session = loadSession(await options.storage.get(options.storageTokenName));\n\t\t\t\t}\n\n\t\t\t\tflowState.initialized = true;\n\n\t\t\t\tdispatchEvent('init', []);\n\t\t\t\toptions.logging?.debug('SDK initialized');\n\n\t\t\t\tif (!flowState.session && !options.serverSessionUri) {\n\t\t\t\t\toptions.logging?.debug('No session found in storage');\n\t\t\t\t}\n\n\t\t\t\tif (flowState.session?.access_token) {\n\t\t\t\t\tdispatchEvent('sessionLoaded', [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tidToken: flowState.session.id_token,\n\t\t\t\t\t\t\taccessToken: flowState.session.access_token,\n\t\t\t\t\t\t\trefreshToken: flowState.session.refresh_token,\n\t\t\t\t\t\t\tclaims: flowState.session.claims,\n\t\t\t\t\t\t},\n\t\t\t\t\t]);\n\t\t\t\t\toptions.logging?.debug('Session loaded from storage');\n\t\t\t\t}\n\n\t\t\t\tif (flowState.session?.access_token && isSessionExpired(flowState.session)) {\n\t\t\t\t\tdispatchEvent('accessTokenExpired', [{ accessToken: flowState.session.access_token, refreshToken: flowState.session.refresh_token }]);\n\t\t\t\t\toptions.logging?.debug('Access token has expired');\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tpromises.init = null;\n\t\t\t}\n\t\t})();\n\n\t\treturn promises.init;\n\t}\n\n\tasync function tokenExchange(params: Parameters<SDK<URLHandlerParams>['tokenExchange']>[0] = {}): ReturnType<SDK<URLHandlerParams>['tokenExchange']> {\n\t\tawait init();\n\n\t\tconst exchangeKey = params.state ?? '';\n\t\tconst inFlight = promises.tokenExchange.get(exchangeKey);\n\n\t\tif (inFlight) {\n\t\t\treturn inFlight;\n\t\t}\n\n\t\tconst exchangePromise = (async () => {\n\t\t\toptions.logging?.debug('Exchanging authorization code for tokens');\n\n\t\t\ttry {\n\t\t\t\tconst session = await exchangeCode({ params, options });\n\n\t\t\t\tif (!session.access_token) {\n\t\t\t\t\tthrow new ProtocolError('Missing access_token');\n\t\t\t\t}\n\n\t\t\t\tawait updateSession(session);\n\n\t\t\t\toptions.logging?.debug('Token exchange successful');\n\n\t\t\t\tdispatchEvent('loggedIn', [\n\t\t\t\t\t{ idToken: session.id_token, accessToken: session.access_token, refreshToken: session.refresh_token, claims: session.claims },\n\t\t\t\t]);\n\n\t\t\t\tif (options.logging) {\n\t\t\t\t\toptions.logging.xEventId = undefined;\n\t\t\t\t\toptions.logging.info('Login successful');\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\toptions.logging?.error('Token exchange failed', error);\n\t\t\t\tthrow error;\n\t\t\t} finally {\n\t\t\t\tpromises.tokenExchange.delete(exchangeKey);\n\t\t\t}\n\t\t})();\n\n\t\tpromises.tokenExchange.set(exchangeKey, exchangePromise);\n\n\t\treturn exchangePromise;\n\t}\n\n\tasync function handleCallback(url?: string | URL): ReturnType<SDK<URLHandlerParams>['handleCallback']> {\n\t\tawait init();\n\n\t\tconst callbackUrl = url ?? globalThis.window?.location.href;\n\t\tconst params = (await options.callbackHandler(callbackUrl, options.responseMode)) as Record<string, string>;\n\t\t// NOTE: read before the exchange, which deletes the state\n\t\tconst serializedState = params.state ? await options.stateStorage.get(`sty.${params.state}`) : null;\n\t\tlet returnTo: unknown;\n\n\t\ttry {\n\t\t\treturnTo = serializedState ? parseState(serializedState).metadata?.returnTo : undefined;\n\t\t} catch {\n\t\t\t// NOTE: an unparsable state has no returnTo\n\t\t}\n\n\t\tawait tokenExchange(params);\n\n\t\treturn typeof returnTo === 'string' && returnTo ? { returnTo } : {};\n\t}\n\n\tasync function refresh(params?: { returnTo?: string }): ReturnType<SDK<URLHandlerParams>['refresh']> {\n\t\tawait init();\n\n\t\tif (promises.refresh) {\n\t\t\treturn promises.refresh;\n\t\t}\n\n\t\toptions.logging?.debug('Attempting to refresh session');\n\n\t\t// NOTE: with server-managed sessions the server owns the refresh token: let its refresh route rotate the cookie and come back\n\t\tif (options.serverSessionUri) {\n\t\t\tawait redirectUrlHandler(appendReturnTo(`${options.authUrlPrefix}/refresh`, params?.returnTo));\n\t\t\treturn;\n\t\t}\n\n\t\tif (typeof flowState.session?.refresh_token !== 'string') {\n\t\t\toptions.logging?.debug('Refresh called without refresh token');\n\t\t\treturn;\n\t\t}\n\n\t\tpromises.refresh = withSessionLock(async () => {\n\t\t\tconst stored = await loadStoredSession();\n\n\t\t\tif (!stored && !options.serverSessionUri) {\n\t\t\t\tif (flowState.session) {\n\t\t\t\t\toptions.logging?.debug('Session was cleared by another tab');\n\t\t\t\t\tflowState.session = null;\n\t\t\t\t\tdispatchEvent('sessionCleared', []);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (stored?.access_token && stored.access_token !== flowState.session?.access_token) {\n\t\t\t\toptions.logging?.debug('Using the session refreshed by another tab');\n\t\t\t\tflowState.session = stored;\n\n\t\t\t\tif (!isSessionExpired(stored, options.refreshSkew)) {\n\t\t\t\t\tdispatchEvent('tokenRefreshed', [\n\t\t\t\t\t\t{ idToken: stored.id_token, accessToken: stored.access_token, refreshToken: stored.refresh_token, claims: stored.claims },\n\t\t\t\t\t]);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (typeof flowState.session?.refresh_token !== 'string') {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst session = await refreshToken({ refreshToken: flowState.session.refresh_token, options, expectedSub: flowState.session?.claims?.sub });\n\t\t\t\tawait updateSession(session);\n\n\t\t\t\tdispatchEvent('tokenRefreshed', [\n\t\t\t\t\t{\n\t\t\t\t\t\tidToken: flowState.session?.id_token,\n\t\t\t\t\t\taccessToken: flowState.session?.access_token,\n\t\t\t\t\t\trefreshToken: flowState.session?.refresh_token,\n\t\t\t\t\t\tclaims: flowState.session?.claims,\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t\toptions.logging?.debug('Session refresh successful');\n\t\t\t} catch (error) {\n\t\t\t\tconst failedRefreshToken = flowState.session?.refresh_token;\n\n\t\t\t\t// NOTE: Transient Network/Server failures must not destroy a session that could still be refreshed later.\n\t\t\t\tif (!(error instanceof NetworkError) && !(error instanceof ServerError)) {\n\t\t\t\t\tawait cleanupSession();\n\t\t\t\t}\n\n\t\t\t\tdispatchEvent('tokenRefreshFailed', [{ refreshToken: failedRefreshToken }]);\n\t\t\t\toptions.logging?.error('Session refresh failed', error);\n\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}).finally(() => {\n\t\t\tpromises.refresh = null;\n\t\t});\n\n\t\treturn promises.refresh;\n\t}\n\n\tasync function revoke(): ReturnType<SDK<URLHandlerParams>['revoke']> {\n\t\tawait init();\n\n\t\tif (promises.revoke) {\n\t\t\treturn promises.revoke;\n\t\t}\n\n\t\tpromises.revoke = (async () => {\n\t\t\ttry {\n\t\t\t\tif (flowState.session?.refresh_token) {\n\t\t\t\t\toptions.logging?.debug('Attempting to revoke refresh token');\n\t\t\t\t} else if (flowState.session?.access_token) {\n\t\t\t\t\toptions.logging?.debug('Attempting to revoke access token');\n\t\t\t\t}\n\n\t\t\t\t// NOTE: Cleanup session before revocation\n\t\t\t\tconst currentSession = await withSessionLock(async () => {\n\t\t\t\t\tconst currentSession = (await loadStoredSession()) ?? flowState.session;\n\t\t\t\t\tawait cleanupSession();\n\n\t\t\t\t\treturn currentSession;\n\t\t\t\t});\n\n\t\t\t\tif (!currentSession?.access_token && !currentSession?.refresh_token) {\n\t\t\t\t\toptions.logging?.debug('Revoke called without session');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst tokenTypeHint = currentSession.refresh_token ? 'refresh_token' : 'access_token';\n\t\t\t\tconst token = (tokenTypeHint === 'refresh_token' ? currentSession.refresh_token : currentSession.access_token)!;\n\n\t\t\t\ttry {\n\t\t\t\t\tawait revokeToken({ tokenTypeHint, token, options });\n\n\t\t\t\t\tif (tokenTypeHint === 'refresh_token') {\n\t\t\t\t\t\tdispatchEvent('tokenRevoked', [{ token: currentSession.refresh_token, tokenTypeHint: 'refresh_token' }]);\n\t\t\t\t\t\toptions.logging?.info('Refresh token successfully revoked');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdispatchEvent('tokenRevoked', [{ token: currentSession.access_token, tokenTypeHint: 'access_token' }]);\n\t\t\t\t\t\toptions.logging?.info('Access token successfully revoked');\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (tokenTypeHint === 'refresh_token') {\n\t\t\t\t\t\tdispatchEvent('tokenRevokeFailed', [{ token: currentSession.refresh_token, tokenTypeHint: 'refresh_token' }]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdispatchEvent('tokenRevokeFailed', [{ token: currentSession.access_token, tokenTypeHint: 'access_token' }]);\n\t\t\t\t\t}\n\n\t\t\t\t\toptions.logging?.error('Token revocation failed', error);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tpromises.revoke = null;\n\t\t\t}\n\t\t})();\n\n\t\treturn promises.revoke;\n\t}\n\n\tasync function logout(\n\t\tparams?: Parameters<SDK<URLHandlerParams>['logout']>[0],\n\t\turlHandlerOverride?: typeof options.urlHandler,\n\t): ReturnType<SDK<URLHandlerParams>['logout']> {\n\t\tawait init();\n\n\t\tif (promises.logout) {\n\t\t\treturn promises.logout;\n\t\t}\n\n\t\tpromises.logout = (async () => {\n\t\t\ttry {\n\t\t\t\toptions.logging?.debug('Attempting to logout');\n\n\t\t\t\t// NOTE: Cleanup session before logout\n\t\t\t\tconst currentSession = await withSessionLock(async () => {\n\t\t\t\t\tconst currentSession = (await loadStoredSession()) ?? flowState.session;\n\t\t\t\t\tawait cleanupSession();\n\n\t\t\t\t\treturn currentSession;\n\t\t\t\t});\n\n\t\t\t\tdispatchEvent('logoutInitiated', [{ idToken: currentSession?.id_token, claims: currentSession?.claims }]);\n\t\t\t\toptions.logging?.debug('Logout initiated');\n\n\t\t\t\tif (!currentSession?.id_token) {\n\t\t\t\t\toptions.logging?.debug('Logout called without id token');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst metadata = await getDiscoveryDocument(options);\n\t\t\t\t\tconst logoutUrl = buildEndSessionUrl({\n\t\t\t\t\t\turl: metadata.end_session_endpoint,\n\t\t\t\t\t\tidToken: currentSession.id_token,\n\t\t\t\t\t\tpostLogoutRedirectUri: params?.postLogoutRedirectUri,\n\t\t\t\t\t});\n\t\t\t\t\tconst urlHandler = urlHandlerOverride ?? options.urlHandler;\n\n\t\t\t\t\tawait urlHandler(logoutUrl, params);\n\t\t\t\t} catch (error) {\n\t\t\t\t\toptions.logging?.error('Unable to redirect to the end-session endpoint', error);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tpromises.logout = null;\n\t\t\t}\n\t\t})();\n\n\t\treturn promises.logout;\n\t}\n\n\treturn {\n\t\tdispatchEvent,\n\t\tsubscribeToEvent,\n\t\tsubscribeToAllEvents,\n\t\tgetSession,\n\t\tupdateSession,\n\t\tcleanupSession,\n\t\tcheckAuthentication,\n\t\tinit,\n\t\ttokenExchange,\n\t\thandleCallback,\n\t\trefresh,\n\t\trevoke,\n\t\tlogout,\n\t};\n}\n"],"mappings":"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"}
@@ -20,7 +20,9 @@ export declare function createBaseFlow<URLHandlerParams extends ExtraRequestArgs
20
20
  init: () => ReturnType<SDK<URLHandlerParams>["init"]>;
21
21
  tokenExchange: (params?: Parameters<SDK<URLHandlerParams>["tokenExchange"]>[0]) => ReturnType<SDK<URLHandlerParams>["tokenExchange"]>;
22
22
  handleCallback: (url?: string | URL) => ReturnType<SDK<URLHandlerParams>["handleCallback"]>;
23
- refresh: () => ReturnType<SDK<URLHandlerParams>["refresh"]>;
23
+ refresh: (params?: {
24
+ returnTo?: string;
25
+ }) => ReturnType<SDK<URLHandlerParams>["refresh"]>;
24
26
  revoke: () => ReturnType<SDK<URLHandlerParams>["revoke"]>;
25
- logout: (params?: Parameters<SDK<URLHandlerParams>["logout"]>[0]) => ReturnType<SDK<URLHandlerParams>["logout"]>;
27
+ logout: (params?: Parameters<SDK<URLHandlerParams>["logout"]>[0], urlHandlerOverride?: typeof options.urlHandler) => ReturnType<SDK<URLHandlerParams>["logout"]>;
26
28
  };
@@ -1,2 +1,2 @@
1
- import{ConfigurationError as e,NetworkError as t,ProtocolError as n,ServerError as r}from"../utils/errors.mjs";import{isSessionExpired as i,loadSession as a,serializeSession as o}from"../utils/session.mjs";import{a as s,g as c,h as l,n as u,p as d,v as f}from"../assets/oidc.mjs";function p(p,m){let h={init:null,refresh:null,revoke:null,logout:null,tokenExchange:new Map},g={accessTokenExpired:new Set,init:new Set,loggedIn:new Set,sessionUpdated:new Set,sessionCleared:new Set,loginInitiated:new Set,flowInitiated:new Set,logoutInitiated:new Set,sessionLoaded:new Set,tokenRefreshed:new Set,tokenRefreshFailed:new Set,tokenRevoked:new Set,tokenRevokeFailed:new Set};function _(e,t){for(let n of g[e])n(...t)}function v(e,t){return g[e].add(t),{dispose:()=>g[e].delete(t)}}function y(e){for(let t in g)g[t].add(e);return{dispose:()=>{for(let t in g)g[t].delete(e)}}}async function b(){return await w(),p.session}async function x(e){await w(),e.id_token&&!e.claims&&(e.claims=await f({idToken:e.id_token,options:m})),m.serverSessionUri||await m.storage.set(m.storageTokenName,o(e)),p.session=e,_(`sessionUpdated`,[{idToken:p.session.id_token,accessToken:p.session.access_token,refreshToken:p.session.refresh_token,claims:p.session.claims}])}async function S(){await w(),m.serverSessionUri||await m.storage.delete(m.storageTokenName),p.session=null,_(`sessionCleared`,[])}async function C(e={autoRefresh:m.autoRefresh}){if(p.session?.access_token&&!i(p.session))return!0;if(e?.autoRefresh&&p.session?.refresh_token)try{await D()}catch{return!1}return!i(p.session)}async function w(){if(!p.initialized)return h.init||=(async()=>{try{if(!m.issuer){let t=new e(`Missing option: issuer`);throw m.logging?.error(`Required option missing`,t),t}if(!m.clientId){let t=new e(`Missing option: clientId`);throw m.logging?.error(`Required option missing`,t),t}if(!m.redirectUri){let t=new e(`Missing option: redirectUri`);throw m.logging?.error(`Required option missing`,t),t}if(m.scopes&&!Array.isArray(m.scopes)){let t=new e(`Invalid option: scopes`);throw m.logging?.error(`Invalid option provided`,t),t}m.serverSessionUri||(p.session=a(await m.storage.get(m.storageTokenName))),p.initialized=!0,_(`init`,[]),m.logging?.debug(`SDK initialized`),!p.session&&!m.serverSessionUri&&m.logging?.debug(`No session found in storage`),p.session?.access_token&&(_(`sessionLoaded`,[{idToken:p.session.id_token,accessToken:p.session.access_token,refreshToken:p.session.refresh_token,claims:p.session.claims}]),m.logging?.debug(`Session loaded from storage`)),p.session?.access_token&&i(p.session)&&(_(`accessTokenExpired`,[{accessToken:p.session.access_token,refreshToken:p.session.refresh_token}]),m.logging?.debug(`Access token has expired`))}finally{h.init=null}})(),h.init}async function T(e={}){await w();let t=e.state??``,r=h.tokenExchange.get(t);if(r)return r;let i=(async()=>{m.logging?.debug(`Exchanging authorization code for tokens`);try{let t=await s({params:e,options:m});if(!t.access_token)throw new n(`Missing access_token`);await x(t),m.logging?.debug(`Token exchange successful`),_(`loggedIn`,[{idToken:t.id_token,accessToken:t.access_token,refreshToken:t.refresh_token,claims:t.claims}]),m.logging&&(m.logging.xEventId=void 0,m.logging.info(`Login successful`))}catch(e){throw m.logging?.error(`Token exchange failed`,e),e}finally{h.tokenExchange.delete(t)}})();return h.tokenExchange.set(t,i),i}async function E(e){await w();let t=e??globalThis.window?.location.href;await T(await m.callbackHandler(t,m.responseMode))}async function D(){if(await w(),h.refresh)return h.refresh;if(h.revoke)try{await h.revoke}catch{}if(h.logout)try{await h.logout}catch{}if(m.logging?.debug(`Attempting to refresh session`),typeof p.session?.refresh_token!=`string`){m.logging?.debug(`Refresh called without refresh token`);return}return h.refresh=(async()=>{try{await x(await l({refreshToken:p.session.refresh_token,options:m,expectedSub:p.session?.claims?.sub})),_(`tokenRefreshed`,[{idToken:p.session?.id_token,accessToken:p.session?.access_token,refreshToken:p.session?.refresh_token,claims:p.session?.claims}]),m.logging?.debug(`Session refresh successful`)}catch(e){let n=p.session?.refresh_token;throw!(e instanceof t)&&!(e instanceof r)&&await S(),_(`tokenRefreshFailed`,[{refreshToken:n}]),m.logging?.error(`Session refresh failed`,e),e}finally{h.refresh=null}})(),h.refresh}async function O(){if(await w(),h.revoke)return h.revoke;if(h.refresh)try{await h.refresh}catch{}if(h.logout)try{await h.logout}catch{}return h.revoke=(async()=>{try{p.session?.refresh_token?m.logging?.debug(`Attempting to revoke refresh token`):p.session?.access_token&&m.logging?.debug(`Attempting to revoke access token`);let e=p.session;if(await S(),!e?.access_token&&!e?.refresh_token){m.logging?.debug(`Revoke called without session`);return}let t=e.refresh_token?`refresh_token`:`access_token`,n=t===`refresh_token`?e.refresh_token:e.access_token;try{await c({tokenTypeHint:t,token:n,options:m}),t===`refresh_token`?(_(`tokenRevoked`,[{token:e.refresh_token,tokenTypeHint:`refresh_token`}]),m.logging?.info(`Refresh token successfully revoked`)):(_(`tokenRevoked`,[{token:e.access_token,tokenTypeHint:`access_token`}]),m.logging?.info(`Access token successfully revoked`))}catch(n){throw t===`refresh_token`?_(`tokenRevokeFailed`,[{token:e.refresh_token,tokenTypeHint:`refresh_token`}]):_(`tokenRevokeFailed`,[{token:e.access_token,tokenTypeHint:`access_token`}]),m.logging?.error(`Token revocation failed`,n),n}}finally{h.revoke=null}})(),h.revoke}async function k(e){if(await w(),h.logout)return h.logout;if(h.revoke)try{await h.revoke}catch{}if(h.refresh)try{await h.refresh}catch{}return h.logout=(async()=>{try{m.logging?.debug(`Attempting to logout`);let t=p.session;if(await S(),_(`logoutInitiated`,[{idToken:t?.id_token,claims:t?.claims}]),m.logging?.debug(`Logout initiated`),!t?.id_token){m.logging?.debug(`Logout called without id token`);return}try{let n=await d(m),r=u({url:n.end_session_endpoint,idToken:t.id_token,postLogoutRedirectUri:e?.postLogoutRedirectUri});await m.urlHandler(r,e)}catch(e){m.logging?.error(`Unable to redirect to the end-session endpoint`,e)}}finally{h.logout=null}})(),h.logout}return{dispatchEvent:_,subscribeToEvent:v,subscribeToAllEvents:y,getSession:b,updateSession:x,cleanupSession:S,checkAuthentication:C,init:w,tokenExchange:T,handleCallback:E,refresh:D,revoke:O,logout:k}}export{p as createBaseFlow};
1
+ import{ConfigurationError as e,NetworkError as t,ProtocolError as n,ServerError as r}from"../utils/errors.mjs";import{isSessionExpired as i,loadSession as a,serializeSession as o}from"../utils/session.mjs";import{a as s,g as c,h as l,n as u,p as d,v as f,x as p}from"../assets/oidc.mjs";import{redirectUrlHandler as m}from"../handlers/redirect.mjs";import{appendReturnTo as h}from"../utils/path.mjs";function g(g,_){let v={init:null,refresh:null,revoke:null,logout:null,tokenExchange:new Map},y=Promise.resolve(),b={accessTokenExpired:new Set,init:new Set,loggedIn:new Set,sessionUpdated:new Set,sessionCleared:new Set,loginInitiated:new Set,flowInitiated:new Set,logoutInitiated:new Set,sessionLoaded:new Set,tokenRefreshed:new Set,tokenRefreshFailed:new Set,tokenRevoked:new Set,tokenRevokeFailed:new Set};function x(e,t){for(let n of b[e])n(...t)}function S(e,t){return b[e].add(t),{dispose:()=>b[e].delete(t)}}function C(e){for(let t in b)b[t].add(e);return{dispose:()=>{for(let t in b)b[t].delete(e)}}}function w(e){let t=globalThis.window?globalThis.navigator?.locks:void 0;if(t)return t.request(`strivacity.session.${_.clientId}.${_.storageTokenName}`,e);let n=y.then(e);return y=n.catch(()=>{}),n}async function T(){return await A(),g.session}async function E(){return _.serverSessionUri?null:a(await _.storage.get(_.storageTokenName))}async function D(e){await A(),e.id_token&&!e.claims&&(e.claims=await f({idToken:e.id_token,options:_})),_.serverSessionUri||await _.storage.set(_.storageTokenName,o(e)),g.session=e,x(`sessionUpdated`,[{idToken:g.session.id_token,accessToken:g.session.access_token,refreshToken:g.session.refresh_token,claims:g.session.claims}])}async function O(){await A(),_.serverSessionUri||await _.storage.delete(_.storageTokenName),g.session=null,x(`sessionCleared`,[])}async function k(e={autoRefresh:_.autoRefresh}){if(await A(),g.session?.access_token&&!i(g.session,_.refreshSkew))return!0;if(e?.autoRefresh&&g.session?.refresh_token&&!_.serverSessionUri)try{await N()}catch{return!1}return!i(g.session)}async function A(){if(!g.initialized)return v.init||=(async()=>{try{if(!_.issuer){let t=new e(`Missing option: issuer`);throw _.logging?.error(`Required option missing`,t),t}if(!_.clientId){let t=new e(`Missing option: clientId`);throw _.logging?.error(`Required option missing`,t),t}if(!_.redirectUri){let t=new e(`Missing option: redirectUri`);throw _.logging?.error(`Required option missing`,t),t}if(_.scopes&&!Array.isArray(_.scopes)){let t=new e(`Invalid option: scopes`);throw _.logging?.error(`Invalid option provided`,t),t}_.serverSessionUri||(g.session=a(await _.storage.get(_.storageTokenName))),g.initialized=!0,x(`init`,[]),_.logging?.debug(`SDK initialized`),!g.session&&!_.serverSessionUri&&_.logging?.debug(`No session found in storage`),g.session?.access_token&&(x(`sessionLoaded`,[{idToken:g.session.id_token,accessToken:g.session.access_token,refreshToken:g.session.refresh_token,claims:g.session.claims}]),_.logging?.debug(`Session loaded from storage`)),g.session?.access_token&&i(g.session)&&(x(`accessTokenExpired`,[{accessToken:g.session.access_token,refreshToken:g.session.refresh_token}]),_.logging?.debug(`Access token has expired`))}finally{v.init=null}})(),v.init}async function j(e={}){await A();let t=e.state??``,r=v.tokenExchange.get(t);if(r)return r;let i=(async()=>{_.logging?.debug(`Exchanging authorization code for tokens`);try{let t=await s({params:e,options:_});if(!t.access_token)throw new n(`Missing access_token`);await D(t),_.logging?.debug(`Token exchange successful`),x(`loggedIn`,[{idToken:t.id_token,accessToken:t.access_token,refreshToken:t.refresh_token,claims:t.claims}]),_.logging&&(_.logging.xEventId=void 0,_.logging.info(`Login successful`))}catch(e){throw _.logging?.error(`Token exchange failed`,e),e}finally{v.tokenExchange.delete(t)}})();return v.tokenExchange.set(t,i),i}async function M(e){await A();let t=e??globalThis.window?.location.href,n=await _.callbackHandler(t,_.responseMode),r=n.state?await _.stateStorage.get(`sty.${n.state}`):null,i;try{i=r?p(r).metadata?.returnTo:void 0}catch{}return await j(n),typeof i==`string`&&i?{returnTo:i}:{}}async function N(e){if(await A(),v.refresh)return v.refresh;if(_.logging?.debug(`Attempting to refresh session`),_.serverSessionUri){await m(h(`${_.authUrlPrefix}/refresh`,e?.returnTo));return}if(typeof g.session?.refresh_token!=`string`){_.logging?.debug(`Refresh called without refresh token`);return}return v.refresh=w(async()=>{let e=await E();if(!e&&!_.serverSessionUri){g.session&&(_.logging?.debug(`Session was cleared by another tab`),g.session=null,x(`sessionCleared`,[]));return}if(e?.access_token&&e.access_token!==g.session?.access_token&&(_.logging?.debug(`Using the session refreshed by another tab`),g.session=e,!i(e,_.refreshSkew))){x(`tokenRefreshed`,[{idToken:e.id_token,accessToken:e.access_token,refreshToken:e.refresh_token,claims:e.claims}]);return}if(typeof g.session?.refresh_token==`string`)try{await D(await l({refreshToken:g.session.refresh_token,options:_,expectedSub:g.session?.claims?.sub})),x(`tokenRefreshed`,[{idToken:g.session?.id_token,accessToken:g.session?.access_token,refreshToken:g.session?.refresh_token,claims:g.session?.claims}]),_.logging?.debug(`Session refresh successful`)}catch(e){let n=g.session?.refresh_token;throw!(e instanceof t)&&!(e instanceof r)&&await O(),x(`tokenRefreshFailed`,[{refreshToken:n}]),_.logging?.error(`Session refresh failed`,e),e}}).finally(()=>{v.refresh=null}),v.refresh}async function P(){return await A(),v.revoke||=(async()=>{try{g.session?.refresh_token?_.logging?.debug(`Attempting to revoke refresh token`):g.session?.access_token&&_.logging?.debug(`Attempting to revoke access token`);let e=await w(async()=>{let e=await E()??g.session;return await O(),e});if(!e?.access_token&&!e?.refresh_token){_.logging?.debug(`Revoke called without session`);return}let t=e.refresh_token?`refresh_token`:`access_token`,n=t===`refresh_token`?e.refresh_token:e.access_token;try{await c({tokenTypeHint:t,token:n,options:_}),t===`refresh_token`?(x(`tokenRevoked`,[{token:e.refresh_token,tokenTypeHint:`refresh_token`}]),_.logging?.info(`Refresh token successfully revoked`)):(x(`tokenRevoked`,[{token:e.access_token,tokenTypeHint:`access_token`}]),_.logging?.info(`Access token successfully revoked`))}catch(n){throw t===`refresh_token`?x(`tokenRevokeFailed`,[{token:e.refresh_token,tokenTypeHint:`refresh_token`}]):x(`tokenRevokeFailed`,[{token:e.access_token,tokenTypeHint:`access_token`}]),_.logging?.error(`Token revocation failed`,n),n}}finally{v.revoke=null}})(),v.revoke}async function F(e,t){return await A(),v.logout||=(async()=>{try{_.logging?.debug(`Attempting to logout`);let n=await w(async()=>{let e=await E()??g.session;return await O(),e});if(x(`logoutInitiated`,[{idToken:n?.id_token,claims:n?.claims}]),_.logging?.debug(`Logout initiated`),!n?.id_token){_.logging?.debug(`Logout called without id token`);return}try{let r=await d(_),i=u({url:r.end_session_endpoint,idToken:n.id_token,postLogoutRedirectUri:e?.postLogoutRedirectUri});await(t??_.urlHandler)(i,e)}catch(e){_.logging?.error(`Unable to redirect to the end-session endpoint`,e)}}finally{v.logout=null}})(),v.logout}return{dispatchEvent:x,subscribeToEvent:S,subscribeToAllEvents:C,getSession:T,updateSession:D,cleanupSession:O,checkAuthentication:k,init:A,tokenExchange:j,handleCallback:M,refresh:N,revoke:P,logout:F}}export{g as createBaseFlow};
2
2
  //# sourceMappingURL=base.mjs.map