@imtbl/auth 2.10.7-alpha.3 → 2.10.7-alpha.5

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.
@@ -0,0 +1,129 @@
1
+ import AuthManager from './authManager';
2
+ import { IAuthConfiguration } from './config';
3
+ import { AuthModuleConfiguration, User, DirectLoginOptions, DeviceTokenResponse, LoginOptions, AuthEventMap } from './types';
4
+ import TypedEventEmitter from './utils/typedEventEmitter';
5
+ /**
6
+ * Public-facing Auth class for authentication
7
+ * Wraps AuthManager with a simpler API
8
+ */
9
+ export declare class Auth {
10
+ private authManager;
11
+ private config;
12
+ /**
13
+ * Event emitter for authentication events (LOGGED_IN, LOGGED_OUT)
14
+ * Exposed for wallet and passport packages to subscribe to auth state changes
15
+ */
16
+ readonly eventEmitter: TypedEventEmitter<AuthEventMap>;
17
+ /**
18
+ * Create a new Auth instance
19
+ *
20
+ * @param config - Auth configuration
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * import { Auth } from '@imtbl/auth';
25
+ *
26
+ * const auth = new Auth({
27
+ * authenticationDomain: 'https://auth.immutable.com',
28
+ * passportDomain: 'https://passport.immutable.com',
29
+ * clientId: 'your-client-id',
30
+ * redirectUri: 'https://your-app.com/callback',
31
+ * scope: 'openid profile email transact',
32
+ * });
33
+ * ```
34
+ */
35
+ constructor(config: AuthModuleConfiguration);
36
+ /**
37
+ * Login the user with extended options
38
+ * Supports cached sessions, silent login, redirect flow, and direct login
39
+ * @param options - Extended login options
40
+ * @returns Promise that resolves with the user or null
41
+ */
42
+ login(options?: LoginOptions): Promise<User | null>;
43
+ /**
44
+ * Login with redirect
45
+ * Redirects the page for authentication
46
+ * @param directLoginOptions - Optional direct login options
47
+ * @returns Promise that resolves when redirect is initiated
48
+ */
49
+ loginWithRedirect(directLoginOptions?: DirectLoginOptions): Promise<void>;
50
+ /**
51
+ * Login callback handler
52
+ * Call this in your redirect URI page
53
+ * @returns Promise that resolves with the authenticated user
54
+ */
55
+ loginCallback(): Promise<User>;
56
+ /**
57
+ * Logout the current user
58
+ * @returns Promise that resolves when logout is complete
59
+ */
60
+ logout(): Promise<void>;
61
+ /**
62
+ * Get the current authenticated user
63
+ * @returns Promise that resolves with the user or null if not authenticated
64
+ */
65
+ getUser(): Promise<User | null>;
66
+ /**
67
+ * Get the ID token for the current user
68
+ * @returns Promise that resolves with the ID token or undefined
69
+ */
70
+ getIdToken(): Promise<string | undefined>;
71
+ /**
72
+ * Get the access token for the current user
73
+ * @returns Promise that resolves with the access token or undefined
74
+ */
75
+ getAccessToken(): Promise<string | undefined>;
76
+ /**
77
+ * Check if user is logged in
78
+ * @returns Promise that resolves with true if user is logged in
79
+ */
80
+ isLoggedIn(): Promise<boolean>;
81
+ /**
82
+ * Force a silent user refresh (for silent login)
83
+ * @returns Promise that resolves with the user or null if refresh fails
84
+ */
85
+ forceUserRefresh(): Promise<User | null>;
86
+ /**
87
+ * Get the PKCE authorization URL for login flow
88
+ * @param directLoginOptions - Optional direct login options
89
+ * @param imPassportTraceId - Optional trace ID for tracking
90
+ * @returns Promise that resolves with the authorization URL
91
+ */
92
+ loginWithPKCEFlow(directLoginOptions?: DirectLoginOptions, imPassportTraceId?: string): Promise<string>;
93
+ /**
94
+ * Handle the PKCE login callback
95
+ * @param authorizationCode - The authorization code from the OAuth provider
96
+ * @param state - The state parameter for CSRF protection
97
+ * @returns Promise that resolves with the authenticated user
98
+ */
99
+ loginWithPKCEFlowCallback(authorizationCode: string, state: string): Promise<User>;
100
+ /**
101
+ * Store tokens from device flow and retrieve user
102
+ * @param tokenResponse - The token response from device flow
103
+ * @returns Promise that resolves with the authenticated user
104
+ */
105
+ storeTokens(tokenResponse: DeviceTokenResponse): Promise<User>;
106
+ /**
107
+ * Get the logout URL
108
+ * @returns Promise that resolves with the logout URL or undefined if not available
109
+ */
110
+ getLogoutUrl(): Promise<string | undefined>;
111
+ /**
112
+ * Handle the silent logout callback
113
+ * @param url - The URL containing logout information
114
+ * @returns Promise that resolves when callback is handled
115
+ */
116
+ 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
+ /**
124
+ * Get auth configuration
125
+ * @internal
126
+ * @returns IAuthConfiguration instance
127
+ */
128
+ getConfig(): IAuthConfiguration;
129
+ }
@@ -1,6 +1,6 @@
1
- import { DirectLoginOptions, User, DeviceTokenResponse, UserZkEvm, UserImx } from './types';
1
+ import { DirectLoginOptions, User, DeviceTokenResponse, UserZkEvm } from './types';
2
2
  import { IAuthConfiguration } from './config';
