@imtbl/auth 2.10.7-alpha.6 → 2.11.1-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,11 +1,11 @@
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';
2
+ import ve, { isAxiosError } from 'axios';
3
+ import X from 'jwt-decode';
4
+ import Ee from 'localforage';
5
+ import { track, identify, getDetail, Detail, trackFlow, trackError } from '@imtbl/metrics';
6
6
  import { EventEmitter } from 'events';
7
7
 
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=`
8
+ var L=(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))(L||{});function D(o){return typeof o=="object"&&o!==null&&"code"in o&&"message"in o}var p=class extends Error{type;constructor(e,t){super(e),this.type=t;}},g=async(o,e)=>{try{return await o()}catch(t){let r;throw t instanceof p&&t.type==="SERVICE_UNAVAILABLE_ERROR"?new p(t.message,t.type):(isAxiosError(t)&&t.response?.data&&D(t.response.data)?r=t.response.data.message:r=t.message,new p(r,e))}};var ee=(o,e,t)=>{let r=e.map(n=>!o[n]&&n).filter(n=>n).join(", ");if(r!==""){let n=`${r} cannot be null`;throw new p(n,"INVALID_CONFIGURATION")}},_=class{authenticationDomain;passportDomain;oidcConfiguration;crossSdkBridgeEnabled;popupOverlayOptions;constructor({authenticationDomain:e,passportDomain:t,crossSdkBridgeEnabled:r,popupOverlayOptions:n,...i}){ee(i,["clientId","redirectUri"]),this.oidcConfiguration=i,this.crossSdkBridgeEnabled=r||!1,this.popupOverlayOptions=n,this.authenticationDomain=e||"https://auth.immutable.com",this.passportDomain=t||"https://passport.immutable.com";}};var N=(e=>(e.ZKEVM="zkEvm",e))(N||{}),w=o=>!!o.zkEvm,S=(t=>(t.OptedIn="opted_in",t.Unsubscribed="unsubscribed",t))(S||{}),U=(t=>(t.LOGGED_OUT="loggedOut",t.LOGGED_IN="loggedIn",t))(U||{});var F="im_passport_embedded_login_prompt";var E="passport-overlay",R="passport-overlay-contents",P=`${E}-close`,I=`${E}-try-again`,H=`
9
9
  <svg
10
10
  viewBox="0 0 20 20"
11
11
  fill="none"
@@ -17,7 +17,7 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
17
17
  fill="#F3F3F3"
18
18
  />
19
19
  </svg>
20
- `,G=`
20
+ `,V=`
21
21
  <svg
22
22
  viewBox="0 0 17 16"
23
23
  fill="none"
@@ -31,7 +31,7 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
31
31
  fill="#E01A3D"
32
32
  />
33
33
  </svg>
34
- `,x=`
34
+ `,b=`
35
35
  <svg
36
36
  style="
37
37
  max-width: 123px !important;
@@ -214,9 +214,9 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
214
214
  </clipPath>
215
215
  </defs>
216
216
  </svg>
217
- `;var ie=()=>`
217
+ `;var te=()=>`
218
218
  <button
219
- id="${L}"
219
+ id="${P}"
220
220
  style="
221
221
  background: #f3f3f326 !important;
222
222
  border: none !important;
@@ -232,9 +232,9 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
232
232
  justify-content: center !important;
233
233
  "
234
234
  >
235
- ${V}
235
+ ${H}
236
236
  </button>
237
- `,B=()=>`
237
+ `,G=()=>`
238
238
  <button
239
239
  id="${I}"
240
240
  style="
@@ -251,8 +251,8 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
251
251
  >
252
252
  Try again
253
253
  </button>
254
- `,ne=()=>`
255
- ${x}
254
+ `,re=()=>`
255
+ ${b}
256
256
  <div
257
257
  style="
258
258
  color: #e01a3d !important;
@@ -262,7 +262,7 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
262
262
  margin-bottom: 10px !important;
263
263
  "
264
264
  >
265
- ${G}
265
+ ${V}
266
266
  Pop-up blocked
267
267
  </div>
268
268
  <p style="
@@ -275,9 +275,9 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
275
275
  If the problem continues, adjust your<br />
