@imtbl/auth 2.12.5 → 2.12.6-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
1
  import { UserManager, User, ErrorTimeout, ErrorResponse, InMemoryWebStorage, WebStorageStateStore } from 'oidc-client-ts';
2
- import Ce from 'localforage';
2
+ import Ve from 'localforage';
3
3
  import { track, identify, getDetail, Detail, trackFlow, trackError } from '@imtbl/metrics';
4
4
 
5
- var P=(a=>(a.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",a.INVALID_CONFIGURATION="INVALID_CONFIGURATION",a.WALLET_CONNECTION_ERROR="WALLET_CONNECTION_ERROR",a.NOT_LOGGED_IN_ERROR="NOT_LOGGED_IN_ERROR",a.SILENT_LOGIN_ERROR="SILENT_LOGIN_ERROR",a.REFRESH_TOKEN_ERROR="REFRESH_TOKEN_ERROR",a.USER_REGISTRATION_ERROR="USER_REGISTRATION_ERROR",a.USER_NOT_REGISTERED_ERROR="USER_NOT_REGISTERED_ERROR",a.LOGOUT_ERROR="LOGOUT_ERROR",a.TRANSFER_ERROR="TRANSFER_ERROR",a.CREATE_ORDER_ERROR="CREATE_ORDER_ERROR",a.CANCEL_ORDER_ERROR="CANCEL_ORDER_ERROR",a.EXCHANGE_TRANSFER_ERROR="EXCHANGE_TRANSFER_ERROR",a.CREATE_TRADE_ERROR="CREATE_TRADE_ERROR",a.OPERATION_NOT_SUPPORTED_ERROR="OPERATION_NOT_SUPPORTED_ERROR",a.LINK_WALLET_ALREADY_LINKED_ERROR="LINK_WALLET_ALREADY_LINKED_ERROR",a.LINK_WALLET_MAX_WALLETS_LINKED_ERROR="LINK_WALLET_MAX_WALLETS_LINKED_ERROR",a.LINK_WALLET_VALIDATION_ERROR="LINK_WALLET_VALIDATION_ERROR",a.LINK_WALLET_DUPLICATE_NONCE_ERROR="LINK_WALLET_DUPLICATE_NONCE_ERROR",a.LINK_WALLET_GENERIC_ERROR="LINK_WALLET_GENERIC_ERROR",a.SERVICE_UNAVAILABLE_ERROR="SERVICE_UNAVAILABLE_ERROR",a.TRANSACTION_REJECTED="TRANSACTION_REJECTED",a))(P||{});function U(n){return typeof n=="object"&&n!==null&&"code"in n&&"message"in n}var ee=n=>{if(U(n))return n;if(typeof n=="object"&&n!==null&&"response"in n){let{response:e}=n;if(e?.data&&U(e.data))return e.data}},p=class extends Error{type;constructor(e,t){super(e),this.type=t;}},g=async(n,e)=>{try{return await n()}catch(t){let r;if(t instanceof p&&t.type==="SERVICE_UNAVAILABLE_ERROR")throw new p(t.message,t.type);let i=ee(t);throw i?r=i.message:r=t.message,new p(r,e)}};var te=(n,e,t)=>{let r=e.map(i=>!n[i]&&i).filter(i=>i).join(", ");if(r!==""){let i=`${r} cannot be null`;throw new p(i,"INVALID_CONFIGURATION")}},y=class{authenticationDomain;passportDomain;oidcConfiguration;crossSdkBridgeEnabled;popupOverlayOptions;constructor({authenticationDomain:e,passportDomain:t,crossSdkBridgeEnabled:r,popupOverlayOptions:i,...o}){te(o,["clientId","redirectUri"]),this.oidcConfiguration=o,this.crossSdkBridgeEnabled=r||!1,this.popupOverlayOptions=i,this.authenticationDomain=e||"https://auth.immutable.com",this.passportDomain=t||"https://passport.immutable.com";}};var F=(e=>(e.ZKEVM="zkEvm",e))(F||{}),I=(t=>(t.ZKEVM="zkevm",t.ARBITRUM_ONE="arbitrum_one",t))(I||{}),x=n=>!!n.zkEvm,H=(r=>(r.OptedIn="opted_in",r.Unsubscribed="unsubscribed",r.Subscribed="subscribed",r))(H||{}),M=(t=>(t.LOGGED_OUT="loggedOut",t.LOGGED_IN="loggedIn",t))(M||{});var V="im_passport_embedded_login_prompt";var h="passport-overlay",R="passport-overlay-contents",A=`${h}-close`,w=`${h}-try-again`,G=`
5
+ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION="INVALID_CONFIGURATION",p.WALLET_CONNECTION_ERROR="WALLET_CONNECTION_ERROR",p.NOT_LOGGED_IN_ERROR="NOT_LOGGED_IN_ERROR",p.SILENT_LOGIN_ERROR="SILENT_LOGIN_ERROR",p.REFRESH_TOKEN_ERROR="REFRESH_TOKEN_ERROR",p.USER_REGISTRATION_ERROR="USER_REGISTRATION_ERROR",p.USER_NOT_REGISTERED_ERROR="USER_NOT_REGISTERED_ERROR",p.LOGOUT_ERROR="LOGOUT_ERROR",p.TRANSFER_ERROR="TRANSFER_ERROR",p.CREATE_ORDER_ERROR="CREATE_ORDER_ERROR",p.CANCEL_ORDER_ERROR="CANCEL_ORDER_ERROR",p.EXCHANGE_TRANSFER_ERROR="EXCHANGE_TRANSFER_ERROR",p.CREATE_TRADE_ERROR="CREATE_TRADE_ERROR",p.OPERATION_NOT_SUPPORTED_ERROR="OPERATION_NOT_SUPPORTED_ERROR",p.LINK_WALLET_ALREADY_LINKED_ERROR="LINK_WALLET_ALREADY_LINKED_ERROR",p.LINK_WALLET_MAX_WALLETS_LINKED_ERROR="LINK_WALLET_MAX_WALLETS_LINKED_ERROR",p.LINK_WALLET_VALIDATION_ERROR="LINK_WALLET_VALIDATION_ERROR",p.LINK_WALLET_DUPLICATE_NONCE_ERROR="LINK_WALLET_DUPLICATE_NONCE_ERROR",p.LINK_WALLET_GENERIC_ERROR="LINK_WALLET_GENERIC_ERROR",p.SERVICE_UNAVAILABLE_ERROR="SERVICE_UNAVAILABLE_ERROR",p.TRANSACTION_REJECTED="TRANSACTION_REJECTED",p))(I||{});function H(n){return typeof n=="object"&&n!==null&&"code"in n&&"message"in n}var ve=n=>{if(H(n))return n;if(typeof n=="object"&&n!==null&&"response"in n){let{response:e}=n;if(e?.data&&H(e.data))return e.data}},f=class extends Error{type;constructor(e,t){super(e),this.type=t;}},h=async(n,e)=>{try{return await n()}catch(t){let r;if(t instanceof f&&t.type==="SERVICE_UNAVAILABLE_ERROR")throw new f(t.message,t.type);let o=ve(t);throw o?r=o.message:r=t.message,new f(r,e)}};var Te=(n,e,t)=>{let r=e.map(o=>!n[o]&&o).filter(o=>o).join(", ");if(r!==""){let o=`${r} cannot be null`;throw new f(o,"INVALID_CONFIGURATION")}},T=class{authenticationDomain;passportDomain;oidcConfiguration;crossSdkBridgeEnabled;popupOverlayOptions;constructor({authenticationDomain:e,passportDomain:t,crossSdkBridgeEnabled:r,popupOverlayOptions:o,...i}){Te(i,["clientId","redirectUri"]),this.oidcConfiguration=i,this.crossSdkBridgeEnabled=r||!1,this.popupOverlayOptions=o,this.authenticationDomain=e||"https://auth.immutable.com",this.passportDomain=t||"https://passport.immutable.com";}};var Y=(e=>(e.ZKEVM="zkEvm",e))(Y||{}),A=(t=>(t.ZKEVM="zkevm",t.ARBITRUM_ONE="arbitrum_one",t))(A||{}),F=n=>!!n.zkEvm,J=(r=>(r.OptedIn="opted_in",r.Unsubscribed="unsubscribed",r.Subscribed="subscribed",r))(J||{}),V=(o=>(o.LOGGED_OUT="loggedOut",o.LOGGED_IN="loggedIn",o.TOKEN_REFRESHED="tokenRefreshed",o.USER_REMOVED="userRemoved",o))(V||{});var Q="im_passport_embedded_login_prompt";var C="passport-overlay",_="passport-overlay-contents",b=`${C}-close`,x=`${C}-try-again`,q=`
6
6
  <svg
7
7
  viewBox="0 0 20 20"
8
8
  fill="none"
@@ -14,7 +14,7 @@ var P=(a=>(a.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",a.INVALID_CONFIGURATION
14
14
  fill="#F3F3F3"
15
15
  />
16
16
  </svg>
17
- `,B=`
17
+ `,X=`
18
18
  <svg
19
19
  viewBox="0 0 17 16"
20
20
  fill="none"
@@ -28,7 +28,7 @@ var P=(a=>(a.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",a.INVALID_CONFIGURATION
28
28
  fill="#E01A3D"
29
29
  />
30
30
  </svg>
31
- `,S=`
31
+ `,G=`
32
32
  <svg
33
33
  style="
34
34
  max-width: 123px !important;
@@ -211,9 +211,9 @@ var P=(a=>(a.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",a.INVALID_CONFIGURATION
211
211
  </clipPath>
212
212
  </defs>
213
213
  </svg>
214
- `;var re=()=>`
214
+ `;var Oe=()=>`
215
215
  <button
216
- id="${A}"
216
+ id="${b}"
217
217
  style="
218
218
  background: #f3f3f326 !important;
219
219
  border: none !important;
@@ -229,11 +229,11 @@ var P=(a=>(a.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",a.INVALID_CONFIGURATION
229
229
  justify-content: center !important;
230
230
  "
231
231
  >
232
- ${G}
232
+ ${q}
233
233
  </button>
234
- `,K=()=>`
234
+ `,j=()=>`
235
235
  <button
236
- id="${w}"
236
+ id="${x}"
237
237
  style="
238
238
  margin-top: 27px !important;
239
239
  color: #f3f3f3 !important;
@@ -248,8 +248,8 @@ var P=(a=>(a.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",a.INVALID_CONFIGURATION
248
248
  >
249
249
  Try again
250
250
  </button>
251
- `,ne=()=>`
252
- ${S}
251
+ `,Le=()=>`
252
+ ${G}
253
253
  <div
254
254
  style="
255
255
  color: #e01a3d !important;
@@ -259,7 +259,7 @@ var P=(a=>(a.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",a.INVALID_CONFIGURATION
259
259
  margin-bottom: 10px !important;
260
260
  "
261
261
  >
262
- ${B}
262
+ ${X}
263
263
  Pop-up blocked
264
264
  </div>
265
265
  <p style="
@@ -272,9 +272,9 @@ var P=(a=>(a.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",a.INVALID_CONFIGURATION
272
272
  If the problem continues, adjust your<br />
273
273
  browser settings.
274
274
  </p>
275
- ${K()}
276
- `,ie=()=>`
277
- ${S}
275
+ ${j()}
276
+ `,Pe=()=>`
277
+ ${G}
278
278
  <p style="
279
279
  color: #b6b6b6 !important;
280
280
  text-align: center !important;
@@ -283,10 +283,10 @@ var P=(a=>(a.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",a.INVALID_CONFIGURATION
283
283
  >
284
284
  Secure pop-up not showing?<br />We'll help you re-launch
285
285
  </p>
286
- ${K()}
287
- `,Z=n=>`
286
+ ${j()}
287
+ `,ee=n=>`
288
288
  <div
289
- id="${h}"
289
+ id="${C}"
290
290
  style="
291
291
  position: fixed !important;
292
292
  top: 0 !important;
@@ -309,9 +309,9 @@ var P=(a=>(a.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",a.INVALID_CONFIGURATION
309
309
  z-index: 2147483647 !important;
310
310
  "
311
311
  >
312
- ${re()}
312
+ ${Oe()}
313
313
  <div
314
- id="${R}"
314
+ id="${_}"
315
315
  style="
316
316
  display: flex !important;
317
317
  flex-direction: column !important;
@@ -322,9 +322,9 @@ var P=(a=>(a.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",a.INVALID_CONFIGURATION
322
322
  ${n??""}
323
323
  </div>
324
324
  </div>
325
- `,W=()=>`
325
+ `,te=()=>`
326
326
  <div
327
- id="${h}"
327
+ id="${C}"
328
328
  style="
329
329
  position: fixed;
330
330
  top: 0;
@@ -342,7 +342,7 @@ var P=(a=>(a.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",a.INVALID_CONFIGURATION
342
342
  "
343
343
  >
344
344
  <div
345
- id="${R}"
345
+ id="${_}"
346
346
  style="
347
347
  display: flex;
348
348
  flex-direction: column;
@@ -351,7 +351,7 @@ var P=(a=>(a.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",a.INVALID_CONFIGURATION
351
351
  "
352
352
  />
353
353
  </div>
354
- `;function k({id:n,href:e,rel:t,crossOrigin:r}){let i=`${h}-${n}`;if(!document.getElementById(i)){let o=document.createElement("link");o.id=i,o.href=e,t&&(o.rel=t),r&&(o.crossOrigin=r),document.head.appendChild(o);}}var $=()=>Z(ne()),z=()=>Z(ie());var u=class{static overlay;static onCloseListener;static closeButton;static remove(){this.onCloseListener&&this.closeButton?.removeEventListener?.("click",this.onCloseListener),this.overlay?.remove(),this.closeButton=void 0,this.onCloseListener=void 0,this.overlay=void 0;}static appendOverlay(e,t){if(!this.overlay){let r=document.createElement("div");r.innerHTML=W(),document.body.insertAdjacentElement("beforeend",r);let i=document.querySelector(`#${R}`);i&&i.appendChild(e),r.addEventListener("click",t),this.overlay=r;}}};var ae=660,de=440,le="16px",Y="passport-embedded-login-keyframes",J="passport-embedded-login-iframe",v=class n{config;constructor(e){this.config=e;}getHref=()=>`${this.config.authenticationDomain}/im-embedded-login-prompt?client_id=${this.config.oidcConfiguration.clientId}&rid=${getDetail(Detail.RUNTIME_ID)}`;static appendIFrameStylesIfNeeded=()=>{if(document.getElementById(Y))return;let e=document.createElement("style");e.id=Y,e.textContent=`
354
+ `;function U({id:n,href:e,rel:t,crossOrigin:r}){let o=`${C}-${n}`;if(!document.getElementById(o)){let i=document.createElement("link");i.id=o,i.href=e,t&&(i.rel=t),r&&(i.crossOrigin=r),document.head.appendChild(i);}}var re=()=>ee(Le()),ne=()=>ee(Pe());var E=class{static overlay;static onCloseListener;static closeButton;static remove(){this.onCloseListener&&this.closeButton?.removeEventListener?.("click",this.onCloseListener),this.overlay?.remove(),this.closeButton=void 0,this.onCloseListener=void 0,this.overlay=void 0;}static appendOverlay(e,t){if(!this.overlay){let r=document.createElement("div");r.innerHTML=te(),document.body.insertAdjacentElement("beforeend",r);let o=document.querySelector(`#${_}`);o&&o.appendChild(e),r.addEventListener("click",t),this.overlay=r;}}};var Ie=660,Ae=440,be="16px",oe="passport-embedded-login-keyframes",ie="passport-embedded-login-iframe",O=class n{config;constructor(e){this.config=e;}getHref=()=>`${this.config.authenticationDomain}/im-embedded-login-prompt?client_id=${this.config.oidcConfiguration.clientId}&rid=${getDetail(Detail.RUNTIME_ID)}`;static appendIFrameStylesIfNeeded=()=>{if(document.getElementById(oe))return;let e=document.createElement("style");e.id=oe,e.textContent=`
355
355
  @keyframes passportEmbeddedLoginPromptPopBounceIn {
356
356
  0% {
357
357
  opacity: 0.5;
@@ -370,7 +370,7 @@ var P=(a=>(a.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",a.INVALID_CONFIGURATION
370
370
  }
371
371
 
372
372
  @media (max-height: 400px) {
373
- #${J} {
373
+ #${ie} {
374
374
  width: 100% !important;
375
375
  max-width: none !important;
376
376
  }
@@ -384,6 +384,58 @@ var P=(a=>(a.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",a.INVALID_CONFIGURATION
384
384
  opacity: 1;
385
385
  }
386
386
  }
387
- `,document.head.appendChild(e);};getEmbeddedLoginIFrame=()=>{let e=document.createElement("iframe");return e.id=J,e.src=this.getHref(),e.style.height="100vh",e.style.width="100vw",e.style.maxHeight=`${ae}px`,e.style.maxWidth=`${de}px`,e.style.borderRadius=le,e.style.opacity="0",e.style.transform="scale(0.6)",e.style.animation="passportEmbeddedLoginPromptPopBounceIn 1s ease forwards",n.appendIFrameStylesIfNeeded(),e};displayEmbeddedLoginPrompt(){return new Promise((e,t)=>{let r=this.getEmbeddedLoginIFrame(),i=({data:o,origin:s})=>{if(!(s!==this.config.authenticationDomain||o.eventType!==V))switch(o.messageType){case"login_method_selected":{let l=o.payload;window.removeEventListener("message",i),u.remove(),e(l);break}case"login_prompt_error":{window.removeEventListener("message",i),u.remove(),t(new Error("Error during embedded login prompt",{cause:o.payload}));break}case"login_prompt_closed":{window.removeEventListener("message",i),u.remove(),t(new Error("Popup closed by user"));break}default:window.removeEventListener("message",i),u.remove(),t(new Error(`Unsupported message type: ${o.messageType}`));break}};window.addEventListener("message",i),u.appendOverlay(r,()=>{window.removeEventListener("message",i),u.remove(),t(new Error("Popup closed by user"));});})}};var C=class{listeners=new Map;emit(e,...t){let r=this.listeners.get(e);!r||r.size===0||[...r].forEach(i=>{i(...t);});}on(e,t){let r=this.listeners.get(e)??new Set;r.add(t),this.listeners.set(e,r);}removeListener(e,t){let r=this.listeners.get(e);r&&(r.delete(t),r.size===0&&this.listeners.delete(e));}};var c=async(n,e,t=!0,r=!0)=>{let i=trackFlow("passport",e,t);try{return await n(i)}catch(o){throw o instanceof Error?trackError("passport",e,o,{flowId:i.details.flowId}):i.addEvent("errored"),o}finally{r&&i.addEvent("End");}};var ue=()=>typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{},me=n=>{let e=n.replace(/-/g,"+").replace(/_/g,"/"),t=e.length%4===0?"":"=".repeat(4-e.length%4);return e+t},ge=n=>{let e=ue();if(typeof e.atob!="function")return null;let t=e.atob(n),r=new Uint8Array(t.length);for(let o=0;o<t.length;o+=1)r[o]=t.charCodeAt(o);if(typeof e.TextDecoder=="function")return new e.TextDecoder("utf-8").decode(r);let i="";for(let o=0;o<r.length;o+=1)i+=String.fromCharCode(r[o]);return i},fe=n=>{if(typeof Buffer<"u")return Buffer.from(n,"base64").toString("utf-8");let e=ge(n);if(e===null)throw new Error("Base64 decoding is not supported in this environment");return e},f=n=>{if(typeof n!="string")throw new Error("JWT must be a string");let e=n.split(".");if(e.length<2)throw new Error("Invalid JWT: payload segment is missing");let t=e[1],r=fe(me(t));try{return JSON.parse(r)}catch{throw new Error("Invalid JWT payload: unable to parse JSON")}};var j="pkce_state",Q="pkce_verifier",Ee=3600,O=class{isTokenValid(e){try{let r=f(e).exp??0,i=Date.now()/1e3+Ee;return r>i}catch{return !1}}savePKCEData(e){localStorage.setItem(j,e.state),localStorage.setItem(Q,e.verifier);}getPKCEData(){let e=localStorage.getItem(j),t=localStorage.getItem(Q);return e&&t?{state:e,verifier:t}:null}};var he=(...n)=>{if(typeof process>"u")return;process?.env?.JEST_WORKER_ID===void 0&&console.warn(...n);},_={warn:he};function q(n){try{let e=f(n),t=Math.floor(Date.now()/1e3);return e.exp?e.exp<=t+30:!0}catch{return !0}}function X(n){let{id_token:e,access_token:t}=n;return !t||!e?!0:q(t)||q(e)}var T=class{disableGenericPopupOverlay;disableBlockedPopupOverlay;overlay;isBlockedOverlay;tryAgainListener;onCloseListener;constructor(e,t=!1){this.disableBlockedPopupOverlay=e.disableBlockedPopupOverlay||!1,this.disableGenericPopupOverlay=e.disableGenericPopupOverlay||!1,this.isBlockedOverlay=t;}append(e,t){this.shouldAppendOverlay()&&(this.appendOverlay(),this.updateTryAgainButton(e),this.updateCloseButton(t));}update(e){this.updateTryAgainButton(e);}remove(){this.overlay&&this.overlay.remove();}shouldAppendOverlay(){return !(this.disableGenericPopupOverlay&&this.disableBlockedPopupOverlay||this.disableGenericPopupOverlay&&!this.isBlockedOverlay||this.disableBlockedPopupOverlay&&this.isBlockedOverlay)}appendOverlay(){if(!this.overlay){k({id:"link-googleapis",href:"https://fonts.googleapis.com"}),k({id:"link-gstatic",href:"https://fonts.gstatic.com",crossOrigin:"anonymous"}),k({id:"link-roboto",href:"https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap",rel:"stylesheet"});let t=document.createElement("div");t.innerHTML=this.isBlockedOverlay?$():z(),document.body.insertAdjacentElement("beforeend",t),this.overlay=t;}}updateTryAgainButton(e){let t=document.getElementById(w);t&&(this.tryAgainListener&&t.removeEventListener("click",this.tryAgainListener),this.tryAgainListener=e,t.addEventListener("click",e));}updateCloseButton(e){let t=document.getElementById(A);t&&(this.onCloseListener&&t.removeEventListener("click",this.onCloseListener),this.onCloseListener=e,t.addEventListener("click",e));}};var b=class{storage;constructor(e,t){this.storage=Ce.createInstance({name:e,driver:t});}get length(){return this.storage.length()}clear(){return this.storage.clear()}getItem(e){return this.storage.getItem(e)}key(e){return this.storage.key(e)}async removeItem(e){await this.storage.removeItem(e);}async setItem(e,t){await this.storage.setItem(e,t);}};var be={"Content-Type":"application/x-www-form-urlencoded"},Ue=n=>{if(n)try{return JSON.parse(n)}catch{return}},xe=(n,e,t)=>{if(n&&typeof n=="object"){let r=n,i=r.error_description??r.message??r.error;if(typeof i=="string"&&i.trim().length>0)return i}return e.trim().length>0?e:`Token request failed with status ${t}`},Me="/v2/logout",Se="/im-logged-out",Ne="/authorize",De=n=>n?Se:Me,Fe=n=>{let{authenticationDomain:e,oidcConfiguration:t}=n,r;n.crossSdkBridgeEnabled?r=new b("ImmutableSDKPassport",Ce.INDEXEDDB):typeof window<"u"?r=window.localStorage:r=new InMemoryWebStorage;let i=new WebStorageStateStore({store:r}),o=new URL(De(n.crossSdkBridgeEnabled),e.replace(/^(?:https?:\/\/)?(.*)/,"https://$1"));return o.searchParams.set("client_id",t.clientId),t.logoutRedirectUri&&o.searchParams.set("returnTo",t.logoutRedirectUri),{authority:e,redirect_uri:t.redirectUri,popup_redirect_uri:t.popupRedirectUri||t.redirectUri,client_id:t.clientId,metadata:{authorization_endpoint:`${e}/authorize`,token_endpoint:`${e}/oauth/token`,userinfo_endpoint:`${e}/userinfo`,end_session_endpoint:o.toString(),revocation_endpoint:`${e}/oauth/revoke`},automaticSilentRenew:!1,scope:t.scope,userStore:i,revokeTokenTypes:["refresh_token"],extraQueryParams:{...t.audience?{audience:t.audience}:{}}}};function N(n){return btoa(String.fromCharCode(...new Uint8Array(n))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function He(n){let t=new TextEncoder().encode(n);return window.crypto.subtle.digest("SHA-256",t)}var D=class n{config;userManager;deviceCredentialsManager;embeddedLoginPrompt;logoutMode;refreshingPromise=null;eventEmitter;constructor(e){this.config=new y(e),this.embeddedLoginPrompt=new v(this.config),this.userManager=new UserManager(Fe(this.config)),this.deviceCredentialsManager=new O,this.logoutMode=this.config.oidcConfiguration.logoutMode||"redirect",this.eventEmitter=new C,track("passport","initialise");}async login(e){return c(async()=>{let{useCachedSession:t=!1,useSilentLogin:r}=e||{},i=null;try{i=await this.getUserInternal();}catch(o){if(o instanceof Error&&!o.message.includes("Unknown or invalid refresh token")&&trackError("passport","login",o),t)throw o;_.warn("Failed to retrieve a cached user session",o);}if(!i&&r)i=await this.forceUserRefreshInternal();else if(!i&&!t){if(e?.useRedirectFlow)return await this.loginWithRedirectInternal(e?.directLoginOptions),null;i=await this.loginWithPopup(e?.directLoginOptions);}return i&&this.handleSuccessfulLogin(i),i},"login")}async loginWithRedirect(e){await this.loginWithRedirectInternal(e);}async loginCallback(){return c(async()=>{let e=await this.loginCallbackInternal();return e&&this.handleSuccessfulLogin(e),e},"loginCallback")}async logout(){await c(async()=>{await this.logoutInternal(),this.eventEmitter.emit("loggedOut");},"logout");}async getUser(){return this.getUserInternal()}async getUserOrLogin(){let e=null;try{e=await this.getUserInternal();}catch(r){_.warn("Failed to retrieve a cached user session",r);}if(e)return e;let t=await this.loginWithPopup();return this.handleSuccessfulLogin(t),t}async getUserZkEvm(){return this.getUserZkEvmInternal()}async getIdToken(){return c(async()=>(await this.getUserInternal())?.idToken,"getIdToken",!1)}async getAccessToken(){return c(async()=>(await this.getUserInternal())?.accessToken,"getAccessToken",!1,!1)}async isLoggedIn(){return await this.getUser()!==null}async forceUserRefresh(){return this.forceUserRefreshInternal()}forceUserRefreshInBackground(){this.forceUserRefreshInBackgroundInternal();}async loginWithPKCEFlow(e,t){return c(async()=>this.getPKCEAuthorizationUrl(e,t),"loginWithPKCEFlow")}async loginWithPKCEFlowCallback(e,t){return c(async()=>{let r=await this.loginWithPKCEFlowCallbackInternal(e,t);return this.handleSuccessfulLogin(r),r},"loginWithPKCEFlowCallback")}async storeTokens(e){return c(async()=>{let t=await this.storeTokensInternal(e);return this.handleSuccessfulLogin(t),t},"storeTokens")}async getLogoutUrl(){return c(async()=>(await this.userManager.removeUser(),this.eventEmitter.emit("loggedOut"),await this.getLogoutUrlInternal()||void 0),"getLogoutUrl")}async logoutSilentCallback(e){return c(()=>this.userManager.signoutSilentCallback(e),"logoutSilentCallback")}getConfig(){return this.config}async getClientId(){return this.config.oidcConfiguration.clientId}handleSuccessfulLogin(e){this.eventEmitter.emit("loggedIn",e),identify({passportId:e.profile.sub});}buildExtraQueryParams(e,t){let r={...this.userManager.settings?.extraQueryParams??{},rid:getDetail(Detail.RUNTIME_ID)||""};if(e){if(e.directLoginMethod==="email"){let i=e.email;i&&(r.direct=e.directLoginMethod,r.email=i);}else r.direct=e.directLoginMethod;e.marketingConsentStatus&&(r.marketingConsent=e.marketingConsentStatus);}return t&&(r.im_passport_trace_id=t),r}async loginWithRedirectInternal(e){await this.userManager.clearStaleState(),await g(async()=>{let t=this.buildExtraQueryParams(e);await this.userManager.signinRedirect({extraQueryParams:t});},"AUTHENTICATION_ERROR");}async loginWithPopup(e){return g(async()=>{let t,r;if(e)t=e;else if(!this.config.popupOverlayOptions?.disableHeadlessLoginPromptOverlay){let{imPassportTraceId:s,...l}=await this.embeddedLoginPrompt.displayEmbeddedLoginPrompt();t=l,r=s;}let i=window.crypto.randomUUID(),o=async()=>{let s=this.buildExtraQueryParams(t,r);return this.userManager.signinPopup({extraQueryParams:s,popupWindowFeatures:{width:410,height:450},popupWindowTarget:i,popupAbortOnClose:!0})};return new Promise((s,l)=>{o().then(m=>s(n.mapOidcUserToDomainModel(m))).catch(m=>{if(!(m instanceof Error)||m.message!=="Attempted to navigate on a disposed window"){l(m);return}let L=!1,d=new T(this.config.popupOverlayOptions||{},!0);d.append(async()=>{try{if(L)window.open("",i);else {L=!0;let E=await o();d.remove(),s(n.mapOidcUserToDomainModel(E));}}catch(E){d.remove(),l(E);}},()=>{d.remove(),l(new Error("Popup closed by user"));});});})},"AUTHENTICATION_ERROR")}static mapOidcUserToDomainModel=e=>{let t,r;if(e.id_token){let s=f(e.id_token);t=s?.passport,s?.username&&(r=s?.username);}let i={expired:e.expired,idToken:e.id_token,accessToken:e.access_token,refreshToken:e.refresh_token,profile:{sub:e.profile.sub,email:e.profile.email,nickname:e.profile.nickname,username:r}};t?.zkevm_eth_address&&t?.zkevm_user_admin_address&&(i.zkEvm={ethAddress:t.zkevm_eth_address,userAdminAddress:t.zkevm_user_admin_address});let o=Object.values(I).filter(s=>s!=="zkevm");for(let s of o){let l=t?.[s];l?.eth_address&&l?.user_admin_address&&(i[s]={ethAddress:l.eth_address,userAdminAddress:l.user_admin_address});}return i};static mapDeviceTokenResponseToOidcUser=e=>{let t=f(e.id_token);return new User({id_token:e.id_token,access_token:e.access_token,refresh_token:e.refresh_token,token_type:e.token_type,profile:{sub:t.sub,iss:t.iss,aud:t.aud,exp:t.exp,iat:t.iat,email:t.email,nickname:t.nickname,passport:t.passport,...t.username?{username:t.username}:{}}})};async loginCallbackInternal(){return g(async()=>{let e=await this.userManager.signinCallback();if(e)return n.mapOidcUserToDomainModel(e)},"AUTHENTICATION_ERROR")}async getPKCEAuthorizationUrl(e,t){let r=N(window.crypto.getRandomValues(new Uint8Array(32))),i=N(await He(r)),o=N(window.crypto.getRandomValues(new Uint8Array(32))),{redirectUri:s,scope:l,audience:m,clientId:L}=this.config.oidcConfiguration;this.deviceCredentialsManager.savePKCEData({state:o,verifier:r});let d=new URL(Ne,this.config.authenticationDomain);if(d.searchParams.set("response_type","code"),d.searchParams.set("code_challenge",i),d.searchParams.set("code_challenge_method","S256"),d.searchParams.set("client_id",L),d.searchParams.set("redirect_uri",s),d.searchParams.set("state",o),l&&d.searchParams.set("scope",l),m&&d.searchParams.set("audience",m),e){if(e.directLoginMethod==="email"){let E=e.email;E&&(d.searchParams.set("direct",e.directLoginMethod),d.searchParams.set("email",E));}else d.searchParams.set("direct",e.directLoginMethod);e.marketingConsentStatus&&d.searchParams.set("marketingConsent",e.marketingConsentStatus);}return t&&d.searchParams.set("im_passport_trace_id",t),d.toString()}async loginWithPKCEFlowCallbackInternal(e,t){return g(async()=>{let r=this.deviceCredentialsManager.getPKCEData();if(!r)throw new Error("No code verifier or state for PKCE");if(t!==r.state)throw new Error("Provided state does not match stored state");let i=await this.getPKCEToken(e,r.verifier),o=n.mapDeviceTokenResponseToOidcUser(i),s=n.mapOidcUserToDomainModel(o);return await this.userManager.storeUser(o),s},"AUTHENTICATION_ERROR")}async getPKCEToken(e,t){let r=await fetch(`${this.config.authenticationDomain}/oauth/token`,{method:"POST",headers:be,body:new URLSearchParams({client_id:this.config.oidcConfiguration.clientId,grant_type:"authorization_code",code_verifier:t,code:e,redirect_uri:this.config.oidcConfiguration.redirectUri})}),i=await r.text(),o=Ue(i);if(!r.ok)throw new Error(xe(o,i,r.status));if(!o||typeof o!="object")throw new Error("Token endpoint returned an invalid response");return o}async storeTokensInternal(e){return g(async()=>{let t=n.mapDeviceTokenResponseToOidcUser(e),r=n.mapOidcUserToDomainModel(t);return await this.userManager.storeUser(t),r},"AUTHENTICATION_ERROR")}async logoutInternal(){await g(async()=>{await this.userManager.revokeTokens(["refresh_token"]),this.logoutMode==="silent"?await this.userManager.signoutSilent():await this.userManager.signoutRedirect();},"LOGOUT_ERROR");}async getLogoutUrlInternal(){let e=this.userManager.settings?.metadata?.end_session_endpoint;return e||(_.warn("Failed to get logout URL"),null)}forceUserRefreshInBackgroundInternal(){this.refreshTokenAndUpdatePromise().catch(e=>{_.warn("Failed to refresh user token",e);});}async forceUserRefreshInternal(){return this.refreshTokenAndUpdatePromise().catch(e=>(_.warn("Failed to refresh user token",e),null))}async refreshTokenAndUpdatePromise(){return this.refreshingPromise?this.refreshingPromise:(this.refreshingPromise=new Promise((e,t)=>{(async()=>{try{let r=await this.userManager.signinSilent();if(r){e(n.mapOidcUserToDomainModel(r));return}e(null);}catch(r){let i="AUTHENTICATION_ERROR",o="Failed to refresh token",s=!0;if(r instanceof ErrorTimeout?(i="SILENT_LOGIN_ERROR",o=`${o}: ${r.message}`,s=!1):r instanceof ErrorResponse?(i="NOT_LOGGED_IN_ERROR",o=`${o}: ${r.message||r.error_description}`):r instanceof Error?o=`${o}: ${r.message}`:typeof r=="string"&&(o=`${o}: ${r}`),s)try{await this.userManager.removeUser();}catch(l){l instanceof Error&&(o=`${o}: Failed to remove user: ${l.message}`);}t(new p(o,i));}finally{this.refreshingPromise=null;}})();}),this.refreshingPromise)}async getUserInternal(e=t=>!0){if(this.refreshingPromise){let r=await this.refreshingPromise;return r&&e(r)?r:null}let t=await this.userManager.getUser();if(!t)return null;if(!X(t)){let r=n.mapOidcUserToDomainModel(t);if(r&&e(r))return r}if(t.refresh_token){let r=await this.refreshTokenAndUpdatePromise();if(r&&e(r))return r}return null}async getUserZkEvmInternal(){let e=await this.getUserInternal(x);if(!e)throw new Error("Failed to obtain a User with the required ZkEvm attributes");return e}};
387
+ `,document.head.appendChild(e);};getEmbeddedLoginIFrame=()=>{let e=document.createElement("iframe");return e.id=ie,e.src=this.getHref(),e.style.height="100vh",e.style.width="100vw",e.style.maxHeight=`${Ie}px`,e.style.maxWidth=`${Ae}px`,e.style.borderRadius=be,e.style.opacity="0",e.style.transform="scale(0.6)",e.style.animation="passportEmbeddedLoginPromptPopBounceIn 1s ease forwards",n.appendIFrameStylesIfNeeded(),e};displayEmbeddedLoginPrompt(){return new Promise((e,t)=>{let r=this.getEmbeddedLoginIFrame(),o=({data:i,origin:s})=>{if(!(s!==this.config.authenticationDomain||i.eventType!==Q))switch(i.messageType){case"login_method_selected":{let a=i.payload;window.removeEventListener("message",o),E.remove(),e(a);break}case"login_prompt_error":{window.removeEventListener("message",o),E.remove(),t(new Error("Error during embedded login prompt",{cause:i.payload}));break}case"login_prompt_closed":{window.removeEventListener("message",o),E.remove(),t(new Error("Popup closed by user"));break}default:window.removeEventListener("message",o),E.remove(),t(new Error(`Unsupported message type: ${i.messageType}`));break}};window.addEventListener("message",o),E.appendOverlay(r,()=>{window.removeEventListener("message",o),E.remove(),t(new Error("Popup closed by user"));});})}};var R=class{listeners=new Map;emit(e,...t){let r=this.listeners.get(e);!r||r.size===0||[...r].forEach(o=>{o(...t);});}on(e,t){let r=this.listeners.get(e)??new Set;r.add(t),this.listeners.set(e,r);}removeListener(e,t){let r=this.listeners.get(e);r&&(r.delete(t),r.size===0&&this.listeners.delete(e));}};var m=async(n,e,t=!0,r=!0)=>{let o=trackFlow("passport",e,t);try{return await n(o)}catch(i){throw i instanceof Error?trackError("passport",e,i,{flowId:o.details.flowId}):o.addEvent("errored"),i}finally{r&&o.addEvent("End");}};var Se=()=>typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{},De=n=>{let e=n.replace(/-/g,"+").replace(/_/g,"/"),t=e.length%4===0?"":"=".repeat(4-e.length%4);return e+t},Me=n=>{let e=Se();if(typeof e.atob!="function")return null;let t=e.atob(n),r=new Uint8Array(t.length);for(let i=0;i<t.length;i+=1)r[i]=t.charCodeAt(i);if(typeof e.TextDecoder=="function")return new e.TextDecoder("utf-8").decode(r);let o="";for(let i=0;i<r.length;i+=1)o+=String.fromCharCode(r[i]);return o},Ne=n=>{if(typeof Buffer<"u")return Buffer.from(n,"base64").toString("utf-8");let e=Me(n);if(e===null)throw new Error("Base64 decoding is not supported in this environment");return e},u=n=>{if(typeof n!="string")throw new Error("JWT must be a string");let e=n.split(".");if(e.length<2)throw new Error("Invalid JWT: payload segment is missing");let t=e[1],r=Ne(De(t));try{return JSON.parse(r)}catch{throw new Error("Invalid JWT payload: unable to parse JSON")}};var se="pkce_state",ae="pkce_verifier",He=3600,L=class{isTokenValid(e){try{let r=u(e).exp??0,o=Date.now()/1e3+He;return r>o}catch{return !1}}savePKCEData(e){localStorage.setItem(se,e.state),localStorage.setItem(ae,e.verifier);}getPKCEData(){let e=localStorage.getItem(se),t=localStorage.getItem(ae);return e&&t?{state:e,verifier:t}:null}};var Fe=(...n)=>{if(typeof process>"u")return;process?.env?.JEST_WORKER_ID===void 0&&console.warn(...n);},v={warn:Fe};function de(n){try{let e=u(n),t=Math.floor(Date.now()/1e3);return e.exp?e.exp<=t+30:!0}catch{return !0}}function le(n){let{id_token:e,access_token:t}=n;return !t||!e?!0:de(t)||de(e)}var P=class{disableGenericPopupOverlay;disableBlockedPopupOverlay;overlay;isBlockedOverlay;tryAgainListener;onCloseListener;constructor(e,t=!1){this.disableBlockedPopupOverlay=e.disableBlockedPopupOverlay||!1,this.disableGenericPopupOverlay=e.disableGenericPopupOverlay||!1,this.isBlockedOverlay=t;}append(e,t){this.shouldAppendOverlay()&&(this.appendOverlay(),this.updateTryAgainButton(e),this.updateCloseButton(t));}update(e){this.updateTryAgainButton(e);}remove(){this.overlay&&this.overlay.remove();}shouldAppendOverlay(){return !(this.disableGenericPopupOverlay&&this.disableBlockedPopupOverlay||this.disableGenericPopupOverlay&&!this.isBlockedOverlay||this.disableBlockedPopupOverlay&&this.isBlockedOverlay)}appendOverlay(){if(!this.overlay){U({id:"link-googleapis",href:"https://fonts.googleapis.com"}),U({id:"link-gstatic",href:"https://fonts.gstatic.com",crossOrigin:"anonymous"}),U({id:"link-roboto",href:"https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap",rel:"stylesheet"});let t=document.createElement("div");t.innerHTML=this.isBlockedOverlay?re():ne(),document.body.insertAdjacentElement("beforeend",t),this.overlay=t;}}updateTryAgainButton(e){let t=document.getElementById(x);t&&(this.tryAgainListener&&t.removeEventListener("click",this.tryAgainListener),this.tryAgainListener=e,t.addEventListener("click",e));}updateCloseButton(e){let t=document.getElementById(b);t&&(this.onCloseListener&&t.removeEventListener("click",this.onCloseListener),this.onCloseListener=e,t.addEventListener("click",e));}};var S=class{storage;constructor(e,t){this.storage=Ve.createInstance({name:e,driver:t});}get length(){return this.storage.length()}clear(){return this.storage.clear()}getItem(e){return this.storage.getItem(e)}key(e){return this.storage.key(e)}async removeItem(e){await this.storage.removeItem(e);}async setItem(e,t){await this.storage.setItem(e,t);}};var je={"Content-Type":"application/x-www-form-urlencoded"},et=n=>{if(n)try{return JSON.parse(n)}catch{return}},tt=(n,e,t)=>{if(n&&typeof n=="object"){let r=n,o=r.error_description??r.message??r.error;if(typeof o=="string"&&o.trim().length>0)return o}return e.trim().length>0?e:`Token request failed with status ${t}`},ce=(n,e)=>({ethAddress:n,userAdminAddress:e}),rt="/v2/logout",nt="/im-logged-out",ot="/authorize",it=n=>n?nt:rt,st=n=>{let{authenticationDomain:e,oidcConfiguration:t}=n,r;n.crossSdkBridgeEnabled?r=new S("ImmutableSDKPassport",Ve.INDEXEDDB):typeof window<"u"?r=window.localStorage:r=new InMemoryWebStorage;let o=new WebStorageStateStore({store:r}),i=new URL(it(n.crossSdkBridgeEnabled),e.replace(/^(?:https?:\/\/)?(.*)/,"https://$1"));return i.searchParams.set("client_id",t.clientId),t.logoutRedirectUri&&i.searchParams.set("returnTo",t.logoutRedirectUri),{authority:e,redirect_uri:t.redirectUri,popup_redirect_uri:t.popupRedirectUri||t.redirectUri,client_id:t.clientId,metadata:{authorization_endpoint:`${e}/authorize`,token_endpoint:`${e}/oauth/token`,userinfo_endpoint:`${e}/userinfo`,end_session_endpoint:i.toString(),revocation_endpoint:`${e}/oauth/revoke`},automaticSilentRenew:!1,scope:t.scope,userStore:o,revokeTokenTypes:["refresh_token"],extraQueryParams:{...t.audience?{audience:t.audience}:{}}}};function B(n){return btoa(String.fromCharCode(...new Uint8Array(n))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function at(n){let t=new TextEncoder().encode(n);return window.crypto.subtle.digest("SHA-256",t)}var K=class n{config;userManager;deviceCredentialsManager;embeddedLoginPrompt;logoutMode;refreshingPromise=null;eventEmitter;constructor(e){this.config=new T(e),this.embeddedLoginPrompt=new O(this.config),this.userManager=new UserManager(st(this.config)),this.deviceCredentialsManager=new L,this.logoutMode=this.config.oidcConfiguration.logoutMode||"redirect",this.eventEmitter=new R,track("passport","initialise");}async login(e){return m(async()=>{let{useCachedSession:t=!1,useSilentLogin:r}=e||{},o=null;try{o=await this.getUserInternal();}catch(i){if(i instanceof Error&&!i.message.includes("Unknown or invalid refresh token")&&trackError("passport","login",i),t)throw i;v.warn("Failed to retrieve a cached user session",i);}if(!o&&r)o=await this.forceUserRefreshInternal();else if(!o&&!t){if(e?.useRedirectFlow)return await this.loginWithRedirectInternal(e?.directLoginOptions),null;o=await this.loginWithPopup(e?.directLoginOptions);}return o&&this.handleSuccessfulLogin(o),o},"login")}async loginWithRedirect(e){await this.loginWithRedirectInternal(e);}async loginCallback(){return m(async()=>{let e=await this.loginCallbackInternal();return e&&this.handleSuccessfulLogin(e),e},"loginCallback")}async logout(){await m(async()=>{await this.logoutInternal(),this.eventEmitter.emit("loggedOut");},"logout");}async getUser(){return this.getUserInternal()}async getUserOrLogin(){let e=null;try{e=await this.getUserInternal();}catch(r){v.warn("Failed to retrieve a cached user session",r);}if(e)return e;let t=await this.loginWithPopup();return this.handleSuccessfulLogin(t),t}async getUserZkEvm(){return this.getUserZkEvmInternal()}async getIdToken(){return m(async()=>(await this.getUserInternal())?.idToken,"getIdToken",!1)}async getAccessToken(){return m(async()=>(await this.getUserInternal())?.accessToken,"getAccessToken",!1,!1)}async isLoggedIn(){return await this.getUser()!==null}async forceUserRefresh(){return this.forceUserRefreshInternal()}forceUserRefreshInBackground(){this.forceUserRefreshInBackgroundInternal();}async loginWithPKCEFlow(e,t){return m(async()=>this.getPKCEAuthorizationUrl(e,t),"loginWithPKCEFlow")}async loginWithPKCEFlowCallback(e,t){return m(async()=>{let r=await this.loginWithPKCEFlowCallbackInternal(e,t);return this.handleSuccessfulLogin(r),r},"loginWithPKCEFlowCallback")}async storeTokens(e){return m(async()=>{let t=await this.storeTokensInternal(e);return this.handleSuccessfulLogin(t),t},"storeTokens")}async getLogoutUrl(){return m(async()=>(await this.userManager.removeUser(),this.eventEmitter.emit("loggedOut"),await this.getLogoutUrlInternal()||void 0),"getLogoutUrl")}async logoutSilentCallback(e){return m(()=>this.userManager.signoutSilentCallback(e),"logoutSilentCallback")}getConfig(){return this.config}async getClientId(){return this.config.oidcConfiguration.clientId}handleSuccessfulLogin(e){this.eventEmitter.emit("loggedIn",e),identify({passportId:e.profile.sub});}buildExtraQueryParams(e,t){let r={...this.userManager.settings?.extraQueryParams??{},rid:getDetail(Detail.RUNTIME_ID)||""};if(e){if(e.directLoginMethod==="email"){let o=e.email;o&&(r.direct=e.directLoginMethod,r.email=o);}else r.direct=e.directLoginMethod;e.marketingConsentStatus&&(r.marketingConsent=e.marketingConsentStatus);}return t&&(r.im_passport_trace_id=t),r}async loginWithRedirectInternal(e){await this.userManager.clearStaleState(),await h(async()=>{let t=this.buildExtraQueryParams(e);await this.userManager.signinRedirect({extraQueryParams:t});},"AUTHENTICATION_ERROR");}async loginWithPopup(e){return h(async()=>{let t,r;if(e)t=e;else if(!this.config.popupOverlayOptions?.disableHeadlessLoginPromptOverlay){let{imPassportTraceId:s,...a}=await this.embeddedLoginPrompt.displayEmbeddedLoginPrompt();t=a,r=s;}let o=window.crypto.randomUUID(),i=async()=>{let s=this.buildExtraQueryParams(t,r);return this.userManager.signinPopup({extraQueryParams:s,popupWindowFeatures:{width:410,height:450},popupWindowTarget:o,popupAbortOnClose:!0})};return new Promise((s,a)=>{i().then(l=>s(n.mapOidcUserToDomainModel(l))).catch(l=>{if(!(l instanceof Error)||l.message!=="Attempted to navigate on a disposed window"){a(l);return}let c=!1,d=new P(this.config.popupOverlayOptions||{},!0);d.append(async()=>{try{if(c)window.open("",o);else {c=!0;let g=await i();d.remove(),s(n.mapOidcUserToDomainModel(g));}}catch(g){d.remove(),a(g);}},()=>{d.remove(),a(new Error("Popup closed by user"));});});})},"AUTHENTICATION_ERROR")}static mapOidcUserToDomainModel=e=>{let t,r;if(e.id_token){let s=u(e.id_token);t=s?.passport,s?.username&&(r=s?.username);}let o={expired:e.expired,idToken:e.id_token,accessToken:e.access_token,refreshToken:e.refresh_token,profile:{sub:e.profile.sub,email:e.profile.email,nickname:e.profile.nickname,username:r}};t?.zkevm_eth_address&&t?.zkevm_user_admin_address&&(o.zkEvm=ce(t.zkevm_eth_address,t.zkevm_user_admin_address));let i=Object.values(A).filter(s=>s!=="zkevm");for(let s of i){let a=t?.[s];a?.eth_address&&a?.user_admin_address&&(o[s]=ce(a.eth_address,a.user_admin_address));}return o};static mapDeviceTokenResponseToOidcUser=e=>{let t=u(e.id_token);return new User({id_token:e.id_token,access_token:e.access_token,refresh_token:e.refresh_token,token_type:e.token_type,profile:{sub:t.sub,iss:t.iss,aud:t.aud,exp:t.exp,iat:t.iat,email:t.email,nickname:t.nickname,passport:t.passport,...t.username?{username:t.username}:{}}})};async loginCallbackInternal(){return h(async()=>{let e=await this.userManager.signinCallback();if(e)return n.mapOidcUserToDomainModel(e)},"AUTHENTICATION_ERROR")}async getPKCEAuthorizationUrl(e,t){let r=B(window.crypto.getRandomValues(new Uint8Array(32))),o=B(await at(r)),i=B(window.crypto.getRandomValues(new Uint8Array(32))),{redirectUri:s,scope:a,audience:l,clientId:c}=this.config.oidcConfiguration;this.deviceCredentialsManager.savePKCEData({state:i,verifier:r});let d=new URL(ot,this.config.authenticationDomain);if(d.searchParams.set("response_type","code"),d.searchParams.set("code_challenge",o),d.searchParams.set("code_challenge_method","S256"),d.searchParams.set("client_id",c),d.searchParams.set("redirect_uri",s),d.searchParams.set("state",i),a&&d.searchParams.set("scope",a),l&&d.searchParams.set("audience",l),e){if(e.directLoginMethod==="email"){let g=e.email;g&&(d.searchParams.set("direct",e.directLoginMethod),d.searchParams.set("email",g));}else d.searchParams.set("direct",e.directLoginMethod);e.marketingConsentStatus&&d.searchParams.set("marketingConsent",e.marketingConsentStatus);}return t&&d.searchParams.set("im_passport_trace_id",t),d.toString()}async loginWithPKCEFlowCallbackInternal(e,t){return h(async()=>{let r=this.deviceCredentialsManager.getPKCEData();if(!r)throw new Error("No code verifier or state for PKCE");if(t!==r.state)throw new Error("Provided state does not match stored state");let o=await this.getPKCEToken(e,r.verifier),i=n.mapDeviceTokenResponseToOidcUser(o),s=n.mapOidcUserToDomainModel(i);return await this.userManager.storeUser(i),s},"AUTHENTICATION_ERROR")}async getPKCEToken(e,t){let r=await fetch(`${this.config.authenticationDomain}/oauth/token`,{method:"POST",headers:je,body:new URLSearchParams({client_id:this.config.oidcConfiguration.clientId,grant_type:"authorization_code",code_verifier:t,code:e,redirect_uri:this.config.oidcConfiguration.redirectUri})}),o=await r.text(),i=et(o);if(!r.ok)throw new Error(tt(i,o,r.status));if(!i||typeof i!="object")throw new Error("Token endpoint returned an invalid response");return i}async storeTokensInternal(e){return h(async()=>{let t=n.mapDeviceTokenResponseToOidcUser(e),r=n.mapOidcUserToDomainModel(t);return await this.userManager.storeUser(t),r},"AUTHENTICATION_ERROR")}async logoutInternal(){await h(async()=>{await this.userManager.revokeTokens(["refresh_token"]),this.logoutMode==="silent"?await this.userManager.signoutSilent():await this.userManager.signoutRedirect();},"LOGOUT_ERROR");}async getLogoutUrlInternal(){let e=this.userManager.settings?.metadata?.end_session_endpoint;return e||(v.warn("Failed to get logout URL"),null)}forceUserRefreshInBackgroundInternal(){this.refreshTokenAndUpdatePromise().catch(e=>{v.warn("Failed to refresh user token",e);});}async forceUserRefreshInternal(){return this.refreshTokenAndUpdatePromise().catch(e=>(v.warn("Failed to refresh user token",e),null))}async refreshTokenAndUpdatePromise(){return this.refreshingPromise?this.refreshingPromise:(this.refreshingPromise=new Promise((e,t)=>{(async()=>{try{let r=await this.userManager.signinSilent();if(r){let o=n.mapOidcUserToDomainModel(r);this.eventEmitter.emit("tokenRefreshed",o),e(o);return}e(null);}catch(r){let o="AUTHENTICATION_ERROR",i="Failed to refresh token",s=!0;if(r instanceof ErrorTimeout?(o="SILENT_LOGIN_ERROR",i=`${i}: ${r.message}`,s=!1):r instanceof ErrorResponse?(o="NOT_LOGGED_IN_ERROR",i=`${i}: ${r.message||r.error_description}`):r instanceof Error?i=`${i}: ${r.message}`:typeof r=="string"&&(i=`${i}: ${r}`),s){this.eventEmitter.emit("userRemoved",{reason:"refresh_failed",error:i});try{await this.userManager.removeUser();}catch(a){a instanceof Error&&(i=`${i}: Failed to remove user: ${a.message}`);}}t(new f(i,o));}finally{this.refreshingPromise=null;}})();}),this.refreshingPromise)}async getUserInternal(e=t=>!0){if(this.refreshingPromise){let r=await this.refreshingPromise;return r&&e(r)?r:null}let t=await this.userManager.getUser();if(!t)return null;if(!le(t)){let r=n.mapOidcUserToDomainModel(t);if(r&&e(r))return r}if(t.refresh_token){let r=await this.refreshTokenAndUpdatePromise();if(r&&e(r))return r}return null}async getUserZkEvmInternal(){let e=await this.getUserInternal(F);if(!e)throw new Error("Failed to obtain a User with the required ZkEvm attributes");return e}};var ct="im_passport_embedded_login_prompt",ue="passport-embedded-login-iframe",ge="passport-overlay";var pt="https://auth.immutable.com",mt="platform_api",ut="openid profile email offline_access transact",gt="/authorize",ft="/oauth/token",Z="imtbl_pkce_data";function fe(n){return btoa(String.fromCharCode(...new Uint8Array(n))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function Et(n){let t=new TextEncoder().encode(n);return window.crypto.subtle.digest("SHA-256",t)}function pe(){return fe(window.crypto.getRandomValues(new Uint8Array(32)))}function $(n){return n.authenticationDomain||pt}function ht(n){try{let e=u(n);if(e.exp)return e.exp*1e3}catch{}return Date.now()+3600*1e3}function _t(n){let{access_token:e,refresh_token:t,id_token:r}=n,o={sub:""},i;if(r)try{let{sub:s,email:a,nickname:l,passport:c}=u(r);o={sub:s,email:a,nickname:l},c?.zkevm_eth_address&&c?.zkevm_user_admin_address&&(i={ethAddress:c.zkevm_eth_address,userAdminAddress:c.zkevm_user_admin_address});}catch{}return {accessToken:e,refreshToken:t,idToken:r,accessTokenExpires:ht(e),profile:o,zkEvm:i}}function yt(n){typeof window<"u"&&window.sessionStorage&&window.sessionStorage.setItem(Z,JSON.stringify(n));}function Ct(){if(typeof window<"u"&&window.sessionStorage){let n=window.sessionStorage.getItem(Z);if(n)try{return JSON.parse(n)}catch{return null}}return null}function me(){typeof window<"u"&&window.sessionStorage&&window.sessionStorage.removeItem(Z);}function Rt(){let n="passport-embedded-login-keyframes";if(document.getElementById(n))return;let e=document.createElement("style");e.id=n,e.textContent=`
388
+ @keyframes passportEmbeddedLoginPromptPopBounceIn {
389
+ 0% {
390
+ opacity: 0.5;
391
+ }
392
+ 50% {
393
+ opacity: 1;
394
+ transform: scale(1.05);
395
+ }
396
+ 75% {
397
+ transform: scale(0.98);
398
+ }
399
+ 100% {
400
+ opacity: 1;
401
+ transform: scale(1);
402
+ }
403
+ }
404
+
405
+ @media (max-height: 400px) {
406
+ #${ue} {
407
+ width: 100% !important;
408
+ max-width: none !important;
409
+ }
410
+ }
411
+
412
+ @keyframes passportEmbeddedLoginPromptOverlayFadeIn {
413
+ from {
414
+ opacity: 0;
415
+ }
416
+ to {
417
+ opacity: 1;
418
+ }
419
+ }
420
+ `,document.head.appendChild(e);}function vt(n,e){let t=getDetail(Detail.RUNTIME_ID),r=document.createElement("iframe");return r.id=ue,r.src=`${n}/im-embedded-login-prompt?client_id=${e}&rid=${t}`,r.style.height="100vh",r.style.width="100vw",r.style.maxHeight="660px",r.style.maxWidth="440px",r.style.borderRadius="16px",r.style.border="none",r.style.opacity="0",r.style.transform="scale(0.6)",r.style.animation="passportEmbeddedLoginPromptPopBounceIn 1s ease forwards",Rt(),r}function Tt(){let n=document.createElement("div");n.id=ge,n.style.cssText=`
421
+ position: fixed;
422
+ top: 0;
423
+ left: 0;
424
+ width: 100%;
425
+ height: 100%;
426
+ display: flex;
427
+ flex-direction: column;
428
+ justify-content: center;
429
+ align-items: center;
430
+ z-index: 2147483647;
431
+ background: rgba(247, 247, 247, 0.24);
432
+ animation-name: passportEmbeddedLoginPromptOverlayFadeIn;
433
+ animation-duration: 0.8s;
434
+ `;let e=document.createElement("div");return e.id=_,e.style.cssText=`
435
+ display: flex;
436
+ flex-direction: column;
437
+ align-items: center;
438
+ width: 100%;
439
+ `,n.appendChild(e),n}function w(){document.getElementById(ge)?.remove();}function Ot(n,e){return new Promise((t,r)=>{let o=vt(n,e),i=Tt(),s=({data:c,origin:d})=>{if(!(d!==n||c.eventType!==ct))switch(c.messageType){case"login_method_selected":{let g=c.payload;window.removeEventListener("message",s),w(),t(g);break}case"login_prompt_error":{window.removeEventListener("message",s),w(),r(new Error("Error during embedded login prompt",{cause:c.payload}));break}case"login_prompt_closed":{window.removeEventListener("message",s),w(),r(new Error("Login closed by user"));break}default:window.removeEventListener("message",s),w(),r(new Error(`Unsupported message type: ${c.messageType}`));break}},a=c=>{c.target===i&&(window.removeEventListener("message",s),i.removeEventListener("click",a),w(),r(new Error("Login closed by user")));};window.addEventListener("message",s),i.addEventListener("click",a);let l=i.querySelector(`#${_}`);l&&l.appendChild(o),document.body.appendChild(i);})}async function Ee(n,e){let t=$(n),r=pe(),o=fe(await Et(r)),i=pe(),s=new URL(gt,t);s.searchParams.set("response_type","code"),s.searchParams.set("code_challenge",o),s.searchParams.set("code_challenge_method","S256"),s.searchParams.set("client_id",n.clientId),s.searchParams.set("redirect_uri",n.redirectUri),s.searchParams.set("state",i),s.searchParams.set("scope",n.scope||ut),n.audience?s.searchParams.set("audience",n.audience):s.searchParams.set("audience",mt);let a=e?.directLoginOptions;return a&&(a.directLoginMethod==="email"?a.email&&(s.searchParams.set("direct","email"),s.searchParams.set("email",a.email)):s.searchParams.set("direct",a.directLoginMethod),a.marketingConsentStatus&&s.searchParams.set("marketingConsent",a.marketingConsentStatus)),{url:s.toString(),verifier:r,state:i}}async function he(n,e,t,r){let i=`${$(n)}${ft}`,s=await fetch(i,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",client_id:n.clientId,code_verifier:t,code:e,redirect_uri:r})});if(!s.ok){let l=await s.text(),c=`Token exchange failed with status ${s.status}`;try{let d=JSON.parse(l);d.error_description?c=d.error_description:d.error&&(c=d.error);}catch{l&&(c=l);}throw new Error(c)}let a=await s.json();return _t(a)}async function _e(n,e){track("passport","standaloneLoginWithPopup");let t=n.popupRedirectUri||n.redirectUri,r={...n,redirectUri:t},{url:o,verifier:i,state:s}=await Ee(r,e);return new Promise((a,l)=>{let g=window.screenX+(window.outerWidth-500)/2,ye=window.screenY+(window.outerHeight-600)/2,y=window.open(o,"immutable_login",`width=500,height=600,left=${g},top=${ye},toolbar=no,menubar=no`);if(!y){l(new Error("Popup was blocked. Please allow popups for this site."));return}let M=setInterval(()=>{try{if(y.closed){clearInterval(M),l(new Error("Login popup was closed"));return}let N=y.location.href;if(N&&N.startsWith(t)){clearInterval(M),y.close();let k=new URL(N),W=k.searchParams.get("code"),Ce=k.searchParams.get("state"),z=k.searchParams.get("error"),Re=k.searchParams.get("error_description");if(z){l(new Error(Re||z));return}if(!W){l(new Error("No authorization code received"));return}if(Ce!==s){l(new Error("State mismatch - possible CSRF attack"));return}he(r,W,i,t).then(a).catch(l);}}catch{}},100);setTimeout(()=>{clearInterval(M),y.closed||y.close(),l(new Error("Login timed out"));},5*60*1e3);})}async function Lt(n){track("passport","standaloneLoginWithEmbedded");let e=$(n),t=await Ot(e,n.clientId),r={directLoginOptions:{directLoginMethod:t.directLoginMethod,marketingConsentStatus:t.marketingConsentStatus,...t.directLoginMethod==="email"&&t.email?{email:t.email}:{}}};return _e(n,r)}async function Pt(n,e){track("passport","standaloneLoginWithRedirect");let{url:t,verifier:r,state:o}=await Ee(n,e);yt({state:o,verifier:r,redirectUri:n.redirectUri}),window.location.href=t;}async function wt(n){if(track("passport","standaloneHandleCallback"),typeof window>"u")return;let e=new URLSearchParams(window.location.search),t=e.get("code"),r=e.get("state"),o=e.get("error"),i=e.get("error_description");if(o)throw new Error(i||o);if(!t)return;let s=Ct();if(!s)throw new Error("No PKCE data found. Login may have been initiated in a different session.");if(r!==s.state)throw me(),new Error("State mismatch - possible CSRF attack");let a=await he(n,t,s.verifier,s.redirectUri);return me(),a}
388
440
 
389
- export { D as Auth, y as AuthConfiguration, M as AuthEvents, I as EvmChain, H as MarketingConsentStatus, p as PassportError, P as PassportErrorType, F as RollupType, C as TypedEventEmitter, f as decodeJwtPayload, U as isAPIError, x as isUserZkEvm, g as withPassportError };
441
+ export { K as Auth, T as AuthConfiguration, V as AuthEvents, A as EvmChain, J as MarketingConsentStatus, f as PassportError, I as PassportErrorType, Y as RollupType, R as TypedEventEmitter, u as decodeJwtPayload, wt as handleLoginCallback, H as isAPIError, F as isUserZkEvm, Lt as loginWithEmbedded, _e as loginWithPopup, Pt as loginWithRedirect, h as withPassportError };
@@ -1,7 +1,8 @@
1
1
  export { Auth } from './Auth';
2
2
  export { AuthConfiguration, type IAuthConfiguration } from './config';
3
- export type { User, UserProfile, UserZkEvm, DirectLoginMethod, DirectLoginOptions, LoginOptions, DeviceTokenResponse, OidcConfiguration, AuthModuleConfiguration, PopupOverlayOptions, PassportMetadata, PassportChainMetadata, ChainAddress, IdTokenPayload, PKCEData, AuthEventMap, } from './types';
3
+ export type { User, UserProfile, UserZkEvm, DirectLoginMethod, DirectLoginOptions, LoginOptions, DeviceTokenResponse, OidcConfiguration, AuthModuleConfiguration, PopupOverlayOptions, PassportMetadata, PassportChainMetadata, ChainAddress, ZkEvmInfo, IdTokenPayload, PKCEData, AuthEventMap, UserRemovedReason, } from './types';
4
4
  export { isUserZkEvm, RollupType, EvmChain, MarketingConsentStatus, AuthEvents, } from './types';
5
5
  export { default as TypedEventEmitter } from './utils/typedEventEmitter';
6
6
  export { PassportError, PassportErrorType, withPassportError, isAPIError, } from './errors';
7
7
  export { decodeJwtPayload } from './utils/jwt';
8
+ export { loginWithPopup, loginWithEmbedded, loginWithRedirect, handleLoginCallback, type LoginConfig, type TokenResponse, type StandaloneLoginOptions, } from './login/standalone';
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Standalone login functions for stateless authentication flows.
3
+ * These functions handle OAuth login without managing session state,
4
+ * making them ideal for use with external session managers like NextAuth.
5
+ */
6
+ import type { DirectLoginOptions, ZkEvmInfo } from '../types';
7
+ /**
8
+ * Configuration for standalone login functions
9
+ */
10
+ export interface LoginConfig {
11
+ /** Your Immutable application client ID */
12
+ clientId: string;
13
+ /** The OAuth redirect URI for your application */
14
+ redirectUri: string;
15
+ /** Optional separate redirect URI for popup flows */
16
+ popupRedirectUri?: string;
17
+ /** OAuth audience (default: "platform_api") */
18
+ audience?: string;
19
+ /** OAuth scopes (default: "openid profile email offline_access transact") */
20
+ scope?: string;
21
+ /** Authentication domain (default: "https://auth.immutable.com") */
22
+ authenticationDomain?: string;
23
+ }
24
+ /**
25
+ * Token response from successful authentication
26
+ */
27
+ export interface TokenResponse {
28
+ /** OAuth access token for API calls */
29
+ accessToken: string;
30
+ /** OAuth refresh token for token renewal */
31
+ refreshToken?: string;
32
+ /** OpenID Connect ID token */
33
+ idToken?: string;
34
+ /** Unix timestamp (ms) when the access token expires */
35
+ accessTokenExpires: number;
36
+ /** User profile information */
37
+ profile: {
38
+ sub: string;
39
+ email?: string;
40
+ nickname?: string;
41
+ };
42
+ /** zkEVM wallet information if available */
43
+ zkEvm?: ZkEvmInfo;
44
+ }
45
+ /**
46
+ * Extended login options for popup/redirect flows
47
+ */
48
+ export interface StandaloneLoginOptions {
49
+ /** Direct login options (social provider, email, etc.) */
50
+ directLoginOptions?: DirectLoginOptions;
51
+ }
52
+ /**
53
+ * Login with a popup window.
54
+ * Opens a popup for OAuth authentication and returns tokens when complete.
55
+ *
56
+ * @param config - Login configuration
57
+ * @param options - Optional login options (direct login, etc.)
58
+ * @returns Promise resolving to token response
59
+ * @throws Error if popup is blocked or login fails
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * import { loginWithPopup } from '@imtbl/auth';
64
+ *
65
+ * const tokens = await loginWithPopup({
66
+ * clientId: 'your-client-id',
67
+ * redirectUri: 'https://your-app.com/callback',
68
+ * });
69
+ * console.log(tokens.accessToken);
70
+ * ```
71
+ */
72
+ export declare function loginWithPopup(config: LoginConfig, options?: StandaloneLoginOptions): Promise<TokenResponse>;
73
+ /**
74
+ * Login with an embedded iframe modal.
75
+ * First displays a modal for the user to select their login method (email, Google, etc.),
76
+ * then opens a popup for OAuth authentication and returns tokens when complete.
77
+ *
78
+ * This provides a smoother user experience compared to loginWithPopup as the user
79
+ * can choose their login method before the OAuth popup opens.
80
+ *
81
+ * @param config - Login configuration
82
+ * @returns Promise resolving to token response
83
+ * @throws Error if modal is closed or login fails
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * import { loginWithEmbedded } from '@imtbl/auth';
88
+ *
89
+ * const tokens = await loginWithEmbedded({
90
+ * clientId: 'your-client-id',
91
+ * redirectUri: 'https://your-app.com/callback',
92
+ * });
93
+ * console.log(tokens.accessToken);
94
+ * ```
95
+ */
96
+ export declare function loginWithEmbedded(config: LoginConfig): Promise<TokenResponse>;
97
+ /**
98
+ * Login with redirect.
99
+ * Redirects the current page to OAuth authentication.
100
+ * After authentication, the user will be redirected back to your redirectUri.
101
+ * Use `handleLoginCallback` to complete the flow.
102
+ *
103
+ * @param config - Login configuration
104
+ * @param options - Optional login options (direct login, etc.)
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * import { loginWithRedirect } from '@imtbl/auth';
109
+ *
110
+ * // In your login button handler
111
+ * loginWithRedirect({
112
+ * clientId: 'your-client-id',
113
+ * redirectUri: 'https://your-app.com/callback',
114
+ * });
115
+ * ```
116
+ */
117
+ export declare function loginWithRedirect(config: LoginConfig, options?: StandaloneLoginOptions): Promise<void>;
118
+ /**
119
+ * Handle the OAuth callback after redirect-based login.
120
+ * Extracts the authorization code from the URL and exchanges it for tokens.
121
+ *
122
+ * @param config - Login configuration (must match what was used in loginWithRedirect)
123
+ * @returns Promise resolving to token response, or undefined if not a valid callback
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * // In your callback page
128
+ * import { handleLoginCallback } from '@imtbl/auth';
129
+ *
130
+ * const tokens = await handleLoginCallback({
131
+ * clientId: 'your-client-id',
132
+ * redirectUri: 'https://your-app.com/callback',
133
+ * });
134
+ *
135
+ * if (tokens) {
136
+ * // Login successful, tokens contains accessToken, refreshToken, etc.
137
+ * await signIn('immutable', { tokens: JSON.stringify(tokens) });
138
+ * }
139
+ * ```
140
+ */
141
+ export declare function handleLoginCallback(config: LoginConfig): Promise<TokenResponse | undefined>;
@@ -22,9 +22,10 @@ export declare enum EvmChain {
22
22
  ARBITRUM_ONE = "arbitrum_one"
23
23
  }
24
24
  export type ChainAddress = {
25
- ethAddress: string;
26
- userAdminAddress: string;
25
+ ethAddress: `0x${string}`;
26
+ userAdminAddress: `0x${string}`;
27
27
  };
28
+ export type ZkEvmInfo = ChainAddress;
28
29
  export type User = {
29
30
  idToken?: string;
30
31
  accessToken: string;
@@ -143,13 +144,41 @@ export type LoginOptions = {
143
144
  */
144
145
  export declare enum AuthEvents {
145
146
  LOGGED_OUT = "loggedOut",
146
- LOGGED_IN = "loggedIn"
147
+ LOGGED_IN = "loggedIn",
148
+ /**
149
+ * Emitted when tokens are refreshed via signinSilent().
150
+ * This is critical for refresh token rotation - when client-side refresh happens,
151
+ * the new tokens must be synced to server-side session to prevent race conditions.
152
+ */
153
+ TOKEN_REFRESHED = "tokenRefreshed",
154
+ /**
155
+ * Emitted when the user is removed from local storage due to a permanent auth error.
156
+ * Only emitted for errors where the refresh token is truly invalid:
157
+ * - invalid_grant: refresh token expired, revoked, or already used
158
+ * - login_required: user must re-authenticate
159
+ * - consent_required / interaction_required: user must interact with auth server
160
+ *
161
+ * NOT emitted for transient errors (network, timeout, server errors) - user stays logged in.
162
+ * Consumers should sync this state by clearing their session (e.g., NextAuth signOut).
163
+ */
164
+ USER_REMOVED = "userRemoved"
147
165
  }
166
+ /**
167
+ * Error reason for USER_REMOVED event.
168
+ * Note: Network/timeout errors do NOT emit USER_REMOVED (user stays logged in),
169
+ * so 'network_error' is not a valid reason.
170
+ */
171
+ export type UserRemovedReason = 'refresh_token_invalid' | 'refresh_failed' | 'unknown';
148
172
  /**
149
173
  * Event map for typed event emitter
150
174
  */
151
175
  export interface AuthEventMap extends Record<string, any> {
152
176
  [AuthEvents.LOGGED_OUT]: [];
153
177
  [AuthEvents.LOGGED_IN]: [User];
178
+ [AuthEvents.TOKEN_REFRESHED]: [User];
179
+ [AuthEvents.USER_REMOVED]: [{
180
+ reason: UserRemovedReason;
181
+ error?: string;
182
+ }];
154
183
  }
155
184
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imtbl/auth",
3
- "version": "2.12.5",
3
+ "version": "2.12.6-alpha.0",
4
4
  "description": "Authentication SDK for Immutable",
5
5
  "author": "Immutable",
6
6
  "bugs": "https://github.com/immutable/ts-immutable-sdk/issues",
@@ -25,18 +25,18 @@
25
25
  }
26
26
  },
27
27
  "dependencies": {
28
- "@imtbl/generated-clients": "2.12.5",
29
- "@imtbl/metrics": "2.12.5",
28
+ "@imtbl/generated-clients": "2.12.6-alpha.0",
29
+ "@imtbl/metrics": "2.12.6-alpha.0",
30
30
  "localforage": "^1.10.0",
31
31
  "oidc-client-ts": "3.4.1"
32
32
  },
33
33
  "devDependencies": {
34
- "@swc/core": "^1.3.36",
34
+ "@swc/core": "^1.4.2",
35
35
  "@swc/jest": "^0.2.37",
36
36
  "@types/jest": "^29.5.12",
37
- "@types/node": "^18.14.2",
37
+ "@types/node": "^22.10.7",
38
38
  "@jest/test-sequencer": "^29.7.0",
39
- "jest": "^29.4.3",
39
+ "jest": "^29.7.0",
40
40
  "jest-environment-jsdom": "^29.4.3",
41
41
  "ts-node": "^10.9.1",
42
42
  "tsup": "^8.3.0",