Web still uses localStorage; Capacitor native app now routes token/user/session-id through capacitor-secure-storage-plugin (iOS Keychain, Android EncryptedSharedPreferences / Keystore). A thin SecureStorage wrapper detects Capacitor at runtime and falls back to localStorage elsewhere, keeping a single auth.js codebase for both targets. To activate on mobile: cd mobile && npm install && npx cap sync android
73 lines
2.5 KiB
JavaScript
73 lines
2.5 KiB
JavaScript
// ============================================================
|
|
// SECURE STORAGE WRAPPER
|
|
// Browser: localStorage
|
|
// Capacitor mobile: iOS Keychain / Android EncryptedSharedPreferences
|
|
// via capacitor-secure-storage-plugin
|
|
// ============================================================
|
|
(function() {
|
|
var memCache = {};
|
|
|
|
function isNative() {
|
|
try {
|
|
return !!(window.Capacitor && typeof window.Capacitor.isNativePlatform === 'function' && window.Capacitor.isNativePlatform());
|
|
} catch(e) { return false; }
|
|
}
|
|
|
|
function plugin() {
|
|
try {
|
|
var p = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.SecureStoragePlugin;
|
|
return p || null;
|
|
} catch(e) { return null; }
|
|
}
|
|
|
|
window.SecureStorage = {
|
|
isNative: isNative,
|
|
|
|
get: function(key) {
|
|
if (isNative() && plugin()) {
|
|
return plugin().get({ key: key })
|
|
.then(function(r) { memCache[key] = r.value; return r.value; })
|
|
.catch(function() { return null; });
|
|
}
|
|
try { return Promise.resolve(localStorage.getItem(key)); } catch(e) { return Promise.resolve(null); }
|
|
},
|
|
|
|
set: function(key, value) {
|
|
memCache[key] = value;
|
|
if (isNative() && plugin()) {
|
|
return plugin().set({ key: key, value: value }).catch(function() {});
|
|
}
|
|
try { localStorage.setItem(key, value); } catch(e) {}
|
|
return Promise.resolve();
|
|
},
|
|
|
|
remove: function(key) {
|
|
delete memCache[key];
|
|
if (isNative() && plugin()) {
|
|
var p = plugin().remove({ key: key }).catch(function() {});
|
|
// Also clear legacy localStorage copy if any
|
|
try { localStorage.removeItem(key); } catch(e) {}
|
|
return p;
|
|
}
|
|
try { localStorage.removeItem(key); } catch(e) {}
|
|
return Promise.resolve();
|
|
},
|
|
|
|
// Synchronous read for hot paths (fetch headers). On native returns cached
|
|
// value populated by prior get/set. On web reads localStorage directly.
|
|
getSync: function(key) {
|
|
if (isNative()) return memCache[key] || null;
|
|
try { return localStorage.getItem(key); } catch(e) { return null; }
|
|
},
|
|
|
|
// Hydrate the memory cache from native storage at boot. Resolves when ready.
|
|
hydrate: function(keys) {
|
|
if (!isNative() || !plugin()) return Promise.resolve();
|
|
return Promise.all(keys.map(function(k) {
|
|
return plugin().get({ key: k })
|
|
.then(function(r) { memCache[k] = r.value; })
|
|
.catch(function() { memCache[k] = null; });
|
|
}));
|
|
}
|
|
};
|
|
})();
|