276
276
  browser settings.
277
277
  </p>
278
- ${B()}
279
- `,oe=()=>`
280
- ${x}
278
+ ${G()}
279
+ `,ne=()=>`
280
+ ${b}
281
281
  <p style="
282
282
  color: #b6b6b6 !important;
283
283
  text-align: center !important;
@@ -286,10 +286,10 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
286
286
  >
287
287
  Secure pop-up not showing?<br />We'll help you re-launch
288
288
  </p>
289
- ${B()}
290
- `,Z=n=>`
289
+ ${G()}
290
+ `,B=o=>`
291
291
  <div
292
- id="${h}"
292
+ id="${E}"
293
293
  style="
294
294
  position: fixed !important;
295
295
  top: 0 !important;
@@ -312,9 +312,9 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
312
312
  z-index: 2147483647 !important;
313
313
  "
314
314
  >
315
- ${ie()}
315
+ ${te()}
316
316
  <div
317
- id="${O}"
317
+ id="${R}"
318
318
  style="
319
319
  display: flex !important;
320
320
  flex-direction: column !important;
@@ -322,12 +322,12 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
322
322
  max-width: 400px !important;
323
323
  "
324
324
  >
325
- ${n??""}
325
+ ${o??""}
326
326
  </div>
327
327
  </div>
328
- `,K=()=>`
328
+ `,Z=()=>`
329
329
  <div
330
- id="${h}"
330
+ id="${E}"
331
331
  style="
332
332
  position: fixed;
333
333
  top: 0;
@@ -345,7 +345,7 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
345
345
  "
346
346
  >
347
347
  <div
348
- id="${O}"
348
+ id="${R}"
349
349
  style="
350
350
  display: flex;
351
351
  flex-direction: column;
@@ -354,7 +354,7 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
354
354
  "
355
355
  />
