@explorins/pers-sdk-react-native 2.1.18 → 2.1.19
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.js +221 -117
- package/dist/index.js.map +1 -1
- package/dist/providers/react-native-auth-provider.d.ts +1 -1
- package/dist/providers/react-native-auth-provider.d.ts.map +1 -1
- package/dist/providers/react-native-auth-provider.js +33 -5
- package/package.json +182 -182
- package/src/providers/react-native-auth-provider.ts +33 -8
package/dist/index.js
CHANGED
|
@@ -9588,7 +9588,113 @@ class AuthTokenManager {
|
|
|
9588
9588
|
const token = await this.getRefreshToken();
|
|
9589
9589
|
return !!token;
|
|
9590
9590
|
}
|
|
9591
|
+
/**
|
|
9592
|
+
* Clears only the refresh token.
|
|
9593
|
+
* Used when DPoP keys are regenerated, invalidating the token binding.
|
|
9594
|
+
*/
|
|
9595
|
+
async clearRefreshToken() {
|
|
9596
|
+
this.cache.refreshToken = null;
|
|
9597
|
+
await this.storage.remove(AUTH_STORAGE_KEYS.REFRESH_TOKEN);
|
|
9598
|
+
}
|
|
9599
|
+
}
|
|
9600
|
+
|
|
9601
|
+
class IndexedDBTokenStorage {
|
|
9602
|
+
constructor() {
|
|
9603
|
+
this.supportsObjects = true;
|
|
9604
|
+
this.dbPromise = null;
|
|
9605
|
+
if (typeof indexedDB === 'undefined') {
|
|
9606
|
+
console.warn('IndexedDB is not available in this environment');
|
|
9607
|
+
}
|
|
9608
|
+
}
|
|
9609
|
+
getDB() {
|
|
9610
|
+
if (this.dbPromise)
|
|
9611
|
+
return this.dbPromise;
|
|
9612
|
+
this.dbPromise = new Promise((resolve, reject) => {
|
|
9613
|
+
if (typeof indexedDB === 'undefined') {
|
|
9614
|
+
return reject(new Error('IndexedDB not supported'));
|
|
9615
|
+
}
|
|
9616
|
+
const request = indexedDB.open(IndexedDBTokenStorage.DB_NAME, IndexedDBTokenStorage.DB_VERSION);
|
|
9617
|
+
request.onupgradeneeded = (event) => {
|
|
9618
|
+
const db = event.target.result;
|
|
9619
|
+
if (!db.objectStoreNames.contains(IndexedDBTokenStorage.STORE_NAME)) {
|
|
9620
|
+
db.createObjectStore(IndexedDBTokenStorage.STORE_NAME);
|
|
9621
|
+
}
|
|
9622
|
+
};
|
|
9623
|
+
request.onsuccess = (event) => {
|
|
9624
|
+
resolve(event.target.result);
|
|
9625
|
+
};
|
|
9626
|
+
request.onerror = (event) => {
|
|
9627
|
+
reject(event.target.error);
|
|
9628
|
+
};
|
|
9629
|
+
});
|
|
9630
|
+
return this.dbPromise;
|
|
9631
|
+
}
|
|
9632
|
+
async get(key) {
|
|
9633
|
+
try {
|
|
9634
|
+
const db = await this.getDB();
|
|
9635
|
+
return new Promise((resolve, reject) => {
|
|
9636
|
+
const transaction = db.transaction(IndexedDBTokenStorage.STORE_NAME, 'readonly');
|
|
9637
|
+
const store = transaction.objectStore(IndexedDBTokenStorage.STORE_NAME);
|
|
9638
|
+
const request = store.get(key);
|
|
9639
|
+
request.onsuccess = () => resolve(request.result || null);
|
|
9640
|
+
request.onerror = () => reject(request.error);
|
|
9641
|
+
});
|
|
9642
|
+
}
|
|
9643
|
+
catch (e) {
|
|
9644
|
+
console.warn('[IndexedDBTokenStorage] Failed to get key', key, e);
|
|
9645
|
+
return null;
|
|
9646
|
+
}
|
|
9647
|
+
}
|
|
9648
|
+
async set(key, value) {
|
|
9649
|
+
try {
|
|
9650
|
+
const db = await this.getDB();
|
|
9651
|
+
return new Promise((resolve, reject) => {
|
|
9652
|
+
const transaction = db.transaction(IndexedDBTokenStorage.STORE_NAME, 'readwrite');
|
|
9653
|
+
const store = transaction.objectStore(IndexedDBTokenStorage.STORE_NAME);
|
|
9654
|
+
const request = store.put(value, key);
|
|
9655
|
+
request.onsuccess = () => resolve();
|
|
9656
|
+
request.onerror = () => reject(request.error);
|
|
9657
|
+
});
|
|
9658
|
+
}
|
|
9659
|
+
catch (e) {
|
|
9660
|
+
console.error('[IndexedDBTokenStorage] Failed to set key', key, e);
|
|
9661
|
+
throw e;
|
|
9662
|
+
}
|
|
9663
|
+
}
|
|
9664
|
+
async remove(key) {
|
|
9665
|
+
try {
|
|
9666
|
+
const db = await this.getDB();
|
|
9667
|
+
return new Promise((resolve, reject) => {
|
|
9668
|
+
const transaction = db.transaction(IndexedDBTokenStorage.STORE_NAME, 'readwrite');
|
|
9669
|
+
const store = transaction.objectStore(IndexedDBTokenStorage.STORE_NAME);
|
|
9670
|
+
const request = store.delete(key);
|
|
9671
|
+
request.onsuccess = () => resolve();
|
|
9672
|
+
request.onerror = () => reject(request.error);
|
|
9673
|
+
});
|
|
9674
|
+
}
|
|
9675
|
+
catch (e) {
|
|
9676
|
+
console.warn('[IndexedDBTokenStorage] Failed to remove key', key, e);
|
|
9677
|
+
}
|
|
9678
|
+
}
|
|
9679
|
+
async clear() {
|
|
9680
|
+
try {
|
|
9681
|
+
const db = await this.getDB();
|
|
9682
|
+
return new Promise((resolve, reject) => {
|
|
9683
|
+
const transaction = db.transaction(IndexedDBTokenStorage.STORE_NAME, 'readwrite');
|
|
9684
|
+
const store = transaction.objectStore(IndexedDBTokenStorage.STORE_NAME);
|
|
9685
|
+
const request = store.clear();
|
|
9686
|
+
request.onsuccess = () => resolve();
|
|
9687
|
+
request.onerror = () => reject(request.error);
|
|
9688
|
+
});
|
|
9689
|
+
}
|
|
9690
|
+
catch (e) {
|
|
9691
|
+
console.warn('[IndexedDBTokenStorage] Failed to clear storage', e);
|
|
9692
|
+
}
|
|
9693
|
+
}
|
|
9591
9694
|
}
|
|
9695
|
+
IndexedDBTokenStorage.DB_NAME = 'pers-sdk-storage';
|
|
9696
|
+
IndexedDBTokenStorage.STORE_NAME = 'auth-tokens';
|
|
9697
|
+
IndexedDBTokenStorage.DB_VERSION = 1;
|
|
9592
9698
|
|
|
9593
9699
|
class WebDPoPCryptoProvider {
|
|
9594
9700
|
get crypto() {
|
|
@@ -9724,13 +9830,30 @@ const DPOP_STORAGE_KEYS = {
|
|
|
9724
9830
|
PRIVATE: 'pers_dpop_private_key'
|
|
9725
9831
|
};
|
|
9726
9832
|
class DPoPManager {
|
|
9727
|
-
constructor(storage, cryptoProvider) {
|
|
9833
|
+
constructor(storage, cryptoProvider, callbacks) {
|
|
9728
9834
|
this.storage = storage;
|
|
9729
9835
|
this.memoryKeyPair = null;
|
|
9730
9836
|
this.cryptoProvider = cryptoProvider || new WebDPoPCryptoProvider();
|
|
9837
|
+
this.callbacks = callbacks || {};
|
|
9838
|
+
}
|
|
9839
|
+
/**
|
|
9840
|
+
* Checks if DPoP keys exist in storage without generating new ones.
|
|
9841
|
+
* Useful for detecting if a key regeneration would be needed.
|
|
9842
|
+
*/
|
|
9843
|
+
async hasStoredKeys() {
|
|
9844
|
+
if (this.memoryKeyPair)
|
|
9845
|
+
return true;
|
|
9846
|
+
const storedPublic = await this.storage.get(DPOP_STORAGE_KEYS.PUBLIC);
|
|
9847
|
+
const storedPrivate = await this.storage.get(DPOP_STORAGE_KEYS.PRIVATE);
|
|
9848
|
+
return !!(storedPublic && storedPrivate);
|
|
9731
9849
|
}
|
|
9732
9850
|
/**
|
|
9733
9851
|
* Ensures a DPoP key pair exists, loading from storage or generating new one.
|
|
9852
|
+
*
|
|
9853
|
+
* IMPORTANT: If keys are regenerated (not loaded from storage), this will
|
|
9854
|
+
* invalidate any refresh tokens bound to the old keys. The onKeysRegenerated
|
|
9855
|
+
* callback should clear the refresh token to prevent "DPoP proof does not
|
|
9856
|
+
* match refresh token binding" errors.
|
|
9734
9857
|
*/
|
|
9735
9858
|
async ensureKeyPair() {
|
|
9736
9859
|
if (this.memoryKeyPair)
|
|
@@ -9746,10 +9869,12 @@ class DPoPManager {
|
|
|
9746
9869
|
return this.memoryKeyPair;
|
|
9747
9870
|
}
|
|
9748
9871
|
catch (e) {
|
|
9749
|
-
console.warn('Corrupted DPoP keys in storage, regenerating.');
|
|
9872
|
+
console.warn('[DPoPManager] Corrupted DPoP keys in storage, regenerating.');
|
|
9750
9873
|
}
|
|
9751
9874
|
}
|
|
9752
9875
|
// Generate new key pair
|
|
9876
|
+
// IMPORTANT: This invalidates any existing refresh tokens bound to the old keys
|
|
9877
|
+
console.info('[DPoPManager] Generating new DPoP key pair');
|
|
9753
9878
|
// Adaptation: If storage supports raw objects (like IndexedDB or Native Keychain),
|
|
9754
9879
|
// we can generate Non-Extractable keys for maximum security.
|
|
9755
9880
|
// If storage is text-only (LocalStorage), we must use Extractable keys to serialize them.
|
|
@@ -9761,6 +9886,15 @@ class DPoPManager {
|
|
|
9761
9886
|
await this.storage.set(DPOP_STORAGE_KEYS.PUBLIC, keyPair.publicKey);
|
|
9762
9887
|
await this.storage.set(DPOP_STORAGE_KEYS.PRIVATE, keyPair.privateKey);
|
|
9763
9888
|
this.memoryKeyPair = keyPair;
|
|
9889
|
+
// Notify that keys were regenerated - refresh tokens bound to old keys are now invalid
|
|
9890
|
+
if (this.callbacks.onKeysRegenerated) {
|
|
9891
|
+
try {
|
|
9892
|
+
this.callbacks.onKeysRegenerated();
|
|
9893
|
+
}
|
|
9894
|
+
catch (e) {
|
|
9895
|
+
console.warn('[DPoPManager] onKeysRegenerated callback failed:', e);
|
|
9896
|
+
}
|
|
9897
|
+
}
|
|
9764
9898
|
return keyPair;
|
|
9765
9899
|
}
|
|
9766
9900
|
/**
|
|
@@ -9814,16 +9948,48 @@ class DefaultAuthProvider {
|
|
|
9814
9948
|
this.config = config;
|
|
9815
9949
|
this.authTypeCache = null;
|
|
9816
9950
|
this.authType = config.authType || exports.AccountOwnerType.USER;
|
|
9951
|
+
// Determine if DPoP can be enabled (requires IndexedDB for key persistence)
|
|
9952
|
+
const canUseDPoP = this.canEnableDPoP();
|
|
9953
|
+
this.dpopEnabled = !!(config.dpop?.enabled && canUseDPoP);
|
|
9954
|
+
if (config.dpop?.enabled && !canUseDPoP) {
|
|
9955
|
+
console.warn('[DefaultAuthProvider] DPoP disabled: IndexedDB not available. CryptoKey persistence requires IndexedDB.');
|
|
9956
|
+
}
|
|
9817
9957
|
const storage = config.storage || this.createStorage();
|
|
9818
9958
|
this.tokenManager = new AuthTokenManager(storage);
|
|
9819
|
-
if (
|
|
9820
|
-
this.dpopManager = new DPoPManager(storage, config.dpop
|
|
9959
|
+
if (this.dpopEnabled) {
|
|
9960
|
+
this.dpopManager = new DPoPManager(storage, config.dpop?.cryptoProvider, {
|
|
9961
|
+
// When DPoP keys are regenerated (corrupted/missing), the refresh token
|
|
9962
|
+
// bound to the old keys becomes invalid. Clear it to prevent
|
|
9963
|
+
// "DPoP proof does not match refresh token binding" errors.
|
|
9964
|
+
onKeysRegenerated: () => {
|
|
9965
|
+
console.info('[DefaultAuthProvider] DPoP keys regenerated, clearing invalid refresh token');
|
|
9966
|
+
this.tokenManager.clearRefreshToken().catch(err => {
|
|
9967
|
+
console.warn('[DefaultAuthProvider] Failed to clear refresh token:', err);
|
|
9968
|
+
});
|
|
9969
|
+
}
|
|
9970
|
+
});
|
|
9821
9971
|
}
|
|
9822
9972
|
}
|
|
9973
|
+
canEnableDPoP() {
|
|
9974
|
+
// DPoP requires IndexedDB for proper CryptoKey persistence
|
|
9975
|
+
// LocalStorage cannot serialize CryptoKey objects correctly
|
|
9976
|
+
return typeof window !== 'undefined' && typeof indexedDB !== 'undefined';
|
|
9977
|
+
}
|
|
9823
9978
|
createStorage() {
|
|
9824
|
-
|
|
9825
|
-
|
|
9826
|
-
|
|
9979
|
+
// Server-side: use memory storage
|
|
9980
|
+
if (typeof window === 'undefined') {
|
|
9981
|
+
return new MemoryTokenStorage();
|
|
9982
|
+
}
|
|
9983
|
+
// Browser with DPoP enabled: use IndexedDB for CryptoKey persistence
|
|
9984
|
+
if (this.dpopEnabled) {
|
|
9985
|
+
return new IndexedDBTokenStorage();
|
|
9986
|
+
}
|
|
9987
|
+
// Browser without DPoP: use LocalStorage
|
|
9988
|
+
if (typeof localStorage !== 'undefined') {
|
|
9989
|
+
return new LocalStorageTokenStorage();
|
|
9990
|
+
}
|
|
9991
|
+
// Fallback
|
|
9992
|
+
return new MemoryTokenStorage();
|
|
9827
9993
|
}
|
|
9828
9994
|
getToken() {
|
|
9829
9995
|
return this.tokenManager.getAccessToken();
|
|
@@ -9905,10 +10071,9 @@ class DefaultAuthProvider {
|
|
|
9905
10071
|
async hasValidToken() {
|
|
9906
10072
|
return this.tokenManager.hasAccessToken();
|
|
9907
10073
|
}
|
|
9908
|
-
async setAuthType(
|
|
9909
|
-
//
|
|
9910
|
-
//
|
|
9911
|
-
// This method exists to satisfy the ExtendedTokenStorageProvider interface
|
|
10074
|
+
async setAuthType(_authType) {
|
|
10075
|
+
// No-op: authType is derived from JWT payload via getAuthType()
|
|
10076
|
+
// @see getAuthType() - reads accountType directly from JWT
|
|
9912
10077
|
}
|
|
9913
10078
|
async getAuthType() {
|
|
9914
10079
|
// Read from JWT instead of separate storage for single source of truth
|
|
@@ -9949,12 +10114,14 @@ class DefaultAuthProvider {
|
|
|
9949
10114
|
* Exported for consumers who need version info.
|
|
9950
10115
|
* Used internally for X-SDK-Version header.
|
|
9951
10116
|
*
|
|
10117
|
+
* Version is injected at build time via @rollup/plugin-replace
|
|
10118
|
+
*
|
|
9952
10119
|
* @module @explorins/pers-sdk/core
|
|
9953
10120
|
*/
|
|
9954
10121
|
/** SDK package name */
|
|
9955
|
-
const SDK_NAME =
|
|
9956
|
-
/** SDK version -
|
|
9957
|
-
const SDK_VERSION =
|
|
10122
|
+
const SDK_NAME = "@explorins/pers-sdk";
|
|
10123
|
+
/** SDK version - injected from package.json at build time */
|
|
10124
|
+
const SDK_VERSION = "2.1.27";
|
|
9958
10125
|
/** Full SDK identifier for headers */
|
|
9959
10126
|
const SDK_USER_AGENT = `${SDK_NAME}/${SDK_VERSION}`;
|
|
9960
10127
|
|
|
@@ -10884,7 +11051,14 @@ class AuthManager {
|
|
|
10884
11051
|
*/
|
|
10885
11052
|
async loginWithRawData(rawUserData) {
|
|
10886
11053
|
const authService = this.apiClient.getAuthService();
|
|
10887
|
-
|
|
11054
|
+
const result = await authService.loginUserWithRawData(rawUserData);
|
|
11055
|
+
this.events?.emitSuccess({
|
|
11056
|
+
domain: 'authentication',
|
|
11057
|
+
type: 'login_success',
|
|
11058
|
+
userMessage: 'Successfully logged in',
|
|
11059
|
+
details: { user: result.user }
|
|
11060
|
+
});
|
|
11061
|
+
return result;
|
|
10888
11062
|
}
|
|
10889
11063
|
/**
|
|
10890
11064
|
* Get current authenticated user
|
|
@@ -18859,104 +19033,6 @@ function createPersSDK(httpClient, config) {
|
|
|
18859
19033
|
return new PersSDK(httpClient, config);
|
|
18860
19034
|
}
|
|
18861
19035
|
|
|
18862
|
-
class IndexedDBTokenStorage {
|
|
18863
|
-
constructor() {
|
|
18864
|
-
this.supportsObjects = true;
|
|
18865
|
-
this.dbPromise = null;
|
|
18866
|
-
if (typeof indexedDB === 'undefined') {
|
|
18867
|
-
console.warn('IndexedDB is not available in this environment');
|
|
18868
|
-
}
|
|
18869
|
-
}
|
|
18870
|
-
getDB() {
|
|
18871
|
-
if (this.dbPromise)
|
|
18872
|
-
return this.dbPromise;
|
|
18873
|
-
this.dbPromise = new Promise((resolve, reject) => {
|
|
18874
|
-
if (typeof indexedDB === 'undefined') {
|
|
18875
|
-
return reject(new Error('IndexedDB not supported'));
|
|
18876
|
-
}
|
|
18877
|
-
const request = indexedDB.open(IndexedDBTokenStorage.DB_NAME, IndexedDBTokenStorage.DB_VERSION);
|
|
18878
|
-
request.onupgradeneeded = (event) => {
|
|
18879
|
-
const db = event.target.result;
|
|
18880
|
-
if (!db.objectStoreNames.contains(IndexedDBTokenStorage.STORE_NAME)) {
|
|
18881
|
-
db.createObjectStore(IndexedDBTokenStorage.STORE_NAME);
|
|
18882
|
-
}
|
|
18883
|
-
};
|
|
18884
|
-
request.onsuccess = (event) => {
|
|
18885
|
-
resolve(event.target.result);
|
|
18886
|
-
};
|
|
18887
|
-
request.onerror = (event) => {
|
|
18888
|
-
reject(event.target.error);
|
|
18889
|
-
};
|
|
18890
|
-
});
|
|
18891
|
-
return this.dbPromise;
|
|
18892
|
-
}
|
|
18893
|
-
async get(key) {
|
|
18894
|
-
try {
|
|
18895
|
-
const db = await this.getDB();
|
|
18896
|
-
return new Promise((resolve, reject) => {
|
|
18897
|
-
const transaction = db.transaction(IndexedDBTokenStorage.STORE_NAME, 'readonly');
|
|
18898
|
-
const store = transaction.objectStore(IndexedDBTokenStorage.STORE_NAME);
|
|
18899
|
-
const request = store.get(key);
|
|
18900
|
-
request.onsuccess = () => resolve(request.result || null);
|
|
18901
|
-
request.onerror = () => reject(request.error);
|
|
18902
|
-
});
|
|
18903
|
-
}
|
|
18904
|
-
catch (e) {
|
|
18905
|
-
console.warn('[IndexedDBTokenStorage] Failed to get key', key, e);
|
|
18906
|
-
return null;
|
|
18907
|
-
}
|
|
18908
|
-
}
|
|
18909
|
-
async set(key, value) {
|
|
18910
|
-
try {
|
|
18911
|
-
const db = await this.getDB();
|
|
18912
|
-
return new Promise((resolve, reject) => {
|
|
18913
|
-
const transaction = db.transaction(IndexedDBTokenStorage.STORE_NAME, 'readwrite');
|
|
18914
|
-
const store = transaction.objectStore(IndexedDBTokenStorage.STORE_NAME);
|
|
18915
|
-
const request = store.put(value, key);
|
|
18916
|
-
request.onsuccess = () => resolve();
|
|
18917
|
-
request.onerror = () => reject(request.error);
|
|
18918
|
-
});
|
|
18919
|
-
}
|
|
18920
|
-
catch (e) {
|
|
18921
|
-
console.error('[IndexedDBTokenStorage] Failed to set key', key, e);
|
|
18922
|
-
throw e;
|
|
18923
|
-
}
|
|
18924
|
-
}
|
|
18925
|
-
async remove(key) {
|
|
18926
|
-
try {
|
|
18927
|
-
const db = await this.getDB();
|
|
18928
|
-
return new Promise((resolve, reject) => {
|
|
18929
|
-
const transaction = db.transaction(IndexedDBTokenStorage.STORE_NAME, 'readwrite');
|
|
18930
|
-
const store = transaction.objectStore(IndexedDBTokenStorage.STORE_NAME);
|
|
18931
|
-
const request = store.delete(key);
|
|
18932
|
-
request.onsuccess = () => resolve();
|
|
18933
|
-
request.onerror = () => reject(request.error);
|
|
18934
|
-
});
|
|
18935
|
-
}
|
|
18936
|
-
catch (e) {
|
|
18937
|
-
console.warn('[IndexedDBTokenStorage] Failed to remove key', key, e);
|
|
18938
|
-
}
|
|
18939
|
-
}
|
|
18940
|
-
async clear() {
|
|
18941
|
-
try {
|
|
18942
|
-
const db = await this.getDB();
|
|
18943
|
-
return new Promise((resolve, reject) => {
|
|
18944
|
-
const transaction = db.transaction(IndexedDBTokenStorage.STORE_NAME, 'readwrite');
|
|
18945
|
-
const store = transaction.objectStore(IndexedDBTokenStorage.STORE_NAME);
|
|
18946
|
-
const request = store.clear();
|
|
18947
|
-
request.onsuccess = () => resolve();
|
|
18948
|
-
request.onerror = () => reject(request.error);
|
|
18949
|
-
});
|
|
18950
|
-
}
|
|
18951
|
-
catch (e) {
|
|
18952
|
-
console.warn('[IndexedDBTokenStorage] Failed to clear storage', e);
|
|
18953
|
-
}
|
|
18954
|
-
}
|
|
18955
|
-
}
|
|
18956
|
-
IndexedDBTokenStorage.DB_NAME = 'pers-sdk-storage';
|
|
18957
|
-
IndexedDBTokenStorage.STORE_NAME = 'auth-tokens';
|
|
18958
|
-
IndexedDBTokenStorage.DB_VERSION = 1;
|
|
18959
|
-
|
|
18960
19036
|
/**
|
|
18961
19037
|
* Environment Detection Utility
|
|
18962
19038
|
* Detects runtime environment for platform-specific behaviors
|
|
@@ -19282,11 +19358,19 @@ class ReactNativeSecureStorage {
|
|
|
19282
19358
|
* React Native Unified Auth Provider
|
|
19283
19359
|
*
|
|
19284
19360
|
* Creates a platform-specific auth provider that automatically selects the appropriate storage:
|
|
19285
|
-
* - Web: Uses
|
|
19361
|
+
* - Web: Uses IndexedDBTokenStorage for DPoP (CryptoKey persistence) or LocalStorage
|
|
19286
19362
|
* - Mobile: Uses AsyncStorage-based storage
|
|
19287
19363
|
*/
|
|
19288
19364
|
// Use React Native's built-in platform detection
|
|
19289
19365
|
const isWebPlatform = reactNative.Platform.OS === 'web';
|
|
19366
|
+
/**
|
|
19367
|
+
* Check if IndexedDB is available (web environments only)
|
|
19368
|
+
* Uses globalThis to avoid TypeScript errors in React Native context
|
|
19369
|
+
*/
|
|
19370
|
+
function hasIndexedDB() {
|
|
19371
|
+
return typeof globalThis !== 'undefined' &&
|
|
19372
|
+
typeof globalThis.indexedDB !== 'undefined';
|
|
19373
|
+
}
|
|
19290
19374
|
/**
|
|
19291
19375
|
* Create a React Native auth provider with platform-appropriate storage
|
|
19292
19376
|
*
|
|
@@ -19304,9 +19388,29 @@ function createReactNativeAuthProvider(projectKey, config = {}) {
|
|
|
19304
19388
|
}
|
|
19305
19389
|
const { keyPrefix = `pers_${projectKey.slice(0, 8)}_`, debug = false, customStorage, authType = exports.AccountOwnerType.USER, dpop } = config;
|
|
19306
19390
|
// Platform-specific storage selection
|
|
19307
|
-
|
|
19308
|
-
|
|
19309
|
-
|
|
19391
|
+
// Web with DPoP: Use IndexedDB for CryptoKey persistence
|
|
19392
|
+
// Web without DPoP or no IndexedDB: Use LocalStorage
|
|
19393
|
+
// Mobile: Use ReactNativeSecureStorage
|
|
19394
|
+
let tokenStorage;
|
|
19395
|
+
if (customStorage) {
|
|
19396
|
+
tokenStorage = customStorage;
|
|
19397
|
+
}
|
|
19398
|
+
else if (isWebPlatform) {
|
|
19399
|
+
// On web, prefer IndexedDB when DPoP is enabled for proper CryptoKey persistence
|
|
19400
|
+
const dpopEnabled = dpop?.enabled ?? true;
|
|
19401
|
+
if (dpopEnabled && hasIndexedDB()) {
|
|
19402
|
+
tokenStorage = new IndexedDBTokenStorage();
|
|
19403
|
+
}
|
|
19404
|
+
else {
|
|
19405
|
+
if (dpopEnabled && !hasIndexedDB()) {
|
|
19406
|
+
console.warn('[ReactNativeAuthProvider] DPoP requested but IndexedDB not available. Falling back to LocalStorage (DPoP will be disabled by DefaultAuthProvider).');
|
|
19407
|
+
}
|
|
19408
|
+
tokenStorage = new LocalStorageTokenStorage();
|
|
19409
|
+
}
|
|
19410
|
+
}
|
|
19411
|
+
else {
|
|
19412
|
+
tokenStorage = new ReactNativeSecureStorage(keyPrefix);
|
|
19413
|
+
}
|
|
19310
19414
|
// Prepare DPoP config ensuring enabled is boolean (default true)
|
|
19311
19415
|
const dpopConfig = dpop ? {
|
|
19312
19416
|
enabled: dpop.enabled ?? true,
|