@imtbl/auth 2.12.6-alpha.0 → 2.12.6-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.
- package/dist/browser/index.js +24 -24
- package/dist/node/index.cjs +42 -39
- package/dist/node/index.js +25 -25
- package/dist/types/index.d.ts +1 -0
- package/dist/types/login/standalone.d.ts +82 -0
- package/dist/types/logout/index.d.ts +27 -0
- package/package.json +3 -3
- package/src/Auth.ts +8 -15
- package/src/index.ts +11 -0
- package/src/login/standalone.ts +161 -0
- package/src/logout/index.ts +52 -0
package/dist/node/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { UserManager, User, ErrorTimeout, ErrorResponse, InMemoryWebStorage, WebStorageStateStore } from 'oidc-client-ts';
|
|
2
|
-
import
|
|
2
|
+
import Be from 'localforage';
|
|
3
3
|
import { track, identify, getDetail, Detail, trackFlow, trackError } from '@imtbl/metrics';
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var b=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION="INVALID_CONFIGURATION",p.WALLET_CONNECTION_ERROR="WALLET_CONNECTION_ERROR",p.NOT_LOGGED_IN_ERROR="NOT_LOGGED_IN_ERROR",p.SILENT_LOGIN_ERROR="SILENT_LOGIN_ERROR",p.REFRESH_TOKEN_ERROR="REFRESH_TOKEN_ERROR",p.USER_REGISTRATION_ERROR="USER_REGISTRATION_ERROR",p.USER_NOT_REGISTERED_ERROR="USER_NOT_REGISTERED_ERROR",p.LOGOUT_ERROR="LOGOUT_ERROR",p.TRANSFER_ERROR="TRANSFER_ERROR",p.CREATE_ORDER_ERROR="CREATE_ORDER_ERROR",p.CANCEL_ORDER_ERROR="CANCEL_ORDER_ERROR",p.EXCHANGE_TRANSFER_ERROR="EXCHANGE_TRANSFER_ERROR",p.CREATE_TRADE_ERROR="CREATE_TRADE_ERROR",p.OPERATION_NOT_SUPPORTED_ERROR="OPERATION_NOT_SUPPORTED_ERROR",p.LINK_WALLET_ALREADY_LINKED_ERROR="LINK_WALLET_ALREADY_LINKED_ERROR",p.LINK_WALLET_MAX_WALLETS_LINKED_ERROR="LINK_WALLET_MAX_WALLETS_LINKED_ERROR",p.LINK_WALLET_VALIDATION_ERROR="LINK_WALLET_VALIDATION_ERROR",p.LINK_WALLET_DUPLICATE_NONCE_ERROR="LINK_WALLET_DUPLICATE_NONCE_ERROR",p.LINK_WALLET_GENERIC_ERROR="LINK_WALLET_GENERIC_ERROR",p.SERVICE_UNAVAILABLE_ERROR="SERVICE_UNAVAILABLE_ERROR",p.TRANSACTION_REJECTED="TRANSACTION_REJECTED",p))(b||{});function F(n){return typeof n=="object"&&n!==null&&"code"in n&&"message"in n}var Oe=n=>{if(F(n))return n;if(typeof n=="object"&&n!==null&&"response"in n){let{response:e}=n;if(e?.data&&F(e.data))return e.data}},f=class extends Error{type;constructor(e,t){super(e),this.type=t;}},E=async(n,e)=>{try{return await n()}catch(t){let r;if(t instanceof f&&t.type==="SERVICE_UNAVAILABLE_ERROR")throw new f(t.message,t.type);let o=Oe(t);throw o?r=o.message:r=t.message,new f(r,e)}};var Le=(n,e,t)=>{let r=e.map(o=>!n[o]&&o).filter(o=>o).join(", ");if(r!==""){let o=`${r} cannot be null`;throw new f(o,"INVALID_CONFIGURATION")}},O=class{authenticationDomain;passportDomain;oidcConfiguration;crossSdkBridgeEnabled;popupOverlayOptions;constructor({authenticationDomain:e,passportDomain:t,crossSdkBridgeEnabled:r,popupOverlayOptions:o,...i}){Le(i,["clientId","redirectUri"]),this.oidcConfiguration=i,this.crossSdkBridgeEnabled=r||!1,this.popupOverlayOptions=o,this.authenticationDomain=e||"https://auth.immutable.com",this.passportDomain=t||"https://passport.immutable.com";}};var Q=(e=>(e.ZKEVM="zkEvm",e))(Q||{}),A=(t=>(t.ZKEVM="zkevm",t.ARBITRUM_ONE="arbitrum_one",t))(A||{}),V=n=>!!n.zkEvm,q=(r=>(r.OptedIn="opted_in",r.Unsubscribed="unsubscribed",r.Subscribed="subscribed",r))(q||{}),G=(o=>(o.LOGGED_OUT="loggedOut",o.LOGGED_IN="loggedIn",o.TOKEN_REFRESHED="tokenRefreshed",o.USER_REMOVED="userRemoved",o))(G||{});var X="im_passport_embedded_login_prompt";var C="passport-overlay",_="passport-overlay-contents",U=`${C}-close`,x=`${C}-try-again`,j=`
|
|
6
6
|
<svg
|
|
7
7
|
viewBox="0 0 20 20"
|
|
8
8
|
fill="none"
|
|
@@ -14,7 +14,7 @@ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION
|
|
|
14
14
|
fill="#F3F3F3"
|
|
15
15
|
/>
|
|
16
16
|
</svg>
|
|
17
|
-
`,
|
|
17
|
+
`,ee=`
|
|
18
18
|
<svg
|
|
19
19
|
viewBox="0 0 17 16"
|
|
20
20
|
fill="none"
|
|
@@ -28,7 +28,7 @@ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION
|
|
|
28
28
|
fill="#E01A3D"
|
|
29
29
|
/>
|
|
30
30
|
</svg>
|
|
31
|
-
`,
|
|
31
|
+
`,B=`
|
|
32
32
|
<svg
|
|
33
33
|
style="
|
|
34
34
|
max-width: 123px !important;
|
|
@@ -211,9 +211,9 @@ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION
|
|
|
211
211
|
</clipPath>
|
|
212
212
|
</defs>
|
|
213
213
|
</svg>
|
|
214
|
-
`;var
|
|
214
|
+
`;var Pe=()=>`
|
|
215
215
|
<button
|
|
216
|
-
id="${
|
|
216
|
+
id="${U}"
|
|
217
217
|
style="
|
|
218
218
|
background: #f3f3f326 !important;
|
|
219
219
|
border: none !important;
|
|
@@ -229,9 +229,9 @@ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION
|
|
|
229
229
|
justify-content: center !important;
|
|
230
230
|
"
|
|
231
231
|
>
|
|
232
|
-
${
|
|
232
|
+
${j}
|
|
233
233
|
</button>
|
|
234
|
-
`,
|
|
234
|
+
`,te=()=>`
|
|
235
235
|
<button
|
|
236
236
|
id="${x}"
|
|
237
237
|
style="
|
|
@@ -248,8 +248,8 @@ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION
|
|
|
248
248
|
>
|
|
249
249
|
Try again
|
|
250
250
|
</button>
|
|
251
|
-
`,
|
|
252
|
-
${
|
|
251
|
+
`,we=()=>`
|
|
252
|
+
${B}
|
|
253
253
|
<div
|
|
254
254
|
style="
|
|
255
255
|
color: #e01a3d !important;
|
|
@@ -259,7 +259,7 @@ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION
|
|
|
259
259
|
margin-bottom: 10px !important;
|
|
260
260
|
"
|
|
261
261
|
>
|
|
262
|
-
${
|
|
262
|
+
${ee}
|
|
263
263
|
Pop-up blocked
|
|
264
264
|
</div>
|
|
265
265
|
<p style="
|
|
@@ -272,9 +272,9 @@ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION
|
|
|
272
272
|
If the problem continues, adjust your<br />
|
|
273
273
|
browser settings.
|
|
274
274
|
</p>
|
|
275
|
-
${
|
|
276
|
-
`,
|
|
277
|
-
${
|
|
275
|
+
${te()}
|
|
276
|
+
`,Ie=()=>`
|
|
277
|
+
${B}
|
|
278
278
|
<p style="
|
|
279
279
|
color: #b6b6b6 !important;
|
|
280
280
|
text-align: center !important;
|
|
@@ -283,8 +283,8 @@ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION
|
|
|
283
283
|
>
|
|
284
284
|
Secure pop-up not showing?<br />We'll help you re-launch
|
|
285
285
|
</p>
|
|
286
|
-
${
|
|
287
|
-
`,
|
|
286
|
+
${te()}
|
|
287
|
+
`,re=n=>`
|
|
288
288
|
<div
|
|
289
289
|
id="${C}"
|
|
290
290
|
style="
|
|
@@ -309,7 +309,7 @@ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION
|
|
|
309
309
|
z-index: 2147483647 !important;
|
|
310
310
|
"
|
|
311
311
|
>
|
|
312
|
-
${
|
|
312
|
+
${Pe()}
|
|
313
313
|
<div
|
|
314
314
|
id="${_}"
|
|
315
315
|
style="
|
|
@@ -322,7 +322,7 @@ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION
|
|
|
322
322
|
${n??""}
|
|
323
323
|
</div>
|
|
324
324
|
</div>
|
|
325
|
-
`,
|
|
325
|
+
`,ne=()=>`
|
|
326
326
|
<div
|
|
327
327
|
id="${C}"
|
|
328
328
|
style="
|
|
@@ -351,7 +351,7 @@ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION
|
|
|
351
351
|
"
|
|
352
352
|
/>
|
|
353
353
|
</div>
|
|
354
|
-
`;function
|
|
354
|
+
`;function S({id:n,href:e,rel:t,crossOrigin:r}){let o=`${C}-${n}`;if(!document.getElementById(o)){let i=document.createElement("link");i.id=o,i.href=e,t&&(i.rel=t),r&&(i.crossOrigin=r),document.head.appendChild(i);}}var oe=()=>re(we()),ie=()=>re(Ie());var h=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=ne(),document.body.insertAdjacentElement("beforeend",r);let o=document.querySelector(`#${_}`);o&&o.appendChild(e),r.addEventListener("click",t),this.overlay=r;}}};var Ae=660,Ue=440,xe="16px",se="passport-embedded-login-keyframes",ae="passport-embedded-login-iframe",L=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(se))return;let e=document.createElement("style");e.id=se,e.textContent=`
|
|
355
355
|
@keyframes passportEmbeddedLoginPromptPopBounceIn {
|
|
356
356
|
0% {
|
|
357
357
|
opacity: 0.5;
|
|
@@ -370,7 +370,7 @@ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION
|
|
|
370
370
|
}
|
|
371
371
|
|
|
372
372
|
@media (max-height: 400px) {
|
|
373
|
-
#${
|
|
373
|
+
#${ae} {
|
|
374
374
|
width: 100% !important;
|
|
375
375
|
max-width: none !important;
|
|
376
376
|
}
|
|
@@ -384,7 +384,7 @@ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION
|
|
|
384
384
|
opacity: 1;
|
|
385
385
|
}
|
|
386
386
|
}
|
|
387
|
-
`,document.head.appendChild(e);};getEmbeddedLoginIFrame=()=>{let e=document.createElement("iframe");return e.id=ie,e.src=this.getHref(),e.style.height="100vh",e.style.width="100vw",e.style.maxHeight=`${Ie}px`,e.style.maxWidth=`${Ae}px`,e.style.borderRadius=be,e.style.opacity="0",e.style.transform="scale(0.6)",e.style.animation="passportEmbeddedLoginPromptPopBounceIn 1s ease forwards",n.appendIFrameStylesIfNeeded(),e};displayEmbeddedLoginPrompt(){return new Promise((e,t)=>{let r=this.getEmbeddedLoginIFrame(),o=({data:i,origin:s})=>{if(!(s!==this.config.authenticationDomain||i.eventType!==Q))switch(i.messageType){case"login_method_selected":{let a=i.payload;window.removeEventListener("message",o),E.remove(),e(a);break}case"login_prompt_error":{window.removeEventListener("message",o),E.remove(),t(new Error("Error during embedded login prompt",{cause:i.payload}));break}case"login_prompt_closed":{window.removeEventListener("message",o),E.remove(),t(new Error("Popup closed by user"));break}default:window.removeEventListener("message",o),E.remove(),t(new Error(`Unsupported message type: ${i.messageType}`));break}};window.addEventListener("message",o),E.appendOverlay(r,()=>{window.removeEventListener("message",o),E.remove(),t(new Error("Popup closed by user"));});})}};var R=class{listeners=new Map;emit(e,...t){let r=this.listeners.get(e);!r||r.size===0||[...r].forEach(o=>{o(...t);});}on(e,t){let r=this.listeners.get(e)??new Set;r.add(t),this.listeners.set(e,r);}removeListener(e,t){let r=this.listeners.get(e);r&&(r.delete(t),r.size===0&&this.listeners.delete(e));}};var m=async(n,e,t=!0,r=!0)=>{let o=trackFlow("passport",e,t);try{return await n(o)}catch(i){throw i instanceof Error?trackError("passport",e,i,{flowId:o.details.flowId}):o.addEvent("errored"),i}finally{r&&o.addEvent("End");}};var Se=()=>typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{},De=n=>{let e=n.replace(/-/g,"+").replace(/_/g,"/"),t=e.length%4===0?"":"=".repeat(4-e.length%4);return e+t},Me=n=>{let e=Se();if(typeof e.atob!="function")return null;let t=e.atob(n),r=new Uint8Array(t.length);for(let i=0;i<t.length;i+=1)r[i]=t.charCodeAt(i);if(typeof e.TextDecoder=="function")return new e.TextDecoder("utf-8").decode(r);let o="";for(let i=0;i<r.length;i+=1)o+=String.fromCharCode(r[i]);return o},Ne=n=>{if(typeof Buffer<"u")return Buffer.from(n,"base64").toString("utf-8");let e=Me(n);if(e===null)throw new Error("Base64 decoding is not supported in this environment");return e},u=n=>{if(typeof n!="string")throw new Error("JWT must be a string");let e=n.split(".");if(e.length<2)throw new Error("Invalid JWT: payload segment is missing");let t=e[1],r=Ne(De(t));try{return JSON.parse(r)}catch{throw new Error("Invalid JWT payload: unable to parse JSON")}};var se="pkce_state",ae="pkce_verifier",He=3600,L=class{isTokenValid(e){try{let r=u(e).exp??0,o=Date.now()/1e3+He;return r>o}catch{return !1}}savePKCEData(e){localStorage.setItem(se,e.state),localStorage.setItem(ae,e.verifier);}getPKCEData(){let e=localStorage.getItem(se),t=localStorage.getItem(ae);return e&&t?{state:e,verifier:t}:null}};var Fe=(...n)=>{if(typeof process>"u")return;process?.env?.JEST_WORKER_ID===void 0&&console.warn(...n);},v={warn:Fe};function de(n){try{let e=u(n),t=Math.floor(Date.now()/1e3);return e.exp?e.exp<=t+30:!0}catch{return !0}}function le(n){let{id_token:e,access_token:t}=n;return !t||!e?!0:de(t)||de(e)}var P=class{disableGenericPopupOverlay;disableBlockedPopupOverlay;overlay;isBlockedOverlay;tryAgainListener;onCloseListener;constructor(e,t=!1){this.disableBlockedPopupOverlay=e.disableBlockedPopupOverlay||!1,this.disableGenericPopupOverlay=e.disableGenericPopupOverlay||!1,this.isBlockedOverlay=t;}append(e,t){this.shouldAppendOverlay()&&(this.appendOverlay(),this.updateTryAgainButton(e),this.updateCloseButton(t));}update(e){this.updateTryAgainButton(e);}remove(){this.overlay&&this.overlay.remove();}shouldAppendOverlay(){return !(this.disableGenericPopupOverlay&&this.disableBlockedPopupOverlay||this.disableGenericPopupOverlay&&!this.isBlockedOverlay||this.disableBlockedPopupOverlay&&this.isBlockedOverlay)}appendOverlay(){if(!this.overlay){U({id:"link-googleapis",href:"https://fonts.googleapis.com"}),U({id:"link-gstatic",href:"https://fonts.gstatic.com",crossOrigin:"anonymous"}),U({id:"link-roboto",href:"https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap",rel:"stylesheet"});let t=document.createElement("div");t.innerHTML=this.isBlockedOverlay?re():ne(),document.body.insertAdjacentElement("beforeend",t),this.overlay=t;}}updateTryAgainButton(e){let t=document.getElementById(x);t&&(this.tryAgainListener&&t.removeEventListener("click",this.tryAgainListener),this.tryAgainListener=e,t.addEventListener("click",e));}updateCloseButton(e){let t=document.getElementById(b);t&&(this.onCloseListener&&t.removeEventListener("click",this.onCloseListener),this.onCloseListener=e,t.addEventListener("click",e));}};var S=class{storage;constructor(e,t){this.storage=Ve.createInstance({name:e,driver:t});}get length(){return this.storage.length()}clear(){return this.storage.clear()}getItem(e){return this.storage.getItem(e)}key(e){return this.storage.key(e)}async removeItem(e){await this.storage.removeItem(e);}async setItem(e,t){await this.storage.setItem(e,t);}};var je={"Content-Type":"application/x-www-form-urlencoded"},et=n=>{if(n)try{return JSON.parse(n)}catch{return}},tt=(n,e,t)=>{if(n&&typeof n=="object"){let r=n,o=r.error_description??r.message??r.error;if(typeof o=="string"&&o.trim().length>0)return o}return e.trim().length>0?e:`Token request failed with status ${t}`},ce=(n,e)=>({ethAddress:n,userAdminAddress:e}),rt="/v2/logout",nt="/im-logged-out",ot="/authorize",it=n=>n?nt:rt,st=n=>{let{authenticationDomain:e,oidcConfiguration:t}=n,r;n.crossSdkBridgeEnabled?r=new S("ImmutableSDKPassport",Ve.INDEXEDDB):typeof window<"u"?r=window.localStorage:r=new InMemoryWebStorage;let o=new WebStorageStateStore({store:r}),i=new URL(it(n.crossSdkBridgeEnabled),e.replace(/^(?:https?:\/\/)?(.*)/,"https://$1"));return i.searchParams.set("client_id",t.clientId),t.logoutRedirectUri&&i.searchParams.set("returnTo",t.logoutRedirectUri),{authority:e,redirect_uri:t.redirectUri,popup_redirect_uri:t.popupRedirectUri||t.redirectUri,client_id:t.clientId,metadata:{authorization_endpoint:`${e}/authorize`,token_endpoint:`${e}/oauth/token`,userinfo_endpoint:`${e}/userinfo`,end_session_endpoint:i.toString(),revocation_endpoint:`${e}/oauth/revoke`},automaticSilentRenew:!1,scope:t.scope,userStore:o,revokeTokenTypes:["refresh_token"],extraQueryParams:{...t.audience?{audience:t.audience}:{}}}};function B(n){return btoa(String.fromCharCode(...new Uint8Array(n))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function at(n){let t=new TextEncoder().encode(n);return window.crypto.subtle.digest("SHA-256",t)}var K=class n{config;userManager;deviceCredentialsManager;embeddedLoginPrompt;logoutMode;refreshingPromise=null;eventEmitter;constructor(e){this.config=new T(e),this.embeddedLoginPrompt=new O(this.config),this.userManager=new UserManager(st(this.config)),this.deviceCredentialsManager=new L,this.logoutMode=this.config.oidcConfiguration.logoutMode||"redirect",this.eventEmitter=new R,track("passport","initialise");}async login(e){return m(async()=>{let{useCachedSession:t=!1,useSilentLogin:r}=e||{},o=null;try{o=await this.getUserInternal();}catch(i){if(i instanceof Error&&!i.message.includes("Unknown or invalid refresh token")&&trackError("passport","login",i),t)throw i;v.warn("Failed to retrieve a cached user session",i);}if(!o&&r)o=await this.forceUserRefreshInternal();else if(!o&&!t){if(e?.useRedirectFlow)return await this.loginWithRedirectInternal(e?.directLoginOptions),null;o=await this.loginWithPopup(e?.directLoginOptions);}return o&&this.handleSuccessfulLogin(o),o},"login")}async loginWithRedirect(e){await this.loginWithRedirectInternal(e);}async loginCallback(){return m(async()=>{let e=await this.loginCallbackInternal();return e&&this.handleSuccessfulLogin(e),e},"loginCallback")}async logout(){await m(async()=>{await this.logoutInternal(),this.eventEmitter.emit("loggedOut");},"logout");}async getUser(){return this.getUserInternal()}async getUserOrLogin(){let e=null;try{e=await this.getUserInternal();}catch(r){v.warn("Failed to retrieve a cached user session",r);}if(e)return e;let t=await this.loginWithPopup();return this.handleSuccessfulLogin(t),t}async getUserZkEvm(){return this.getUserZkEvmInternal()}async getIdToken(){return m(async()=>(await this.getUserInternal())?.idToken,"getIdToken",!1)}async getAccessToken(){return m(async()=>(await this.getUserInternal())?.accessToken,"getAccessToken",!1,!1)}async isLoggedIn(){return await this.getUser()!==null}async forceUserRefresh(){return this.forceUserRefreshInternal()}forceUserRefreshInBackground(){this.forceUserRefreshInBackgroundInternal();}async loginWithPKCEFlow(e,t){return m(async()=>this.getPKCEAuthorizationUrl(e,t),"loginWithPKCEFlow")}async loginWithPKCEFlowCallback(e,t){return m(async()=>{let r=await this.loginWithPKCEFlowCallbackInternal(e,t);return this.handleSuccessfulLogin(r),r},"loginWithPKCEFlowCallback")}async storeTokens(e){return m(async()=>{let t=await this.storeTokensInternal(e);return this.handleSuccessfulLogin(t),t},"storeTokens")}async getLogoutUrl(){return m(async()=>(await this.userManager.removeUser(),this.eventEmitter.emit("loggedOut"),await this.getLogoutUrlInternal()||void 0),"getLogoutUrl")}async logoutSilentCallback(e){return m(()=>this.userManager.signoutSilentCallback(e),"logoutSilentCallback")}getConfig(){return this.config}async getClientId(){return this.config.oidcConfiguration.clientId}handleSuccessfulLogin(e){this.eventEmitter.emit("loggedIn",e),identify({passportId:e.profile.sub});}buildExtraQueryParams(e,t){let r={...this.userManager.settings?.extraQueryParams??{},rid:getDetail(Detail.RUNTIME_ID)||""};if(e){if(e.directLoginMethod==="email"){let o=e.email;o&&(r.direct=e.directLoginMethod,r.email=o);}else r.direct=e.directLoginMethod;e.marketingConsentStatus&&(r.marketingConsent=e.marketingConsentStatus);}return t&&(r.im_passport_trace_id=t),r}async loginWithRedirectInternal(e){await this.userManager.clearStaleState(),await h(async()=>{let t=this.buildExtraQueryParams(e);await this.userManager.signinRedirect({extraQueryParams:t});},"AUTHENTICATION_ERROR");}async loginWithPopup(e){return h(async()=>{let t,r;if(e)t=e;else if(!this.config.popupOverlayOptions?.disableHeadlessLoginPromptOverlay){let{imPassportTraceId:s,...a}=await this.embeddedLoginPrompt.displayEmbeddedLoginPrompt();t=a,r=s;}let o=window.crypto.randomUUID(),i=async()=>{let s=this.buildExtraQueryParams(t,r);return this.userManager.signinPopup({extraQueryParams:s,popupWindowFeatures:{width:410,height:450},popupWindowTarget:o,popupAbortOnClose:!0})};return new Promise((s,a)=>{i().then(l=>s(n.mapOidcUserToDomainModel(l))).catch(l=>{if(!(l instanceof Error)||l.message!=="Attempted to navigate on a disposed window"){a(l);return}let c=!1,d=new P(this.config.popupOverlayOptions||{},!0);d.append(async()=>{try{if(c)window.open("",o);else {c=!0;let g=await i();d.remove(),s(n.mapOidcUserToDomainModel(g));}}catch(g){d.remove(),a(g);}},()=>{d.remove(),a(new Error("Popup closed by user"));});});})},"AUTHENTICATION_ERROR")}static mapOidcUserToDomainModel=e=>{let t,r;if(e.id_token){let s=u(e.id_token);t=s?.passport,s?.username&&(r=s?.username);}let o={expired:e.expired,idToken:e.id_token,accessToken:e.access_token,refreshToken:e.refresh_token,profile:{sub:e.profile.sub,email:e.profile.email,nickname:e.profile.nickname,username:r}};t?.zkevm_eth_address&&t?.zkevm_user_admin_address&&(o.zkEvm=ce(t.zkevm_eth_address,t.zkevm_user_admin_address));let i=Object.values(A).filter(s=>s!=="zkevm");for(let s of i){let a=t?.[s];a?.eth_address&&a?.user_admin_address&&(o[s]=ce(a.eth_address,a.user_admin_address));}return o};static mapDeviceTokenResponseToOidcUser=e=>{let t=u(e.id_token);return new User({id_token:e.id_token,access_token:e.access_token,refresh_token:e.refresh_token,token_type:e.token_type,profile:{sub:t.sub,iss:t.iss,aud:t.aud,exp:t.exp,iat:t.iat,email:t.email,nickname:t.nickname,passport:t.passport,...t.username?{username:t.username}:{}}})};async loginCallbackInternal(){return h(async()=>{let e=await this.userManager.signinCallback();if(e)return n.mapOidcUserToDomainModel(e)},"AUTHENTICATION_ERROR")}async getPKCEAuthorizationUrl(e,t){let r=B(window.crypto.getRandomValues(new Uint8Array(32))),o=B(await at(r)),i=B(window.crypto.getRandomValues(new Uint8Array(32))),{redirectUri:s,scope:a,audience:l,clientId:c}=this.config.oidcConfiguration;this.deviceCredentialsManager.savePKCEData({state:i,verifier:r});let d=new URL(ot,this.config.authenticationDomain);if(d.searchParams.set("response_type","code"),d.searchParams.set("code_challenge",o),d.searchParams.set("code_challenge_method","S256"),d.searchParams.set("client_id",c),d.searchParams.set("redirect_uri",s),d.searchParams.set("state",i),a&&d.searchParams.set("scope",a),l&&d.searchParams.set("audience",l),e){if(e.directLoginMethod==="email"){let g=e.email;g&&(d.searchParams.set("direct",e.directLoginMethod),d.searchParams.set("email",g));}else d.searchParams.set("direct",e.directLoginMethod);e.marketingConsentStatus&&d.searchParams.set("marketingConsent",e.marketingConsentStatus);}return t&&d.searchParams.set("im_passport_trace_id",t),d.toString()}async loginWithPKCEFlowCallbackInternal(e,t){return h(async()=>{let r=this.deviceCredentialsManager.getPKCEData();if(!r)throw new Error("No code verifier or state for PKCE");if(t!==r.state)throw new Error("Provided state does not match stored state");let o=await this.getPKCEToken(e,r.verifier),i=n.mapDeviceTokenResponseToOidcUser(o),s=n.mapOidcUserToDomainModel(i);return await this.userManager.storeUser(i),s},"AUTHENTICATION_ERROR")}async getPKCEToken(e,t){let r=await fetch(`${this.config.authenticationDomain}/oauth/token`,{method:"POST",headers:je,body:new URLSearchParams({client_id:this.config.oidcConfiguration.clientId,grant_type:"authorization_code",code_verifier:t,code:e,redirect_uri:this.config.oidcConfiguration.redirectUri})}),o=await r.text(),i=et(o);if(!r.ok)throw new Error(tt(i,o,r.status));if(!i||typeof i!="object")throw new Error("Token endpoint returned an invalid response");return i}async storeTokensInternal(e){return h(async()=>{let t=n.mapDeviceTokenResponseToOidcUser(e),r=n.mapOidcUserToDomainModel(t);return await this.userManager.storeUser(t),r},"AUTHENTICATION_ERROR")}async logoutInternal(){await h(async()=>{await this.userManager.revokeTokens(["refresh_token"]),this.logoutMode==="silent"?await this.userManager.signoutSilent():await this.userManager.signoutRedirect();},"LOGOUT_ERROR");}async getLogoutUrlInternal(){let e=this.userManager.settings?.metadata?.end_session_endpoint;return e||(v.warn("Failed to get logout URL"),null)}forceUserRefreshInBackgroundInternal(){this.refreshTokenAndUpdatePromise().catch(e=>{v.warn("Failed to refresh user token",e);});}async forceUserRefreshInternal(){return this.refreshTokenAndUpdatePromise().catch(e=>(v.warn("Failed to refresh user token",e),null))}async refreshTokenAndUpdatePromise(){return this.refreshingPromise?this.refreshingPromise:(this.refreshingPromise=new Promise((e,t)=>{(async()=>{try{let r=await this.userManager.signinSilent();if(r){let o=n.mapOidcUserToDomainModel(r);this.eventEmitter.emit("tokenRefreshed",o),e(o);return}e(null);}catch(r){let o="AUTHENTICATION_ERROR",i="Failed to refresh token",s=!0;if(r instanceof ErrorTimeout?(o="SILENT_LOGIN_ERROR",i=`${i}: ${r.message}`,s=!1):r instanceof ErrorResponse?(o="NOT_LOGGED_IN_ERROR",i=`${i}: ${r.message||r.error_description}`):r instanceof Error?i=`${i}: ${r.message}`:typeof r=="string"&&(i=`${i}: ${r}`),s){this.eventEmitter.emit("userRemoved",{reason:"refresh_failed",error:i});try{await this.userManager.removeUser();}catch(a){a instanceof Error&&(i=`${i}: Failed to remove user: ${a.message}`);}}t(new f(i,o));}finally{this.refreshingPromise=null;}})();}),this.refreshingPromise)}async getUserInternal(e=t=>!0){if(this.refreshingPromise){let r=await this.refreshingPromise;return r&&e(r)?r:null}let t=await this.userManager.getUser();if(!t)return null;if(!le(t)){let r=n.mapOidcUserToDomainModel(t);if(r&&e(r))return r}if(t.refresh_token){let r=await this.refreshTokenAndUpdatePromise();if(r&&e(r))return r}return null}async getUserZkEvmInternal(){let e=await this.getUserInternal(F);if(!e)throw new Error("Failed to obtain a User with the required ZkEvm attributes");return e}};var ct="im_passport_embedded_login_prompt",ue="passport-embedded-login-iframe",ge="passport-overlay";var pt="https://auth.immutable.com",mt="platform_api",ut="openid profile email offline_access transact",gt="/authorize",ft="/oauth/token",Z="imtbl_pkce_data";function fe(n){return btoa(String.fromCharCode(...new Uint8Array(n))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function Et(n){let t=new TextEncoder().encode(n);return window.crypto.subtle.digest("SHA-256",t)}function pe(){return fe(window.crypto.getRandomValues(new Uint8Array(32)))}function $(n){return n.authenticationDomain||pt}function ht(n){try{let e=u(n);if(e.exp)return e.exp*1e3}catch{}return Date.now()+3600*1e3}function _t(n){let{access_token:e,refresh_token:t,id_token:r}=n,o={sub:""},i;if(r)try{let{sub:s,email:a,nickname:l,passport:c}=u(r);o={sub:s,email:a,nickname:l},c?.zkevm_eth_address&&c?.zkevm_user_admin_address&&(i={ethAddress:c.zkevm_eth_address,userAdminAddress:c.zkevm_user_admin_address});}catch{}return {accessToken:e,refreshToken:t,idToken:r,accessTokenExpires:ht(e),profile:o,zkEvm:i}}function yt(n){typeof window<"u"&&window.sessionStorage&&window.sessionStorage.setItem(Z,JSON.stringify(n));}function Ct(){if(typeof window<"u"&&window.sessionStorage){let n=window.sessionStorage.getItem(Z);if(n)try{return JSON.parse(n)}catch{return null}}return null}function me(){typeof window<"u"&&window.sessionStorage&&window.sessionStorage.removeItem(Z);}function Rt(){let n="passport-embedded-login-keyframes";if(document.getElementById(n))return;let e=document.createElement("style");e.id=n,e.textContent=`
|
|
387
|
+
`,document.head.appendChild(e);};getEmbeddedLoginIFrame=()=>{let e=document.createElement("iframe");return e.id=ae,e.src=this.getHref(),e.style.height="100vh",e.style.width="100vw",e.style.maxHeight=`${Ae}px`,e.style.maxWidth=`${Ue}px`,e.style.borderRadius=xe,e.style.opacity="0",e.style.transform="scale(0.6)",e.style.animation="passportEmbeddedLoginPromptPopBounceIn 1s ease forwards",n.appendIFrameStylesIfNeeded(),e};displayEmbeddedLoginPrompt(){return new Promise((e,t)=>{let r=this.getEmbeddedLoginIFrame(),o=({data:i,origin:s})=>{if(!(s!==this.config.authenticationDomain||i.eventType!==X))switch(i.messageType){case"login_method_selected":{let a=i.payload;window.removeEventListener("message",o),h.remove(),e(a);break}case"login_prompt_error":{window.removeEventListener("message",o),h.remove(),t(new Error("Error during embedded login prompt",{cause:i.payload}));break}case"login_prompt_closed":{window.removeEventListener("message",o),h.remove(),t(new Error("Popup closed by user"));break}default:window.removeEventListener("message",o),h.remove(),t(new Error(`Unsupported message type: ${i.messageType}`));break}};window.addEventListener("message",o),h.appendOverlay(r,()=>{window.removeEventListener("message",o),h.remove(),t(new Error("Popup closed by user"));});})}};var R=class{listeners=new Map;emit(e,...t){let r=this.listeners.get(e);!r||r.size===0||[...r].forEach(o=>{o(...t);});}on(e,t){let r=this.listeners.get(e)??new Set;r.add(t),this.listeners.set(e,r);}removeListener(e,t){let r=this.listeners.get(e);r&&(r.delete(t),r.size===0&&this.listeners.delete(e));}};var u=async(n,e,t=!0,r=!0)=>{let o=trackFlow("passport",e,t);try{return await n(o)}catch(i){throw i instanceof Error?trackError("passport",e,i,{flowId:o.details.flowId}):o.addEvent("errored"),i}finally{r&&o.addEvent("End");}};var Me=()=>typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{},Ne=n=>{let e=n.replace(/-/g,"+").replace(/_/g,"/"),t=e.length%4===0?"":"=".repeat(4-e.length%4);return e+t},He=n=>{let e=Me();if(typeof e.atob!="function")return null;let t=e.atob(n),r=new Uint8Array(t.length);for(let i=0;i<t.length;i+=1)r[i]=t.charCodeAt(i);if(typeof e.TextDecoder=="function")return new e.TextDecoder("utf-8").decode(r);let o="";for(let i=0;i<r.length;i+=1)o+=String.fromCharCode(r[i]);return o},Fe=n=>{if(typeof Buffer<"u")return Buffer.from(n,"base64").toString("utf-8");let e=He(n);if(e===null)throw new Error("Base64 decoding is not supported in this environment");return e},m=n=>{if(typeof n!="string")throw new Error("JWT must be a string");let e=n.split(".");if(e.length<2)throw new Error("Invalid JWT: payload segment is missing");let t=e[1],r=Fe(Ne(t));try{return JSON.parse(r)}catch{throw new Error("Invalid JWT payload: unable to parse JSON")}};var de="pkce_state",le="pkce_verifier",Ve=3600,P=class{isTokenValid(e){try{let r=m(e).exp??0,o=Date.now()/1e3+Ve;return r>o}catch{return !1}}savePKCEData(e){localStorage.setItem(de,e.state),localStorage.setItem(le,e.verifier);}getPKCEData(){let e=localStorage.getItem(de),t=localStorage.getItem(le);return e&&t?{state:e,verifier:t}:null}};var Ge=(...n)=>{if(typeof process>"u")return;process?.env?.JEST_WORKER_ID===void 0&&console.warn(...n);},v={warn:Ge};function ce(n){try{let e=m(n),t=Math.floor(Date.now()/1e3);return e.exp?e.exp<=t+30:!0}catch{return !0}}function pe(n){let{id_token:e,access_token:t}=n;return !t||!e?!0:ce(t)||ce(e)}var w=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){S({id:"link-googleapis",href:"https://fonts.googleapis.com"}),S({id:"link-gstatic",href:"https://fonts.gstatic.com",crossOrigin:"anonymous"}),S({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?oe():ie(),document.body.insertAdjacentElement("beforeend",t),this.overlay=t;}}updateTryAgainButton(e){let t=document.getElementById(x);t&&(this.tryAgainListener&&t.removeEventListener("click",this.tryAgainListener),this.tryAgainListener=e,t.addEventListener("click",e));}updateCloseButton(e){let t=document.getElementById(U);t&&(this.onCloseListener&&t.removeEventListener("click",this.onCloseListener),this.onCloseListener=e,t.addEventListener("click",e));}};var D=class{storage;constructor(e,t){this.storage=Be.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="/v2/logout",Ze="/im-logged-out",$e="https://auth.immutable.com";function We(n){return n.replace(/^(?:https?:\/\/)?(.*)/,"https://$1")}function M(n){let e=We(n.authenticationDomain||$e),t=n.crossSdkBridgeEnabled?Ze:Ke,r=new URL(t,e);return r.searchParams.set("client_id",n.clientId),n.logoutRedirectUri&&r.searchParams.set("returnTo",n.logoutRedirectUri),r.toString()}var it={"Content-Type":"application/x-www-form-urlencoded"},st=n=>{if(n)try{return JSON.parse(n)}catch{return}},at=(n,e,t)=>{if(n&&typeof n=="object"){let r=n,o=r.error_description??r.message??r.error;if(typeof o=="string"&&o.trim().length>0)return o}return e.trim().length>0?e:`Token request failed with status ${t}`},ue=(n,e)=>({ethAddress:n,userAdminAddress:e}),dt="/authorize",lt=n=>{let{authenticationDomain:e,oidcConfiguration:t}=n,r;n.crossSdkBridgeEnabled?r=new D("ImmutableSDKPassport",Be.INDEXEDDB):typeof window<"u"?r=window.localStorage:r=new InMemoryWebStorage;let o=new WebStorageStateStore({store:r}),i=M({clientId:t.clientId,authenticationDomain:e,logoutRedirectUri:t.logoutRedirectUri,crossSdkBridgeEnabled:n.crossSdkBridgeEnabled});return {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,revocation_endpoint:`${e}/oauth/revoke`},automaticSilentRenew:!1,scope:t.scope,userStore:o,revokeTokenTypes:["refresh_token"],extraQueryParams:{...t.audience?{audience:t.audience}:{}}}};function K(n){return btoa(String.fromCharCode(...new Uint8Array(n))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function ct(n){let t=new TextEncoder().encode(n);return window.crypto.subtle.digest("SHA-256",t)}var Z=class n{config;userManager;deviceCredentialsManager;embeddedLoginPrompt;logoutMode;refreshingPromise=null;eventEmitter;constructor(e){this.config=new O(e),this.embeddedLoginPrompt=new L(this.config),this.userManager=new UserManager(lt(this.config)),this.deviceCredentialsManager=new P,this.logoutMode=this.config.oidcConfiguration.logoutMode||"redirect",this.eventEmitter=new R,track("passport","initialise");}async login(e){return u(async()=>{let{useCachedSession:t=!1,useSilentLogin:r}=e||{},o=null;try{o=await this.getUserInternal();}catch(i){if(i instanceof Error&&!i.message.includes("Unknown or invalid refresh token")&&trackError("passport","login",i),t)throw i;v.warn("Failed to retrieve a cached user session",i);}if(!o&&r)o=await this.forceUserRefreshInternal();else if(!o&&!t){if(e?.useRedirectFlow)return await this.loginWithRedirectInternal(e?.directLoginOptions),null;o=await this.loginWithPopup(e?.directLoginOptions);}return o&&this.handleSuccessfulLogin(o),o},"login")}async loginWithRedirect(e){await this.loginWithRedirectInternal(e);}async loginCallback(){return u(async()=>{let e=await this.loginCallbackInternal();return e&&this.handleSuccessfulLogin(e),e},"loginCallback")}async logout(){await u(async()=>{await this.logoutInternal(),this.eventEmitter.emit("loggedOut");},"logout");}async getUser(){return this.getUserInternal()}async getUserOrLogin(){let e=null;try{e=await this.getUserInternal();}catch(r){v.warn("Failed to retrieve a cached user session",r);}if(e)return e;let t=await this.loginWithPopup();return this.handleSuccessfulLogin(t),t}async getUserZkEvm(){return this.getUserZkEvmInternal()}async getIdToken(){return u(async()=>(await this.getUserInternal())?.idToken,"getIdToken",!1)}async getAccessToken(){return u(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 u(async()=>this.getPKCEAuthorizationUrl(e,t),"loginWithPKCEFlow")}async loginWithPKCEFlowCallback(e,t){return u(async()=>{let r=await this.loginWithPKCEFlowCallbackInternal(e,t);return this.handleSuccessfulLogin(r),r},"loginWithPKCEFlowCallback")}async storeTokens(e){return u(async()=>{let t=await this.storeTokensInternal(e);return this.handleSuccessfulLogin(t),t},"storeTokens")}async getLogoutUrl(){return u(async()=>(await this.userManager.removeUser(),this.eventEmitter.emit("loggedOut"),await this.getLogoutUrlInternal()||void 0),"getLogoutUrl")}async logoutSilentCallback(e){return u(()=>this.userManager.signoutSilentCallback(e),"logoutSilentCallback")}getConfig(){return this.config}async getClientId(){return this.config.oidcConfiguration.clientId}handleSuccessfulLogin(e){this.eventEmitter.emit("loggedIn",e),identify({passportId:e.profile.sub});}buildExtraQueryParams(e,t){let r={...this.userManager.settings?.extraQueryParams??{},rid:getDetail(Detail.RUNTIME_ID)||""};if(e){if(e.directLoginMethod==="email"){let o=e.email;o&&(r.direct=e.directLoginMethod,r.email=o);}else r.direct=e.directLoginMethod;e.marketingConsentStatus&&(r.marketingConsent=e.marketingConsentStatus);}return t&&(r.im_passport_trace_id=t),r}async loginWithRedirectInternal(e){await this.userManager.clearStaleState(),await E(async()=>{let t=this.buildExtraQueryParams(e);await this.userManager.signinRedirect({extraQueryParams:t});},"AUTHENTICATION_ERROR");}async loginWithPopup(e){return E(async()=>{let t,r;if(e)t=e;else if(!this.config.popupOverlayOptions?.disableHeadlessLoginPromptOverlay){let{imPassportTraceId:s,...a}=await this.embeddedLoginPrompt.displayEmbeddedLoginPrompt();t=a,r=s;}let o=window.crypto.randomUUID(),i=async()=>{let s=this.buildExtraQueryParams(t,r);return this.userManager.signinPopup({extraQueryParams:s,popupWindowFeatures:{width:410,height:450},popupWindowTarget:o,popupAbortOnClose:!0})};return new Promise((s,a)=>{i().then(d=>s(n.mapOidcUserToDomainModel(d))).catch(d=>{if(!(d instanceof Error)||d.message!=="Attempted to navigate on a disposed window"){a(d);return}let c=!1,l=new w(this.config.popupOverlayOptions||{},!0);l.append(async()=>{try{if(c)window.open("",o);else {c=!0;let g=await i();l.remove(),s(n.mapOidcUserToDomainModel(g));}}catch(g){l.remove(),a(g);}},()=>{l.remove(),a(new Error("Popup closed by user"));});});})},"AUTHENTICATION_ERROR")}static mapOidcUserToDomainModel=e=>{let t,r;if(e.id_token){let s=m(e.id_token);t=s?.passport,s?.username&&(r=s?.username);}let o={expired:e.expired,idToken:e.id_token,accessToken:e.access_token,refreshToken:e.refresh_token,profile:{sub:e.profile.sub,email:e.profile.email,nickname:e.profile.nickname,username:r}};t?.zkevm_eth_address&&t?.zkevm_user_admin_address&&(o.zkEvm=ue(t.zkevm_eth_address,t.zkevm_user_admin_address));let i=Object.values(A).filter(s=>s!=="zkevm");for(let s of i){let a=t?.[s];a?.eth_address&&a?.user_admin_address&&(o[s]=ue(a.eth_address,a.user_admin_address));}return o};static mapDeviceTokenResponseToOidcUser=e=>{let t=m(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 E(async()=>{let e=await this.userManager.signinCallback();if(e)return n.mapOidcUserToDomainModel(e)},"AUTHENTICATION_ERROR")}async getPKCEAuthorizationUrl(e,t){let r=K(window.crypto.getRandomValues(new Uint8Array(32))),o=K(await ct(r)),i=K(window.crypto.getRandomValues(new Uint8Array(32))),{redirectUri:s,scope:a,audience:d,clientId:c}=this.config.oidcConfiguration;this.deviceCredentialsManager.savePKCEData({state:i,verifier:r});let l=new URL(dt,this.config.authenticationDomain);if(l.searchParams.set("response_type","code"),l.searchParams.set("code_challenge",o),l.searchParams.set("code_challenge_method","S256"),l.searchParams.set("client_id",c),l.searchParams.set("redirect_uri",s),l.searchParams.set("state",i),a&&l.searchParams.set("scope",a),d&&l.searchParams.set("audience",d),e){if(e.directLoginMethod==="email"){let g=e.email;g&&(l.searchParams.set("direct",e.directLoginMethod),l.searchParams.set("email",g));}else l.searchParams.set("direct",e.directLoginMethod);e.marketingConsentStatus&&l.searchParams.set("marketingConsent",e.marketingConsentStatus);}return t&&l.searchParams.set("im_passport_trace_id",t),l.toString()}async loginWithPKCEFlowCallbackInternal(e,t){return E(async()=>{let r=this.deviceCredentialsManager.getPKCEData();if(!r)throw new Error("No code verifier or state for PKCE");if(t!==r.state)throw new Error("Provided state does not match stored state");let o=await this.getPKCEToken(e,r.verifier),i=n.mapDeviceTokenResponseToOidcUser(o),s=n.mapOidcUserToDomainModel(i);return await this.userManager.storeUser(i),s},"AUTHENTICATION_ERROR")}async getPKCEToken(e,t){let r=await fetch(`${this.config.authenticationDomain}/oauth/token`,{method:"POST",headers:it,body:new URLSearchParams({client_id:this.config.oidcConfiguration.clientId,grant_type:"authorization_code",code_verifier:t,code:e,redirect_uri:this.config.oidcConfiguration.redirectUri})}),o=await r.text(),i=st(o);if(!r.ok)throw new Error(at(i,o,r.status));if(!i||typeof i!="object")throw new Error("Token endpoint returned an invalid response");return i}async storeTokensInternal(e){return E(async()=>{let t=n.mapDeviceTokenResponseToOidcUser(e),r=n.mapOidcUserToDomainModel(t);return await this.userManager.storeUser(t),r},"AUTHENTICATION_ERROR")}async logoutInternal(){await E(async()=>{await this.userManager.revokeTokens(["refresh_token"]),this.logoutMode==="silent"?await this.userManager.signoutSilent():await this.userManager.signoutRedirect();},"LOGOUT_ERROR");}async getLogoutUrlInternal(){let e=this.userManager.settings?.metadata?.end_session_endpoint;return e||(v.warn("Failed to get logout URL"),null)}forceUserRefreshInBackgroundInternal(){this.refreshTokenAndUpdatePromise().catch(e=>{v.warn("Failed to refresh user token",e);});}async forceUserRefreshInternal(){return this.refreshTokenAndUpdatePromise().catch(e=>(v.warn("Failed to refresh user token",e),null))}async refreshTokenAndUpdatePromise(){return this.refreshingPromise?this.refreshingPromise:(this.refreshingPromise=new Promise((e,t)=>{(async()=>{try{let r=await this.userManager.signinSilent();if(r){let o=n.mapOidcUserToDomainModel(r);this.eventEmitter.emit("tokenRefreshed",o),e(o);return}e(null);}catch(r){let o="AUTHENTICATION_ERROR",i="Failed to refresh token",s=!0;if(r instanceof ErrorTimeout?(o="SILENT_LOGIN_ERROR",i=`${i}: ${r.message}`,s=!1):r instanceof ErrorResponse?(o="NOT_LOGGED_IN_ERROR",i=`${i}: ${r.message||r.error_description}`):r instanceof Error?i=`${i}: ${r.message}`:typeof r=="string"&&(i=`${i}: ${r}`),s){this.eventEmitter.emit("userRemoved",{reason:"refresh_failed",error:i});try{await this.userManager.removeUser();}catch(a){a instanceof Error&&(i=`${i}: Failed to remove user: ${a.message}`);}}t(new f(i,o));}finally{this.refreshingPromise=null;}})();}),this.refreshingPromise)}async getUserInternal(e=t=>!0){if(this.refreshingPromise){let r=await this.refreshingPromise;return r&&e(r)?r:null}let t=await this.userManager.getUser();if(!t)return null;if(!pe(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(V);if(!e)throw new Error("Failed to obtain a User with the required ZkEvm attributes");return e}};var mt="im_passport_embedded_login_prompt",fe="passport-embedded-login-iframe",he="passport-overlay";var gt="https://auth.immutable.com",ft="platform_api",ht="openid profile email offline_access transact",Et="/authorize",_t="/oauth/token",$="imtbl_pkce_data";function Ee(n){return btoa(String.fromCharCode(...new Uint8Array(n))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function yt(n){let t=new TextEncoder().encode(n);return window.crypto.subtle.digest("SHA-256",t)}function me(){return Ee(window.crypto.getRandomValues(new Uint8Array(32)))}function W(n){return n.authenticationDomain||gt}function Ct(n){try{let e=m(n);if(e.exp)return e.exp*1e3}catch{}return Date.now()+3600*1e3}function Rt(n){let{access_token:e,refresh_token:t,id_token:r}=n,o={sub:""},i;if(r)try{let{sub:s,email:a,nickname:d,passport:c}=m(r);o={sub:s,email:a,nickname:d},c?.zkevm_eth_address&&c?.zkevm_user_admin_address&&(i={ethAddress:c.zkevm_eth_address,userAdminAddress:c.zkevm_user_admin_address});}catch{}return {accessToken:e,refreshToken:t,idToken:r,accessTokenExpires:Ct(e),profile:o,zkEvm:i}}function vt(n){typeof window<"u"&&window.sessionStorage&&window.sessionStorage.setItem($,JSON.stringify(n));}function Tt(){if(typeof window<"u"&&window.sessionStorage){let n=window.sessionStorage.getItem($);if(n)try{return JSON.parse(n)}catch{return null}}return null}function ge(){typeof window<"u"&&window.sessionStorage&&window.sessionStorage.removeItem($);}function Ot(){let n="passport-embedded-login-keyframes";if(document.getElementById(n))return;let e=document.createElement("style");e.id=n,e.textContent=`
|
|
388
388
|
@keyframes passportEmbeddedLoginPromptPopBounceIn {
|
|
389
389
|
0% {
|
|
390
390
|
opacity: 0.5;
|
|
@@ -403,7 +403,7 @@ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION
|
|
|
403
403
|
}
|
|
404
404
|
|
|
405
405
|
@media (max-height: 400px) {
|
|
406
|
-
#${
|
|
406
|
+
#${fe} {
|
|
407
407
|
width: 100% !important;
|
|
408
408
|
max-width: none !important;
|
|
409
409
|
}
|
|
@@ -417,7 +417,7 @@ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION
|
|
|
417
417
|
opacity: 1;
|
|
418
418
|
}
|
|
419
419
|
}
|
|
420
|
-
`,document.head.appendChild(e);}function
|
|
420
|
+
`,document.head.appendChild(e);}function Lt(n,e){let t=getDetail(Detail.RUNTIME_ID),r=document.createElement("iframe");return r.id=fe,r.src=`${n}/im-embedded-login-prompt?client_id=${e}&rid=${t}`,r.style.height="100vh",r.style.width="100vw",r.style.maxHeight="660px",r.style.maxWidth="440px",r.style.borderRadius="16px",r.style.border="none",r.style.opacity="0",r.style.transform="scale(0.6)",r.style.animation="passportEmbeddedLoginPromptPopBounceIn 1s ease forwards",Ot(),r}function Pt(){let n=document.createElement("div");n.id=he,n.style.cssText=`
|
|
421
421
|
position: fixed;
|
|
422
422
|
top: 0;
|
|
423
423
|
left: 0;
|
|
@@ -436,6 +436,6 @@ var I=(p=>(p.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",p.INVALID_CONFIGURATION
|
|
|
436
436
|
flex-direction: column;
|
|
437
437
|
align-items: center;
|
|
438
438
|
width: 100%;
|
|
439
|
-
`,n.appendChild(e),n}function
|
|
439
|
+
`,n.appendChild(e),n}function I(){document.getElementById(he)?.remove();}function wt(n,e){return new Promise((t,r)=>{let o=Lt(n,e),i=Pt(),s=({data:c,origin:l})=>{if(!(l!==n||c.eventType!==mt))switch(c.messageType){case"login_method_selected":{let g=c.payload;window.removeEventListener("message",s),I(),t(g);break}case"login_prompt_error":{window.removeEventListener("message",s),I(),r(new Error("Error during embedded login prompt",{cause:c.payload}));break}case"login_prompt_closed":{window.removeEventListener("message",s),I(),r(new Error("Login closed by user"));break}default:window.removeEventListener("message",s),I(),r(new Error(`Unsupported message type: ${c.messageType}`));break}},a=c=>{c.target===i&&(window.removeEventListener("message",s),i.removeEventListener("click",a),I(),r(new Error("Login closed by user")));};window.addEventListener("message",s),i.addEventListener("click",a);let d=i.querySelector(`#${_}`);d&&d.appendChild(o),document.body.appendChild(i);})}async function _e(n,e){let t=W(n),r=me(),o=Ee(await yt(r)),i=me(),s=new URL(Et,t);s.searchParams.set("response_type","code"),s.searchParams.set("code_challenge",o),s.searchParams.set("code_challenge_method","S256"),s.searchParams.set("client_id",n.clientId),s.searchParams.set("redirect_uri",n.redirectUri),s.searchParams.set("state",i),s.searchParams.set("scope",n.scope||ht),n.audience?s.searchParams.set("audience",n.audience):s.searchParams.set("audience",ft);let a=e?.directLoginOptions;return a&&(a.directLoginMethod==="email"?a.email&&(s.searchParams.set("direct","email"),s.searchParams.set("email",a.email)):s.searchParams.set("direct",a.directLoginMethod),a.marketingConsentStatus&&s.searchParams.set("marketingConsent",a.marketingConsentStatus)),{url:s.toString(),verifier:r,state:i}}async function ye(n,e,t,r){let i=`${W(n)}${_t}`,s=await fetch(i,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",client_id:n.clientId,code_verifier:t,code:e,redirect_uri:r})});if(!s.ok){let d=await s.text(),c=`Token exchange failed with status ${s.status}`;try{let l=JSON.parse(d);l.error_description?c=l.error_description:l.error&&(c=l.error);}catch{d&&(c=d);}throw new Error(c)}let a=await s.json();return Rt(a)}async function Ce(n,e){track("passport","standaloneLoginWithPopup");let t=n.popupRedirectUri||n.redirectUri,r={...n,redirectUri:t},{url:o,verifier:i,state:s}=await _e(r,e);return new Promise((a,d)=>{let g=window.screenX+(window.outerWidth-500)/2,Re=window.screenY+(window.outerHeight-600)/2,y=window.open(o,"immutable_login",`width=500,height=600,left=${g},top=${Re},toolbar=no,menubar=no`);if(!y){d(new Error("Popup was blocked. Please allow popups for this site."));return}let N=setInterval(()=>{try{if(y.closed){clearInterval(N),d(new Error("Login popup was closed"));return}let H=y.location.href;if(H&&H.startsWith(t)){clearInterval(N),y.close();let k=new URL(H),Y=k.searchParams.get("code"),ve=k.searchParams.get("state"),J=k.searchParams.get("error"),Te=k.searchParams.get("error_description");if(J){d(new Error(Te||J));return}if(!Y){d(new Error("No authorization code received"));return}if(ve!==s){d(new Error("State mismatch - possible CSRF attack"));return}ye(r,Y,i,t).then(a).catch(d);}}catch{}},100);setTimeout(()=>{clearInterval(N),y.closed||y.close(),d(new Error("Login timed out"));},5*60*1e3);})}async function It(n){track("passport","standaloneLoginWithEmbedded");let e=W(n),t=await wt(e,n.clientId),r={directLoginOptions:{directLoginMethod:t.directLoginMethod,marketingConsentStatus:t.marketingConsentStatus,...t.directLoginMethod==="email"&&t.email?{email:t.email}:{}}};return Ce(n,r)}async function kt(n,e){track("passport","standaloneLoginWithRedirect");let{url:t,verifier:r,state:o}=await _e(n,e);vt({state:o,verifier:r,redirectUri:n.redirectUri}),window.location.href=t;}async function bt(n){if(track("passport","standaloneHandleCallback"),typeof window>"u")return;let e=new URLSearchParams(window.location.search),t=e.get("code"),r=e.get("state"),o=e.get("error"),i=e.get("error_description");if(o)throw new Error(i||o);if(!t)return;let s=Tt();if(!s)throw new Error("No PKCE data found. Login may have been initiated in a different session.");if(r!==s.state)throw ge(),new Error("State mismatch - possible CSRF attack");let a=await ye(n,t,s.verifier,s.redirectUri);return ge(),a}function z(n){return M(n)}function At(n){track("passport","standaloneLogoutWithRedirect");let e=z(n);window.location.href=e;}async function Ut(n,e=5e3){return track("passport","standaloneLogoutSilent"),new Promise((t,r)=>{let o=z(n),i=document.createElement("iframe");i.style.display="none",i.setAttribute("aria-hidden","true");let s,a=!1,d=()=>{s&&clearTimeout(s),i.remove();},c=()=>{a||(a=!0,d(),t());},l=()=>{a||(a=!0,d(),r(new Error("Silent logout failed: iframe load error")));};i.addEventListener("load",c),i.addEventListener("error",l),s=setTimeout(()=>{a||(a=!0,d(),t());},e),i.src=o,document.body.appendChild(i);})}
|
|
440
440
|
|
|
441
|
-
export {
|
|
441
|
+
export { Z as Auth, O as AuthConfiguration, G as AuthEvents, A as EvmChain, q as MarketingConsentStatus, f as PassportError, b as PassportErrorType, Q as RollupType, R as TypedEventEmitter, z as buildLogoutUrl, m as decodeJwtPayload, bt as handleLoginCallback, F as isAPIError, V as isUserZkEvm, It as loginWithEmbedded, Ce as loginWithPopup, kt as loginWithRedirect, Ut as logoutSilent, At as logoutWithRedirect, E as withPassportError };
|
package/dist/types/index.d.ts
CHANGED
|
@@ -6,3 +6,4 @@ export { default as TypedEventEmitter } from './utils/typedEventEmitter';
|
|
|
6
6
|
export { PassportError, PassportErrorType, withPassportError, isAPIError, } from './errors';
|
|
7
7
|
export { decodeJwtPayload } from './utils/jwt';
|
|
8
8
|
export { loginWithPopup, loginWithEmbedded, loginWithRedirect, handleLoginCallback, type LoginConfig, type TokenResponse, type StandaloneLoginOptions, } from './login/standalone';
|
|
9
|
+
export { logoutWithRedirect, logoutSilent, buildLogoutUrl, type LogoutConfig, } from './login/standalone';
|
|
@@ -139,3 +139,85 @@ export declare function loginWithRedirect(config: LoginConfig, options?: Standal
|
|
|
139
139
|
* ```
|
|
140
140
|
*/
|
|
141
141
|
export declare function handleLoginCallback(config: LoginConfig): Promise<TokenResponse | undefined>;
|
|
142
|
+
/**
|
|
143
|
+
* Configuration for standalone logout functions
|
|
144
|
+
*/
|
|
145
|
+
export interface LogoutConfig {
|
|
146
|
+
/** Your Immutable application client ID */
|
|
147
|
+
clientId: string;
|
|
148
|
+
/** URL to redirect to after logout completes (must be registered in your app settings) */
|
|
149
|
+
logoutRedirectUri?: string;
|
|
150
|
+
/** Authentication domain (default: "https://auth.immutable.com") */
|
|
151
|
+
authenticationDomain?: string;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Build the logout URL for federated logout.
|
|
155
|
+
* This URL can be used to redirect to the auth domain's logout endpoint,
|
|
156
|
+
* which clears the session on the auth server (including social provider sessions).
|
|
157
|
+
*
|
|
158
|
+
* @param config - Logout configuration
|
|
159
|
+
* @returns The full logout URL
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```typescript
|
|
163
|
+
* import { buildLogoutUrl } from '@imtbl/auth';
|
|
164
|
+
*
|
|
165
|
+
* const logoutUrl = buildLogoutUrl({
|
|
166
|
+
* clientId: 'your-client-id',
|
|
167
|
+
* logoutRedirectUri: 'https://your-app.com',
|
|
168
|
+
* });
|
|
169
|
+
* // => "https://auth.immutable.com/v2/logout?client_id=your-client-id&returnTo=https://your-app.com"
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
export declare function buildLogoutUrl(config: LogoutConfig): string;
|
|
173
|
+
/**
|
|
174
|
+
* Logout with redirect.
|
|
175
|
+
* Redirects the current page to the auth domain's logout endpoint,
|
|
176
|
+
* which clears the session on the auth server (including social provider sessions like Google).
|
|
177
|
+
*
|
|
178
|
+
* This is the recommended logout method for most applications as it ensures
|
|
179
|
+
* complete session cleanup. After logout, the user will be redirected to
|
|
180
|
+
* the `logoutRedirectUri` if provided.
|
|
181
|
+
*
|
|
182
|
+
* @param config - Logout configuration
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```typescript
|
|
186
|
+
* import { logoutWithRedirect } from '@imtbl/auth';
|
|
187
|
+
*
|
|
188
|
+
* // In your logout button handler
|
|
189
|
+
* logoutWithRedirect({
|
|
190
|
+
* clientId: 'your-client-id',
|
|
191
|
+
* logoutRedirectUri: 'https://your-app.com',
|
|
192
|
+
* });
|
|
193
|
+
* // Page will redirect to auth domain, then back to your app
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
export declare function logoutWithRedirect(config: LogoutConfig): void;
|
|
197
|
+
/**
|
|
198
|
+
* Logout silently using a hidden iframe.
|
|
199
|
+
* Clears the session on the auth server without redirecting the current page.
|
|
200
|
+
*
|
|
201
|
+
* Note: Silent logout may not work in all browsers due to third-party cookie
|
|
202
|
+
* restrictions. For more reliable session cleanup, use `logoutWithRedirect`.
|
|
203
|
+
*
|
|
204
|
+
* @param config - Logout configuration
|
|
205
|
+
* @param timeout - Timeout in milliseconds (default: 5000)
|
|
206
|
+
* @returns Promise that resolves when logout is complete or times out
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```typescript
|
|
210
|
+
* import { logoutSilent } from '@imtbl/auth';
|
|
211
|
+
*
|
|
212
|
+
* try {
|
|
213
|
+
* await logoutSilent({
|
|
214
|
+
* clientId: 'your-client-id',
|
|
215
|
+
* });
|
|
216
|
+
* console.log('Logged out silently');
|
|
217
|
+
* } catch (error) {
|
|
218
|
+
* console.error('Silent logout failed:', error);
|
|
219
|
+
* // Fall back to redirect logout
|
|
220
|
+
* }
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
export declare function logoutSilent(config: LogoutConfig, timeout?: number): Promise<void>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal logout utilities shared between Auth class and standalone functions.
|
|
3
|
+
* NOT exported from package index - only used internally.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Internal config for building logout URLs.
|
|
7
|
+
* Includes crossSdkBridgeEnabled for Auth class (Passport SDK).
|
|
8
|
+
* NOT exported publicly from the package.
|
|
9
|
+
*/
|
|
10
|
+
export interface InternalLogoutConfig {
|
|
11
|
+
/** The client ID for the application */
|
|
12
|
+
clientId: string;
|
|
13
|
+
/** The authentication domain (defaults to https://auth.immutable.com) */
|
|
14
|
+
authenticationDomain?: string;
|
|
15
|
+
/** The URI to redirect to after logout */
|
|
16
|
+
logoutRedirectUri?: string;
|
|
17
|
+
/** Whether cross-SDK bridge is enabled (internal to Auth class) */
|
|
18
|
+
crossSdkBridgeEnabled?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Build logout URL for federated logout.
|
|
22
|
+
* Used by both Auth class (with crossSdkBridgeEnabled) and standalone functions.
|
|
23
|
+
*
|
|
24
|
+
* @param config - Configuration for building the logout URL
|
|
25
|
+
* @returns The complete logout URL string
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildLogoutUrl(config: InternalLogoutConfig): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@imtbl/auth",
|
|
3
|
-
"version": "2.12.6-alpha.
|
|
3
|
+
"version": "2.12.6-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,8 +25,8 @@
|
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@imtbl/generated-clients": "2.12.6-alpha.
|
|
29
|
-
"@imtbl/metrics": "2.12.6-alpha.
|
|
28
|
+
"@imtbl/generated-clients": "2.12.6-alpha.1",
|
|
29
|
+
"@imtbl/metrics": "2.12.6-alpha.1",
|
|
30
30
|
"localforage": "^1.10.0",
|
|
31
31
|
"oidc-client-ts": "3.4.1"
|
|
32
32
|
},
|
package/src/Auth.ts
CHANGED
|
@@ -42,6 +42,7 @@ import logger from './utils/logger';
|
|
|
42
42
|
import { isAccessTokenExpiredOrExpiring } from './utils/token';
|
|
43
43
|
import LoginPopupOverlay from './overlay/loginPopupOverlay';
|
|
44
44
|
import { LocalForageAsyncStorage } from './storage/LocalForageAsyncStorage';
|
|
45
|
+
import { buildLogoutUrl } from './logout';
|
|
45
46
|
|
|
46
47
|
const formUrlEncodedHeaders = {
|
|
47
48
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
@@ -81,14 +82,8 @@ const toChainAddress = (ethAddress: string, userAdminAddress: string): ChainAddr
|
|
|
81
82
|
userAdminAddress: userAdminAddress as `0x${string}`,
|
|
82
83
|
});
|
|
83
84
|
|
|
84
|
-
const logoutEndpoint = '/v2/logout';
|
|
85
|
-
const crossSdkBridgeLogoutEndpoint = '/im-logged-out';
|
|
86
85
|
const authorizeEndpoint = '/authorize';
|
|
87
86
|
|
|
88
|
-
const getLogoutEndpointPath = (crossSdkBridgeEnabled: boolean): string => (
|
|
89
|
-
crossSdkBridgeEnabled ? crossSdkBridgeLogoutEndpoint : logoutEndpoint
|
|
90
|
-
);
|
|
91
|
-
|
|
92
87
|
const getAuthConfiguration = (config: IAuthConfiguration): UserManagerSettings => {
|
|
93
88
|
const { authenticationDomain, oidcConfiguration } = config;
|
|
94
89
|
|
|
@@ -102,14 +97,12 @@ const getAuthConfiguration = (config: IAuthConfiguration): UserManagerSettings =
|
|
|
102
97
|
}
|
|
103
98
|
const userStore = new WebStorageStateStore({ store });
|
|
104
99
|
|
|
105
|
-
const endSessionEndpoint =
|
|
106
|
-
|
|
107
|
-
authenticationDomain
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
endSessionEndpoint.searchParams.set('returnTo', oidcConfiguration.logoutRedirectUri);
|
|
112
|
-
}
|
|
100
|
+
const endSessionEndpoint = buildLogoutUrl({
|
|
101
|
+
clientId: oidcConfiguration.clientId,
|
|
102
|
+
authenticationDomain,
|
|
103
|
+
logoutRedirectUri: oidcConfiguration.logoutRedirectUri,
|
|
104
|
+
crossSdkBridgeEnabled: config.crossSdkBridgeEnabled,
|
|
105
|
+
});
|
|
113
106
|
|
|
114
107
|
return {
|
|
115
108
|
authority: authenticationDomain,
|
|
@@ -120,7 +113,7 @@ const getAuthConfiguration = (config: IAuthConfiguration): UserManagerSettings =
|
|
|
120
113
|
authorization_endpoint: `${authenticationDomain}/authorize`,
|
|
121
114
|
token_endpoint: `${authenticationDomain}/oauth/token`,
|
|
122
115
|
userinfo_endpoint: `${authenticationDomain}/userinfo`,
|
|
123
|
-
end_session_endpoint: endSessionEndpoint
|
|
116
|
+
end_session_endpoint: endSessionEndpoint,
|
|
124
117
|
revocation_endpoint: `${authenticationDomain}/oauth/revoke`,
|
|
125
118
|
},
|
|
126
119
|
automaticSilentRenew: false,
|
package/src/index.ts
CHANGED
|
@@ -56,3 +56,14 @@ export {
|
|
|
56
56
|
type TokenResponse,
|
|
57
57
|
type StandaloneLoginOptions,
|
|
58
58
|
} from './login/standalone';
|
|
59
|
+
|
|
60
|
+
// ============================================================================
|
|
61
|
+
// Standalone Logout Functions (stateless, for use with NextAuth or similar)
|
|
62
|
+
// ============================================================================
|
|
63
|
+
|
|
64
|
+
export {
|
|
65
|
+
logoutWithRedirect,
|
|
66
|
+
logoutSilent,
|
|
67
|
+
buildLogoutUrl,
|
|
68
|
+
type LogoutConfig,
|
|
69
|
+
} from './login/standalone';
|