@ollaid/native-sso 2.7.2 → 2.7.4

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/index.cjs CHANGED
@@ -7108,6 +7108,27 @@ function isRawStorageKey(key) {
7108
7108
  function getLegacyStorageKey(key) {
7109
7109
  return LEGACY_STORAGE_KEYS[key] || null;
7110
7110
  }
7111
+ function normalizeStorageValue(value) {
7112
+ if (typeof value === "string") return value;
7113
+ if (value === null || value === void 0) return "";
7114
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
7115
+ return String(value);
7116
+ }
7117
+ try {
7118
+ const serialized = JSON.stringify(value);
7119
+ return serialized ?? "";
7120
+ } catch {
7121
+ return String(value);
7122
+ }
7123
+ }
7124
+ function safeJSONStringify(value) {
7125
+ try {
7126
+ const serialized = JSON.stringify(value);
7127
+ return serialized ?? "null";
7128
+ } catch {
7129
+ return "null";
7130
+ }
7131
+ }
7111
7132
  function migrateLegacyValue(base, key, legacyKey, rawValue) {
7112
7133
  base.setItem(key, encryptStorageValue(rawValue));
7113
7134
  base.removeItem(legacyKey);
@@ -7116,31 +7137,44 @@ function migrateLegacyValue(base, key, legacyKey, rawValue) {
7116
7137
  function getStorageEncryptionSecret() {
7117
7138
  var _a;
7118
7139
  const storage = rawStorageAdapter;
7119
- let seed = storage.getItem("native_sso_storage_seed");
7140
+ let seed = storage.getItem(STORAGE_SEED_KEY);
7120
7141
  if (!seed) {
7121
7142
  seed = `seed_${Date.now()}_${Math.random().toString(36).substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
7122
- storage.setItem("native_sso_storage_seed", seed);
7143
+ storage.setItem(STORAGE_SEED_KEY, seed);
7123
7144
  }
7124
7145
  const origin = typeof window !== "undefined" && ((_a = window.location) == null ? void 0 : _a.origin) ? window.location.origin : "unknown-origin";
7125
7146
  const prefix = config.configPrefix || "iam";
7126
7147
  return `${STORAGE_ENCRYPTION_SECRET_PREFIX}::${origin}::${prefix}::${seed}`;
7127
7148
  }
7128
7149
  function encryptStorageValue(value) {
7129
- const secret = getStorageEncryptionSecret();
7130
- const ciphertext = cryptoJsExports.AES.encrypt(value, secret).toString();
7131
- return `${STORAGE_ENCRYPTION_PREFIX}${ciphertext}`;
7150
+ const normalizedValue = normalizeStorageValue(value);
7151
+ try {
7152
+ const secret = getStorageEncryptionSecret();
7153
+ const ciphertext = cryptoJsExports.AES.encrypt(normalizedValue, secret).toString();
7154
+ return `${STORAGE_ENCRYPTION_PREFIX}${ciphertext}`;
7155
+ } catch (error) {
7156
+ if (isDebugMode()) {
7157
+ console.warn("⚠️ [native-sso] Encryption storage fallback to plain value", error);
7158
+ }
7159
+ return normalizedValue;
7160
+ }
7132
7161
  }
7133
7162
  function decryptStorageValue(value) {
7134
- if (!value.startsWith(STORAGE_ENCRYPTION_PREFIX)) {
7135
- return value;
7163
+ const normalizedValue = normalizeStorageValue(value);
7164
+ if (!normalizedValue.startsWith(STORAGE_ENCRYPTION_PREFIX)) {
7165
+ return normalizedValue;
7136
7166
  }
7137
- const secret = getStorageEncryptionSecret();
7138
- const ciphertext = value.slice(STORAGE_ENCRYPTION_PREFIX.length);
7167
+ const ciphertext = normalizedValue.slice(STORAGE_ENCRYPTION_PREFIX.length);
7168
+ if (!ciphertext) return null;
7139
7169
  try {
7170
+ const secret = getStorageEncryptionSecret();
7140
7171
  const bytes = cryptoJsExports.AES.decrypt(ciphertext, secret);
7141
7172
  const plaintext = bytes.toString(cryptoJsExports.enc.Utf8);
7142
7173
  return plaintext || null;
7143
- } catch {
7174
+ } catch (error) {
7175
+ if (isDebugMode()) {
7176
+ console.warn("⚠️ [native-sso] Failed to decrypt storage value, clearing corrupted entry", error);
7177
+ }
7144
7178
  return null;
7145
7179
  }
7146
7180
  }
@@ -7156,8 +7190,9 @@ function createEncryptedStorageAdapter(base) {
7156
7190
  if (decrypted !== null) {
7157
7191
  return decrypted;
7158
7192
  }
7159
- if (rawValue.length > 0) {
7160
- base.setItem(key, encryptStorageValue(rawValue));
7193
+ if (normalizeStorageValue(rawValue).startsWith(STORAGE_ENCRYPTION_PREFIX)) {
7194
+ base.removeItem(key);
7195
+ return null;
7161
7196
  }
7162
7197
  return rawValue;
7163
7198
  }
@@ -7178,7 +7213,7 @@ function createEncryptedStorageAdapter(base) {
7178
7213
  },
7179
7214
  setItem: (key, value) => {
7180
7215
  if (isRawStorageKey(key)) {
7181
- base.setItem(key, value);
7216
+ base.setItem(key, normalizeStorageValue(value));
7182
7217
  return;
7183
7218
  }
7184
7219
  base.setItem(key, encryptStorageValue(value));
@@ -7230,6 +7265,7 @@ const getIamApiBaseUrl = () => {
7230
7265
  };
7231
7266
  const DEVICE_ID_KEY = "sso_device_id";
7232
7267
  const SESSION_UUID_KEY = "sso_session_uuid";
7268
+ const STORAGE_SEED_KEY = "native_sso_storage_seed";
7233
7269
  function generateUuid() {
7234
7270
  const globalCrypto = typeof globalThis !== "undefined" ? globalThis.crypto : void 0;
7235
7271
  if (globalCrypto && typeof globalCrypto.randomUUID === "function") {
@@ -7337,8 +7373,26 @@ const PROFILE_STORAGE = {
7337
7373
  IMAGE_LAST_CHECK: "sso_image_last_check",
7338
7374
  IMAGE_RECHECK_AT: "sso_image_recheck_at"
7339
7375
  };
7376
+ const ALL_SESSION_STORAGE_KEYS = [
7377
+ STORAGE.AUTH_TOKEN,
7378
+ STORAGE.TOKEN,
7379
+ STORAGE.USER,
7380
+ STORAGE.ACCOUNT_TYPE,
7381
+ STORAGE.ALIAS_REFERENCE,
7382
+ STORAGE.APP_ACCESS_TOKEN_REF,
7383
+ STORAGE.REFRESH_TOKEN,
7384
+ STORAGE.TOKEN_EXPIRES_AT,
7385
+ STORAGE.REFRESH_EXPIRES_AT,
7386
+ PROFILE_STORAGE.IMAGE_LAST_STATUS,
7387
+ PROFILE_STORAGE.IMAGE_LAST_CHECK,
7388
+ PROFILE_STORAGE.IMAGE_RECHECK_AT,
7389
+ DEVICE_ID_KEY,
7390
+ SESSION_UUID_KEY,
7391
+ STORAGE_SEED_KEY
7392
+ ];
7340
7393
  const setAuthToken = (token) => {
7341
7394
  const storage = getNativeStorage();
7395
+ if (typeof token !== "string" || token.length === 0) return;
7342
7396
  storage.setItem(STORAGE.AUTH_TOKEN, token);
7343
7397
  };
7344
7398
  const getAuthToken = () => {
@@ -7347,15 +7401,68 @@ const getAuthToken = () => {
7347
7401
  };
7348
7402
  const clearAuthToken = () => {
7349
7403
  const storage = getNativeStorage();
7350
- storage.removeItem(STORAGE.AUTH_TOKEN);
7351
- storage.removeItem(STORAGE.TOKEN);
7352
- storage.removeItem(STORAGE.USER);
7353
- storage.removeItem(STORAGE.ACCOUNT_TYPE);
7354
- storage.removeItem(STORAGE.ALIAS_REFERENCE);
7355
- storage.removeItem(STORAGE.APP_ACCESS_TOKEN_REF);
7356
- storage.removeItem(STORAGE.REFRESH_TOKEN);
7357
- storage.removeItem(STORAGE.TOKEN_EXPIRES_AT);
7358
- storage.removeItem(STORAGE.REFRESH_EXPIRES_AT);
7404
+ [
7405
+ STORAGE.AUTH_TOKEN,
7406
+ STORAGE.TOKEN,
7407
+ STORAGE.USER,
7408
+ STORAGE.ACCOUNT_TYPE,
7409
+ STORAGE.ALIAS_REFERENCE,
7410
+ STORAGE.APP_ACCESS_TOKEN_REF,
7411
+ STORAGE.REFRESH_TOKEN,
7412
+ STORAGE.TOKEN_EXPIRES_AT,
7413
+ STORAGE.REFRESH_EXPIRES_AT
7414
+ ].forEach((key) => {
7415
+ try {
7416
+ storage.removeItem(key);
7417
+ } catch {
7418
+ }
7419
+ });
7420
+ };
7421
+ const clearNativeSsoStorage = (options) => {
7422
+ const storage = getNativeStorage();
7423
+ const preserveDeviceIdentity = (options == null ? void 0 : options.preserveDeviceIdentity) === true;
7424
+ ALL_SESSION_STORAGE_KEYS.forEach((key) => {
7425
+ if (preserveDeviceIdentity && (key === DEVICE_ID_KEY || key === SESSION_UUID_KEY || key === STORAGE_SEED_KEY)) {
7426
+ return;
7427
+ }
7428
+ try {
7429
+ storage.removeItem(key);
7430
+ } catch {
7431
+ }
7432
+ });
7433
+ };
7434
+ const repairNativeSsoStorage = () => {
7435
+ try {
7436
+ const storage = getNativeStorage();
7437
+ const authToken = getAuthToken();
7438
+ const userRaw = storage.getItem(STORAGE.USER);
7439
+ if (userRaw && !authToken) {
7440
+ clearNativeSsoStorage();
7441
+ return { cleaned: true, reason: "incomplete_session" };
7442
+ }
7443
+ if (authToken && !userRaw) {
7444
+ clearNativeSsoStorage();
7445
+ return { cleaned: true, reason: "incomplete_session" };
7446
+ }
7447
+ if (userRaw) {
7448
+ try {
7449
+ JSON.parse(userRaw);
7450
+ } catch {
7451
+ clearNativeSsoStorage();
7452
+ return { cleaned: true, reason: "invalid_user_json" };
7453
+ }
7454
+ }
7455
+ return { cleaned: false, reason: null };
7456
+ } catch (error) {
7457
+ if (isDebugMode()) {
7458
+ console.warn("⚠️ [native-sso] Storage repair failed, forcing cleanup", error);
7459
+ }
7460
+ try {
7461
+ clearNativeSsoStorage();
7462
+ } catch {
7463
+ }
7464
+ return { cleaned: true, reason: "incomplete_session" };
7465
+ }
7359
7466
  };
7360
7467
  const logout = async () => {
7361
7468
  const { nativeAuthService: nativeAuthService2 } = await Promise.resolve().then(() => nativeAuth);
@@ -7363,7 +7470,7 @@ const logout = async () => {
7363
7470
  return nativeAuthService2.logout(token || void 0);
7364
7471
  };
7365
7472
  const setAuthUser = (user) => {
7366
- getNativeStorage().setItem(STORAGE.USER, JSON.stringify(user));
7473
+ getNativeStorage().setItem(STORAGE.USER, safeJSONStringify(user));
7367
7474
  };
7368
7475
  const getAuthUser = () => {
7369
7476
  const user = getNativeStorage().getItem(STORAGE.USER);
@@ -8189,6 +8296,12 @@ function getErrorMessage$2(err, context) {
8189
8296
  function useMobilePassword(options) {
8190
8297
  const { saasApiUrl, iamApiUrl, autoLoadCredentials = true } = options;
8191
8298
  const configuredRef = react.useRef(false);
8299
+ react.useEffect(() => {
8300
+ const repairResult = repairNativeSsoStorage();
8301
+ if (repairResult.cleaned && isDebugMode()) {
8302
+ console.warn("🔧 [useMobilePassword] Storage SSO réparé", repairResult.reason);
8303
+ }
8304
+ }, []);
8192
8305
  react.useEffect(() => {
8193
8306
  if (!configuredRef.current) {
8194
8307
  setNativeAuthConfig({ saasApiUrl, iamApiUrl });
@@ -8834,6 +8947,12 @@ function useNativeAuth(options) {
8834
8947
  setNativeStorage(storage);
8835
8948
  }
8836
8949
  const configuredRef = react.useRef(false);
8950
+ react.useEffect(() => {
8951
+ const repairResult = repairNativeSsoStorage();
8952
+ if (repairResult.cleaned && isDebugMode()) {
8953
+ console.warn("🔧 [useNativeAuth] Storage SSO réparé", repairResult.reason);
8954
+ }
8955
+ }, []);
8837
8956
  const [isDebug, setIsDebug] = react.useState(isDebugMode());
8838
8957
  react.useEffect(() => {
8839
8958
  if (!configuredRef.current) {
@@ -13288,6 +13407,16 @@ function NativeSSOPage({
13288
13407
  react.useEffect(() => {
13289
13408
  sessionRef.current = session;
13290
13409
  }, [session]);
13410
+ react.useEffect(() => {
13411
+ const repairResult = repairNativeSsoStorage();
13412
+ if (repairResult.cleaned) {
13413
+ setSession(null);
13414
+ const isDev = Boolean(false);
13415
+ if (isDev) {
13416
+ console.warn("🔧 [NativeSSOPage] Storage SSO réparé", repairResult.reason);
13417
+ }
13418
+ }
13419
+ }, []);
13291
13420
  react.useEffect(() => {
13292
13421
  if (!redirectingTarget) return;
13293
13422
  const timer = window.setTimeout(() => {
@@ -14035,6 +14164,7 @@ exports.PhoneInput = PhoneInput;
14035
14164
  exports.STORAGE_KEYS = STORAGE;
14036
14165
  exports.SignupModal = SignupModal;
14037
14166
  exports.clearAuthToken = clearAuthToken;
14167
+ exports.clearNativeSsoStorage = clearNativeSsoStorage;
14038
14168
  exports.getAccountType = getAccountType;
14039
14169
  exports.getAuthToken = getAuthToken;
14040
14170
  exports.getAuthUser = getAuthUser;
@@ -14055,6 +14185,7 @@ exports.mobilePasswordService = mobilePasswordService;
14055
14185
  exports.nativeAuthService = nativeAuthService;
14056
14186
  exports.profileChangeService = profileChangeService;
14057
14187
  exports.profileMediaService = profileMediaService;
14188
+ exports.repairNativeSsoStorage = repairNativeSsoStorage;
14058
14189
  exports.searchCountries = searchCountries;
14059
14190
  exports.setNativeAuthConfig = setNativeAuthConfig;
14060
14191
  exports.setNativeStorage = setNativeStorage;