@imtbl/auth 2.11.1-alpha.0 → 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 ve, { isAxiosError } from 'axios';
3
- import X from 'jwt-decode';
4
- import Ee from 'localforage';
2
+ import he from 'localforage';
5
3
  import { track, identify, getDetail, Detail, trackFlow, trackError } from '@imtbl/metrics';
6
- import { EventEmitter } from 'events';
7
4
 
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=`
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"
@@ -17,7 +14,7 @@ var L=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
17
14
  fill="#F3F3F3"
18
15
  />
19
16
  </svg>
20
- `,V=`
17
+ `,G=`
21
18
  <svg
22
19
  viewBox="0 0 17 16"
23
20
  fill="none"
@@ -31,7 +28,7 @@ var L=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
31
28
  fill="#E01A3D"
32
29
  />
33
30
  </svg>
34
- `,b=`
31
+ `,S=`
35
32
  <svg
36
33
  style="
37
34
  max-width: 123px !important;
@@ -216,7 +213,7 @@ var L=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
216
213
  </svg>
217
214
  `;var te=()=>`
218
215
  <button
219
- id="${P}"
216
+ id="${I}"
220
217
  style="
221
218
  background: #f3f3f326 !important;
222
219
  border: none !important;
@@ -232,11 +229,11 @@ var L=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
232
229
  justify-content: center !important;
233
230
  "
234
231
  >
235
- ${H}
232
+ ${V}
236
233
  </button>
237
- `,G=()=>`
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;
@@ -252,7 +249,7 @@ var L=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
252
249
  Try again
253
250
  </button>
254
251
  `,re=()=>`
255
- ${b}
252
+ ${S}
256
253
  <div
257
254
  style="
258
255
  color: #e01a3d !important;
@@ -262,7 +259,7 @@ var L=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
262
259
  margin-bottom: 10px !important;
263
260
  "
264
261
  >
265
- ${V}
262
+ ${G}
266
263
  Pop-up blocked
267
264
  </div>
268
265
  <p style="
@@ -275,9 +272,9 @@ var L=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
275
272
  If the problem continues, adjust your<br />
276
273
  browser settings.
277
274
  </p>
278
- ${G()}
275
+ ${B()}
279
276
  `,ne=()=>`
280
- ${b}
277
+ ${S}
281
278
  <p style="
282
279
  color: #b6b6b6 !important;
283
280
  text-align: center !important;
@@ -286,10 +283,10 @@ var L=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
286
283
  >
287
284
  Secure pop-up not showing?<br />We'll help you re-launch
288
285
  </p>
289
- ${G()}
290
- `,B=o=>`
286
+ ${B()}
287
+ `,K=n=>`
291
288
  <div
292
- id="${E}"
289
+ id="${h}"
293
290
  style="
294
291
  position: fixed !important;
295
292
  top: 0 !important;
@@ -322,12 +319,12 @@ var L=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
322
319
  max-width: 400px !important;
323
320
  "
324
321
  >
325
- ${o??""}
322
+ ${n??""}
326
323
  </div>
327
324
  </div>
328
325
  `,Z=()=>`
329
326
  <div
330
- id="${E}"
327
+ id="${h}"
331
328
  style="
332
329
  position: fixed;
333
330
  top: 0;
@@ -354,7 +351,7 @@ var L=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
354
351
  "
355
352
  />
356
353
  </div>
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=`
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;
@@ -373,7 +370,7 @@ var L=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION
373
370
  }
374
371
 
375
372
  @media (max-height: 400px) {
376
- #${Y} {
373
+ #${z} {
377
374
  width: 100% !important;
378
375
  max-width: none !important;
379
376
  }
@@ -387,6 +384,6 @@ var L=(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=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}};
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 { 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 };
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 };
@@ -4,3 +4,4 @@ export type { User, UserProfile, UserZkEvm, DirectLoginMethod, DirectLoginOption
4
4
  export { isUserZkEvm, RollupType, MarketingConsentStatus, AuthEvents, } from './types';
5
5
  export { default as TypedEventEmitter } from './utils/typedEventEmitter';
6
6
  export { PassportError, PassportErrorType, withPassportError, isAPIError, } from './errors';
7
+ export { decodeJwtPayload } from './utils/jwt';
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imtbl/auth",
3
- "version": "2.11.1-alpha.0",
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,16 +25,11 @@
25
25
  }
