@imtbl/auth 2.10.7-alpha.5 → 2.11.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +1 -1
- package/dist/browser/index.js +26 -26
- package/dist/node/index.cjs +41 -41
- package/dist/node/index.js +31 -31
- package/dist/types/Auth.d.ts +51 -14
- package/dist/types/errors.d.ts +2 -1
- package/dist/types/index.d.ts +1 -2
- package/dist/types/types.d.ts +2 -0
- package/jest.config.ts +27 -0
- package/jest.setup.js +4 -0
- package/package.json +14 -6
- package/src/Auth.test.ts +186 -0
- package/src/Auth.ts +582 -47
- package/src/errors.test.ts +21 -0
- package/src/errors.ts +7 -1
- package/src/index.ts +3 -4
- package/src/types.ts +2 -0
- package/tsconfig.eslint.json +6 -0
- package/tsconfig.json +4 -0
- package/dist/types/authManager.d.ts +0 -61
- package/src/authManager.ts +0 -643
package/dist/node/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { UserManager, User, ErrorTimeout, ErrorResponse, InMemoryWebStorage, WebStorageStateStore } from 'oidc-client-ts';
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
2
|
+
import ve, { isAxiosError } from 'axios';
|
|
3
|
+
import X from 'jwt-decode';
|
|
4
|
+
import Ee from 'localforage';
|
|
5
|
+
import { track, identify, getDetail, Detail, trackFlow, trackError } from '@imtbl/metrics';
|
|
6
6
|
import { EventEmitter } from 'events';
|
|
7
7
|
|
|
8
|
-
var
|
|
8
|
+
var L=(s=>(s.AUTHENTICATION_ERROR="AUTHENTICATION_ERROR",s.INVALID_CONFIGURATION="INVALID_CONFIGURATION",s.WALLET_CONNECTION_ERROR="WALLET_CONNECTION_ERROR",s.NOT_LOGGED_IN_ERROR="NOT_LOGGED_IN_ERROR",s.SILENT_LOGIN_ERROR="SILENT_LOGIN_ERROR",s.REFRESH_TOKEN_ERROR="REFRESH_TOKEN_ERROR",s.USER_REGISTRATION_ERROR="USER_REGISTRATION_ERROR",s.USER_NOT_REGISTERED_ERROR="USER_NOT_REGISTERED_ERROR",s.LOGOUT_ERROR="LOGOUT_ERROR",s.TRANSFER_ERROR="TRANSFER_ERROR",s.CREATE_ORDER_ERROR="CREATE_ORDER_ERROR",s.CANCEL_ORDER_ERROR="CANCEL_ORDER_ERROR",s.EXCHANGE_TRANSFER_ERROR="EXCHANGE_TRANSFER_ERROR",s.CREATE_TRADE_ERROR="CREATE_TRADE_ERROR",s.OPERATION_NOT_SUPPORTED_ERROR="OPERATION_NOT_SUPPORTED_ERROR",s.LINK_WALLET_ALREADY_LINKED_ERROR="LINK_WALLET_ALREADY_LINKED_ERROR",s.LINK_WALLET_MAX_WALLETS_LINKED_ERROR="LINK_WALLET_MAX_WALLETS_LINKED_ERROR",s.LINK_WALLET_VALIDATION_ERROR="LINK_WALLET_VALIDATION_ERROR",s.LINK_WALLET_DUPLICATE_NONCE_ERROR="LINK_WALLET_DUPLICATE_NONCE_ERROR",s.LINK_WALLET_GENERIC_ERROR="LINK_WALLET_GENERIC_ERROR",s.SERVICE_UNAVAILABLE_ERROR="SERVICE_UNAVAILABLE_ERROR",s.TRANSACTION_REJECTED="TRANSACTION_REJECTED",s))(L||{});function D(o){return typeof o=="object"&&o!==null&&"code"in o&&"message"in o}var p=class extends Error{type;constructor(e,t){super(e),this.type=t;}},g=async(o,e)=>{try{return await o()}catch(t){let r;throw t instanceof p&&t.type==="SERVICE_UNAVAILABLE_ERROR"?new p(t.message,t.type):(isAxiosError(t)&&t.response?.data&&D(t.response.data)?r=t.response.data.message:r=t.message,new p(r,e))}};var ee=(o,e,t)=>{let r=e.map(n=>!o[n]&&n).filter(n=>n).join(", ");if(r!==""){let n=`${r} cannot be null`;throw new p(n,"INVALID_CONFIGURATION")}},_=class{authenticationDomain;passportDomain;oidcConfiguration;crossSdkBridgeEnabled;popupOverlayOptions;constructor({authenticationDomain:e,passportDomain:t,crossSdkBridgeEnabled:r,popupOverlayOptions:n,...i}){ee(i,["clientId","redirectUri"]),this.oidcConfiguration=i,this.crossSdkBridgeEnabled=r||!1,this.popupOverlayOptions=n,this.authenticationDomain=e||"https://auth.immutable.com",this.passportDomain=t||"https://passport.immutable.com";}};var N=(e=>(e.ZKEVM="zkEvm",e))(N||{}),w=o=>!!o.zkEvm,S=(t=>(t.OptedIn="opted_in",t.Unsubscribed="unsubscribed",t))(S||{}),U=(t=>(t.LOGGED_OUT="loggedOut",t.LOGGED_IN="loggedIn",t))(U||{});var F="im_passport_embedded_login_prompt";var E="passport-overlay",R="passport-overlay-contents",P=`${E}-close`,I=`${E}-try-again`,H=`
|
|
9
9
|
<svg
|
|
10
10
|
viewBox="0 0 20 20"
|
|
11
11
|
fill="none"
|
|
@@ -17,7 +17,7 @@ var F="pkce_state",H="pkce_verifier",re=3600,O=class{isTokenValid(e){try{let r=q
|
|
|
17
17
|
fill="#F3F3F3"
|
|
18
18
|
/>
|
|
19
19
|
</svg>
|
|
20
|
-
|
|
20
|
+
`,V=`
|
|
21
21
|
<svg
|
|
22
22
|
viewBox="0 0 17 16"
|
|
23
23
|
fill="none"
|
|
@@ -31,7 +31,7 @@ var F="pkce_state",H="pkce_verifier",re=3600,O=class{isTokenValid(e){try{let r=q
|
|
|
31
31
|
fill="#E01A3D"
|
|
32
32
|
/>
|
|
33
33
|
</svg>
|
|
34
|
-
`,
|
|
34
|
+
`,b=`
|
|
35
35
|
<svg
|
|
36
36
|
style="
|
|
37
37
|
max-width: 123px !important;
|
|
@@ -214,9 +214,9 @@ var F="pkce_state",H="pkce_verifier",re=3600,O=class{isTokenValid(e){try{let r=q
|
|
|
214
214
|
</clipPath>
|
|
215
215
|
</defs>
|
|
216
216
|
</svg>
|
|
217
|
-
`;var
|
|
217
|
+
`;var te=()=>`
|
|
218
218
|
<button
|
|
219
|
-
id="${
|
|
219
|
+
id="${P}"
|
|
220
220
|
style="
|
|
221
221
|
background: #f3f3f326 !important;
|
|
222
222
|
border: none !important;
|
|
@@ -232,11 +232,11 @@ var F="pkce_state",H="pkce_verifier",re=3600,O=class{isTokenValid(e){try{let r=q
|
|
|
232
232
|
justify-content: center !important;
|
|
233
233
|
"
|
|
234
234
|
>
|
|
235
|
-
${
|
|
235
|
+
${H}
|
|
236
236
|
</button>
|
|
237
|
-
`,
|
|
237
|
+
`,G=()=>`
|
|
238
238
|
<button
|
|
239
|
-
id="${
|
|
239
|
+
id="${I}"
|
|
240
240
|
style="
|
|
241
241
|
margin-top: 27px !important;
|
|
242
242
|
color: #f3f3f3 !important;
|
|
@@ -251,8 +251,8 @@ var F="pkce_state",H="pkce_verifier",re=3600,O=class{isTokenValid(e){try{let r=q
|
|
|
251
251
|
>
|
|
252
252
|
Try again
|
|
253
253
|
</button>
|
|
254
|
-
`,
|
|
255
|
-
${
|
|
254
|
+
`,re=()=>`
|
|
255
|
+
${b}
|
|
256
256
|
<div
|
|
257
257
|
style="
|
|
258
258
|
color: #e01a3d !important;
|
|
@@ -262,7 +262,7 @@ var F="pkce_state",H="pkce_verifier",re=3600,O=class{isTokenValid(e){try{let r=q
|
|
|
262
262
|
margin-bottom: 10px !important;
|
|
263
263
|
"
|
|
264
264
|
>
|
|
265
|
-
${
|
|
265
|
+
${V}
|
|
266
266
|
Pop-up blocked
|
|
267
267
|
</div>
|
|
268
268
|
<p style="
|
|
@@ -275,9 +275,9 @@ var F="pkce_state",H="pkce_verifier",re=3600,O=class{isTokenValid(e){try{let r=q
|
|
|
275
275
|
If the problem continues, adjust your<br />
|
|
276
276
|
browser settings.
|
|
277
277
|
</p>
|
|
278
|
-
${
|
|
279
|
-
`,
|
|
280
|
-
${
|
|
278
|
+
${G()}
|
|
279
|
+
`,ne=()=>`
|
|
280
|
+
${b}
|
|
281
281
|
<p style="
|
|
282
282
|
color: #b6b6b6 !important;
|
|
283
283
|
text-align: center !important;
|
|
@@ -286,10 +286,10 @@ var F="pkce_state",H="pkce_verifier",re=3600,O=class{isTokenValid(e){try{let r=q
|
|
|
286
286
|
>
|
|
287
287
|
Secure pop-up not showing?<br />We'll help you re-launch
|
|
288
288
|
</p>
|
|
289
|
-
${
|
|
290
|
-
`,
|
|
289
|
+
${G()}
|
|
290
|
+
`,B=o=>`
|
|
291
291
|
<div
|
|
292
|
-
id="${
|
|
292
|
+
id="${E}"
|
|
293
293
|
style="
|
|
294
294
|
position: fixed !important;
|
|
295
295
|
top: 0 !important;
|
|
@@ -312,9 +312,9 @@ var F="pkce_state",H="pkce_verifier",re=3600,O=class{isTokenValid(e){try{let r=q
|
|
|
312
312
|
z-index: 2147483647 !important;
|
|
313
313
|
"
|
|
314
314
|
>
|
|
315
|
-
${
|
|
315
|
+
${te()}
|
|
316
316
|
<div
|
|
317
|
-
id="${
|
|
317
|
+
id="${R}"
|
|
318
318
|
style="
|
|
319
319
|
display: flex !important;
|
|
320
320
|
flex-direction: column !important;
|
|
@@ -322,12 +322,12 @@ var F="pkce_state",H="pkce_verifier",re=3600,O=class{isTokenValid(e){try{let r=q
|
|
|
322
322
|
max-width: 400px !important;
|
|
323
323
|
"
|
|
324
324
|
>
|
|
325
|
-
${
|
|
325
|
+
${o??""}
|
|
326
326
|
</div>
|
|
327
327
|
</div>
|
|
328
|
-
`,
|
|
328
|
+
`,Z=()=>`
|
|
329
329
|
<div
|
|
330
|
-
id="${
|
|
330
|
+
id="${E}"
|
|
331
331
|
style="
|
|
332
332
|
position: fixed;
|
|
333
333
|
top: 0;
|
|
@@ -345,7 +345,7 @@ var F="pkce_state",H="pkce_verifier",re=3600,O=class{isTokenValid(e){try{let r=q
|
|
|
345
345
|
"
|
|
346
346
|
>
|
|
347
347
|
<div
|
|
348
|
-
id="${
|
|
348
|
+
id="${R}"
|
|
349
349
|
style="
|
|
350
350
|
display: flex;
|
|
351
351
|
flex-direction: column;
|
|
@@ -354,7 +354,7 @@ var F="pkce_state",H="pkce_verifier",re=3600,O=class{isTokenValid(e){try{let r=q
|
|
|
354
354
|
"
|
|
355
355
|
/>
|
|
356
356
|
</div>
|
|
357
|
-
`;function w({id:i,href:e,rel:t,crossOrigin:r}){let o=`${C}-${i}`;if(!document.getElementById(o)){let n=document.createElement("link");n.id=o,n.href=e,t&&(n.rel=t),r&&(n.crossOrigin=r),document.head.appendChild(n);}}var j=()=>Y(le()),Q=()=>Y(de());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){w({id:"link-googleapis",href:"https://fonts.googleapis.com"}),w({id:"link-gstatic",href:"https://fonts.gstatic.com",crossOrigin:"anonymous"}),w({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?j():Q(),document.body.insertAdjacentElement("beforeend",t),this.overlay=t;}}updateTryAgainButton(e){let t=document.getElementById(A);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=ce.createInstance({name:e,driver:t});}get length(){return this.storage.length()}clear(){return this.storage.clear()}getItem(e){return this.storage.getItem(e)}key(e){return this.storage.key(e)}async removeItem(e){await this.storage.removeItem(e);}async setItem(e,t){await this.storage.setItem(e,t);}};var Oe=500,ye={headers:{"Content-Type":"application/x-www-form-urlencoded"}},ve="/v2/logout",Te="/im-logged-out",Le="/authorize",Pe=i=>i?Te:ve,Ie=i=>{let{authenticationDomain:e,oidcConfiguration:t}=i,r;i.crossSdkBridgeEnabled?r=new k("ImmutableSDKPassport",ce.INDEXEDDB):typeof window<"u"?r=window.localStorage:r=new InMemoryWebStorage;let o=new WebStorageStateStore({store:r}),n=new URL(Pe(i.crossSdkBridgeEnabled),e.replace(/^(?:https?:\/\/)?(.*)/,"https://$1"));return n.searchParams.set("client_id",t.clientId),t.logoutRedirectUri&&n.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:n.toString(),revocation_endpoint:`${e}/oauth/revoke`},automaticSilentRenew:!1,scope:t.scope,userStore:o,revokeTokenTypes:["refresh_token"],extraQueryParams:{...t.audience?{audience:t.audience}:{}}}};function D(i){return btoa(String.fromCharCode(...new Uint8Array(i))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function Ae(i){let t=new TextEncoder().encode(i);return await window.crypto.subtle.digest("SHA-256",t)}var _=class i{userManager;deviceCredentialsManager;config;embeddedLoginPrompt;logoutMode;refreshingPromise=null;constructor(e,t){this.config=e,this.userManager=new UserManager(Ie(e)),this.deviceCredentialsManager=new O,this.embeddedLoginPrompt=t,this.logoutMode=e.oidcConfiguration.logoutMode||"redirect";}static mapOidcUserToDomainModel=e=>{let t;e.id_token&&(t=q(e.id_token)?.passport);let r={expired:e.expired,idToken:e.id_token,accessToken:e.access_token,refreshToken:e.refresh_token,profile:{sub:e.profile.sub,email:e.profile.email,nickname:e.profile.nickname}};return t?.zkevm_eth_address&&t?.zkevm_user_admin_address&&(r.zkEvm={ethAddress:t.zkevm_eth_address,userAdminAddress:t.zkevm_user_admin_address}),r};static mapDeviceTokenResponseToOidcUser=e=>{let t=q(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}})};buildExtraQueryParams(e,t){let r={...this.userManager.settings?.extraQueryParams??{},rid:getDetail(Detail.RUNTIME_ID)||"",third_party_a_id:""};if(e){if(e.directLoginMethod==="email"){let 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 getClientId(){return this.config.oidcConfiguration.clientId}async loginWithRedirect(e){return await this.userManager.clearStaleState(),f(async()=>{let t=this.buildExtraQueryParams(e);await this.userManager.signinRedirect({extraQueryParams:t});},"AUTHENTICATION_ERROR")}async login(e){return f(async()=>{let t,r;if(e)t=e;else if(!this.config.popupOverlayOptions?.disableHeadlessLoginPromptOverlay){let{imPassportTraceId:d,...l}=await this.embeddedLoginPrompt.displayEmbeddedLoginPrompt();t=l,r=d;}let o=window.crypto.randomUUID(),n=async()=>{let d=this.buildExtraQueryParams(t,r),l=this.userManager.signinPopup({extraQueryParams:d,popupWindowFeatures:{width:410,height:450},popupWindowTarget:o}),c=window.open("",o);if(c){let E=new Promise((a,g)=>{let S=setInterval(()=>{c.closed&&(clearInterval(S),g(new Error("Popup closed by user")));},Oe);l.finally(()=>{clearInterval(S),c.close();});});return Promise.race([l,E])}return l};return new Promise((d,l)=>{n().then(c=>{d(i.mapOidcUserToDomainModel(c));}).catch(c=>{if(!(c instanceof Error)||c.message!=="Attempted to navigate on a disposed window"){l(c);return}let E=!1,a=new v(this.config.popupOverlayOptions||{},!0);a.append(async()=>{try{if(E)window.open("",o);else {E=!0;let g=await n();a.remove(),d(i.mapOidcUserToDomainModel(g));}}catch(g){a.remove(),l(g);}},()=>{a.remove(),l(new Error("Popup closed by user"));});});})},"AUTHENTICATION_ERROR")}async getUserOrLogin(){let e=null;try{e=await this.getUser();}catch(t){h.warn("Failed to retrieve a cached user session",t);}return e||this.login()}static shouldUseSigninPopupCallback(){try{let r=`oidc.${new URLSearchParams(window.location.search).get("state")}`,o=localStorage.getItem(r);return JSON.parse(o||"{}")?.request_type==="si:p"}catch{return !1}}async loginCallback(){return f(async()=>{if(i.shouldUseSigninPopupCallback()){await this.userManager.signinPopupCallback(void 0,!0);return}let e=await this.userManager.signinCallback();if(e)return i.mapOidcUserToDomainModel(e)},"AUTHENTICATION_ERROR")}async getPKCEAuthorizationUrl(e,t){let r=D(window.crypto.getRandomValues(new Uint8Array(32))),o=D(await Ae(r)),n=D(window.crypto.getRandomValues(new Uint8Array(32))),{redirectUri:d,scope:l,audience:c,clientId:E}=this.config.oidcConfiguration;this.deviceCredentialsManager.savePKCEData({state:n,verifier:r});let a=new URL(Le,this.config.authenticationDomain);if(a.searchParams.set("response_type","code"),a.searchParams.set("code_challenge",o),a.searchParams.set("code_challenge_method","S256"),a.searchParams.set("client_id",E),a.searchParams.set("redirect_uri",d),a.searchParams.set("state",n),l&&a.searchParams.set("scope",l),c&&a.searchParams.set("audience",c),e){if(e.directLoginMethod==="email"){let g=e.email;g&&(a.searchParams.set("direct",e.directLoginMethod),a.searchParams.set("email",g));}else a.searchParams.set("direct",e.directLoginMethod);e.marketingConsentStatus&&a.searchParams.set("marketingConsent",e.marketingConsentStatus);}return t&&a.searchParams.set("im_passport_trace_id",t),a.toString()}async loginWithPKCEFlowCallback(e,t){return f(async()=>{let r=this.deviceCredentialsManager.getPKCEData();if(!r)throw new Error("No code verifier or state for PKCE");if(t!==r.state)throw new Error("Provided state does not match stored state");let o=await this.getPKCEToken(e,r.verifier),n=i.mapDeviceTokenResponseToOidcUser(o),d=i.mapOidcUserToDomainModel(n);return await this.userManager.storeUser(n),d},"AUTHENTICATION_ERROR")}async getPKCEToken(e,t){return (await Ee.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},ye)).data}async storeTokens(e){return f(async()=>{let t=i.mapDeviceTokenResponseToOidcUser(e),r=i.mapOidcUserToDomainModel(t);return await this.userManager.storeUser(t),r},"AUTHENTICATION_ERROR")}async logout(){return f(async()=>{await this.userManager.revokeTokens(["refresh_token"]),this.logoutMode==="silent"?await this.userManager.signoutSilent():await this.userManager.signoutRedirect();},"LOGOUT_ERROR")}async logoutSilentCallback(e){return this.userManager.signoutSilentCallback(e)}async removeUser(){return this.userManager.removeUser()}async getLogoutUrl(){let e=this.userManager.settings?.metadata?.end_session_endpoint;return e||(h.warn("Failed to get logout URL"),null)}forceUserRefreshInBackground(){this.refreshTokenAndUpdatePromise().catch(e=>{h.warn("Failed to refresh user token",e);});}async forceUserRefresh(){return this.refreshTokenAndUpdatePromise().catch(e=>(h.warn("Failed to refresh user token",e),null))}async refreshTokenAndUpdatePromise(){return this.refreshingPromise?this.refreshingPromise:(this.refreshingPromise=new Promise(async(e,t)=>{try{let r=await this.userManager.signinSilent();if(r){e(i.mapOidcUserToDomainModel(r));return}e(null);}catch(r){let o="AUTHENTICATION_ERROR",n="Failed to refresh token",d=!0;if(r instanceof ErrorTimeout?(o="SILENT_LOGIN_ERROR",n=`${n}: ${r.message}`,d=!1):r instanceof ErrorResponse?(o="NOT_LOGGED_IN_ERROR",n=`${n}: ${r.message||r.error_description}`):r instanceof Error?n=`${n}: ${r.message}`:typeof r=="string"&&(n=`${n}: ${r}`),d)try{await this.userManager.removeUser();}catch(l){l instanceof Error&&(n=`${n}: Failed to remove user: ${l.message}`);}t(new u(n,o));}finally{this.refreshingPromise=null;}}),this.refreshingPromise)}async getUser(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(!G(t)){let r=i.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 getUserZkEvm(){let e=await this.getUser(M);if(!e)throw new Error("Failed to obtain a User with the required ZkEvm attributes");return e}};var we=(i,e,t)=>{let r=e.map(o=>!i[o]&&o).filter(o=>o).join(", ");if(r!==""){let o=`${r} cannot be null`;throw new u(o,"INVALID_CONFIGURATION")}},T=class{authenticationDomain;passportDomain;oidcConfiguration;crossSdkBridgeEnabled;popupOverlayOptions;constructor({authenticationDomain:e,passportDomain:t,crossSdkBridgeEnabled:r,popupOverlayOptions:o,...n}){we(n,["clientId","redirectUri"]),this.oidcConfiguration=n,this.crossSdkBridgeEnabled=r||!1,this.popupOverlayOptions=o,this.authenticationDomain=e||"https://auth.immutable.com",this.passportDomain=t||"https://passport.immutable.com";}};var X="im_passport_embedded_login_prompt";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 o=document.querySelector(`#${y}`);o&&o.appendChild(e),r.addEventListener("click",t),this.overlay=r;}}};var Me=660,Ue=440,xe="16px",J="passport-embedded-login-keyframes",ee="passport-embedded-login-iframe",L=class i{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(J))return;let e=document.createElement("style");e.id=J,e.textContent=`
|
|
357
|
+
`;function A({id:o,href:e,rel:t,crossOrigin:r}){let n=`${E}-${o}`;if(!document.getElementById(n)){let i=document.createElement("link");i.id=n,i.href=e,t&&(i.rel=t),r&&(i.crossOrigin=r),document.head.appendChild(i);}}var K=()=>B(re()),W=()=>B(ne());var m=class{static overlay;static onCloseListener;static closeButton;static remove(){this.onCloseListener&&this.closeButton?.removeEventListener?.("click",this.onCloseListener),this.overlay?.remove(),this.closeButton=void 0,this.onCloseListener=void 0,this.overlay=void 0;}static appendOverlay(e,t){if(!this.overlay){let r=document.createElement("div");r.innerHTML=Z(),document.body.insertAdjacentElement("beforeend",r);let n=document.querySelector(`#${R}`);n&&n.appendChild(e),r.addEventListener("click",t),this.overlay=r;}}};var se=660,ae=440,le="16px",$="passport-embedded-login-keyframes",Y="passport-embedded-login-iframe",O=class o{config;constructor(e){this.config=e;}getHref=()=>`${this.config.authenticationDomain}/im-embedded-login-prompt?client_id=${this.config.oidcConfiguration.clientId}&rid=${getDetail(Detail.RUNTIME_ID)}`;static appendIFrameStylesIfNeeded=()=>{if(document.getElementById($))return;let e=document.createElement("style");e.id=$,e.textContent=`
|
|
358
358
|
@keyframes passportEmbeddedLoginPromptPopBounceIn {
|
|
359
359
|
0% {
|
|
360
360
|
opacity: 0.5;
|
|
@@ -373,7 +373,7 @@ var F="pkce_state",H="pkce_verifier",re=3600,O=class{isTokenValid(e){try{let r=q
|
|
|
373
373
|
}
|
|
374
374
|
|
|
375
375
|
@media (max-height: 400px) {
|
|
376
|
-
#${
|
|
376
|
+
#${Y} {
|
|
377
377
|
width: 100% !important;
|
|
378
378
|
max-width: none !important;
|
|
379
379
|
}
|
|
@@ -387,6 +387,6 @@ var F="pkce_state",H="pkce_verifier",re=3600,O=class{isTokenValid(e){try{let r=q
|
|
|
387
387
|
opacity: 1;
|
|
388
388
|
}
|
|
389
389
|
}
|
|
390
|
-
`,document.head.appendChild(e);};getEmbeddedLoginIFrame=()=>{let e=document.createElement("iframe");return e.id=ee,e.src=this.getHref(),e.style.height="100vh",e.style.width="100vw",e.style.maxHeight=`${Me}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",i.appendIFrameStylesIfNeeded(),e};displayEmbeddedLoginPrompt(){return new Promise((e,t)=>{let r=this.getEmbeddedLoginIFrame(),o=({data:n,origin:d})=>{if(!(d!==this.config.authenticationDomain||n.eventType!==X))switch(n.messageType){case"login_method_selected":{let l=n.payload;window.removeEventListener("message",o),m.remove(),e(l);break}case"login_prompt_error":{window.removeEventListener("message",o),m.remove(),t(new Error("Error during embedded login prompt",{cause:n.payload}));break}case"login_prompt_closed":{window.removeEventListener("message",o),m.remove(),t(new Error("Popup closed by user"));break}default:window.removeEventListener("message",o),m.remove(),t(new Error(`Unsupported message type: ${n.messageType}`));break}};window.addEventListener("message",o),m.appendOverlay(r,()=>{window.removeEventListener("message",o),m.remove(),t(new Error("Popup closed by user"));});})}};var R=class{emitter=new EventEmitter;emit(e,...t){this.emitter.emit(e,...t);}on(e,t){this.emitter.on(e,t);}removeListener(e,t){this.emitter.removeListener(e,t);}};var p=async(i,e,t=!0,r=!0)=>{let o=trackFlow("passport",e,t);try{return await i(o)}catch(n){throw n instanceof Error?trackError("passport",e,n,{flowId:o.details.flowId}):o.addEvent("errored"),n}finally{r&&o.addEvent("End");}};var N=class{authManager;config;eventEmitter;constructor(e){this.config=new T(e);let t=new L(this.config);this.authManager=new _(this.config,t),this.eventEmitter=new R,track("passport","initialise");}async login(e){return p(async()=>{let{useCachedSession:t=!1,useSilentLogin:r}=e||{},o=null;try{o=await this.authManager.getUser();}catch(n){if(n instanceof Error&&!n.message.includes("Unknown or invalid refresh token")&&trackError("passport","login",n),t)throw n;h.warn("Failed to retrieve a cached user session",n);}if(!o&&r)o=await this.authManager.forceUserRefresh();else if(!o&&!t){if(e?.useRedirectFlow)return await this.authManager.loginWithRedirect(e?.directLoginOptions),null;o=await this.authManager.login(e?.directLoginOptions);}return o&&(this.eventEmitter.emit("loggedIn",o),identify({passportId:o.profile.sub})),o},"login")}async loginWithRedirect(e){await this.authManager.loginWithRedirect(e);}async loginCallback(){return p(async()=>{let e=await this.authManager.loginCallback();if(!e)throw new Error("Login callback failed - no user returned");return this.eventEmitter.emit("loggedIn",e),identify({passportId:e.profile.sub}),e},"loginCallback")}async logout(){await p(async()=>{await this.authManager.logout(),this.eventEmitter.emit("loggedOut");},"logout");}async getUser(){return p(async()=>this.authManager.getUser(),"getUserInfo",!1)}async getIdToken(){return p(async()=>(await this.authManager.getUser())?.idToken,"getIdToken",!1)}async getAccessToken(){return p(async()=>(await this.authManager.getUser())?.accessToken,"getAccessToken",!1,!1)}async isLoggedIn(){return await this.getUser()!==null}async forceUserRefresh(){return this.authManager.forceUserRefresh()}async loginWithPKCEFlow(e,t){return p(async()=>this.authManager.getPKCEAuthorizationUrl(e,t),"loginWithPKCEFlow")}async loginWithPKCEFlowCallback(e,t){return p(async()=>{let r=await this.authManager.loginWithPKCEFlowCallback(e,t);return this.eventEmitter.emit("loggedIn",r),identify({passportId:r.profile.sub}),r},"loginWithPKCEFlowCallback")}async storeTokens(e){return p(async()=>{let t=await this.authManager.storeTokens(e);return this.eventEmitter.emit("loggedIn",t),identify({passportId:t.profile.sub}),t},"storeTokens")}async getLogoutUrl(){return p(async()=>(await this.authManager.removeUser(),this.eventEmitter.emit("loggedOut"),await this.authManager.getLogoutUrl()||void 0),"getLogoutUrl")}async logoutSilentCallback(e){return p(()=>this.authManager.logoutSilentCallback(e),"logoutSilentCallback")}getAuthManager(){return this.authManager}getConfig(){return this.config}};
|
|
390
|
+
`,document.head.appendChild(e);};getEmbeddedLoginIFrame=()=>{let e=document.createElement("iframe");return e.id=Y,e.src=this.getHref(),e.style.height="100vh",e.style.width="100vw",e.style.maxHeight=`${se}px`,e.style.maxWidth=`${ae}px`,e.style.borderRadius=le,e.style.opacity="0",e.style.transform="scale(0.6)",e.style.animation="passportEmbeddedLoginPromptPopBounceIn 1s ease forwards",o.appendIFrameStylesIfNeeded(),e};displayEmbeddedLoginPrompt(){return new Promise((e,t)=>{let r=this.getEmbeddedLoginIFrame(),n=({data:i,origin:l})=>{if(!(l!==this.config.authenticationDomain||i.eventType!==F))switch(i.messageType){case"login_method_selected":{let d=i.payload;window.removeEventListener("message",n),m.remove(),e(d);break}case"login_prompt_error":{window.removeEventListener("message",n),m.remove(),t(new Error("Error during embedded login prompt",{cause:i.payload}));break}case"login_prompt_closed":{window.removeEventListener("message",n),m.remove(),t(new Error("Popup closed by user"));break}default:window.removeEventListener("message",n),m.remove(),t(new Error(`Unsupported message type: ${i.messageType}`));break}};window.addEventListener("message",n),m.appendOverlay(r,()=>{window.removeEventListener("message",n),m.remove(),t(new Error("Popup closed by user"));});})}};var h=class{emitter=new EventEmitter;emit(e,...t){this.emitter.emit(e,...t);}on(e,t){this.emitter.on(e,t);}removeListener(e,t){this.emitter.removeListener(e,t);}};var c=async(o,e,t=!0,r=!0)=>{let n=trackFlow("passport",e,t);try{return await o(n)}catch(i){throw i instanceof Error?trackError("passport",e,i,{flowId:n.details.flowId}):n.addEvent("errored"),i}finally{r&&n.addEvent("End");}};var z="pkce_state",j="pkce_verifier",ue=3600,y=class{isTokenValid(e){try{let r=X(e).exp??0,n=Date.now()/1e3+ue;return r>n}catch{return !1}}savePKCEData(e){localStorage.setItem(z,e.state),localStorage.setItem(j,e.verifier);}getPKCEData(){let e=localStorage.getItem(z),t=localStorage.getItem(j);return e&&t?{state:e,verifier:t}:null}};var ge=(...o)=>{if(typeof process>"u")return;process?.env?.JEST_WORKER_ID===void 0&&console.warn(...o);},C={warn:ge};function Q(o){try{let e=X(o),t=Math.floor(Date.now()/1e3);return e.exp?e.exp<=t+30:!0}catch{return !0}}function J(o){let{id_token:e,access_token:t}=o;return !t||!e?!0:Q(t)||Q(e)}var v=class{disableGenericPopupOverlay;disableBlockedPopupOverlay;overlay;isBlockedOverlay;tryAgainListener;onCloseListener;constructor(e,t=!1){this.disableBlockedPopupOverlay=e.disableBlockedPopupOverlay||!1,this.disableGenericPopupOverlay=e.disableGenericPopupOverlay||!1,this.isBlockedOverlay=t;}append(e,t){this.shouldAppendOverlay()&&(this.appendOverlay(),this.updateTryAgainButton(e),this.updateCloseButton(t));}update(e){this.updateTryAgainButton(e);}remove(){this.overlay&&this.overlay.remove();}shouldAppendOverlay(){return !(this.disableGenericPopupOverlay&&this.disableBlockedPopupOverlay||this.disableGenericPopupOverlay&&!this.isBlockedOverlay||this.disableBlockedPopupOverlay&&this.isBlockedOverlay)}appendOverlay(){if(!this.overlay){A({id:"link-googleapis",href:"https://fonts.googleapis.com"}),A({id:"link-gstatic",href:"https://fonts.gstatic.com",crossOrigin:"anonymous"}),A({id:"link-roboto",href:"https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap",rel:"stylesheet"});let t=document.createElement("div");t.innerHTML=this.isBlockedOverlay?K():W(),document.body.insertAdjacentElement("beforeend",t),this.overlay=t;}}updateTryAgainButton(e){let t=document.getElementById(I);t&&(this.tryAgainListener&&t.removeEventListener("click",this.tryAgainListener),this.tryAgainListener=e,t.addEventListener("click",e));}updateCloseButton(e){let t=document.getElementById(P);t&&(this.onCloseListener&&t.removeEventListener("click",this.onCloseListener),this.onCloseListener=e,t.addEventListener("click",e));}};var k=class{storage;constructor(e,t){this.storage=Ee.createInstance({name:e,driver:t});}get length(){return this.storage.length()}clear(){return this.storage.clear()}getItem(e){return this.storage.getItem(e)}key(e){return this.storage.key(e)}async removeItem(e){await this.storage.removeItem(e);}async setItem(e,t){await this.storage.setItem(e,t);}};var we={headers:{"Content-Type":"application/x-www-form-urlencoded"}},Ue="/v2/logout",be="/im-logged-out",xe="/authorize",Me=o=>o?be:Ue,De=o=>{let{authenticationDomain:e,oidcConfiguration:t}=o,r;o.crossSdkBridgeEnabled?r=new k("ImmutableSDKPassport",Ee.INDEXEDDB):typeof window<"u"?r=window.localStorage:r=new InMemoryWebStorage;let n=new WebStorageStateStore({store:r}),i=new URL(Me(o.crossSdkBridgeEnabled),e.replace(/^(?:https?:\/\/)?(.*)/,"https://$1"));return i.searchParams.set("client_id",t.clientId),t.logoutRedirectUri&&i.searchParams.set("returnTo",t.logoutRedirectUri),{authority:e,redirect_uri:t.redirectUri,popup_redirect_uri:t.popupRedirectUri||t.redirectUri,client_id:t.clientId,metadata:{authorization_endpoint:`${e}/authorize`,token_endpoint:`${e}/oauth/token`,userinfo_endpoint:`${e}/userinfo`,end_session_endpoint:i.toString(),revocation_endpoint:`${e}/oauth/revoke`},automaticSilentRenew:!1,scope:t.scope,userStore:n,revokeTokenTypes:["refresh_token"],extraQueryParams:{...t.audience?{audience:t.audience}:{}}}};function x(o){return btoa(String.fromCharCode(...new Uint8Array(o))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function Ne(o){let t=new TextEncoder().encode(o);return window.crypto.subtle.digest("SHA-256",t)}var M=class o{config;userManager;deviceCredentialsManager;embeddedLoginPrompt;logoutMode;refreshingPromise=null;eventEmitter;constructor(e){this.config=new _(e),this.embeddedLoginPrompt=new O(this.config),this.userManager=new UserManager(De(this.config)),this.deviceCredentialsManager=new y,this.logoutMode=this.config.oidcConfiguration.logoutMode||"redirect",this.eventEmitter=new h,track("passport","initialise");}async login(e){return c(async()=>{let{useCachedSession:t=!1,useSilentLogin:r}=e||{},n=null;try{n=await this.getUserInternal();}catch(i){if(i instanceof Error&&!i.message.includes("Unknown or invalid refresh token")&&trackError("passport","login",i),t)throw i;C.warn("Failed to retrieve a cached user session",i);}if(!n&&r)n=await this.forceUserRefreshInternal();else if(!n&&!t){if(e?.useRedirectFlow)return await this.loginWithRedirectInternal(e?.directLoginOptions),null;n=await this.loginWithPopup(e?.directLoginOptions);}return n&&this.handleSuccessfulLogin(n),n},"login")}async loginWithRedirect(e){await this.loginWithRedirectInternal(e);}async loginCallback(){return c(async()=>{let e=await this.loginCallbackInternal();return e&&this.handleSuccessfulLogin(e),e},"loginCallback")}async logout(){await c(async()=>{await this.logoutInternal(),this.eventEmitter.emit("loggedOut");},"logout");}async getUser(){return this.getUserInternal()}async getUserOrLogin(){let e=null;try{e=await this.getUserInternal();}catch(r){C.warn("Failed to retrieve a cached user session",r);}if(e)return e;let t=await this.loginWithPopup();return this.handleSuccessfulLogin(t),t}async getUserZkEvm(){return this.getUserZkEvmInternal()}async getIdToken(){return c(async()=>(await this.getUserInternal())?.idToken,"getIdToken",!1)}async getAccessToken(){return c(async()=>(await this.getUserInternal())?.accessToken,"getAccessToken",!1,!1)}async isLoggedIn(){return await this.getUser()!==null}async forceUserRefresh(){return this.forceUserRefreshInternal()}forceUserRefreshInBackground(){this.forceUserRefreshInBackgroundInternal();}async loginWithPKCEFlow(e,t){return c(async()=>this.getPKCEAuthorizationUrl(e,t),"loginWithPKCEFlow")}async loginWithPKCEFlowCallback(e,t){return c(async()=>{let r=await this.loginWithPKCEFlowCallbackInternal(e,t);return this.handleSuccessfulLogin(r),r},"loginWithPKCEFlowCallback")}async storeTokens(e){return c(async()=>{let t=await this.storeTokensInternal(e);return this.handleSuccessfulLogin(t),t},"storeTokens")}async getLogoutUrl(){return c(async()=>(await this.userManager.removeUser(),this.eventEmitter.emit("loggedOut"),await this.getLogoutUrlInternal()||void 0),"getLogoutUrl")}async logoutSilentCallback(e){return c(()=>this.userManager.signoutSilentCallback(e),"logoutSilentCallback")}getConfig(){return this.config}async getClientId(){return this.config.oidcConfiguration.clientId}handleSuccessfulLogin(e){this.eventEmitter.emit("loggedIn",e),identify({passportId:e.profile.sub});}buildExtraQueryParams(e,t){let r={...this.userManager.settings?.extraQueryParams??{},rid:getDetail(Detail.RUNTIME_ID)||""};if(e){if(e.directLoginMethod==="email"){let n=e.email;n&&(r.direct=e.directLoginMethod,r.email=n);}else r.direct=e.directLoginMethod;e.marketingConsentStatus&&(r.marketingConsent=e.marketingConsentStatus);}return t&&(r.im_passport_trace_id=t),r}async loginWithRedirectInternal(e){await this.userManager.clearStaleState(),await g(async()=>{let t=this.buildExtraQueryParams(e);await this.userManager.signinRedirect({extraQueryParams:t});},"AUTHENTICATION_ERROR");}async loginWithPopup(e){return g(async()=>{let t,r;if(e)t=e;else if(!this.config.popupOverlayOptions?.disableHeadlessLoginPromptOverlay){let{imPassportTraceId:l,...d}=await this.embeddedLoginPrompt.displayEmbeddedLoginPrompt();t=d,r=l;}let n=window.crypto.randomUUID(),i=async()=>{let l=this.buildExtraQueryParams(t,r);return this.userManager.signinPopup({extraQueryParams:l,popupWindowFeatures:{width:410,height:450},popupWindowTarget:n})};return new Promise((l,d)=>{i().then(u=>l(o.mapOidcUserToDomainModel(u))).catch(u=>{if(!(u instanceof Error)||u.message!=="Attempted to navigate on a disposed window"){d(u);return}let T=!1,a=new v(this.config.popupOverlayOptions||{},!0);a.append(async()=>{try{if(T)window.open("",n);else {T=!0;let f=await i();a.remove(),l(o.mapOidcUserToDomainModel(f));}}catch(f){a.remove(),d(f);}},()=>{a.remove(),d(new Error("Popup closed by user"));});});})},"AUTHENTICATION_ERROR")}static mapOidcUserToDomainModel=e=>{let t,r;if(e.id_token){let i=X(e.id_token);t=i?.passport,i?.username&&(r=i?.username);}let n={expired:e.expired,idToken:e.id_token,accessToken:e.access_token,refreshToken:e.refresh_token,profile:{sub:e.profile.sub,email:e.profile.email,nickname:e.profile.nickname,username:r}};return t?.zkevm_eth_address&&t?.zkevm_user_admin_address&&(n.zkEvm={ethAddress:t.zkevm_eth_address,userAdminAddress:t.zkevm_user_admin_address}),n};static mapDeviceTokenResponseToOidcUser=e=>{let t=X(e.id_token);return new User({id_token:e.id_token,access_token:e.access_token,refresh_token:e.refresh_token,token_type:e.token_type,profile:{sub:t.sub,iss:t.iss,aud:t.aud,exp:t.exp,iat:t.iat,email:t.email,nickname:t.nickname,passport:t.passport,...t.username?{username:t.username}:{}}})};async loginCallbackInternal(){return g(async()=>{let e=await this.userManager.signinCallback();if(e)return o.mapOidcUserToDomainModel(e)},"AUTHENTICATION_ERROR")}async getPKCEAuthorizationUrl(e,t){let r=x(window.crypto.getRandomValues(new Uint8Array(32))),n=x(await Ne(r)),i=x(window.crypto.getRandomValues(new Uint8Array(32))),{redirectUri:l,scope:d,audience:u,clientId:T}=this.config.oidcConfiguration;this.deviceCredentialsManager.savePKCEData({state:i,verifier:r});let a=new URL(xe,this.config.authenticationDomain);if(a.searchParams.set("response_type","code"),a.searchParams.set("code_challenge",n),a.searchParams.set("code_challenge_method","S256"),a.searchParams.set("client_id",T),a.searchParams.set("redirect_uri",l),a.searchParams.set("state",i),d&&a.searchParams.set("scope",d),u&&a.searchParams.set("audience",u),e){if(e.directLoginMethod==="email"){let f=e.email;f&&(a.searchParams.set("direct",e.directLoginMethod),a.searchParams.set("email",f));}else a.searchParams.set("direct",e.directLoginMethod);e.marketingConsentStatus&&a.searchParams.set("marketingConsent",e.marketingConsentStatus);}return t&&a.searchParams.set("im_passport_trace_id",t),a.toString()}async loginWithPKCEFlowCallbackInternal(e,t){return g(async()=>{let r=this.deviceCredentialsManager.getPKCEData();if(!r)throw new Error("No code verifier or state for PKCE");if(t!==r.state)throw new Error("Provided state does not match stored state");let n=await this.getPKCEToken(e,r.verifier),i=o.mapDeviceTokenResponseToOidcUser(n),l=o.mapOidcUserToDomainModel(i);return await this.userManager.storeUser(i),l},"AUTHENTICATION_ERROR")}async getPKCEToken(e,t){return (await ve.post(`${this.config.authenticationDomain}/oauth/token`,{client_id:this.config.oidcConfiguration.clientId,grant_type:"authorization_code",code_verifier:t,code:e,redirect_uri:this.config.oidcConfiguration.redirectUri},we)).data}async storeTokensInternal(e){return g(async()=>{let t=o.mapDeviceTokenResponseToOidcUser(e),r=o.mapOidcUserToDomainModel(t);return await this.userManager.storeUser(t),r},"AUTHENTICATION_ERROR")}async logoutInternal(){await g(async()=>{await this.userManager.revokeTokens(["refresh_token"]),this.logoutMode==="silent"?await this.userManager.signoutSilent():await this.userManager.signoutRedirect();},"LOGOUT_ERROR");}async getLogoutUrlInternal(){let e=this.userManager.settings?.metadata?.end_session_endpoint;return e||(C.warn("Failed to get logout URL"),null)}forceUserRefreshInBackgroundInternal(){this.refreshTokenAndUpdatePromise().catch(e=>{C.warn("Failed to refresh user token",e);});}async forceUserRefreshInternal(){return this.refreshTokenAndUpdatePromise().catch(e=>(C.warn("Failed to refresh user token",e),null))}async refreshTokenAndUpdatePromise(){return this.refreshingPromise?this.refreshingPromise:(this.refreshingPromise=new Promise((e,t)=>{(async()=>{try{let r=await this.userManager.signinSilent();if(r){e(o.mapOidcUserToDomainModel(r));return}e(null);}catch(r){let n="AUTHENTICATION_ERROR",i="Failed to refresh token",l=!0;if(r instanceof ErrorTimeout?(n="SILENT_LOGIN_ERROR",i=`${i}: ${r.message}`,l=!1):r instanceof ErrorResponse?(n="NOT_LOGGED_IN_ERROR",i=`${i}: ${r.message||r.error_description}`):r instanceof Error?i=`${i}: ${r.message}`:typeof r=="string"&&(i=`${i}: ${r}`),l)try{await this.userManager.removeUser();}catch(d){d instanceof Error&&(i=`${i}: Failed to remove user: ${d.message}`);}t(new p(i,n));}finally{this.refreshingPromise=null;}})();}),this.refreshingPromise)}async getUserInternal(e=t=>!0){if(this.refreshingPromise){let r=await this.refreshingPromise;return r&&e(r)?r:null}let t=await this.userManager.getUser();if(!t)return null;if(!J(t)){let r=o.mapOidcUserToDomainModel(t);if(r&&e(r))return r}if(t.refresh_token){let r=await this.refreshTokenAndUpdatePromise();if(r&&e(r))return r}return null}async getUserZkEvmInternal(){let e=await this.getUserInternal(w);if(!e)throw new Error("Failed to obtain a User with the required ZkEvm attributes");return e}};
|
|
391
391
|
|
|
392
|
-
export {
|
|
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 };
|
package/dist/types/Auth.d.ts
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
import AuthManager from './authManager';
|
|
2
1
|
import { IAuthConfiguration } from './config';
|
|
3
|
-
import { AuthModuleConfiguration, User, DirectLoginOptions, DeviceTokenResponse, LoginOptions, AuthEventMap } from './types';
|
|
2
|
+
import { AuthModuleConfiguration, User, DirectLoginOptions, DeviceTokenResponse, LoginOptions, AuthEventMap, UserZkEvm } from './types';
|
|
4
3
|
import TypedEventEmitter from './utils/typedEventEmitter';
|
|
5
4
|
/**
|
|
6
5
|
* Public-facing Auth class for authentication
|
|
7
|
-
*
|
|
6
|
+
* Provides login/logout helpers and exposes auth state events
|
|
8
7
|
*/
|
|
9
8
|
export declare class Auth {
|
|
10
|
-
private
|
|
11
|
-
private
|
|
9
|
+
private readonly config;
|
|
10
|
+
private readonly userManager;
|
|
11
|
+
private readonly deviceCredentialsManager;
|
|
12
|
+
private readonly embeddedLoginPrompt;
|
|
13
|
+
private readonly logoutMode;
|
|
14
|
+
/**
|
|
15
|
+
* Promise that is used to prevent multiple concurrent calls to the refresh token endpoint.
|
|
16
|
+
*/
|
|
17
|
+
private refreshingPromise;
|
|
12
18
|
/**
|
|
13
19
|
* Event emitter for authentication events (LOGGED_IN, LOGGED_OUT)
|
|
14
20
|
* Exposed for wallet and passport packages to subscribe to auth state changes
|
|
@@ -49,10 +55,10 @@ export declare class Auth {
|
|
|
49
55
|
loginWithRedirect(directLoginOptions?: DirectLoginOptions): Promise<void>;
|
|
50
56
|
/**
|
|
51
57
|
* Login callback handler
|
|
52
|
-
* Call this in your redirect
|
|
53
|
-
* @returns Promise that resolves with the authenticated user
|
|
58
|
+
* Call this in your redirect or popup callback page
|
|
59
|
+
* @returns Promise that resolves with the authenticated user or undefined (for popup flows)
|
|
54
60
|
*/
|
|
55
|
-
loginCallback(): Promise<User>;
|
|
61
|
+
loginCallback(): Promise<User | undefined>;
|
|
56
62
|
/**
|
|
57
63
|
* Logout the current user
|
|
58
64
|
* @returns Promise that resolves when logout is complete
|
|
@@ -63,6 +69,16 @@ export declare class Auth {
|
|
|
63
69
|
* @returns Promise that resolves with the user or null if not authenticated
|
|
64
70
|
*/
|
|
65
71
|
getUser(): Promise<User | null>;
|
|
72
|
+
/**
|
|
73
|
+
* Get the current authenticated user or initiate login if needed
|
|
74
|
+
* @returns Promise that resolves with an authenticated user
|
|
75
|
+
*/
|
|
76
|
+
getUserOrLogin(): Promise<User>;
|
|
77
|
+
/**
|
|
78
|
+
* Get the current authenticated zkEVM user
|
|
79
|
+
* @returns Promise that resolves with a zkEVM-capable user
|
|
80
|
+
*/
|
|
81
|
+
getUserZkEvm(): Promise<UserZkEvm>;
|
|
66
82
|
/**
|
|
67
83
|
* Get the ID token for the current user
|
|
68
84
|
* @returns Promise that resolves with the ID token or undefined
|
|
@@ -83,6 +99,10 @@ export declare class Auth {
|
|
|
83
99
|
* @returns Promise that resolves with the user or null if refresh fails
|
|
84
100
|
*/
|
|
85
101
|
forceUserRefresh(): Promise<User | null>;
|
|
102
|
+
/**
|
|
103
|
+
* Trigger a background user refresh without awaiting the result
|
|
104
|
+
*/
|
|
105
|
+
forceUserRefreshInBackground(): void;
|
|
86
106
|
/**
|
|
87
107
|
* Get the PKCE authorization URL for login flow
|
|
88
108
|
* @param directLoginOptions - Optional direct login options
|
|
@@ -114,16 +134,33 @@ export declare class Auth {
|
|
|
114
134
|
* @returns Promise that resolves when callback is handled
|
|
115
135
|
*/
|
|
116
136
|
logoutSilentCallback(url: string): Promise<void>;
|
|
117
|
-
/**
|
|
118
|
-
* Get internal AuthManager instance
|
|
119
|
-
* @internal
|
|
120
|
-
* @returns AuthManager instance for advanced use cases
|
|
121
|
-
*/
|
|
122
|
-
getAuthManager(): AuthManager;
|
|
123
137
|
/**
|
|
124
138
|
* Get auth configuration
|
|
125
139
|
* @internal
|
|
126
140
|
* @returns IAuthConfiguration instance
|
|
127
141
|
*/
|
|
128
142
|
getConfig(): IAuthConfiguration;
|
|
143
|
+
/**
|
|
144
|
+
* Get the configured OIDC client ID
|
|
145
|
+
* @returns Promise that resolves with the client ID string
|
|
146
|
+
*/
|
|
147
|
+
getClientId(): Promise<string>;
|
|
148
|
+
private handleSuccessfulLogin;
|
|
149
|
+
private buildExtraQueryParams;
|
|
150
|
+
private loginWithRedirectInternal;
|
|
151
|
+
private loginWithPopup;
|
|
152
|
+
private static mapOidcUserToDomainModel;
|
|
153
|
+
private static mapDeviceTokenResponseToOidcUser;
|
|
154
|
+
private loginCallbackInternal;
|
|
155
|
+
private getPKCEAuthorizationUrl;
|
|
156
|
+
private loginWithPKCEFlowCallbackInternal;
|
|
157
|
+
private getPKCEToken;
|
|
158
|
+
private storeTokensInternal;
|
|
159
|
+
private logoutInternal;
|
|
160
|
+
private getLogoutUrlInternal;
|
|
161
|
+
private forceUserRefreshInBackgroundInternal;
|
|
162
|
+
private forceUserRefreshInternal;
|
|
163
|
+
private refreshTokenAndUpdatePromise;
|
|
164
|
+
private getUserInternal;
|
|
165
|
+
private getUserZkEvmInternal;
|
|
129
166
|
}
|
package/dist/types/errors.d.ts
CHANGED
|
@@ -20,7 +20,8 @@ export declare enum PassportErrorType {
|
|
|
20
20
|
LINK_WALLET_VALIDATION_ERROR = "LINK_WALLET_VALIDATION_ERROR",
|
|
21
21
|
LINK_WALLET_DUPLICATE_NONCE_ERROR = "LINK_WALLET_DUPLICATE_NONCE_ERROR",
|
|
22
22
|
LINK_WALLET_GENERIC_ERROR = "LINK_WALLET_GENERIC_ERROR",
|
|
23
|
-
SERVICE_UNAVAILABLE_ERROR = "SERVICE_UNAVAILABLE_ERROR"
|
|
23
|
+
SERVICE_UNAVAILABLE_ERROR = "SERVICE_UNAVAILABLE_ERROR",
|
|
24
|
+
TRANSACTION_REJECTED = "TRANSACTION_REJECTED"
|
|
24
25
|
}
|
|
25
26
|
export declare function isAPIError(error: any): error is imx.APIError;
|
|
26
27
|
export declare class PassportError extends Error {
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { Auth } from './Auth';
|
|
2
|
-
export { default as AuthManager } from './authManager';
|
|
3
2
|
export { AuthConfiguration, type IAuthConfiguration } from './config';
|
|
4
3
|
export type { User, UserProfile, UserZkEvm, DirectLoginMethod, DirectLoginOptions, LoginOptions, DeviceTokenResponse, OidcConfiguration, AuthModuleConfiguration, PopupOverlayOptions, PassportMetadata, IdTokenPayload, PKCEData, AuthEventMap, } from './types';
|
|
5
4
|
export { isUserZkEvm, RollupType, MarketingConsentStatus, AuthEvents, } from './types';
|
|
6
5
|
export { default as TypedEventEmitter } from './utils/typedEventEmitter';
|
|
7
|
-
export { PassportError, PassportErrorType, withPassportError } from './errors';
|
|
6
|
+
export { PassportError, PassportErrorType, withPassportError, isAPIError, } from './errors';
|
package/dist/types/types.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export type UserProfile = {
|
|
|
8
8
|
email?: string;
|
|
9
9
|
nickname?: string;
|
|
10
10
|
sub: string;
|
|
11
|
+
username?: string;
|
|
11
12
|
};
|
|
12
13
|
export declare enum RollupType {
|
|
13
14
|
ZKEVM = "zkEvm"
|
|
@@ -77,6 +78,7 @@ export type TokenPayload = {
|
|
|
77
78
|
};
|
|
78
79
|
export type IdTokenPayload = {
|
|
79
80
|
passport?: PassportMetadata;
|
|
81
|
+
username?: string;
|
|
80
82
|
email: string;
|
|
81
83
|
nickname: string;
|
|
82
84
|
aud: string;
|
package/jest.config.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Config } from 'jest';
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import { name } from './package.json';
|
|
4
|
+
|
|
5
|
+
const rootDirs = execSync(`pnpm --filter ${name}... exec pwd`)
|
|
6
|
+
.toString()
|
|
7
|
+
.split('\n')
|
|
8
|
+
.filter(Boolean)
|
|
9
|
+
.map((dir) => `${dir}/dist`);
|
|
10
|
+
|
|
11
|
+
const config: Config = {
|
|
12
|
+
clearMocks: true,
|
|
13
|
+
roots: ['<rootDir>/src', ...rootDirs],
|
|
14
|
+
coverageProvider: 'v8',
|
|
15
|
+
moduleDirectories: ['node_modules', 'src'],
|
|
16
|
+
moduleNameMapper: { '^@imtbl/(.*)$': '<rootDir>/../../node_modules/@imtbl/$1/src' },
|
|
17
|
+
testEnvironment: 'jsdom',
|
|
18
|
+
transform: {
|
|
19
|
+
'^.+\\.(t|j)sx?$': '@swc/jest',
|
|
20
|
+
},
|
|
21
|
+
transformIgnorePatterns: [],
|
|
22
|
+
restoreMocks: true,
|
|
23
|
+
setupFiles: ['<rootDir>/jest.setup.js'],
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default config;
|
|
27
|
+
|
package/jest.setup.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@imtbl/auth",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.1-alpha.0",
|
|
4
4
|
"description": "Authentication SDK for Immutable",
|
|
5
5
|
"author": "Immutable",
|
|
6
6
|
"bugs": "https://github.com/immutable/ts-immutable-sdk/issues",
|
|
@@ -25,17 +25,24 @@
|
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@imtbl/config": "2.
|
|
29
|
-
"@imtbl/metrics": "2.
|
|
28
|
+
"@imtbl/config": "2.11.1-alpha.0",
|
|
29
|
+
"@imtbl/metrics": "2.11.1-alpha.0",
|
|
30
30
|
"axios": "^1.6.5",
|
|
31
31
|
"jwt-decode": "^3.1.2",
|
|
32
32
|
"localforage": "^1.10.0",
|
|
33
|
-
"oidc-client-ts": "3.
|
|
33
|
+
"oidc-client-ts": "3.4.1",
|
|
34
34
|
"uuid": "^9.0.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@imtbl/toolkit": "2.
|
|
37
|
+
"@imtbl/toolkit": "2.11.1-alpha.0",
|
|
38
|
+
"@swc/core": "^1.3.36",
|
|
39
|
+
"@swc/jest": "^0.2.37",
|
|
40
|
+
"@types/jest": "^29.5.12",
|
|
38
41
|
"@types/node": "^18.14.2",
|
|
42
|
+
"@jest/test-sequencer": "^29.7.0",
|
|
43
|
+
"jest": "^29.4.3",
|
|
44
|
+
"jest-environment-jsdom": "^29.4.3",
|
|
45
|
+
"ts-node": "^10.9.1",
|
|
39
46
|
"tsup": "^8.3.0",
|
|
40
47
|
"typescript": "^5.6.2"
|
|
41
48
|
},
|
|
@@ -50,6 +57,7 @@
|
|
|
50
57
|
"typegen": "tsc --customConditions default --emitDeclarationOnly --outDir dist/types",
|
|
51
58
|
"pack:root": "pnpm pack --pack-destination $(dirname $(pnpm root -w))",
|
|
52
59
|
"lint": "eslint ./src --ext .ts,.jsx,.tsx --max-warnings=0",
|
|
53
|
-
"typecheck": "tsc --customConditions default --noEmit --jsx preserve"
|
|
60
|
+
"typecheck": "tsc --customConditions default --noEmit --jsx preserve",
|
|
61
|
+
"test": "jest"
|
|
54
62
|
}
|
|
55
63
|
}
|