@imtbl/auth 2.10.7-alpha.6 → 2.11.1-alpha.1

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,11 +1,8 @@
1
1
  import { UserManager, User, ErrorTimeout, ErrorResponse, InMemoryWebStorage, WebStorageStateStore } from 'oidc-client-ts';
2
- import Pe, { isAxiosError } from 'axios';
3
- import J from 'jwt-decode';
4
- import Ce from 'localforage';
5
- import { track, getDetail, Detail, trackFlow, trackError, identify } from '@imtbl/metrics';
6
- import { EventEmitter } from 'events';
2
+ import he from 'localforage';
3
+ import { track, identify, getDetail, Detail, trackFlow, trackError } from '@imtbl/metrics';
7
4
 
8
- var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION="INVALID_CONFIGURATION",s.WALLET_CONNECTION_ERROR="WALLET_CONNECTION_ERROR",s.NOT_LOGGED_IN_ERROR="NOT_LOGGED_IN_ERROR",s.SILENT_LOGIN_ERROR="SILENT_LOGIN_ERROR",s.REFRESH_TOKEN_ERROR="REFRESH_TOKEN_ERROR",s.USER_REGISTRATION_ERROR="USER_REGISTRATION_ERROR",s.USER_NOT_REGISTERED_ERROR="USER_NOT_REGISTERED_ERROR",s.LOGOUT_ERROR="LOGOUT_ERROR",s.TRANSFER_ERROR="TRANSFER_ERROR",s.CREATE_ORDER_ERROR="CREATE_ORDER_ERROR",s.CANCEL_ORDER_ERROR="CANCEL_ORDER_ERROR",s.EXCHANGE_TRANSFER_ERROR="EXCHANGE_TRANSFER_ERROR",s.CREATE_TRADE_ERROR="CREATE_TRADE_ERROR",s.OPERATION_NOT_SUPPORTED_ERROR="OPERATION_NOT_SUPPORTED_ERROR",s.LINK_WALLET_ALREADY_LINKED_ERROR="LINK_WALLET_ALREADY_LINKED_ERROR",s.LINK_WALLET_MAX_WALLETS_LINKED_ERROR="LINK_WALLET_MAX_WALLETS_LINKED_ERROR",s.LINK_WALLET_VALIDATION_ERROR="LINK_WALLET_VALIDATION_ERROR",s.LINK_WALLET_DUPLICATE_NONCE_ERROR="LINK_WALLET_DUPLICATE_NONCE_ERROR",s.LINK_WALLET_GENERIC_ERROR="LINK_WALLET_GENERIC_ERROR",s.SERVICE_UNAVAILABLE_ERROR="SERVICE_UNAVAILABLE_ERROR",s))(P||{});function te(n){return "code"in n&&"message"in n}var m=class extends Error{type;constructor(e,t){super(e),this.type=t;}},f=async(n,e)=>{try{return await n()}catch(t){let r;throw t instanceof m&&t.type==="SERVICE_UNAVAILABLE_ERROR"?new m(t.message,t.type):(isAxiosError(t)&&t.response?.data&&te(t.response.data)?r=t.response.data.message:r=t.message,new m(r,e))}};var re=(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 m(i,"INVALID_CONFIGURATION")}},R=class{authenticationDomain;passportDomain;oidcConfiguration;crossSdkBridgeEnabled;popupOverlayOptions;constructor({authenticationDomain:e,passportDomain:t,crossSdkBridgeEnabled:r,popupOverlayOptions:i,...o}){re(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 S=(e=>(e.ZKEVM="zkEvm",e))(S||{}),U=n=>!!n.zkEvm,F=(t=>(t.OptedIn="opted_in",t.Unsubscribed="unsubscribed",t))(F||{}),b=(t=>(t.LOGGED_OUT="loggedOut",t.LOGGED_IN="loggedIn",t))(b||{});var H="im_passport_embedded_login_prompt";var h="passport-overlay",O="passport-overlay-contents",L=`${h}-close`,I=`${h}-try-again`,V=`
5
+ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION="INVALID_CONFIGURATION",s.WALLET_CONNECTION_ERROR="WALLET_CONNECTION_ERROR",s.NOT_LOGGED_IN_ERROR="NOT_LOGGED_IN_ERROR",s.SILENT_LOGIN_ERROR="SILENT_LOGIN_ERROR",s.REFRESH_TOKEN_ERROR="REFRESH_TOKEN_ERROR",s.USER_REGISTRATION_ERROR="USER_REGISTRATION_ERROR",s.USER_NOT_REGISTERED_ERROR="USER_NOT_REGISTERED_ERROR",s.LOGOUT_ERROR="LOGOUT_ERROR",s.TRANSFER_ERROR="TRANSFER_ERROR",s.CREATE_ORDER_ERROR="CREATE_ORDER_ERROR",s.CANCEL_ORDER_ERROR="CANCEL_ORDER_ERROR",s.EXCHANGE_TRANSFER_ERROR="EXCHANGE_TRANSFER_ERROR",s.CREATE_TRADE_ERROR="CREATE_TRADE_ERROR",s.OPERATION_NOT_SUPPORTED_ERROR="OPERATION_NOT_SUPPORTED_ERROR",s.LINK_WALLET_ALREADY_LINKED_ERROR="LINK_WALLET_ALREADY_LINKED_ERROR",s.LINK_WALLET_MAX_WALLETS_LINKED_ERROR="LINK_WALLET_MAX_WALLETS_LINKED_ERROR",s.LINK_WALLET_VALIDATION_ERROR="LINK_WALLET_VALIDATION_ERROR",s.LINK_WALLET_DUPLICATE_NONCE_ERROR="LINK_WALLET_DUPLICATE_NONCE_ERROR",s.LINK_WALLET_GENERIC_ERROR="LINK_WALLET_GENERIC_ERROR",s.SERVICE_UNAVAILABLE_ERROR="SERVICE_UNAVAILABLE_ERROR",s.TRANSACTION_REJECTED="TRANSACTION_REJECTED",s))(P||{});function b(n){return typeof n=="object"&&n!==null&&"code"in n&&"message"in n}var X=n=>{if(b(n))return n;if(typeof n=="object"&&n!==null&&"response"in n){let{response:e}=n;if(e?.data&&b(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=X(t);throw i?r=i.message:r=t.message,new p(r,e)}};var ee=(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")}},_=class{authenticationDomain;passportDomain;oidcConfiguration;crossSdkBridgeEnabled;popupOverlayOptions;constructor({authenticationDomain:e,passportDomain:t,crossSdkBridgeEnabled:r,popupOverlayOptions:i,...o}){ee(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 D=(e=>(e.ZKEVM="zkEvm",e))(D||{}),U=n=>!!n.zkEvm,F=(t=>(t.OptedIn="opted_in",t.Unsubscribed="unsubscribed",t))(F||{}),x=(t=>(t.LOGGED_OUT="loggedOut",t.LOGGED_IN="loggedIn",t))(x||{});var H="im_passport_embedded_login_prompt";var h="passport-overlay",R="passport-overlay-contents",I=`${h}-close`,w=`${h}-try-again`,V=`
9
6
  <svg
10
7
  viewBox="0 0 20 20"
11
8
  fill="none"
@@ -31,7 +28,7 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
31
28
  fill="#E01A3D"
32
29
  />
33
30
  </svg>
34
- `,x=`
31
+ `,S=`
35
32
  <svg
36
33
  style="
37
34
  max-width: 123px !important;
@@ -214,9 +211,9 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
214
211
  </clipPath>
215
212
  </defs>
216
213
  </svg>
217
- `;var ie=()=>`
214
+ `;var te=()=>`
218
215
  <button
219
- id="${L}"
216
+ id="${I}"
220
217
  style="
221
218
  background: #f3f3f326 !important;
222
219
  border: none !important;
@@ -236,7 +233,7 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
236
233
  </button>
237
234
  `,B=()=>`
238
235
  <button
239
- id="${I}"
236
+ id="${w}"
240
237
  style="
241
238
  margin-top: 27px !important;
242
239
  color: #f3f3f3 !important;
@@ -251,8 +248,8 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
251
248
  >
252
249
  Try again
253
250
  </button>
254
- `,ne=()=>`
255
- ${x}
251
+ `,re=()=>`
252
+ ${S}
256
253
  <div
257
254
  style="
258
255
  color: #e01a3d !important;
@@ -276,8 +273,8 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
276
273
  browser settings.
277
274
  </p>
278
275
  ${B()}
279
- `,oe=()=>`
280
- ${x}
276
+ `,ne=()=>`
277
+ ${S}
281
278
  <p style="
282
279
  color: #b6b6b6 !important;
283
280
  text-align: center !important;
@@ -287,7 +284,7 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
287
284
  Secure pop-up not showing?<br />We'll help you re-launch
288
285
  </p>
289
286
  ${B()}
290
- `,Z=n=>`
287
+ `,K=n=>`
291
288
  <div
292
289
  id="${h}"
293
290
  style="
@@ -312,9 +309,9 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
312
309
  z-index: 2147483647 !important;
313
310
  "
314
311
  >
315
- ${ie()}
312
+ ${te()}
316
313
  <div
317
- id="${O}"
314
+ id="${R}"
318
315
  style="
319
316
  display: flex !important;
320
317
  flex-direction: column !important;
@@ -325,7 +322,7 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
325
322
  ${n??""}
326
323
  </div>
327
324
  </div>
328
- `,K=()=>`
325
+ `,Z=()=>`
329
326
  <div
330
327
  id="${h}"
331
328
  style="
@@ -345,7 +342,7 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
345
342
  "
346
343
  >
347
344
  <div
348
- id="${O}"
345
+ id="${R}"
349
346
  style="
350
347
  display: flex;
351
348
  flex-direction: column;
@@ -354,7 +351,7 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
354
351
  "
355
352
  />
356
353
  </div>
357
- `;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()),W=()=>Z(oe());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=K(),document.body.insertAdjacentElement("beforeend",r);let i=document.querySelector(`#${O}`);i&&i.appendChild(e),r.addEventListener("click",t),this.overlay=r;}}};var le=660,de=440,ce="16px",Y="passport-embedded-login-keyframes",z="passport-embedded-login-iframe",y=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 A({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 W=()=>K(re()),$=()=>K(ne());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=Z(),document.body.insertAdjacentElement("beforeend",r);let i=document.querySelector(`#${R}`);i&&i.appendChild(e),r.addEventListener("click",t),this.overlay=r;}}};var se=660,ae=440,le="16px",Y="passport-embedded-login-keyframes",z="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(Y))return;let e=document.createElement("style");e.id=Y,e.textContent=`
358
355
  @keyframes passportEmbeddedLoginPromptPopBounceIn {
359
356
  0% {
360
357
  opacity: 0.5;
@@ -387,6 +384,6 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
387
384
  opacity: 1;
388
385
  }
389
386
  }
390
- `,document.head.appendChild(e);};getEmbeddedLoginIFrame=()=>{let e=document.createElement("iframe");return e.id=z,e.src=this.getHref(),e.style.height="100vh",e.style.width="100vw",e.style.maxHeight=`${le}px`,e.style.maxWidth=`${de}px`,e.style.borderRadius=ce,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:d})=>{if(!(d!==this.config.authenticationDomain||o.eventType!==H))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{emitter=new EventEmitter;emit(e,...t){this.emitter.emit(e,...t);}on(e,t){this.emitter.on(e,t);}removeListener(e,t){this.emitter.removeListener(e,t);}};var p=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 j="pkce_state",Q="pkce_verifier",fe=3600,v=class{isTokenValid(e){try{let r=J(e).exp??0,i=Date.now()/1e3+fe;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 Ee=(...n)=>{if(typeof process>"u")return;process?.env?.JEST_WORKER_ID===void 0&&console.warn(...n);},_={warn:Ee};function q(n){try{let e=J(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?$():W(),document.body.insertAdjacentElement("beforeend",t),this.overlay=t;}}updateTryAgainButton(e){let t=document.getElementById(I);t&&(this.tryAgainListener&&t.removeEventListener("click",this.tryAgainListener),this.tryAgainListener=e,t.addEventListener("click",e));}updateCloseButton(e){let t=document.getElementById(L);t&&(this.onCloseListener&&t.removeEventListener("click",this.onCloseListener),this.onCloseListener=e,t.addEventListener("click",e));}};var w=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 Ue=500,be={headers:{"Content-Type":"application/x-www-form-urlencoded"}},xe="/v2/logout",Me="/im-logged-out",De="/authorize",Ne=n=>n?Me:xe,Se=n=>{let{authenticationDomain:e,oidcConfiguration:t}=n,r;n.crossSdkBridgeEnabled?r=new w("ImmutableSDKPassport",Ce.INDEXEDDB):typeof window<"u"?r=window.localStorage:r=new InMemoryWebStorage;let i=new WebStorageStateStore({store:r}),o=new URL(Ne(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 M(n){return btoa(String.fromCharCode(...new Uint8Array(n))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function Fe(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 R(e),this.embeddedLoginPrompt=new y(this.config),this.userManager=new UserManager(Se(this.config)),this.deviceCredentialsManager=new v,this.logoutMode=this.config.oidcConfiguration.logoutMode||"redirect",this.eventEmitter=new C,track("passport","initialise");}async login(e){return p(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.eventEmitter.emit("loggedIn",i),identify({passportId:i.profile.sub})),i},"login")}async loginWithRedirect(e){await this.loginWithRedirectInternal(e);}async loginCallback(){return p(async()=>{let e=await this.loginCallbackInternal();return e&&(this.eventEmitter.emit("loggedIn",e),identify({passportId:e.profile.sub})),e},"loginCallback")}async logout(){await p(async()=>{await this.logoutInternal(),this.eventEmitter.emit("loggedOut");},"logout");}async getUser(){return p(async()=>this.getUserInternal(),"getUserInfo",!1)}async getUserOrLogin(){let e=null;try{e=await this.getUserInternal();}catch(t){_.warn("Failed to retrieve a cached user session",t);}return e||this.loginWithPopup()}async getUserZkEvm(){return this.getUserZkEvmInternal()}async getIdToken(){return p(async()=>(await this.getUserInternal())?.idToken,"getIdToken",!1)}async getAccessToken(){return p(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 p(async()=>this.getPKCEAuthorizationUrl(e,t),"loginWithPKCEFlow")}async loginWithPKCEFlowCallback(e,t){return p(async()=>{let r=await this.loginWithPKCEFlowCallbackInternal(e,t);return this.eventEmitter.emit("loggedIn",r),identify({passportId:r.profile.sub}),r},"loginWithPKCEFlowCallback")}async storeTokens(e){return p(async()=>{let t=await this.storeTokensInternal(e);return this.eventEmitter.emit("loggedIn",t),identify({passportId:t.profile.sub}),t},"storeTokens")}async getLogoutUrl(){return p(async()=>(await this.userManager.removeUser(),this.eventEmitter.emit("loggedOut"),await this.getLogoutUrlInternal()||void 0),"getLogoutUrl")}async logoutSilentCallback(e){return p(()=>this.userManager.signoutSilentCallback(e),"logoutSilentCallback")}getConfig(){return this.config}async getClientId(){return this.config.oidcConfiguration.clientId}buildExtraQueryParams(e,t){let r={...this.userManager.settings?.extraQueryParams??{},rid:getDetail(Detail.RUNTIME_ID)||"",third_party_a_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 f(async()=>{let t=this.buildExtraQueryParams(e);await this.userManager.signinRedirect({extraQueryParams:t});},"AUTHENTICATION_ERROR");}async loginWithPopup(e){return f(async()=>{let t,r;if(e)t=e;else if(!this.config.popupOverlayOptions?.disableHeadlessLoginPromptOverlay){let{imPassportTraceId:d,...l}=await this.embeddedLoginPrompt.displayEmbeddedLoginPrompt();t=l,r=d;}let i=window.crypto.randomUUID(),o=async()=>{let d=this.buildExtraQueryParams(t,r),l=this.userManager.signinPopup({extraQueryParams:d,popupWindowFeatures:{width:410,height:450},popupWindowTarget:i}),c=window.open("",i);if(c){let E=new Promise((a,g)=>{let N=setInterval(()=>{c.closed&&(clearInterval(N),g(new Error("Popup closed by user")));},Ue);l.finally(()=>{clearInterval(N),c.close();});});return Promise.race([l,E])}return l};return new Promise((d,l)=>{o().then(c=>d(n.mapOidcUserToDomainModel(c))).catch(c=>{if(!(c instanceof Error)||c.message!=="Attempted to navigate on a disposed window"){l(c);return}let E=!1,a=new T(this.config.popupOverlayOptions||{},!0);a.append(async()=>{try{if(E)window.open("",i);else {E=!0;let g=await o();a.remove(),d(n.mapOidcUserToDomainModel(g));}}catch(g){a.remove(),l(g);}},()=>{a.remove(),l(new Error("Popup closed by user"));});});})},"AUTHENTICATION_ERROR")}static mapOidcUserToDomainModel=e=>{let t;e.id_token&&(t=J(e.id_token)?.passport);let r={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}};return t?.zkevm_eth_address&&t?.zkevm_user_admin_address&&(r.zkEvm={ethAddress:t.zkevm_eth_address,userAdminAddress:t.zkevm_user_admin_address}),r};static mapDeviceTokenResponseToOidcUser=e=>{let t=J(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}})};static shouldUseSigninPopupCallback(){try{let r=`oidc.${new URLSearchParams(window.location.search).get("state")}`,i=localStorage.getItem(r);return JSON.parse(i||"{}")?.request_type==="si:p"}catch{return !1}}async loginCallbackInternal(){return f(async()=>{if(n.shouldUseSigninPopupCallback()){await this.userManager.signinPopupCallback(void 0,!0);return}let e=await this.userManager.signinCallback();if(e)return n.mapOidcUserToDomainModel(e)},"AUTHENTICATION_ERROR")}async getPKCEAuthorizationUrl(e,t){let r=M(window.crypto.getRandomValues(new Uint8Array(32))),i=M(await Fe(r)),o=M(window.crypto.getRandomValues(new Uint8Array(32))),{redirectUri:d,scope:l,audience:c,clientId:E}=this.config.oidcConfiguration;this.deviceCredentialsManager.savePKCEData({state:o,verifier:r});let a=new URL(De,this.config.authenticationDomain);if(a.searchParams.set("response_type","code"),a.searchParams.set("code_challenge",i),a.searchParams.set("code_challenge_method","S256"),a.searchParams.set("client_id",E),a.searchParams.set("redirect_uri",d),a.searchParams.set("state",o),l&&a.searchParams.set("scope",l),c&&a.searchParams.set("audience",c),e){if(e.directLoginMethod==="email"){let g=e.email;g&&(a.searchParams.set("direct",e.directLoginMethod),a.searchParams.set("email",g));}else a.searchParams.set("direct",e.directLoginMethod);e.marketingConsentStatus&&a.searchParams.set("marketingConsent",e.marketingConsentStatus);}return t&&a.searchParams.set("im_passport_trace_id",t),a.toString()}async loginWithPKCEFlowCallbackInternal(e,t){return f(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),d=n.mapOidcUserToDomainModel(o);return await this.userManager.storeUser(o),d},"AUTHENTICATION_ERROR")}async getPKCEToken(e,t){return (await Pe.post(`${this.config.authenticationDomain}/oauth/token`,{client_id:this.config.oidcConfiguration.clientId,grant_type:"authorization_code",code_verifier:t,code:e,redirect_uri:this.config.oidcConfiguration.redirectUri},be)).data}async storeTokensInternal(e){return f(async()=>{let t=n.mapDeviceTokenResponseToOidcUser(e),r=n.mapOidcUserToDomainModel(t);return await this.userManager.storeUser(t),r},"AUTHENTICATION_ERROR")}async logoutInternal(){await f(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",d=!0;if(r instanceof ErrorTimeout?(i="SILENT_LOGIN_ERROR",o=`${o}: ${r.message}`,d=!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}`),d)try{await this.userManager.removeUser();}catch(l){l instanceof Error&&(o=`${o}: Failed to remove user: ${l.message}`);}t(new m(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(U);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=z,e.src=this.getHref(),e.style.height="100vh",e.style.width="100vw",e.style.maxHeight=`${se}px`,e.style.maxWidth=`${ae}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:l})=>{if(!(l!==this.config.authenticationDomain||o.eventType!==H))switch(o.messageType){case"login_method_selected":{let d=o.payload;window.removeEventListener("message",i),u.remove(),e(d);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 pe=()=>typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{},ue=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=pe();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},ge=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},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=ge(ue(t));try{return JSON.parse(r)}catch{throw new Error("Invalid JWT payload: unable to parse JSON")}};var J="pkce_state",j="pkce_verifier",fe=3600,v=class{isTokenValid(e){try{let r=f(e).exp??0,i=Date.now()/1e3+fe;return r>i}catch{return !1}}savePKCEData(e){localStorage.setItem(J,e.state),localStorage.setItem(j,e.verifier);}getPKCEData(){let e=localStorage.getItem(J),t=localStorage.getItem(j);return e&&t?{state:e,verifier:t}:null}};var Ee=(...n)=>{if(typeof process>"u")return;process?.env?.JEST_WORKER_ID===void 0&&console.warn(...n);},y={warn:Ee};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 q(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){A({id:"link-googleapis",href:"https://fonts.googleapis.com"}),A({id:"link-gstatic",href:"https://fonts.gstatic.com",crossOrigin:"anonymous"}),A({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?W():$(),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(I);t&&(this.onCloseListener&&t.removeEventListener("click",this.onCloseListener),this.onCloseListener=e,t.addEventListener("click",e));}};var k=class{storage;constructor(e,t){this.storage=he.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 ke={"Content-Type":"application/x-www-form-urlencoded"},be=n=>{if(n)try{return JSON.parse(n)}catch{return}},Ue=(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}`},xe="/v2/logout",Se="/im-logged-out",Me="/authorize",Ne=n=>n?Se:xe,De=n=>{let{authenticationDomain:e,oidcConfiguration:t}=n,r;n.crossSdkBridgeEnabled?r=new k("ImmutableSDKPassport",he.INDEXEDDB):typeof window<"u"?r=window.localStorage:r=new InMemoryWebStorage;let i=new WebStorageStateStore({store:r}),o=new URL(Ne(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 M(n){return btoa(String.fromCharCode(...new Uint8Array(n))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function Fe(n){let t=new TextEncoder().encode(n);return window.crypto.subtle.digest("SHA-256",t)}var N=class n{config;userManager;deviceCredentialsManager;embeddedLoginPrompt;logoutMode;refreshingPromise=null;eventEmitter;constructor(e){this.config=new _(e),this.embeddedLoginPrompt=new O(this.config),this.userManager=new UserManager(De(this.config)),this.deviceCredentialsManager=new v,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;y.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){y.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:l,...d}=await this.embeddedLoginPrompt.displayEmbeddedLoginPrompt();t=d,r=l;}let i=window.crypto.randomUUID(),o=async()=>{let l=this.buildExtraQueryParams(t,r);return this.userManager.signinPopup({extraQueryParams:l,popupWindowFeatures:{width:410,height:450},popupWindowTarget:i})};return new Promise((l,d)=>{o().then(m=>l(n.mapOidcUserToDomainModel(m))).catch(m=>{if(!(m instanceof Error)||m.message!=="Attempted to navigate on a disposed window"){d(m);return}let L=!1,a=new T(this.config.popupOverlayOptions||{},!0);a.append(async()=>{try{if(L)window.open("",i);else {L=!0;let E=await o();a.remove(),l(n.mapOidcUserToDomainModel(E));}}catch(E){a.remove(),d(E);}},()=>{a.remove(),d(new Error("Popup closed by user"));});});})},"AUTHENTICATION_ERROR")}static mapOidcUserToDomainModel=e=>{let t,r;if(e.id_token){let o=f(e.id_token);t=o?.passport,o?.username&&(r=o?.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}};return t?.zkevm_eth_address&&t?.zkevm_user_admin_address&&(i.zkEvm={ethAddress:t.zkevm_eth_address,userAdminAddress:t.zkevm_user_admin_address}),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=M(window.crypto.getRandomValues(new Uint8Array(32))),i=M(await Fe(r)),o=M(window.crypto.getRandomValues(new Uint8Array(32))),{redirectUri:l,scope:d,audience:m,clientId:L}=this.config.oidcConfiguration;this.deviceCredentialsManager.savePKCEData({state:o,verifier:r});let a=new URL(Me,this.config.authenticationDomain);if(a.searchParams.set("response_type","code"),a.searchParams.set("code_challenge",i),a.searchParams.set("code_challenge_method","S256"),a.searchParams.set("client_id",L),a.searchParams.set("redirect_uri",l),a.searchParams.set("state",o),d&&a.searchParams.set("scope",d),m&&a.searchParams.set("audience",m),e){if(e.directLoginMethod==="email"){let E=e.email;E&&(a.searchParams.set("direct",e.directLoginMethod),a.searchParams.set("email",E));}else a.searchParams.set("direct",e.directLoginMethod);e.marketingConsentStatus&&a.searchParams.set("marketingConsent",e.marketingConsentStatus);}return t&&a.searchParams.set("im_passport_trace_id",t),a.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),l=n.mapOidcUserToDomainModel(o);return await this.userManager.storeUser(o),l},"AUTHENTICATION_ERROR")}async getPKCEToken(e,t){let r=await fetch(`${this.config.authenticationDomain}/oauth/token`,{method:"POST",headers:ke,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=be(i);if(!r.ok)throw new Error(Ue(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||(y.warn("Failed to get logout URL"),null)}forceUserRefreshInBackgroundInternal(){this.refreshTokenAndUpdatePromise().catch(e=>{y.warn("Failed to refresh user token",e);});}async forceUserRefreshInternal(){return this.refreshTokenAndUpdatePromise().catch(e=>(y.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",l=!0;if(r instanceof ErrorTimeout?(i="SILENT_LOGIN_ERROR",o=`${o}: ${r.message}`,l=!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}`),l)try{await this.userManager.removeUser();}catch(d){d instanceof Error&&(o=`${o}: Failed to remove user: ${d.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(!q(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(U);if(!e)throw new Error("Failed to obtain a User with the required ZkEvm attributes");return e}};
391
388
 
392
- export { D as Auth, R as AuthConfiguration, b as AuthEvents, F as MarketingConsentStatus, m as PassportError, P as PassportErrorType, S as RollupType, C as TypedEventEmitter, U as isUserZkEvm, f as withPassportError };
389
+ export { N as Auth, _ as AuthConfiguration, x as AuthEvents, F as MarketingConsentStatus, p as PassportError, P as PassportErrorType, D as RollupType, C as TypedEventEmitter, f as decodeJwtPayload, b as isAPIError, U as isUserZkEvm, g as withPassportError };
@@ -145,12 +145,12 @@ export declare class Auth {
145
145
  * @returns Promise that resolves with the client ID string
146
146
  */
147
147
  getClientId(): Promise<string>;
148
+ private handleSuccessfulLogin;
148
149
  private buildExtraQueryParams;
149
150
  private loginWithRedirectInternal;
150
151
  private loginWithPopup;
151
152
  private static mapOidcUserToDomainModel;
152
153
  private static mapDeviceTokenResponseToOidcUser;
153
- private static shouldUseSigninPopupCallback;
154
154
  private loginCallbackInternal;
155
155
  private getPKCEAuthorizationUrl;
156
156
  private loginWithPKCEFlowCallbackInternal;
@@ -20,7 +20,8 @@ export declare enum PassportErrorType {
20
20
  LINK_WALLET_VALIDATION_ERROR = "LINK_WALLET_VALIDATION_ERROR",
21
21
  LINK_WALLET_DUPLICATE_NONCE_ERROR = "LINK_WALLET_DUPLICATE_NONCE_ERROR",
22
22
  LINK_WALLET_GENERIC_ERROR = "LINK_WALLET_GENERIC_ERROR",
23
- SERVICE_UNAVAILABLE_ERROR = "SERVICE_UNAVAILABLE_ERROR"
23
+ SERVICE_UNAVAILABLE_ERROR = "SERVICE_UNAVAILABLE_ERROR",
24
+ TRANSACTION_REJECTED = "TRANSACTION_REJECTED"
24
25
  }
25
26
  export declare function isAPIError(error: any): error is imx.APIError;
26
27
  export declare class PassportError extends Error {
@@ -3,4 +3,5 @@ export { AuthConfiguration, type IAuthConfiguration } from './config';
3
3
  export type { User, UserProfile, UserZkEvm, DirectLoginMethod, DirectLoginOptions, LoginOptions, DeviceTokenResponse, OidcConfiguration, AuthModuleConfiguration, PopupOverlayOptions, PassportMetadata, IdTokenPayload, PKCEData, AuthEventMap, } from './types';
4
4
  export { isUserZkEvm, RollupType, MarketingConsentStatus, AuthEvents, } from './types';
5
5
  export { default as TypedEventEmitter } from './utils/typedEventEmitter';
6
- export { PassportError, PassportErrorType, withPassportError } from './errors';
6
+ export { PassportError, PassportErrorType, withPassportError, isAPIError, } from './errors';
7
+ export { decodeJwtPayload } from './utils/jwt';
@@ -8,6 +8,7 @@ export type UserProfile = {
8
8
  email?: string;
9
9
  nickname?: string;
10
10
  sub: string;
11
+ username?: string;
11
12
  };
12
13
  export declare enum RollupType {
13
14
  ZKEVM = "zkEvm"
@@ -77,6 +78,7 @@ export type TokenPayload = {
77
78
  };
78
79
  export type IdTokenPayload = {
79
80
  passport?: PassportMetadata;
81
+ username?: string;
80
82
  email: string;
81
83
  nickname: string;
82
84
  aud: string;
@@ -0,0 +1 @@
1
+ export declare const decodeJwtPayload: <T>(token: string) => T;
@@ -1,6 +1,9 @@
1
+ type StringEventKey<T> = Extract<keyof T, string>;
2
+ type EventArgs<TEvents, TEventName extends keyof TEvents> = TEvents[TEventName] extends readonly [...infer A] ? [...A] : TEvents[TEventName] extends readonly any[] ? [...TEvents[TEventName]] : [TEvents[TEventName]];
1
3
  export default class TypedEventEmitter<TEvents extends Record<string, any>> {
2
- private emitter;
3
- emit<TEventName extends keyof TEvents & string>(eventName: TEventName, ...eventArg: TEvents[TEventName]): void;
4
- on<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void): void;
5
- removeListener<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void): void;
4
+ private listeners;
5
+ emit<TEventName extends StringEventKey<TEvents>>(eventName: TEventName, ...eventArg: EventArgs<TEvents, TEventName>): void;
6
+ on<TEventName extends StringEventKey<TEvents>>(eventName: TEventName, handler: (...eventArg: EventArgs<TEvents, TEventName>) => void): void;
7
+ removeListener<TEventName extends StringEventKey<TEvents>>(eventName: TEventName, handler: (...eventArg: EventArgs<TEvents, TEventName>) => void): void;
6
8
  }
9
+ export {};
package/jest.config.ts ADDED
@@ -0,0 +1,27 @@
1
+ import type { Config } from 'jest';
2
+ import { execSync } from 'child_process';
3
+ import { name } from './package.json';
4
+
5
+ const rootDirs = execSync(`pnpm --filter ${name}... exec pwd`)
6
+ .toString()
7
+ .split('\n')
8
+ .filter(Boolean)
9
+ .map((dir) => `${dir}/dist`);
10
+
11
+ const config: Config = {
12
+ clearMocks: true,
13
+ roots: ['<rootDir>/src', ...rootDirs],
14
+ coverageProvider: 'v8',
15
+ moduleDirectories: ['node_modules', 'src'],
16
+ moduleNameMapper: { '^@imtbl/(.*)$': '<rootDir>/../../node_modules/@imtbl/$1/src' },
17
+ testEnvironment: 'jsdom',
18
+ transform: {
19
+ '^.+\\.(t|j)sx?$': '@swc/jest',
20
+ },
21
+ transformIgnorePatterns: [],
22
+ restoreMocks: true,
23
+ setupFiles: ['<rootDir>/jest.setup.js'],
24
+ };
25
+
26
+ export default config;
27
+
package/jest.setup.js ADDED
@@ -0,0 +1,4 @@
1
+ import { TextEncoder } from 'util';
2
+
3
+ global.TextEncoder = TextEncoder;
4
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imtbl/auth",
3
- "version": "2.10.7-alpha.6",
3
+ "version": "2.11.1-alpha.1",
4
4
  "description": "Authentication SDK for Immutable",
5
5
  "author": "Immutable",
6
6
  "bugs": "https://github.com/immutable/ts-immutable-sdk/issues",
@@ -25,17 +25,19 @@
25
25
  }
26
26
  },
27
27
  "dependencies": {
28
- "@imtbl/config": "2.10.7-alpha.6",
29
- "@imtbl/metrics": "2.10.7-alpha.6",
30
- "axios": "^1.6.5",
31
- "jwt-decode": "^3.1.2",
28
+ "@imtbl/metrics": "2.11.1-alpha.1",
32
29
  "localforage": "^1.10.0",
33
- "oidc-client-ts": "3.3.0",
34
- "uuid": "^9.0.1"
30
+ "oidc-client-ts": "3.4.1"
35
31
  },
36
32
  "devDependencies": {
37
- "@imtbl/toolkit": "2.10.7-alpha.6",
33
+ "@swc/core": "^1.3.36",
34
+ "@swc/jest": "^0.2.37",
35
+ "@types/jest": "^29.5.12",
38
36
  "@types/node": "^18.14.2",
37
+ "@jest/test-sequencer": "^29.7.0",
38
+ "jest": "^29.4.3",
39
+ "jest-environment-jsdom": "^29.4.3",
40
+ "ts-node": "^10.9.1",
39
41
  "tsup": "^8.3.0",
40
42
  "typescript": "^5.6.2"
41
43
  },
@@ -50,6 +52,7 @@
50
52
  "typegen": "tsc --customConditions default --emitDeclarationOnly --outDir dist/types",
51
53
  "pack:root": "pnpm pack --pack-destination $(dirname $(pnpm root -w))",
52
54
  "lint": "eslint ./src --ext .ts,.jsx,.tsx --max-warnings=0",
53
- "typecheck": "tsc --customConditions default --noEmit --jsx preserve"
55
+ "typecheck": "tsc --customConditions default --noEmit --jsx preserve",
56
+ "test": "jest"
54
57
  }
55
58
  }
@@ -0,0 +1,188 @@
1
+ import { Auth } from './Auth';
2
+ import { AuthEvents, User } from './types';
3
+ import { withMetricsAsync } from './utils/metrics';
4
+ import { decodeJwtPayload } from './utils/jwt';
5
+
6
+ const trackFlowMock = jest.fn();
7
+ const trackErrorMock = jest.fn();
8
+ const identifyMock = jest.fn();
9
+ const trackMock = jest.fn();
10
+ const getDetailMock = jest.fn();
11
+
12
+ jest.mock('@imtbl/metrics', () => ({
13
+ Detail: { RUNTIME_ID: 'runtime-id' },
14
+ trackFlow: (...args: any[]) => trackFlowMock(...args),
15
+ trackError: (...args: any[]) => trackErrorMock(...args),
16
+ identify: (...args: any[]) => identifyMock(...args),
17
+ track: (...args: any[]) => trackMock(...args),
18
+ getDetail: (...args: any[]) => getDetailMock(...args),
19
+ }));
20
+
21
+ jest.mock('./utils/jwt', () => ({
22
+ decodeJwtPayload: jest.fn(),
23
+ }));
24
+
25
+ beforeEach(() => {
26
+ trackFlowMock.mockReset();
27
+ trackErrorMock.mockReset();
28
+ identifyMock.mockReset();
29
+ trackMock.mockReset();
30
+ getDetailMock.mockReset();
31
+ (decodeJwtPayload as jest.Mock).mockReset();
32
+ });
33
+
34
+ describe('withMetricsAsync', () => {
35
+ it('resolves with function result and tracks flow', async () => {
36
+ const flow = {
37
+ addEvent: jest.fn(),
38
+ details: { flowId: 'flow-id' },
39
+ };
40
+ trackFlowMock.mockReturnValue(flow);
41
+
42
+ const result = await withMetricsAsync(async () => 'done', 'login');
43
+
44
+ expect(result).toEqual('done');
45
+ expect(trackFlowMock).toHaveBeenCalledWith('passport', 'login', true);
46
+ expect(flow.addEvent).toHaveBeenCalledWith('End');
47
+ });
48
+
49
+ it('tracks error when function throws', async () => {
50
+ const flow = {
51
+ addEvent: jest.fn(),
52
+ details: { flowId: 'flow-id' },
53
+ };
54
+ trackFlowMock.mockReturnValue(flow);
55
+ const error = new Error('boom');
56
+
57
+ await expect(withMetricsAsync(async () => {
58
+ throw error;
59
+ }, 'login')).rejects.toThrow(error);
60
+
61
+ expect(trackErrorMock).toHaveBeenCalledWith('passport', 'login', error, { flowId: 'flow-id' });
62
+ expect(flow.addEvent).toHaveBeenCalledWith('End');
63
+ });
64
+
65
+ it('does not fail when non-error is thrown', async () => {
66
+ const flow = {
67
+ addEvent: jest.fn(),
68
+ details: { flowId: 'flow-id' },
69
+ };
70
+ trackFlowMock.mockReturnValue(flow);
71
+
72
+ const nonError = { message: 'failure' };
73
+ await expect(withMetricsAsync(async () => {
74
+ throw nonError as unknown as Error;
75
+ }, 'login')).rejects.toBe(nonError);
76
+
77
+ expect(flow.addEvent).toHaveBeenCalledWith('errored');
78
+ });
79
+ });
80
+
81
+ describe('Auth', () => {
82
+ describe('getUserOrLogin', () => {
83
+ const createMockUser = (): User => ({
84
+ accessToken: 'access',
85
+ idToken: 'id',
86
+ refreshToken: 'refresh',
87
+ expired: false,
88
+ profile: {
89
+ sub: 'user-123',
90
+ email: 'test@example.com',
91
+ nickname: 'tester',
92
+ },
93
+ });
94
+
95
+ it('emits LOGGED_IN event and identifies user when login is required', async () => {
96
+ const auth = Object.create(Auth.prototype) as Auth;
97
+ const loginWithPopup = jest.fn().mockResolvedValue(createMockUser());
98
+
99
+ (auth as any).eventEmitter = { emit: jest.fn() };
100
+ (auth as any).getUserInternal = jest.fn().mockResolvedValue(null);
101
+ (auth as any).loginWithPopup = loginWithPopup;
102
+
103
+ const user = await auth.getUserOrLogin();
104
+
105
+ expect(loginWithPopup).toHaveBeenCalledTimes(1);
106
+ expect((auth as any).eventEmitter.emit).toHaveBeenCalledWith(AuthEvents.LOGGED_IN, user);
107
+ expect(identifyMock).toHaveBeenCalledWith({ passportId: user.profile.sub });
108
+ });
109
+
110
+ it('returns cached user without triggering login', async () => {
111
+ const auth = Object.create(Auth.prototype) as Auth;
112
+ const cachedUser = createMockUser();
113
+
114
+ (auth as any).eventEmitter = { emit: jest.fn() };
115
+ (auth as any).getUserInternal = jest.fn().mockResolvedValue(cachedUser);
116
+ (auth as any).loginWithPopup = jest.fn();
117
+
118
+ const user = await auth.getUserOrLogin();
119
+
120
+ expect(user).toBe(cachedUser);
121
+ expect((auth as any).loginWithPopup).not.toHaveBeenCalled();
122
+ expect((auth as any).eventEmitter.emit).not.toHaveBeenCalled();
123
+ expect(identifyMock).not.toHaveBeenCalled();
124
+ });
125
+ });
126
+
127
+ describe('buildExtraQueryParams', () => {
128
+ it('omits third_party_a_id when no anonymous id is provided', () => {
129
+ const auth = Object.create(Auth.prototype) as Auth;
130
+ (auth as any).userManager = { settings: { extraQueryParams: {} } };
131
+ getDetailMock.mockReturnValue('runtime-id-value');
132
+
133
+ const params = (auth as any).buildExtraQueryParams();
134
+
135
+ expect(params.third_party_a_id).toBeUndefined();
136
+ expect(params.rid).toEqual('runtime-id-value');
137
+ });
138
+ });
139
+
140
+ describe('username extraction', () => {
141
+ it('extracts username from id token when present', () => {
142
+ const mockOidcUser = {
143
+ id_token: 'token',
144
+ access_token: 'access',
145
+ refresh_token: 'refresh',
146
+ expired: false,
147
+ profile: { sub: 'user-123', email: 'test@example.com', nickname: 'tester' },
148
+ };
149
+
150
+ (decodeJwtPayload as jest.Mock).mockReturnValue({
151
+ username: 'username123',
152
+ passport: undefined,
153
+ });
154
+
155
+ const result = (Auth as any).mapOidcUserToDomainModel(mockOidcUser);
156
+
157
+ expect(decodeJwtPayload).toHaveBeenCalledWith('token');
158
+ expect(result.profile.username).toEqual('username123');
159
+ });
160
+
161
+ it('maps username when creating OIDC user from device tokens', () => {
162
+ const tokenResponse = {
163
+ id_token: 'token',
164
+ access_token: 'access',
165
+ refresh_token: 'refresh',
166
+ token_type: 'Bearer',
167
+ expires_in: 3600,
168
+ };
169
+
170
+ (decodeJwtPayload as jest.Mock).mockReturnValue({
171
+ sub: 'user-123',
172
+ iss: 'issuer',
173
+ aud: 'audience',
174
+ exp: 1,
175
+ iat: 0,
176
+ email: 'test@example.com',
177
+ nickname: 'tester',
178
+ username: 'username123',
179
+ passport: undefined,
180
+ });
181
+
182
+ const oidcUser = (Auth as any).mapDeviceTokenResponseToOidcUser(tokenResponse);
183
+
184
+ expect(decodeJwtPayload).toHaveBeenCalledWith('token');
185
+ expect(oidcUser.profile.username).toEqual('username123');
186
+ });
187
+ });
188
+ });