26
26
  },
27
27
  "dependencies": {
28
- "@imtbl/config": "2.11.1-alpha.0",
29
- "@imtbl/metrics": "2.11.1-alpha.0",
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.4.1",
34
- "uuid": "^9.0.1"
30
+ "oidc-client-ts": "3.4.1"
35
31
  },
36
32
  "devDependencies": {
37
- "@imtbl/toolkit": "2.11.1-alpha.0",
38
33
  "@swc/core": "^1.3.36",
39
34
  "@swc/jest": "^0.2.37",
40
35
  "@types/jest": "^29.5.12",
package/src/Auth.test.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Auth } from './Auth';
2
2
  import { AuthEvents, User } from './types';
3
3
  import { withMetricsAsync } from './utils/metrics';
4
- import jwt_decode from 'jwt-decode';
4
+ import { decodeJwtPayload } from './utils/jwt';
5
5
 
6
6
  const trackFlowMock = jest.fn();
7
7
  const trackErrorMock = jest.fn();
@@ -18,7 +18,9 @@ jest.mock('@imtbl/metrics', () => ({
18
18
  getDetail: (...args: any[]) => getDetailMock(...args),
19
19
  }));
20
20
 
21
- jest.mock('jwt-decode', () => jest.fn());
21
+ jest.mock('./utils/jwt', () => ({
22
+ decodeJwtPayload: jest.fn(),
23
+ }));
22
24
 