3
- import { EmbeddedLoginPrompt } from './confirmation';
3
+ import EmbeddedLoginPrompt from './login/embeddedLoginPrompt';
4
4
  export default class AuthManager {
5
5
  private userManager;
6
6
  private deviceCredentialsManager;
@@ -15,16 +15,16 @@ export default class AuthManager {
15
15
  private static mapOidcUserToDomainModel;
16
16
  private static mapDeviceTokenResponseToOidcUser;
17
17
  private buildExtraQueryParams;
18
- loginWithRedirect(anonymousId?: string, directLoginOptions?: DirectLoginOptions): Promise<void>;
18
+ getClientId(): Promise<string>;
19
+ loginWithRedirect(directLoginOptions?: DirectLoginOptions): Promise<void>;
19
20
  /**
20
21
  * login
21
- * @param anonymousId Caller can pass an anonymousId if they want to associate their user's identity with immutable's internal instrumentation.
22
22
  * @param directLoginOptions If provided, contains login method and marketing consent options
23
23
  * @param directLoginOptions.directLoginMethod The login method to use (e.g., 'google', 'apple', 'email')
24
24
  * @param directLoginOptions.marketingConsentStatus Marketing consent status ('opted_in' or 'unsubscribed')
25
25
  * @param directLoginOptions.email Required when directLoginMethod is 'email'
26
26
  */
27
- login(anonymousId?: string, directLoginOptions?: DirectLoginOptions): Promise<User>;
27
+ login(directLoginOptions?: DirectLoginOptions): Promise<User>;
28
28
  getUserOrLogin(): Promise<User>;
29
29
  private static shouldUseSigninPopupCallback;
30
30
  loginCallback(): Promise<undefined | User>;
@@ -58,5 +58,4 @@ export default class AuthManager {
58
58
  */
59
59
  getUser<T extends User>(typeAssertion?: (user: User) => user is T): Promise<T | null>;
60
60
  getUserZkEvm(): Promise<UserZkEvm>;
61
- getUserImx(): Promise<UserImx>;
62
61
  }
@@ -1,8 +1,7 @@
1
+ export { Auth } from './Auth';
1
2
  export { default as AuthManager } from './authManager';
2
3
  export { AuthConfiguration, type IAuthConfiguration } from './config';
3
- export type { User, UserProfile, UserImx, UserZkEvm, DirectLoginMethod, DirectLoginOptions, DeviceTokenResponse, OidcConfiguration, AuthModuleConfiguration, PopupOverlayOptions, PassportMetadata, IdTokenPayload, PKCEData, } from './types';
4
- export { isUserZkEvm, isUserImx, RollupType, MarketingConsentStatus, } from './types';
4
+ export type { User, UserProfile, UserZkEvm, DirectLoginMethod, DirectLoginOptions, LoginOptions, DeviceTokenResponse, OidcConfiguration, AuthModuleConfiguration, PopupOverlayOptions, PassportMetadata, IdTokenPayload, PKCEData, AuthEventMap, } from './types';
5
+ export { isUserZkEvm, RollupType, MarketingConsentStatus, AuthEvents, } from './types';
6
+ export { default as TypedEventEmitter } from './utils/typedEventEmitter';
5
7
  export { PassportError, PassportErrorType, withPassportError } from './errors';
6
- export { default as ConfirmationScreen } from './confirmation/confirmation';
7
- export { default as EmbeddedLoginPrompt } from './confirmation/embeddedLoginPrompt';
8
- export { default as ConfirmationOverlay } from './overlay/confirmationOverlay';
@@ -6,5 +6,5 @@ export default class EmbeddedLoginPrompt {
6
6
  private getHref;
7
7
  private static appendIFrameStylesIfNeeded;
8
8
  private getEmbeddedLoginIFrame;
9
- displayEmbeddedLoginPrompt(anonymousId?: string): Promise<EmbeddedLoginPromptResult>;
9
+ displayEmbeddedLoginPrompt(): Promise<EmbeddedLoginPromptResult>;
10
10
  }
@@ -1,5 +1,5 @@
1
1
  import { PopupOverlayOptions } from '../types';
2
- export default class ConfirmationOverlay {
2
+ export default class LoginPopupOverlay {
3
3
  private disableGenericPopupOverlay;
4
4
  private disableBlockedPopupOverlay;
5
5
  private overlay;
@@ -10,7 +10,6 @@ export type UserProfile = {
10
10
  sub: string;
11
11
  };
12
12
  export declare enum RollupType {
13
- IMX = "imx",
14
13
  ZKEVM = "zkEvm"
15
14
  }
16
15
  export type User = {
@@ -19,22 +18,14 @@ export type User = {
19
18
  refreshToken?: string;
20
19
  profile: UserProfile;
21
20
  expired?: boolean;
22
- [RollupType.IMX]?: {
23
- ethAddress: string;
24
- starkAddress: string;
25
- userAdminAddress: string;
26
- };
27
21
  [RollupType.ZKEVM]?: {
28
22
  ethAddress: string;
29
23
  userAdminAddress: string;
30
24
  };
31
25
  };
32
26
  export type PassportMetadata = {
33
- imx_eth_address: string;
34
- imx_stark_address: string;
35
- imx_user_admin_address: string;
36
- zkevm_eth_address: string;
37
- zkevm_user_admin_address: string;
27
+ zkevm_eth_address?: string;
28
+ zkevm_user_admin_address?: string;
38
29
  };
39
30
  export interface OidcConfiguration {
40
31
  clientId: string;
@@ -72,10 +63,8 @@ export interface AuthModuleConfiguration extends OidcConfiguration {
72
63
  type WithRequired<T, K extends keyof T> = T & {
73
64
  [P in K]-?: T[P];
74
65
  };
75
- export type UserImx = WithRequired<User, RollupType.IMX>;
76
66
  export type UserZkEvm = WithRequired<User, RollupType.ZKEVM>;
77
67
  export declare const isUserZkEvm: (user: User) => user is UserZkEvm;
78
- export declare const isUserImx: (user: User) => user is UserImx;
79
68
  export type DeviceTokenResponse = {
80
69
  access_token: string;
81
70
  refresh_token?: string;
@@ -105,8 +94,39 @@ export declare enum MarketingConsentStatus {
105
94
  Unsubscribed = "unsubscribed"
106
95
  }
107
96
  export type DirectLoginOptions = {
108
- directLoginMethod: DirectLoginMethod;
109
- marketingConsentStatus?: MarketingConsentStatus;
110
- email?: string;
97
+ marketingConsentStatus: MarketingConsentStatus;
98
+ } & ({
99
+ directLoginMethod: 'email';
100
+ email: string;
101
+ } | {
102
+ directLoginMethod: Exclude<DirectLoginMethod, 'email'>;
103
+ email?: never;
104
+ });
105
+ /**
106
+ * Extended login options with caching and silent login support
107
+ */
108
+ export type LoginOptions = {
109
+ /** If true, attempts to use cached session without user interaction */
110
+ useCachedSession?: boolean;
111
+ /** If true, attempts silent authentication (force token refresh) */
112
+ useSilentLogin?: boolean;
113
+ /** If true, uses redirect flow instead of popup flow */
114
+ useRedirectFlow?: boolean;
115
+ /** Direct login options (social provider, email, etc.) */
116
+ directLoginOptions?: DirectLoginOptions;
111
117
  };
118
+ /**
119
+ * Authentication events emitted by the Auth class
120
+ */
121
+ export declare enum AuthEvents {
122
+ LOGGED_OUT = "loggedOut",
123
+ LOGGED_IN = "loggedIn"
124
+ }
125
+ /**
126
+ * Event map for typed event emitter
127
+ */
128
+ export interface AuthEventMap extends Record<string, any> {
129
+ [AuthEvents.LOGGED_OUT]: [];
130
+ [AuthEvents.LOGGED_IN]: [User];
131
+ }
112
132
  export {};
@@ -0,0 +1,2 @@
1
+ import { Flow } from '@imtbl/metrics';
2
+ export declare const withMetricsAsync: <T>(fn: (flow: Flow) => Promise<T>, flowName: string, trackStartEvent?: boolean, trackEndEvent?: boolean) => Promise<T>;
@@ -0,0 +1,6 @@
1
+ export default class TypedEventEmitter<TEvents extends Record<string, any>> {
2
+ private emitter;
3
+ emit<TEventName extends keyof TEvents & string>(eventName: TEventName, ...eventArg: TEvents[TEventName]): void;
4
+ on<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void): void;
5
+ removeListener<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: (...eventArg: TEvents[TEventName]) => void): void;
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imtbl/auth",
3
- "version": "2.10.7-alpha.3",
3
+ "version": "2.10.7-alpha.5",
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/config": "2.10.7-alpha.3",
29
- "@imtbl/metrics": "2.10.7-alpha.3",
28
+ "@imtbl/config": "2.10.7-alpha.5",
29
+ "@imtbl/metrics": "2.10.7-alpha.5",
30
30
  "axios": "^1.6.5",
31
31
  "jwt-decode": "^3.1.2",
32
32
  "localforage": "^1.10.0",
@@ -34,7 +34,7 @@
34
34
  "uuid": "^9.0.1"
35
35
  },
36
36
  "devDependencies": {
37
- "@imtbl/toolkit": "2.10.7-alpha.3",
37
+ "@imtbl/toolkit": "2.10.7-alpha.5",
38
38
  "@types/node": "^18.14.2",
39
39
  "tsup": "^8.3.0",
40
40
  "typescript": "^5.6.2"
package/src/Auth.ts ADDED
@@ -0,0 +1,264 @@
1
+ import AuthManager from './authManager';
2
+ import { AuthConfiguration, IAuthConfiguration } from './config';
3
+ import {
4
+ AuthModuleConfiguration, User, DirectLoginOptions, DeviceTokenResponse, LoginOptions, AuthEventMap, AuthEvents,
5
+ } from './types';
6
+ import EmbeddedLoginPrompt from './login/embeddedLoginPrompt';
7
+ import TypedEventEmitter from './utils/typedEventEmitter';
8
+ import { withMetricsAsync } from './utils/metrics';
9
+ import { identify, track, trackError } from '@imtbl/metrics';
10
+ import logger from './utils/logger';
11
+
12
+ /**
13
+ * Public-facing Auth class for authentication
14
+ * Wraps AuthManager with a simpler API
15
+ */
16
+ export class Auth {
17
+ private authManager: AuthManager;
18
+
19
+ private config: IAuthConfiguration;
20
+
21
+ /**
22
+ * Event emitter for authentication events (LOGGED_IN, LOGGED_OUT)
23
+ * Exposed for wallet and passport packages to subscribe to auth state changes
24
+ */
25
+ public readonly eventEmitter: TypedEventEmitter<AuthEventMap>;
26
+
27
+ /**
28
+ * Create a new Auth instance
29
+ *
30
+ * @param config - Auth configuration
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * import { Auth } from '@imtbl/auth';
35
+ *
36
+ * const auth = new Auth({
37
+ * authenticationDomain: 'https://auth.immutable.com',
38
+ * passportDomain: 'https://passport.immutable.com',
39
+ * clientId: 'your-client-id',
40
+ * redirectUri: 'https://your-app.com/callback',
41
+ * scope: 'openid profile email transact',
42
+ * });
43
+ * ```
44
+ */
45
+ constructor(config: AuthModuleConfiguration) {
46
+ this.config = new AuthConfiguration(config);
47
+ const embeddedLoginPrompt = new EmbeddedLoginPrompt(this.config);
48
+ this.authManager = new AuthManager(this.config, embeddedLoginPrompt);
49
+ this.eventEmitter = new TypedEventEmitter<AuthEventMap>();
50
+ track('passport', 'initialise');
51
+ }
52
+
53
+ /**
54
+ * Login the user with extended options
55
+ * Supports cached sessions, silent login, redirect flow, and direct login
56
+ * @param options - Extended login options
57
+ * @returns Promise that resolves with the user or null
58
+ */
59
+ async login(options?: LoginOptions): Promise<User | null> {
60
+ return withMetricsAsync(async () => {
61
+ const { useCachedSession = false, useSilentLogin } = options || {};
62
+ let user: User | null = null;
63
+
64
+ // Try to get cached user
65
+ try {
66
+ user = await this.authManager.getUser();
67
+ } catch (error: any) {
68
+ if (error instanceof Error && !error.message.includes('Unknown or invalid refresh token')) {
69
+ trackError('passport', 'login', error);
70
+ }
71
+ if (useCachedSession) {
72
+ throw error;
73
+ }
74
+ logger.warn('Failed to retrieve a cached user session', error);
75
+ }
76
+
77
+ // If no cached user, try silent login or regular login
78
+ if (!user && useSilentLogin) {
79
+ user = await this.authManager.forceUserRefresh();
80
+ } else if (!user && !useCachedSession) {
81
+ if (options?.useRedirectFlow) {
82
+ await this.authManager.loginWithRedirect(options?.directLoginOptions);
83
+ return null; // Redirect doesn't return user immediately
84
+ }
85
+ user = await this.authManager.login(options?.directLoginOptions);
86
+ }
87
+
88
+ // Emit LOGGED_IN event and identify user if logged in
89
+ if (user) {
90
+ this.eventEmitter.emit(AuthEvents.LOGGED_IN, user);
91
+ identify({ passportId: user.profile.sub });
92
+ }
93
+
94
+ return user;
95
+ }, 'login');
96
+ }
97
+
98
+ /**
99
+ * Login with redirect
100
+ * Redirects the page for authentication
101
+ * @param directLoginOptions - Optional direct login options
102
+ * @returns Promise that resolves when redirect is initiated
103
+ */
104
+ async loginWithRedirect(directLoginOptions?: DirectLoginOptions): Promise<void> {
105
+ await this.authManager.loginWithRedirect(directLoginOptions);
106
+ }
107
+
108
+ /**
109
+ * Login callback handler
110
+ * Call this in your redirect URI page
111
+ * @returns Promise that resolves with the authenticated user
112
+ */
113
+ async loginCallback(): Promise<User> {
114
+ return withMetricsAsync(async () => {
115
+ const user = await this.authManager.loginCallback();
116
+ if (!user) {
117
+ throw new Error('Login callback failed - no user returned');
118
+ }
119
+ this.eventEmitter.emit(AuthEvents.LOGGED_IN, user);
120
+ identify({ passportId: user.profile.sub });
121
+ return user;
122
+ }, 'loginCallback');
123
+ }
124
+
125
+ /**
126
+ * Logout the current user
127
+ * @returns Promise that resolves when logout is complete
128
+ */
129
+ async logout(): Promise<void> {
130
+ await withMetricsAsync(async () => {
131
+ await this.authManager.logout();
132
+ this.eventEmitter.emit(AuthEvents.LOGGED_OUT);
133
+ }, 'logout');
134
+ }
135
+
136
+ /**
137
+ * Get the current authenticated user
138
+ * @returns Promise that resolves with the user or null if not authenticated
139
+ */
140
+ async getUser(): Promise<User | null> {
141
+ return withMetricsAsync(async () => this.authManager.getUser(), 'getUserInfo', false);
142
+ }
143
+
144
+ /**
145
+ * Get the ID token for the current user
146
+ * @returns Promise that resolves with the ID token or undefined
147
+ */
148
+ async getIdToken(): Promise<string | undefined> {
149
+ return withMetricsAsync(async () => {
150
+ const user = await this.authManager.getUser();
151
+ return user?.idToken;
152
+ }, 'getIdToken', false);
153
+ }
154
+
155
+ /**
156
+ * Get the access token for the current user
157
+ * @returns Promise that resolves with the access token or undefined
158
+ */
159
+ async getAccessToken(): Promise<string | undefined> {
160
+ return withMetricsAsync(async () => {
161
+ const user = await this.authManager.getUser();
162
+ return user?.accessToken;
163
+ }, 'getAccessToken', false, false);
164
+ }
165
+
166
+ /**
167
+ * Check if user is logged in
168
+ * @returns Promise that resolves with true if user is logged in
169
+ */
170
+ async isLoggedIn(): Promise<boolean> {
171
+ const user = await this.getUser();
172
+ return user !== null;
173
+ }
174
+
175
+ /**
176
+ * Force a silent user refresh (for silent login)
177
+ * @returns Promise that resolves with the user or null if refresh fails
178
+ */
179
+ async forceUserRefresh(): Promise<User | null> {
180
+ return this.authManager.forceUserRefresh();
181
+ }
182
+
183
+ /**
184
+ * Get the PKCE authorization URL for login flow
185
+ * @param directLoginOptions - Optional direct login options
186
+ * @param imPassportTraceId - Optional trace ID for tracking
187
+ * @returns Promise that resolves with the authorization URL
188
+ */
189
+ async loginWithPKCEFlow(directLoginOptions?: DirectLoginOptions, imPassportTraceId?: string): Promise<string> {
190
+ return withMetricsAsync(
191
+ async () => this.authManager.getPKCEAuthorizationUrl(directLoginOptions, imPassportTraceId),
192
+ 'loginWithPKCEFlow',
193
+ );
194
+ }
195
+
196
+ /**
197
+ * Handle the PKCE login callback
198
+ * @param authorizationCode - The authorization code from the OAuth provider
199
+ * @param state - The state parameter for CSRF protection
200
+ * @returns Promise that resolves with the authenticated user
201
+ */
202
+ async loginWithPKCEFlowCallback(authorizationCode: string, state: string): Promise<User> {
203
+ return withMetricsAsync(async () => {
204
+ const user = await this.authManager.loginWithPKCEFlowCallback(authorizationCode, state);
205
+ this.eventEmitter.emit(AuthEvents.LOGGED_IN, user);
206
+ identify({ passportId: user.profile.sub });
207
+ return user;
208
+ }, 'loginWithPKCEFlowCallback');
209
+ }
210
+
211
+ /**
212
+ * Store tokens from device flow and retrieve user
213
+ * @param tokenResponse - The token response from device flow
214
+ * @returns Promise that resolves with the authenticated user
215
+ */
216
+ async storeTokens(tokenResponse: DeviceTokenResponse): Promise<User> {
217
+ return withMetricsAsync(async () => {
218
+ const user = await this.authManager.storeTokens(tokenResponse);
219
+ this.eventEmitter.emit(AuthEvents.LOGGED_IN, user);
220
+ identify({ passportId: user.profile.sub });
221
+ return user;
222
+ }, 'storeTokens');
223
+ }
224
+
225
+ /**
226
+ * Get the logout URL
227
+ * @returns Promise that resolves with the logout URL or undefined if not available
228
+ */
229
+ async getLogoutUrl(): Promise<string | undefined> {
230
+ return withMetricsAsync(async () => {
231
+ await this.authManager.removeUser();
232
+ this.eventEmitter.emit(AuthEvents.LOGGED_OUT);
233
+ const url = await this.authManager.getLogoutUrl();
234
+ return url || undefined;
235
+ }, 'getLogoutUrl');
236
+ }
237
+
238
+ /**
239
+ * Handle the silent logout callback
240
+ * @param url - The URL containing logout information
241
+ * @returns Promise that resolves when callback is handled
242
+ */
243
+ async logoutSilentCallback(url: string): Promise<void> {
244
+ return withMetricsAsync(() => this.authManager.logoutSilentCallback(url), 'logoutSilentCallback');
245
+ }
246
+
247
+ /**
248
+ * Get internal AuthManager instance
249
+ * @internal
250
+ * @returns AuthManager instance for advanced use cases
251
+ */
252
+ getAuthManager(): AuthManager {
253
+ return this.authManager;
254
+ }
255
+
256
+ /**
257
+ * Get auth configuration
258
+ * @internal
259
+ * @returns IAuthConfiguration instance
260
+ */
261
+ getConfig(): IAuthConfiguration {
262
+ return this.config;
263
+ }
264
+ }