@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/src/login/standalone.ts
CHANGED
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
DirectLoginOptions, IdTokenPayload, MarketingConsentStatus, ZkEvmInfo,
|
|
11
11
|
} from '../types';
|
|
12
12
|
import { PASSPORT_OVERLAY_CONTENTS_ID } from '../overlay/constants';
|
|
13
|
+
import { buildLogoutUrl as internalBuildLogoutUrl } from '../logout';
|
|
13
14
|
|
|
14
15
|
// ============================================================================
|
|
15
16
|
// Types
|
|
@@ -743,3 +744,163 @@ export async function handleLoginCallback(
|
|
|
743
744
|
|
|
744
745
|
return tokens;
|
|
745
746
|
}
|
|
747
|
+
|
|
748
|
+
// ============================================================================
|
|
749
|
+
// Logout Types
|
|
750
|
+
// ============================================================================
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* Configuration for standalone logout functions
|
|
754
|
+
*/
|
|
755
|
+
export interface LogoutConfig {
|
|
756
|
+
/** Your Immutable application client ID */
|
|
757
|
+
clientId: string;
|
|
758
|
+
/** URL to redirect to after logout completes (must be registered in your app settings) */
|
|
759
|
+
logoutRedirectUri?: string;
|
|
760
|
+
/** Authentication domain (default: "https://auth.immutable.com") */
|
|
761
|
+
authenticationDomain?: string;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// ============================================================================
|
|
765
|
+
// Logout Functions
|
|
766
|
+
// ============================================================================
|
|
767
|
+
|
|
768
|
+
/**
|
|
769
|
+
* Build the logout URL for federated logout.
|
|
770
|
+
* This URL can be used to redirect to the auth domain's logout endpoint,
|
|
771
|
+
* which clears the session on the auth server (including social provider sessions).
|
|
772
|
+
*
|
|
773
|
+
* @param config - Logout configuration
|
|
774
|
+
* @returns The full logout URL
|
|
775
|
+
*
|
|
776
|
+
* @example
|
|
777
|
+
* ```typescript
|
|
778
|
+
* import { buildLogoutUrl } from '@imtbl/auth';
|
|
779
|
+
*
|
|
780
|
+
* const logoutUrl = buildLogoutUrl({
|
|
781
|
+
* clientId: 'your-client-id',
|
|
782
|
+
* logoutRedirectUri: 'https://your-app.com',
|
|
783
|
+
* });
|
|
784
|
+
* // => "https://auth.immutable.com/v2/logout?client_id=your-client-id&returnTo=https://your-app.com"
|
|
785
|
+
* ```
|
|
786
|
+
*/
|
|
787
|
+
export function buildLogoutUrl(config: LogoutConfig): string {
|
|
788
|
+
// Use internal implementation (crossSdkBridgeEnabled defaults to false for public API)
|
|
789
|
+
return internalBuildLogoutUrl(config);
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
/**
|
|
793
|
+
* Logout with redirect.
|
|
794
|
+
* Redirects the current page to the auth domain's logout endpoint,
|
|
795
|
+
* which clears the session on the auth server (including social provider sessions like Google).
|
|
796
|
+
*
|
|
797
|
+
* This is the recommended logout method for most applications as it ensures
|
|
798
|
+
* complete session cleanup. After logout, the user will be redirected to
|
|
799
|
+
* the `logoutRedirectUri` if provided.
|
|
800
|
+
*
|
|
801
|
+
* @param config - Logout configuration
|
|
802
|
+
*
|
|
803
|
+
* @example
|
|
804
|
+
* ```typescript
|
|
805
|
+
* import { logoutWithRedirect } from '@imtbl/auth';
|
|
806
|
+
*
|
|
807
|
+
* // In your logout button handler
|
|
808
|
+
* logoutWithRedirect({
|
|
809
|
+
* clientId: 'your-client-id',
|
|
810
|
+
* logoutRedirectUri: 'https://your-app.com',
|
|
811
|
+
* });
|
|
812
|
+
* // Page will redirect to auth domain, then back to your app
|
|
813
|
+
* ```
|
|
814
|
+
*/
|
|
815
|
+
export function logoutWithRedirect(config: LogoutConfig): void {
|
|
816
|
+
track('passport', 'standaloneLogoutWithRedirect');
|
|
817
|
+
|
|
818
|
+
const logoutUrl = buildLogoutUrl(config);
|
|
819
|
+
window.location.href = logoutUrl;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* Logout silently using a hidden iframe.
|
|
824
|
+
* Clears the session on the auth server without redirecting the current page.
|
|
825
|
+
*
|
|
826
|
+
* Note: Silent logout may not work in all browsers due to third-party cookie
|
|
827
|
+
* restrictions. For more reliable session cleanup, use `logoutWithRedirect`.
|
|
828
|
+
*
|
|
829
|
+
* @param config - Logout configuration
|
|
830
|
+
* @param timeout - Timeout in milliseconds (default: 5000)
|
|
831
|
+
* @returns Promise that resolves when logout is complete or times out
|
|
832
|
+
*
|
|
833
|
+
* @example
|
|
834
|
+
* ```typescript
|
|
835
|
+
* import { logoutSilent } from '@imtbl/auth';
|
|
836
|
+
*
|
|
837
|
+
* try {
|
|
838
|
+
* await logoutSilent({
|
|
839
|
+
* clientId: 'your-client-id',
|
|
840
|
+
* });
|
|
841
|
+
* console.log('Logged out silently');
|
|
842
|
+
* } catch (error) {
|
|
843
|
+
* console.error('Silent logout failed:', error);
|
|
844
|
+
* // Fall back to redirect logout
|
|
845
|
+
* }
|
|
846
|
+
* ```
|
|
847
|
+
*/
|
|
848
|
+
export async function logoutSilent(
|
|
849
|
+
config: LogoutConfig,
|
|
850
|
+
timeout: number = 5000,
|
|
851
|
+
): Promise<void> {
|
|
852
|
+
track('passport', 'standaloneLogoutSilent');
|
|
853
|
+
|
|
854
|
+
return new Promise((resolve, reject) => {
|
|
855
|
+
const logoutUrl = buildLogoutUrl(config);
|
|
856
|
+
|
|
857
|
+
// Create hidden iframe
|
|
858
|
+
const iframe = document.createElement('iframe');
|
|
859
|
+
iframe.style.display = 'none';
|
|
860
|
+
iframe.setAttribute('aria-hidden', 'true');
|
|
861
|
+
|
|
862
|
+
let timeoutId: ReturnType<typeof setTimeout>;
|
|
863
|
+
let resolved = false;
|
|
864
|
+
|
|
865
|
+
const cleanup = () => {
|
|
866
|
+
if (timeoutId) {
|
|
867
|
+
clearTimeout(timeoutId);
|
|
868
|
+
}
|
|
869
|
+
iframe.remove();
|
|
870
|
+
};
|
|
871
|
+
|
|
872
|
+
const handleLoad = () => {
|
|
873
|
+
if (!resolved) {
|
|
874
|
+
resolved = true;
|
|
875
|
+
cleanup();
|
|
876
|
+
resolve();
|
|
877
|
+
}
|
|
878
|
+
};
|
|
879
|
+
|
|
880
|
+
const handleError = () => {
|
|
881
|
+
if (!resolved) {
|
|
882
|
+
resolved = true;
|
|
883
|
+
cleanup();
|
|
884
|
+
reject(new Error('Silent logout failed: iframe load error'));
|
|
885
|
+
}
|
|
886
|
+
};
|
|
887
|
+
|
|
888
|
+
iframe.addEventListener('load', handleLoad);
|
|
889
|
+
iframe.addEventListener('error', handleError);
|
|
890
|
+
|
|
891
|
+
// Set timeout
|
|
892
|
+
timeoutId = setTimeout(() => {
|
|
893
|
+
if (!resolved) {
|
|
894
|
+
resolved = true;
|
|
895
|
+
cleanup();
|
|
896
|
+
// Resolve instead of reject on timeout - the logout request was sent,
|
|
897
|
+
// we just can't confirm it completed due to cross-origin restrictions
|
|
898
|
+
resolve();
|
|
899
|
+
}
|
|
900
|
+
}, timeout);
|
|
901
|
+
|
|
902
|
+
// Start logout
|
|
903
|
+
iframe.src = logoutUrl;
|
|
904
|
+
document.body.appendChild(iframe);
|
|
905
|
+
});
|
|
906
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal logout utilities shared between Auth class and standalone functions.
|
|
3
|
+
* NOT exported from package index - only used internally.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const LOGOUT_ENDPOINT = '/v2/logout';
|
|
7
|
+
const CROSS_SDK_BRIDGE_LOGOUT_ENDPOINT = '/im-logged-out';
|
|
8
|
+
const DEFAULT_AUTH_DOMAIN = 'https://auth.immutable.com';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Internal config for building logout URLs.
|
|
12
|
+
* Includes crossSdkBridgeEnabled for Auth class (Passport SDK).
|
|
13
|
+
* NOT exported publicly from the package.
|
|
14
|
+
*/
|
|
15
|
+
export interface InternalLogoutConfig {
|
|
16
|
+
/** The client ID for the application */
|
|
17
|
+
clientId: string;
|
|
18
|
+
/** The authentication domain (defaults to https://auth.immutable.com) */
|
|
19
|
+
authenticationDomain?: string;
|
|
20
|
+
/** The URI to redirect to after logout */
|
|
21
|
+
logoutRedirectUri?: string;
|
|
22
|
+
/** Whether cross-SDK bridge is enabled (internal to Auth class) */
|
|
23
|
+
crossSdkBridgeEnabled?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Normalize authentication domain to ensure https:// prefix.
|
|
28
|
+
*/
|
|
29
|
+
function normalizeAuthDomain(domain: string): string {
|
|
30
|
+
return domain.replace(/^(?:https?:\/\/)?(.*)/, 'https://$1');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Build logout URL for federated logout.
|
|
35
|
+
* Used by both Auth class (with crossSdkBridgeEnabled) and standalone functions.
|
|
36
|
+
*
|
|
37
|
+
* @param config - Configuration for building the logout URL
|
|
38
|
+
* @returns The complete logout URL string
|
|
39
|
+
*/
|
|
40
|
+
export function buildLogoutUrl(config: InternalLogoutConfig): string {
|
|
41
|
+
const authDomain = normalizeAuthDomain(config.authenticationDomain || DEFAULT_AUTH_DOMAIN);
|
|
42
|
+
const endpoint = config.crossSdkBridgeEnabled
|
|
43
|
+
? CROSS_SDK_BRIDGE_LOGOUT_ENDPOINT
|
|
44
|
+
: LOGOUT_ENDPOINT;
|
|
45
|
+
|
|
46
|
+
const url = new URL(endpoint, authDomain);
|
|
47
|
+
url.searchParams.set('client_id', config.clientId);
|
|
48
|
+
if (config.logoutRedirectUri) {
|
|
49
|
+
url.searchParams.set('returnTo', config.logoutRedirectUri);
|
|
50
|
+
}
|
|
51
|
+
return url.toString();
|
|
52
|
+
}
|