@ollaid/native-sso 1.0.8 → 2.1.2
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/README.md +247 -58
- package/dist/hooks/useLogout.d.ts +41 -0
- package/dist/hooks/useTokenHealthCheck.d.ts +11 -5
- package/dist/index.cjs +150 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +150 -44
- package/dist/index.js.map +1 -1
- package/dist/services/api.d.ts +26 -0
- package/dist/services/nativeAuth.d.ts +1 -1
- package/dist/types/native.d.ts +5 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -496,7 +496,8 @@ const STORAGE = {
|
|
|
496
496
|
TOKEN: "token",
|
|
497
497
|
USER: "user",
|
|
498
498
|
ACCOUNT_TYPE: "account_type",
|
|
499
|
-
ALIAS_REFERENCE: "alias_reference"
|
|
499
|
+
ALIAS_REFERENCE: "alias_reference",
|
|
500
|
+
APP_ACCESS_TOKEN_REF: "app_access_token_ref"
|
|
500
501
|
};
|
|
501
502
|
const setAuthToken = (token) => {
|
|
502
503
|
if (typeof localStorage !== "undefined") {
|
|
@@ -515,8 +516,14 @@ const clearAuthToken = () => {
|
|
|
515
516
|
localStorage.removeItem(STORAGE.USER);
|
|
516
517
|
localStorage.removeItem(STORAGE.ACCOUNT_TYPE);
|
|
517
518
|
localStorage.removeItem(STORAGE.ALIAS_REFERENCE);
|
|
519
|
+
localStorage.removeItem(STORAGE.APP_ACCESS_TOKEN_REF);
|
|
518
520
|
}
|
|
519
521
|
};
|
|
522
|
+
const logout = async () => {
|
|
523
|
+
const { nativeAuthService: nativeAuthService2 } = await Promise.resolve().then(() => nativeAuth);
|
|
524
|
+
const token = getAuthToken();
|
|
525
|
+
return nativeAuthService2.logout(token || void 0);
|
|
526
|
+
};
|
|
520
527
|
const setAuthUser = (user) => {
|
|
521
528
|
if (typeof localStorage !== "undefined") {
|
|
522
529
|
localStorage.setItem(STORAGE.USER, JSON.stringify(user));
|
|
@@ -810,7 +817,7 @@ const nativeAuthService = {
|
|
|
810
817
|
);
|
|
811
818
|
},
|
|
812
819
|
async exchange(callbackToken) {
|
|
813
|
-
var _a;
|
|
820
|
+
var _a, _b;
|
|
814
821
|
const config2 = getNativeAuthConfig();
|
|
815
822
|
if (!config2.saasApiUrl) {
|
|
816
823
|
throw new ApiError("saasApiUrl non configurée", "unknown");
|
|
@@ -832,9 +839,16 @@ const nativeAuthService = {
|
|
|
832
839
|
if (response.user) {
|
|
833
840
|
setAuthUser(response.user);
|
|
834
841
|
}
|
|
842
|
+
if (response.app_access_token_ref && typeof localStorage !== "undefined") {
|
|
843
|
+
localStorage.setItem(STORAGE.APP_ACCESS_TOKEN_REF, response.app_access_token_ref);
|
|
844
|
+
}
|
|
845
|
+
const aliasRef = ((_a = response.user) == null ? void 0 : _a.alias_reference) || response.alias_reference;
|
|
846
|
+
if (aliasRef && typeof localStorage !== "undefined") {
|
|
847
|
+
localStorage.setItem(STORAGE.ALIAS_REFERENCE, aliasRef);
|
|
848
|
+
}
|
|
835
849
|
}
|
|
836
850
|
if (isDebugMode()) {
|
|
837
|
-
console.log("✅ [SaaS] Session établie:", { user: (
|
|
851
|
+
console.log("✅ [SaaS] Session établie:", { user: (_b = response.user) == null ? void 0 : _b.name });
|
|
838
852
|
}
|
|
839
853
|
return response;
|
|
840
854
|
},
|
|
@@ -855,7 +869,13 @@ const nativeAuthService = {
|
|
|
855
869
|
},
|
|
856
870
|
1e4
|
|
857
871
|
);
|
|
858
|
-
|
|
872
|
+
if (response.status === "connected" && response.user) {
|
|
873
|
+
return { valid: true, user: response.user };
|
|
874
|
+
}
|
|
875
|
+
if (response.success !== false) {
|
|
876
|
+
return { valid: true, user: response.user };
|
|
877
|
+
}
|
|
878
|
+
return { valid: false };
|
|
859
879
|
} catch (err) {
|
|
860
880
|
if (err instanceof ApiError && err.statusCode === 401) {
|
|
861
881
|
return { valid: false };
|
|
@@ -865,28 +885,53 @@ const nativeAuthService = {
|
|
|
865
885
|
},
|
|
866
886
|
async logout(token) {
|
|
867
887
|
const config2 = getNativeAuthConfig();
|
|
868
|
-
|
|
869
|
-
|
|
888
|
+
const iamToken = typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE.AUTH_TOKEN) || localStorage.getItem(STORAGE.TOKEN) : null;
|
|
889
|
+
const appAccessTokenRef = typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE.APP_ACCESS_TOKEN_REF) : null;
|
|
890
|
+
const promises = [];
|
|
891
|
+
if (config2.saasApiUrl && token) {
|
|
892
|
+
promises.push(
|
|
893
|
+
fetchWithTimeout(
|
|
894
|
+
`${config2.saasApiUrl}/native/logout`,
|
|
895
|
+
{
|
|
896
|
+
method: "POST",
|
|
897
|
+
headers: getHeaders(token, true)
|
|
898
|
+
},
|
|
899
|
+
config2.timeout || 3e4
|
|
900
|
+
).catch((err) => {
|
|
901
|
+
if (isDebugMode()) {
|
|
902
|
+
console.warn("⚠️ [SaaS] Échec logout (non-bloquant):", err instanceof Error ? err.message : err);
|
|
903
|
+
}
|
|
904
|
+
})
|
|
905
|
+
);
|
|
870
906
|
}
|
|
871
|
-
|
|
872
|
-
const
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
907
|
+
if (config2.iamApiUrl && (iamToken || appAccessTokenRef)) {
|
|
908
|
+
const payload = {};
|
|
909
|
+
if (iamToken) payload.sanctum_token = iamToken;
|
|
910
|
+
if (appAccessTokenRef) payload.app_access_token_ref = appAccessTokenRef;
|
|
911
|
+
promises.push(
|
|
912
|
+
fetchWithTimeout(
|
|
913
|
+
`${config2.iamApiUrl}/iam/disconnect`,
|
|
914
|
+
{
|
|
915
|
+
method: "POST",
|
|
916
|
+
headers: { "Content-Type": "application/json", "Accept": "application/json" },
|
|
917
|
+
body: JSON.stringify(payload)
|
|
918
|
+
},
|
|
919
|
+
5e3
|
|
920
|
+
).catch((err) => {
|
|
921
|
+
if (isDebugMode()) {
|
|
922
|
+
console.warn("⚠️ [IAM] Échec disconnect (non-bloquant):", err instanceof Error ? err.message : err);
|
|
923
|
+
}
|
|
924
|
+
})
|
|
879
925
|
);
|
|
880
|
-
clearAuthToken();
|
|
881
|
-
credentials = null;
|
|
882
|
-
credentialsLoadedAt = 0;
|
|
883
|
-
return response;
|
|
884
|
-
} catch {
|
|
885
|
-
clearAuthToken();
|
|
886
|
-
credentials = null;
|
|
887
|
-
credentialsLoadedAt = 0;
|
|
888
|
-
return { success: true };
|
|
889
926
|
}
|
|
927
|
+
await Promise.allSettled(promises);
|
|
928
|
+
if (isDebugMode()) {
|
|
929
|
+
console.log("✅ [Logout] Double revocation terminée — nettoyage local");
|
|
930
|
+
}
|
|
931
|
+
clearAuthToken();
|
|
932
|
+
credentials = null;
|
|
933
|
+
credentialsLoadedAt = 0;
|
|
934
|
+
return { success: true };
|
|
890
935
|
},
|
|
891
936
|
clearCredentials() {
|
|
892
937
|
credentials = null;
|
|
@@ -947,6 +992,10 @@ const nativeAuthService = {
|
|
|
947
992
|
return this.init(native_token);
|
|
948
993
|
}
|
|
949
994
|
};
|
|
995
|
+
const nativeAuth = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
996
|
+
__proto__: null,
|
|
997
|
+
nativeAuthService
|
|
998
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
950
999
|
function getIAMHeaders() {
|
|
951
1000
|
const creds = nativeAuthService.getCredentials();
|
|
952
1001
|
if (!creds) {
|
|
@@ -1524,8 +1573,8 @@ function PasswordRecoveryModal({ open, onOpenChange, onSuccess, saasApiUrl, iamA
|
|
|
1524
1573
|
] })
|
|
1525
1574
|
] }) });
|
|
1526
1575
|
}
|
|
1527
|
-
const FIRST_CHECK_DELAY =
|
|
1528
|
-
const INTERVAL_DELAY =
|
|
1576
|
+
const FIRST_CHECK_DELAY = 60 * 1e3;
|
|
1577
|
+
const INTERVAL_DELAY = 2 * 60 * 1e3;
|
|
1529
1578
|
async function checkTokenValidity(saasApiUrl, token, debug) {
|
|
1530
1579
|
if (typeof navigator !== "undefined" && !navigator.onLine) {
|
|
1531
1580
|
if (debug) console.log("🔄 [HealthCheck] Offline — skip");
|
|
@@ -1545,7 +1594,7 @@ async function checkTokenValidity(saasApiUrl, token, debug) {
|
|
|
1545
1594
|
});
|
|
1546
1595
|
clearTimeout(timeoutId);
|
|
1547
1596
|
if (response.status === 401) {
|
|
1548
|
-
if (debug) console.log("🔄 [HealthCheck] Token invalide (401)");
|
|
1597
|
+
if (debug) console.log("🔄 [HealthCheck] Token invalide (401) — déconnexion");
|
|
1549
1598
|
return { valid: false };
|
|
1550
1599
|
}
|
|
1551
1600
|
if (!response.ok) {
|
|
@@ -1553,11 +1602,15 @@ async function checkTokenValidity(saasApiUrl, token, debug) {
|
|
|
1553
1602
|
throw new Error(`server_error_${response.status}`);
|
|
1554
1603
|
}
|
|
1555
1604
|
const data = await response.json();
|
|
1556
|
-
if (
|
|
1557
|
-
|
|
1558
|
-
valid: data.
|
|
1559
|
-
|
|
1560
|
-
|
|
1605
|
+
if (data.status === "connected" && data.user) {
|
|
1606
|
+
if (debug) console.log("🔄 [HealthCheck] Token valide ✅ — user_infos mis à jour");
|
|
1607
|
+
return { valid: true, user: data.user };
|
|
1608
|
+
}
|
|
1609
|
+
if (data.success !== false) {
|
|
1610
|
+
if (debug) console.log("🔄 [HealthCheck] Token valide ✅");
|
|
1611
|
+
return { valid: true, user: data.user };
|
|
1612
|
+
}
|
|
1613
|
+
return { valid: false };
|
|
1561
1614
|
} catch (error) {
|
|
1562
1615
|
clearTimeout(timeoutId);
|
|
1563
1616
|
if (error instanceof Error && error.message === "offline") {
|
|
@@ -1570,8 +1623,34 @@ async function checkTokenValidity(saasApiUrl, token, debug) {
|
|
|
1570
1623
|
throw error;
|
|
1571
1624
|
}
|
|
1572
1625
|
}
|
|
1626
|
+
function revokeOnIam(iamApiUrl, sanctumToken, debug) {
|
|
1627
|
+
try {
|
|
1628
|
+
const controller = new AbortController();
|
|
1629
|
+
setTimeout(() => controller.abort(), 5e3);
|
|
1630
|
+
const appAccessTokenRef = typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE.APP_ACCESS_TOKEN_REF) : null;
|
|
1631
|
+
const payload = { sanctum_token: sanctumToken };
|
|
1632
|
+
if (appAccessTokenRef) {
|
|
1633
|
+
payload.app_access_token_ref = appAccessTokenRef;
|
|
1634
|
+
}
|
|
1635
|
+
if (debug) {
|
|
1636
|
+
console.log("🔄 [HealthCheck] Revocation IAM:", { hasRef: !!appAccessTokenRef });
|
|
1637
|
+
}
|
|
1638
|
+
fetch(`${iamApiUrl}/iam/disconnect`, {
|
|
1639
|
+
method: "POST",
|
|
1640
|
+
headers: {
|
|
1641
|
+
"Content-Type": "application/json",
|
|
1642
|
+
"Accept": "application/json"
|
|
1643
|
+
},
|
|
1644
|
+
body: JSON.stringify(payload),
|
|
1645
|
+
signal: controller.signal
|
|
1646
|
+
}).catch(() => {
|
|
1647
|
+
if (debug) console.log("🔄 [HealthCheck] Échec revocation IAM (non-bloquant)");
|
|
1648
|
+
});
|
|
1649
|
+
} catch {
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1573
1652
|
function useTokenHealthCheck(options) {
|
|
1574
|
-
const { enabled, saasApiUrl, onTokenInvalid, onUserUpdated, debug = false } = options;
|
|
1653
|
+
const { enabled, saasApiUrl, iamApiUrl, onTokenInvalid, onUserUpdated, debug = false } = options;
|
|
1575
1654
|
const timerRef = react.useRef(null);
|
|
1576
1655
|
const intervalRef = react.useRef(null);
|
|
1577
1656
|
const enabledRef = react.useRef(enabled);
|
|
@@ -1588,15 +1667,19 @@ function useTokenHealthCheck(options) {
|
|
|
1588
1667
|
try {
|
|
1589
1668
|
const result = await checkTokenValidity(saasApiUrl, token, debug);
|
|
1590
1669
|
if (!result.valid) {
|
|
1670
|
+
if (iamApiUrl) {
|
|
1671
|
+
if (debug) console.log("🔄 [HealthCheck] Revocation IAM avec sanctum_token...");
|
|
1672
|
+
revokeOnIam(iamApiUrl, token, debug);
|
|
1673
|
+
}
|
|
1591
1674
|
callbacksRef.current.onTokenInvalid();
|
|
1592
1675
|
return;
|
|
1593
1676
|
}
|
|
1594
|
-
if (result.
|
|
1595
|
-
callbacksRef.current.onUserUpdated(result.
|
|
1677
|
+
if (result.user && callbacksRef.current.onUserUpdated) {
|
|
1678
|
+
callbacksRef.current.onUserUpdated(result.user);
|
|
1596
1679
|
}
|
|
1597
1680
|
} catch {
|
|
1598
1681
|
}
|
|
1599
|
-
}, [saasApiUrl, debug]);
|
|
1682
|
+
}, [saasApiUrl, iamApiUrl, debug]);
|
|
1600
1683
|
react.useEffect(() => {
|
|
1601
1684
|
if (timerRef.current) {
|
|
1602
1685
|
clearTimeout(timerRef.current);
|
|
@@ -1607,7 +1690,7 @@ function useTokenHealthCheck(options) {
|
|
|
1607
1690
|
intervalRef.current = null;
|
|
1608
1691
|
}
|
|
1609
1692
|
if (!enabled || !saasApiUrl) return;
|
|
1610
|
-
if (debug) console.log("🔄 [HealthCheck] Activé — premier check dans 2 min");
|
|
1693
|
+
if (debug) console.log("🔄 [HealthCheck] Activé — premier check dans 60s, puis toutes les 2 min");
|
|
1611
1694
|
timerRef.current = setTimeout(() => {
|
|
1612
1695
|
performCheck();
|
|
1613
1696
|
intervalRef.current = setInterval(performCheck, INTERVAL_DELAY);
|
|
@@ -1634,6 +1717,9 @@ function saveSession(exchangeResult, accountType) {
|
|
|
1634
1717
|
if (aliasRef) {
|
|
1635
1718
|
localStorage.setItem(STORAGE.ALIAS_REFERENCE, aliasRef);
|
|
1636
1719
|
}
|
|
1720
|
+
if (exchangeResult.app_access_token_ref) {
|
|
1721
|
+
localStorage.setItem(STORAGE.APP_ACCESS_TOKEN_REF, exchangeResult.app_access_token_ref);
|
|
1722
|
+
}
|
|
1637
1723
|
const acctType = typeof accountType === "string" ? accountType : "user";
|
|
1638
1724
|
localStorage.setItem(STORAGE.USER, JSON.stringify(userToStore));
|
|
1639
1725
|
localStorage.setItem(STORAGE.ACCOUNT_TYPE, acctType);
|
|
@@ -1645,6 +1731,7 @@ function clearSession() {
|
|
|
1645
1731
|
localStorage.removeItem(STORAGE.USER);
|
|
1646
1732
|
localStorage.removeItem(STORAGE.ACCOUNT_TYPE);
|
|
1647
1733
|
localStorage.removeItem(STORAGE.ALIAS_REFERENCE);
|
|
1734
|
+
localStorage.removeItem(STORAGE.APP_ACCESS_TOKEN_REF);
|
|
1648
1735
|
}
|
|
1649
1736
|
function getErrorMessage$1(err, context) {
|
|
1650
1737
|
if (err instanceof Error) {
|
|
@@ -1718,6 +1805,7 @@ function useNativeAuth(options) {
|
|
|
1718
1805
|
useTokenHealthCheck({
|
|
1719
1806
|
enabled: state.status === "completed" && state.user !== null,
|
|
1720
1807
|
saasApiUrl,
|
|
1808
|
+
iamApiUrl,
|
|
1721
1809
|
onTokenInvalid: handleTokenInvalid,
|
|
1722
1810
|
onUserUpdated: handleUserUpdated,
|
|
1723
1811
|
debug: isDebug
|
|
@@ -2194,7 +2282,7 @@ function useNativeAuth(options) {
|
|
|
2194
2282
|
processToken: null
|
|
2195
2283
|
}));
|
|
2196
2284
|
}, [defaultAccountType]);
|
|
2197
|
-
const
|
|
2285
|
+
const logout2 = react.useCallback(async () => {
|
|
2198
2286
|
const token = localStorage.getItem(STORAGE.AUTH_TOKEN) || localStorage.getItem(STORAGE.TOKEN);
|
|
2199
2287
|
try {
|
|
2200
2288
|
if (token) {
|
|
@@ -2266,7 +2354,7 @@ function useNativeAuth(options) {
|
|
|
2266
2354
|
grantAccess,
|
|
2267
2355
|
resendOtp,
|
|
2268
2356
|
setSession,
|
|
2269
|
-
logout,
|
|
2357
|
+
logout: logout2,
|
|
2270
2358
|
reset,
|
|
2271
2359
|
clearError,
|
|
2272
2360
|
register,
|
|
@@ -4720,12 +4808,8 @@ function NativeSSOPage({
|
|
|
4720
4808
|
onLoginSuccess == null ? void 0 : onLoginSuccess(pendingSession.token, pendingSession.user);
|
|
4721
4809
|
if (redirectAfterLogin) window.location.href = redirectAfterLogin;
|
|
4722
4810
|
}, [pendingSession, onLoginSuccess, redirectAfterLogin]);
|
|
4723
|
-
const handleLogout = react.useCallback(() => {
|
|
4724
|
-
|
|
4725
|
-
localStorage.removeItem(STORAGE.TOKEN);
|
|
4726
|
-
localStorage.removeItem(STORAGE.USER);
|
|
4727
|
-
localStorage.removeItem(STORAGE.ACCOUNT_TYPE);
|
|
4728
|
-
localStorage.removeItem(STORAGE.ALIAS_REFERENCE);
|
|
4811
|
+
const handleLogout = react.useCallback(async () => {
|
|
4812
|
+
await logout();
|
|
4729
4813
|
setSession(null);
|
|
4730
4814
|
onLogout == null ? void 0 : onLogout();
|
|
4731
4815
|
if (redirectAfterLogout) window.location.href = redirectAfterLogout;
|
|
@@ -4881,6 +4965,26 @@ function useNativeSSOConfig() {
|
|
|
4881
4965
|
}
|
|
4882
4966
|
return ctx;
|
|
4883
4967
|
}
|
|
4968
|
+
const useLogout = (options) => {
|
|
4969
|
+
const [loading, setLoading] = react.useState(false);
|
|
4970
|
+
const [error, setError] = react.useState(null);
|
|
4971
|
+
const handleLogout = react.useCallback(async () => {
|
|
4972
|
+
var _a, _b;
|
|
4973
|
+
setLoading(true);
|
|
4974
|
+
setError(null);
|
|
4975
|
+
try {
|
|
4976
|
+
await logout();
|
|
4977
|
+
(_a = options == null ? void 0 : options.onSuccess) == null ? void 0 : _a.call(options);
|
|
4978
|
+
} catch (err) {
|
|
4979
|
+
const message = err instanceof Error ? err.message : "Erreur de déconnexion";
|
|
4980
|
+
setError(message);
|
|
4981
|
+
(_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, err instanceof Error ? err : new Error(message));
|
|
4982
|
+
} finally {
|
|
4983
|
+
setLoading(false);
|
|
4984
|
+
}
|
|
4985
|
+
}, [options]);
|
|
4986
|
+
return { logout: handleLogout, loading, error };
|
|
4987
|
+
};
|
|
4884
4988
|
function getCredentialsOrThrow(params) {
|
|
4885
4989
|
const app_key = params.app_key;
|
|
4886
4990
|
const secret_key = params.secret_key;
|
|
@@ -5050,10 +5154,12 @@ exports.getCountryByDialCode = getCountryByDialCode;
|
|
|
5050
5154
|
exports.getDefaultCountry = getDefaultCountry;
|
|
5051
5155
|
exports.getNativeAuthConfig = getNativeAuthConfig;
|
|
5052
5156
|
exports.iamAccountService = iamAccountService;
|
|
5157
|
+
exports.logout = logout;
|
|
5053
5158
|
exports.mobilePasswordService = mobilePasswordService;
|
|
5054
5159
|
exports.nativeAuthService = nativeAuthService;
|
|
5055
5160
|
exports.searchCountries = searchCountries;
|
|
5056
5161
|
exports.setNativeAuthConfig = setNativeAuthConfig;
|
|
5162
|
+
exports.useLogout = useLogout;
|
|
5057
5163
|
exports.useMobilePassword = useMobilePassword;
|
|
5058
5164
|
exports.useMobileRegistration = useMobileRegistration;
|
|
5059
5165
|
exports.useNativeAuth = useNativeAuth;
|