23
25
  beforeEach(() => {
24
26
  trackFlowMock.mockReset();
@@ -26,7 +28,7 @@ beforeEach(() => {
26
28
  identifyMock.mockReset();
27
29
  trackMock.mockReset();
28
30
  getDetailMock.mockReset();
29
- (jwt_decode as jest.Mock).mockReset();
31
+ (decodeJwtPayload as jest.Mock).mockReset();
30
32
  });
31
33
 
32
34
  describe('withMetricsAsync', () => {
@@ -145,14 +147,14 @@ describe('Auth', () => {
145
147
  profile: { sub: 'user-123', email: 'test@example.com', nickname: 'tester' },
146
148
  };
147
149
 
148
- (jwt_decode as jest.Mock).mockReturnValue({
150
+ (decodeJwtPayload as jest.Mock).mockReturnValue({
149
151
  username: 'username123',
150
152
  passport: undefined,
151
153
  });
152
154
 
153
155
  const result = (Auth as any).mapOidcUserToDomainModel(mockOidcUser);
154
156
 
155
- expect(jwt_decode).toHaveBeenCalledWith('token');
157
+ expect(decodeJwtPayload).toHaveBeenCalledWith('token');
156
158
  expect(result.profile.username).toEqual('username123');
157
159
  });
158
160
 
@@ -165,7 +167,7 @@ describe('Auth', () => {
165
167
  expires_in: 3600,
166
168
  };
167
169
 
168
- (jwt_decode as jest.Mock).mockReturnValue({
170
+ (decodeJwtPayload as jest.Mock).mockReturnValue({
169
171
  sub: 'user-123',
170
172
  iss: 'issuer',
171
173
  aud: 'audience',
@@ -179,7 +181,7 @@ describe('Auth', () => {
179
181
 
180
182
  const oidcUser = (Auth as any).mapDeviceTokenResponseToOidcUser(tokenResponse);
181
183
 
182
- expect(jwt_decode).toHaveBeenCalledWith('token');
184
+ expect(decodeJwtPayload).toHaveBeenCalledWith('token');
183
185
  expect(oidcUser.profile.username).toEqual('username123');
184
186
  });
185
187
  });
package/src/Auth.ts CHANGED
@@ -7,8 +7,6 @@ import {
7
7
  UserManagerSettings,
8
8
  WebStorageStateStore,
9
9
  } from 'oidc-client-ts';
10
- import axios from 'axios';
11
- import jwt_decode from 'jwt-decode';
12
10
  import localForage from 'localforage';
13
11
  import {
14
12
  Detail,
@@ -35,6 +33,7 @@ import {
35
33
  import EmbeddedLoginPrompt from './login/embeddedLoginPrompt';
36
34
  import TypedEventEmitter from './utils/typedEventEmitter';
37
35
  import { withMetricsAsync } from './utils/metrics';
36
+ import { decodeJwtPayload } from './utils/jwt';
38
37
  import DeviceCredentialsManager from './storage/device_credentials_manager';
39
38
  import { PassportError, PassportErrorType, withPassportError } from './errors';
40
39
  import logger from './utils/logger';
@@ -42,10 +41,37 @@ import { isAccessTokenExpiredOrExpiring } from './utils/token';
42
41
  import LoginPopupOverlay from './overlay/loginPopupOverlay';
43
42
  import { LocalForageAsyncStorage } from './storage/LocalForageAsyncStorage';
44
43
 
45
- const formUrlEncodedHeader = {
46
- headers: {
47
- 'Content-Type': 'application/x-www-form-urlencoded',
48
- },
44
+ const formUrlEncodedHeaders = {
45
+ 'Content-Type': 'application/x-www-form-urlencoded',
46
+ };
47
+
48
+ const parseJsonSafely = (text: string): unknown => {
49
+ if (!text) {
50
+ return undefined;
51
+ }
52
+ try {
53
+ return JSON.parse(text);
54
+ } catch {
55
+ return undefined;
56
+ }
57
+ };
58
+
59
+ const extractTokenErrorMessage = (
60
+ payload: unknown,
61
+ fallbackText: string,
62
+ status: number,
63
+ ): string => {
64
+ if (payload && typeof payload === 'object') {
65
+ const data = payload as Record<string, unknown>;
66
+ const description = data.error_description ?? data.message ?? data.error;
67
+ if (typeof description === 'string' && description.trim().length > 0) {
68
+ return description;
69
+ }
70
+ }
71
+ if (fallbackText.trim().length > 0) {
72
+ return fallbackText;
73
+ }
74
+ return `Token request failed with status ${status}`;
49
75
  };
50
76
 
51
77
  const logoutEndpoint = '/v2/logout';
@@ -523,7 +549,7 @@ export class Auth {
523
549
  let passport: PassportMetadata | undefined;
524
550
  let username: string | undefined;
525
551
  if (oidcUser.id_token) {
526
- const idTokenPayload = jwt_decode<IdTokenPayload>(oidcUser.id_token);
552
+ const idTokenPayload = decodeJwtPayload<IdTokenPayload>(oidcUser.id_token);
527
553
  passport = idTokenPayload?.passport;
528
554
  if (idTokenPayload?.username) {
529
555
  username = idTokenPayload?.username;
@@ -552,7 +578,7 @@ export class Auth {
552
578
  };
553
579
 
554
580
  private static mapDeviceTokenResponseToOidcUser = (tokenResponse: DeviceTokenResponse): OidcUser => {
555
- const idTokenPayload: IdTokenPayload = jwt_decode(tokenResponse.id_token);
581
+ const idTokenPayload: IdTokenPayload = decodeJwtPayload(tokenResponse.id_token);
556
582
  return new OidcUser({
557
583
  id_token: tokenResponse.id_token,
558
584
  access_token: tokenResponse.access_token,
@@ -650,18 +676,39 @@ export class Auth {
650
676
  }
651
677
 
652
678
  private async getPKCEToken(authorizationCode: string, codeVerifier: string): Promise<DeviceTokenResponse> {
653
- const response = await axios.post<DeviceTokenResponse>(
679
+ const response = await fetch(
654
680
  `${this.config.authenticationDomain}/oauth/token`,
655
681
  {
656
- client_id: this.config.oidcConfiguration.clientId,
657
- grant_type: 'authorization_code',
658
- code_verifier: codeVerifier,
659
- code: authorizationCode,
660
- redirect_uri: this.config.oidcConfiguration.redirectUri,
682
+ method: 'POST',
683
+ headers: formUrlEncodedHeaders,
684
+ body: new URLSearchParams({
685
+ client_id: this.config.oidcConfiguration.clientId,
686
+ grant_type: 'authorization_code',
687
+ code_verifier: codeVerifier,
688
+ code: authorizationCode,
689
+ redirect_uri: this.config.oidcConfiguration.redirectUri,
690
+ }),
661
691
  },
662
- formUrlEncodedHeader,
663
692
  );
664
- return response.data;
693
+
694
+ const responseText = await response.text();
695
+ const parsedBody = parseJsonSafely(responseText);
696
+
697
+ if (!response.ok) {
698
+ throw new Error(
699
+ extractTokenErrorMessage(
700
+ parsedBody,
701
+ responseText,
702
+ response.status,
703
+ ),
704
+ );
705
+ }
706
+
707
+ if (!parsedBody || typeof parsedBody !== 'object') {
708
+ throw new Error('Token endpoint returned an invalid response');
709
+ }
710
+
711
+ return parsedBody as DeviceTokenResponse;
665
712
  }
666
713
 
667
714
  private async storeTokensInternal(tokenResponse: DeviceTokenResponse): Promise<User> {
package/src/errors.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { isAxiosError } from 'axios';
2
1
  import { imx } from '@imtbl/generated-clients';
3
2
 
4
3
  export enum PassportErrorType {
@@ -35,6 +34,31 @@ export function isAPIError(error: any): error is imx.APIError {
35
34
  );
36
35
  }
37
36
 
37
+ type AxiosLikeError = {
38
+ response?: {
39
+ data?: unknown;
40
+ };
41
+ };
42
+
43
+ const extractApiError = (error: unknown): imx.APIError | undefined => {
44
+ if (isAPIError(error)) {
45
+ return error;
46
+ }
47
+
48
+ if (
49
+ typeof error === 'object'
50
+ && error !== null
51
+ && 'response' in error
52
+ ) {
53
+ const { response } = error as AxiosLikeError;
54
+ if (response?.data && isAPIError(response.data)) {
55
+ return response.data;
56
+ }
57
+ }
58
+
59
+ return undefined;
60
+ };
61
+
38
62
  export class PassportError extends Error {
39
63
  public type: PassportErrorType;
40
64
 
@@ -57,8 +81,9 @@ export const withPassportError = async <T>(
57
81
  throw new PassportError(error.message, error.type);
58
82
  }
59
83
 
60
- if (isAxiosError(error) && error.response?.data && isAPIError(error.response.data)) {
61
- errorMessage = error.response.data.message;
84
+ const apiError = extractApiError(error);
85
+ if (apiError) {
86
+ errorMessage = apiError.message;
62
87
  } else {
63
88
  errorMessage = (error as Error).message;
64
89
  }
package/src/index.ts CHANGED
@@ -32,3 +32,5 @@ export { default as TypedEventEmitter } from './utils/typedEventEmitter';
32
32
  export {
33
33
  PassportError, PassportErrorType, withPassportError, isAPIError,
34
34
  } from './errors';
35
+
36
+ export { decodeJwtPayload } from './utils/jwt';
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable class-methods-use-this */
2
- import jwt_decode from 'jwt-decode';
3
2
  import { TokenPayload, PKCEData } from '../types';
3
+ import { decodeJwtPayload } from '../utils/jwt';
4
4
 
5
5
  const KEY_PKCE_STATE = 'pkce_state';
6
6
  const KEY_PKCE_VERIFIER = 'pkce_verifier';
@@ -9,7 +9,7 @@ const validCredentialsMinTtlSec = 3600; // 1 hour
9
9
  export default class DeviceCredentialsManager {
10
10
  private isTokenValid(jwt: string): boolean {
11
11
  try {
12
- const tokenPayload: TokenPayload = jwt_decode(jwt);
12
+ const tokenPayload: TokenPayload = decodeJwtPayload(jwt);
13
13
  const expiresAt = tokenPayload.exp ?? 0;
14
14
  const now = (Date.now() / 1000) + validCredentialsMinTtlSec;
15
15
  return expiresAt > now;
@@ -0,0 +1,78 @@
1
+ /* eslint-disable no-restricted-globals */
2
+ const getGlobal = (): typeof globalThis => {
3
+ if (typeof globalThis !== 'undefined') {
4
+ return globalThis;
5
+ }
6
+ if (typeof self !== 'undefined') {
7
+ return self;
8
+ }
9
+ if (typeof window !== 'undefined') {
10
+ return window;
11
+ }
12
+ if (typeof global !== 'undefined') {
13
+ return global;
14
+ }
15
+ return {} as typeof globalThis;
16
+ };
17
+
18
+ const base64UrlToBase64 = (input: string): string => {
19
+ const normalized = input.replace(/-/g, '+').replace(/_/g, '/');
20
+ const padding = normalized.length % 4 === 0 ? '' : '='.repeat(4 - (normalized.length % 4));
21
+ return normalized + padding;
22
+ };
23
+
24
+ const decodeWithAtob = (value: string): string | null => {
25
+ const globalRef = getGlobal();
26
+ if (typeof globalRef.atob !== 'function') {
27
+ return null;
28
+ }
29
+
30
+ const binary = globalRef.atob(value);
31
+ const bytes = new Uint8Array(binary.length);
32
+ for (let i = 0; i < binary.length; i += 1) {
33
+ bytes[i] = binary.charCodeAt(i);
34
+ }
35
+
36
+ if (typeof globalRef.TextDecoder === 'function') {
37
+ return new globalRef.TextDecoder('utf-8').decode(bytes);
38
+ }
39
+
40
+ let result = '';
41
+ for (let i = 0; i < bytes.length; i += 1) {
42
+ result += String.fromCharCode(bytes[i]);
43
+ }
44
+ return result;
45
+ };
46
+
47
+ const base64Decode = (value: string): string => {
48
+ if (typeof Buffer !== 'undefined') {
49
+ return Buffer.from(value, 'base64').toString('utf-8');
50
+ }
51
+
52
+ const decoded = decodeWithAtob(value);
53
+ if (decoded === null) {
54
+ throw new Error('Base64 decoding is not supported in this environment');
55
+ }
56
+
57
+ return decoded;
58
+ };
59
+
60
+ export const decodeJwtPayload = <T>(token: string): T => {
61
+ if (typeof token !== 'string') {
62
+ throw new Error('JWT must be a string');
63
+ }
64
+
65
+ const segments = token.split('.');
66
+ if (segments.length < 2) {
67
+ throw new Error('Invalid JWT: payload segment is missing');
68
+ }
69
+
70
+ const payloadSegment = segments[1];
71
+ const json = base64Decode(base64UrlToBase64(payloadSegment));
72
+
73
+ try {
74
+ return JSON.parse(json) as T;
75
+ } catch {
76
+ throw new Error('Invalid JWT payload: unable to parse JSON');
77
+ }
78
+ };
@@ -1,13 +1,13 @@
1
- import jwt_decode from 'jwt-decode';
2
1
  import {
3
2
  User as OidcUser,
4
3
  } from 'oidc-client-ts';
5
4
  import { IdTokenPayload, TokenPayload } from '../types';
5
+ import { decodeJwtPayload } from './jwt';
6
6
 
7
7
  function isTokenExpiredOrExpiring(token: string): boolean {
8
8
  try {
9
9
  // try to decode the token as access token payload or id token payload
10
- const decodedToken = jwt_decode<TokenPayload | IdTokenPayload>(token);
10
+ const decodedToken = decodeJwtPayload<TokenPayload | IdTokenPayload>(token);
11
11
  const now = Math.floor(Date.now() / 1000);
12
12
 
13
13
  // Tokens without expiration claims are invalid (security vulnerability)