356
356
  </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=`
357
+ `;function A({id:o,href:e,rel:t,crossOrigin:r}){let n=`${E}-${o}`;if(!document.getElementById(n)){let i=document.createElement("link");i.id=n,i.href=e,t&&(i.rel=t),r&&(i.crossOrigin=r),document.head.appendChild(i);}}var K=()=>B(re()),W=()=>B(ne());var m=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 n=document.querySelector(`#${R}`);n&&n.appendChild(e),r.addEventListener("click",t),this.overlay=r;}}};var se=660,ae=440,le="16px",$="passport-embedded-login-keyframes",Y="passport-embedded-login-iframe",O=class o{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($))return;let e=document.createElement("style");e.id=$,e.textContent=`
358
358
  @keyframes passportEmbeddedLoginPromptPopBounceIn {
359
359
  0% {
360
360
  opacity: 0.5;
@@ -373,7 +373,7 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
373
373
  }
374
374
 
375
375
  @media (max-height: 400px) {
376
- #${z} {
376
+ #${Y} {
377
377
  width: 100% !important;
378
378
  max-width: none !important;
379
379
  }
@@ -387,6 +387,6 @@ var P=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
387
387
  opacity: 1;
388
388
  }
389
389
  }
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}};
390
+ `,document.head.appendChild(e);};getEmbeddedLoginIFrame=()=>{let e=document.createElement("iframe");return e.id=Y,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",o.appendIFrameStylesIfNeeded(),e};displayEmbeddedLoginPrompt(){return new Promise((e,t)=>{let r=this.getEmbeddedLoginIFrame(),n=({data:i,origin:l})=>{if(!(l!==this.config.authenticationDomain||i.eventType!==F))switch(i.messageType){case"login_method_selected":{let d=i.payload;window.removeEventListener("message",n),m.remove(),e(d);break}case"login_prompt_error":{window.removeEventListener("message",n),m.remove(),t(new Error("Error during embedded login prompt",{cause:i.payload}));break}case"login_prompt_closed":{window.removeEventListener("message",n),m.remove(),t(new Error("Popup closed by user"));break}default:window.removeEventListener("message",n),m.remove(),t(new Error(`Unsupported message type: ${i.messageType}`));break}};window.addEventListener("message",n),m.appendOverlay(r,()=>{window.removeEventListener("message",n),m.remove(),t(new Error("Popup closed by user"));});})}};var h=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 c=async(o,e,t=!0,r=!0)=>{let n=trackFlow("passport",e,t);try{return await o(n)}catch(i){throw i instanceof Error?trackError("passport",e,i,{flowId:n.details.flowId}):n.addEvent("errored"),i}finally{r&&n.addEvent("End");}};var z="pkce_state",j="pkce_verifier",ue=3600,y=class{isTokenValid(e){try{let r=X(e).exp??0,n=Date.now()/1e3+ue;return r>n}catch{return !1}}savePKCEData(e){localStorage.setItem(z,e.state),localStorage.setItem(j,e.verifier);}getPKCEData(){let e=localStorage.getItem(z),t=localStorage.getItem(j);return e&&t?{state:e,verifier:t}:null}};var ge=(...o)=>{if(typeof process>"u")return;process?.env?.JEST_WORKER_ID===void 0&&console.warn(...o);},C={warn:ge};function Q(o){try{let e=X(o),t=Math.floor(Date.now()/1e3);return e.exp?e.exp<=t+30:!0}catch{return !0}}function J(o){let{id_token:e,access_token:t}=o;return !t||!e?!0:Q(t)||Q(e)}var v=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?K():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(P);t&&(this.onCloseListener&&t.removeEventListener("click",this.onCloseListener),this.onCloseListener=e,t.addEventListener("click",e));}};var k=class{storage;constructor(e,t){this.storage=Ee.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 we={headers:{"Content-Type":"application/x-www-form-urlencoded"}},Ue="/v2/logout",be="/im-logged-out",xe="/authorize",Me=o=>o?be:Ue,De=o=>{let{authenticationDomain:e,oidcConfiguration:t}=o,r;o.crossSdkBridgeEnabled?r=new k("ImmutableSDKPassport",Ee.INDEXEDDB):typeof window<"u"?r=window.localStorage:r=new InMemoryWebStorage;let n=new WebStorageStateStore({store:r}),i=new URL(Me(o.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:n,revokeTokenTypes:["refresh_token"],extraQueryParams:{...t.audience?{audience:t.audience}:{}}}};function x(o){return btoa(String.fromCharCode(...new Uint8Array(o))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function Ne(o){let t=new TextEncoder().encode(o);return window.crypto.subtle.digest("SHA-256",t)}var M=class o{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 y,this.logoutMode=this.config.oidcConfiguration.logoutMode||"redirect",this.eventEmitter=new h,track("passport","initialise");}async login(e){return c(async()=>{let{useCachedSession:t=!1,useSilentLogin:r}=e||{},n=null;try{n=await this.getUserInternal();}catch(i){if(i instanceof Error&&!i.message.includes("Unknown or invalid refresh token")&&trackError("passport","login",i),t)throw i;C.warn("Failed to retrieve a cached user session",i);}if(!n&&r)n=await this.forceUserRefreshInternal();else if(!n&&!t){if(e?.useRedirectFlow)return await this.loginWithRedirectInternal(e?.directLoginOptions),null;n=await this.loginWithPopup(e?.directLoginOptions);}return n&&this.handleSuccessfulLogin(n),n},"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){C.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 n=e.email;n&&(r.direct=e.directLoginMethod,r.email=n);}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 n=window.crypto.randomUUID(),i=async()=>{let l=this.buildExtraQueryParams(t,r);return this.userManager.signinPopup({extraQueryParams:l,popupWindowFeatures:{width:410,height:450},popupWindowTarget:n})};return new Promise((l,d)=>{i().then(u=>l(o.mapOidcUserToDomainModel(u))).catch(u=>{if(!(u instanceof Error)||u.message!=="Attempted to navigate on a disposed window"){d(u);return}let T=!1,a=new v(this.config.popupOverlayOptions||{},!0);a.append(async()=>{try{if(T)window.open("",n);else {T=!0;let f=await i();a.remove(),l(o.mapOidcUserToDomainModel(f));}}catch(f){a.remove(),d(f);}},()=>{a.remove(),d(new Error("Popup closed by user"));});});})},"AUTHENTICATION_ERROR")}static mapOidcUserToDomainModel=e=>{let t,r;if(e.id_token){let i=X(e.id_token);t=i?.passport,i?.username&&(r=i?.username);}let n={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&&(n.zkEvm={ethAddress:t.zkevm_eth_address,userAdminAddress:t.zkevm_user_admin_address}),n};static mapDeviceTokenResponseToOidcUser=e=>{let t=X(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 o.mapOidcUserToDomainModel(e)},"AUTHENTICATION_ERROR")}async getPKCEAuthorizationUrl(e,t){let r=x(window.crypto.getRandomValues(new Uint8Array(32))),n=x(await Ne(r)),i=x(window.crypto.getRandomValues(new Uint8Array(32))),{redirectUri:l,scope:d,audience:u,clientId:T}=this.config.oidcConfiguration;this.deviceCredentialsManager.savePKCEData({state:i,verifier:r});let a=new URL(xe,this.config.authenticationDomain);if(a.searchParams.set("response_type","code"),a.searchParams.set("code_challenge",n),a.searchParams.set("code_challenge_method","S256"),a.searchParams.set("client_id",T),a.searchParams.set("redirect_uri",l),a.searchParams.set("state",i),d&&a.searchParams.set("scope",d),u&&a.searchParams.set("audience",u),e){if(e.directLoginMethod==="email"){let f=e.email;f&&(a.searchParams.set("direct",e.directLoginMethod),a.searchParams.set("email",f));}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 n=await this.getPKCEToken(e,r.verifier),i=o.mapDeviceTokenResponseToOidcUser(n),l=o.mapOidcUserToDomainModel(i);return await this.userManager.storeUser(i),l},"AUTHENTICATION_ERROR")}async getPKCEToken(e,t){return (await ve.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},we)).data}async storeTokensInternal(e){return g(async()=>{let t=o.mapDeviceTokenResponseToOidcUser(e),r=o.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||(C.warn("Failed to get logout URL"),null)}forceUserRefreshInBackgroundInternal(){this.refreshTokenAndUpdatePromise().catch(e=>{C.warn("Failed to refresh user token",e);});}async forceUserRefreshInternal(){return this.refreshTokenAndUpdatePromise().catch(e=>(C.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(o.mapOidcUserToDomainModel(r));return}e(null);}catch(r){let n="AUTHENTICATION_ERROR",i="Failed to refresh token",l=!0;if(r instanceof ErrorTimeout?(n="SILENT_LOGIN_ERROR",i=`${i}: ${r.message}`,l=!1):r instanceof ErrorResponse?(n="NOT_LOGGED_IN_ERROR",i=`${i}: ${r.message||r.error_description}`):r instanceof Error?i=`${i}: ${r.message}`:typeof r=="string"&&(i=`${i}: ${r}`),l)try{await this.userManager.removeUser();}catch(d){d instanceof Error&&(i=`${i}: Failed to remove user: ${d.message}`);}t(new p(i,n));}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(!J(t)){let r=o.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(w);if(!e)throw new Error("Failed to obtain a User with the required ZkEvm attributes");return e}};
391
391
 
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 };
392
+ export { M as Auth, _ as AuthConfiguration, U as AuthEvents, S as MarketingConsentStatus, p as PassportError, L as PassportErrorType, N as RollupType, h as TypedEventEmitter, D as isAPIError, w 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,4 @@ 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';
@@ -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;
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.0",
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,24 @@
25
25
  }
26
26
  },
27
27
  "dependencies": {
28
- "@imtbl/config": "2.10.7-alpha.6",
29
- "@imtbl/metrics": "2.10.7-alpha.6",
28
+ "@imtbl/config": "2.11.1-alpha.0",
29
+ "@imtbl/metrics": "2.11.1-alpha.0",
30
30
  "axios": "^1.6.5",
31
31
  "jwt-decode": "^3.1.2",
32
32
  "localforage": "^1.10.0",
33
- "oidc-client-ts": "3.3.0",
33
+ "oidc-client-ts": "3.4.1",
34
34
  "uuid": "^9.0.1"
35
35
  },
36
36
  "devDependencies": {
37
- "@imtbl/toolkit": "2.10.7-alpha.6",
37
+ "@imtbl/toolkit": "2.11.1-alpha.0",
38
+ "@swc/core": "^1.3.36",
39
+ "@swc/jest": "^0.2.37",
40
+ "@types/jest": "^29.5.12",
38
41
  "@types/node": "^18.14.2",
42
+ "@jest/test-sequencer": "^29.7.0",
43
+ "jest": "^29.4.3",
44
+ "jest-environment-jsdom": "^29.4.3",
45
+ "ts-node": "^10.9.1",
39
46
  "tsup": "^8.3.0",
40
47
  "typescript": "^5.6.2"
41
48
  },
@@ -50,6 +57,7 @@
50
57
  "typegen": "tsc --customConditions default --emitDeclarationOnly --outDir dist/types",
51
58
  "pack:root": "pnpm pack --pack-destination $(dirname $(pnpm root -w))",
52
59
  "lint": "eslint ./src --ext .ts,.jsx,.tsx --max-warnings=0",
53
- "typecheck": "tsc --customConditions default --noEmit --jsx preserve"
60
+ "typecheck": "tsc --customConditions default --noEmit --jsx preserve",
61
+ "test": "jest"
54
62
  }
55
63
  }
@@ -0,0 +1,186 @@
1
+ import { Auth } from './Auth';
2
+ import { AuthEvents, User } from './types';
3
+ import { withMetricsAsync } from './utils/metrics';
4
+ import jwt_decode from 'jwt-decode';
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('jwt-decode', () => jest.fn());
22
+
23
+ beforeEach(() => {
24
+ trackFlowMock.mockReset();
25
+ trackErrorMock.mockReset();
26
+ identifyMock.mockReset();
27
+ trackMock.mockReset();
28
+ getDetailMock.mockReset();
29
+ (jwt_decode as jest.Mock).mockReset();
30
+ });
31
+
32
+ describe('withMetricsAsync', () => {
33
+ it('resolves with function result and tracks flow', async () => {
34
+ const flow = {
35
+ addEvent: jest.fn(),
36
+ details: { flowId: 'flow-id' },
37
+ };
38
+ trackFlowMock.mockReturnValue(flow);
39
+
40
+ const result = await withMetricsAsync(async () => 'done', 'login');
41
+
42
+ expect(result).toEqual('done');
43
+ expect(trackFlowMock).toHaveBeenCalledWith('passport', 'login', true);
44
+ expect(flow.addEvent).toHaveBeenCalledWith('End');
45
+ });
46
+
47
+ it('tracks error when function throws', async () => {
48
+ const flow = {
49
+ addEvent: jest.fn(),
50
+ details: { flowId: 'flow-id' },
51
+ };
52
+ trackFlowMock.mockReturnValue(flow);
53
+ const error = new Error('boom');
54
+
55
+ await expect(withMetricsAsync(async () => {
56
+ throw error;
57
+ }, 'login')).rejects.toThrow(error);
58
+
59
+ expect(trackErrorMock).toHaveBeenCalledWith('passport', 'login', error, { flowId: 'flow-id' });
60
+ expect(flow.addEvent).toHaveBeenCalledWith('End');
61
+ });
62
+
63
+ it('does not fail when non-error is thrown', async () => {
64
+ const flow = {
65
+ addEvent: jest.fn(),
66
+ details: { flowId: 'flow-id' },
67
+ };
68
+ trackFlowMock.mockReturnValue(flow);
69
+
70
+ const nonError = { message: 'failure' };
71
+ await expect(withMetricsAsync(async () => {
72
+ throw nonError as unknown as Error;
73
+ }, 'login')).rejects.toBe(nonError);
74
+
75
+ expect(flow.addEvent).toHaveBeenCalledWith('errored');
76
+ });
77
+ });
78
+
79
+ describe('Auth', () => {
80
+ describe('getUserOrLogin', () => {
81
+ const createMockUser = (): User => ({
82
+ accessToken: 'access',
83
+ idToken: 'id',
84
+ refreshToken: 'refresh',
85
+ expired: false,
86
+ profile: {
87
+ sub: 'user-123',
88
+ email: 'test@example.com',
89
+ nickname: 'tester',
90
+ },
91
+ });
92
+
93
+ it('emits LOGGED_IN event and identifies user when login is required', async () => {
94
+ const auth = Object.create(Auth.prototype) as Auth;
95
+ const loginWithPopup = jest.fn().mockResolvedValue(createMockUser());
96
+
97
+ (auth as any).eventEmitter = { emit: jest.fn() };
98
+ (auth as any).getUserInternal = jest.fn().mockResolvedValue(null);
99
+ (auth as any).loginWithPopup = loginWithPopup;
100
+
101
+ const user = await auth.getUserOrLogin();
102
+
103
+ expect(loginWithPopup).toHaveBeenCalledTimes(1);
104
+ expect((auth as any).eventEmitter.emit).toHaveBeenCalledWith(AuthEvents.LOGGED_IN, user);
105
+ expect(identifyMock).toHaveBeenCalledWith({ passportId: user.profile.sub });
106
+ });
107
+
108
+ it('returns cached user without triggering login', async () => {
109
+ const auth = Object.create(Auth.prototype) as Auth;
110
+ const cachedUser = createMockUser();
111
+
112
+ (auth as any).eventEmitter = { emit: jest.fn() };
113
+ (auth as any).getUserInternal = jest.fn().mockResolvedValue(cachedUser);
114
+ (auth as any).loginWithPopup = jest.fn();
115
+
116
+ const user = await auth.getUserOrLogin();
117
+
118
+ expect(user).toBe(cachedUser);
119
+ expect((auth as any).loginWithPopup).not.toHaveBeenCalled();
120
+ expect((auth as any).eventEmitter.emit).not.toHaveBeenCalled();
121
+ expect(identifyMock).not.toHaveBeenCalled();
122
+ });
123
+ });
124
+
125
+ describe('buildExtraQueryParams', () => {
126
+ it('omits third_party_a_id when no anonymous id is provided', () => {
127
+ const auth = Object.create(Auth.prototype) as Auth;
128
+ (auth as any).userManager = { settings: { extraQueryParams: {} } };
129
+ getDetailMock.mockReturnValue('runtime-id-value');
130
+
131
+ const params = (auth as any).buildExtraQueryParams();
132
+
133
+ expect(params.third_party_a_id).toBeUndefined();
134
+ expect(params.rid).toEqual('runtime-id-value');
135
+ });
136
+ });
137
+
138
+ describe('username extraction', () => {
139
+ it('extracts username from id token when present', () => {
140
+ const mockOidcUser = {
141
+ id_token: 'token',
142
+ access_token: 'access',
143
+ refresh_token: 'refresh',
144
+ expired: false,
145
+ profile: { sub: 'user-123', email: 'test@example.com', nickname: 'tester' },
146
+ };
147
+
148
+ (jwt_decode as jest.Mock).mockReturnValue({
149
+ username: 'username123',
150
+ passport: undefined,
151
+ });
152
+
153
+ const result = (Auth as any).mapOidcUserToDomainModel(mockOidcUser);
154
+
155
+ expect(jwt_decode).toHaveBeenCalledWith('token');
156
+ expect(result.profile.username).toEqual('username123');
157
+ });
158
+
159
+ it('maps username when creating OIDC user from device tokens', () => {
160
+ const tokenResponse = {
161
+ id_token: 'token',
162
+ access_token: 'access',
163
+ refresh_token: 'refresh',
164
+ token_type: 'Bearer',
165
+ expires_in: 3600,
166
+ };
167
+
168
+ (jwt_decode as jest.Mock).mockReturnValue({
169
+ sub: 'user-123',
170
+ iss: 'issuer',
171
+ aud: 'audience',
172
+ exp: 1,
173
+ iat: 0,
174
+ email: 'test@example.com',
175
+ nickname: 'tester',
176
+ username: 'username123',
177
+ passport: undefined,
178
+ });
179
+
180
+ const oidcUser = (Auth as any).mapDeviceTokenResponseToOidcUser(tokenResponse);
181
+
182
+ expect(jwt_decode).toHaveBeenCalledWith('token');
183
+ expect(oidcUser.profile.username).toEqual('username123');
184
+ });
185
+ });
186
+ });