@onairos/react-native 3.1.16 → 3.1.18
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 +404 -0
- package/lib/commonjs/assets/images/Checkbox.svg +3 -3
- package/lib/commonjs/assets/images/EnochE.svg +19 -19
- package/lib/commonjs/assets/images/Personalityprofile.svg +3 -3
- package/lib/commonjs/assets/images/Personalitytraits.svg +3 -3
- package/lib/commonjs/assets/images/Userpreferences.svg +3 -3
- package/lib/commonjs/assets/images/arrow.svg +20 -20
- package/lib/commonjs/assets/images/basicproficon.svg +43 -43
- package/lib/commonjs/assets/images/basicprofile.svg +3 -3
- package/lib/commonjs/assets/images/checkmark.svg +4 -4
- package/lib/commonjs/assets/images/contentanalysis.svg +3 -3
- package/lib/commonjs/assets/images/contenticon.svg +23 -23
- package/lib/commonjs/assets/images/personalityicon.svg +18 -18
- package/lib/commonjs/assets/images/x-close.svg +3 -3
- package/lib/commonjs/components/ModalSheet.js +8 -2
- package/lib/commonjs/components/ModalSheet.js.map +1 -1
- package/lib/commonjs/components/OnairosButton.js +290 -0
- package/lib/commonjs/components/OnairosButton.js.map +1 -0
- package/lib/commonjs/components/OnairosSignInButton.js +32 -8
- package/lib/commonjs/components/OnairosSignInButton.js.map +1 -1
- package/lib/commonjs/components/UniversalOnboarding.js +4 -4
- package/lib/commonjs/components/WelcomeScreen.js +29 -13
- package/lib/commonjs/components/WelcomeScreen.js.map +1 -1
- package/lib/commonjs/config/api.js +2 -2
- package/lib/commonjs/hooks/useConnections.js +6 -6
- package/lib/commonjs/hooks/useUserConnections.js +10 -10
- package/lib/commonjs/index.js +13 -6
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/services/apiClient.js +35 -35
- package/lib/commonjs/services/apiKeyService.js +99 -99
- package/lib/commonjs/services/authService.js +82 -82
- package/lib/commonjs/services/biometricPinService.js +10 -10
- package/lib/commonjs/services/connectedAccountsService.js +32 -32
- package/lib/commonjs/services/googleAuthService.js +15 -15
- package/lib/commonjs/services/imageCompressionService.js +15 -15
- package/lib/commonjs/services/jwtStorageService.js +59 -59
- package/lib/commonjs/services/mobileTrainingService.js +14 -14
- package/lib/commonjs/services/pinEncryptionService.js +10 -10
- package/lib/commonjs/services/pinStorageUtils.js +15 -15
- package/lib/commonjs/services/platformAuthService.js +47 -47
- package/lib/commonjs/services/storageService.js +31 -31
- package/lib/commonjs/services/trainingApiHelpers.js +33 -33
- package/lib/commonjs/services/userConnectionsService.js +24 -24
- package/lib/commonjs/utils/Portal.js +4 -4
- package/lib/commonjs/utils/api.js +24 -24
- package/lib/commonjs/utils/auth.js +18 -18
- package/lib/commonjs/utils/crypto.js +13 -13
- package/lib/commonjs/utils/encryption.js +12 -12
- package/lib/commonjs/utils/eventUtils.js +52 -52
- package/lib/commonjs/utils/programmaticFlow.js +16 -16
- package/lib/commonjs/utils/retryHelper.js +27 -27
- package/lib/module/assets/images/Checkbox.svg +3 -3
- package/lib/module/assets/images/EnochE.svg +19 -19
- package/lib/module/assets/images/Personalityprofile.svg +3 -3
- package/lib/module/assets/images/Personalitytraits.svg +3 -3
- package/lib/module/assets/images/Userpreferences.svg +3 -3
- package/lib/module/assets/images/arrow.svg +20 -20
- package/lib/module/assets/images/basicproficon.svg +43 -43
- package/lib/module/assets/images/basicprofile.svg +3 -3
- package/lib/module/assets/images/checkmark.svg +4 -4
- package/lib/module/assets/images/contentanalysis.svg +3 -3
- package/lib/module/assets/images/contenticon.svg +23 -23
- package/lib/module/assets/images/personalityicon.svg +18 -18
- package/lib/module/assets/images/x-close.svg +3 -3
- package/lib/module/components/ModalSheet.js +7 -2
- package/lib/module/components/ModalSheet.js.map +1 -1
- package/lib/module/components/OnairosButton.js +282 -0
- package/lib/module/components/OnairosButton.js.map +1 -0
- package/lib/module/components/OnairosSignInButton.js +32 -8
- package/lib/module/components/OnairosSignInButton.js.map +1 -1
- package/lib/module/components/UniversalOnboarding.js +4 -4
- package/lib/module/components/WelcomeScreen.js +25 -10
- package/lib/module/components/WelcomeScreen.js.map +1 -1
- package/lib/module/config/api.js +2 -2
- package/lib/module/hooks/useConnections.js +6 -6
- package/lib/module/hooks/useUserConnections.js +10 -10
- package/lib/module/index.js +11 -11
- package/lib/module/index.js.map +1 -1
- package/lib/module/services/apiClient.js +35 -35
- package/lib/module/services/apiKeyService.js +99 -99
- package/lib/module/services/authService.js +82 -82
- package/lib/module/services/biometricPinService.js +10 -10
- package/lib/module/services/connectedAccountsService.js +32 -32
- package/lib/module/services/googleAuthService.js +15 -15
- package/lib/module/services/imageCompressionService.js +15 -15
- package/lib/module/services/jwtStorageService.js +59 -59
- package/lib/module/services/mobileTrainingService.js +14 -14
- package/lib/module/services/pinEncryptionService.js +10 -10
- package/lib/module/services/pinStorageUtils.js +15 -15
- package/lib/module/services/platformAuthService.js +47 -47
- package/lib/module/services/storageService.js +31 -31
- package/lib/module/services/trainingApiHelpers.js +33 -33
- package/lib/module/services/userConnectionsService.js +24 -24
- package/lib/module/utils/Portal.js +4 -4
- package/lib/module/utils/api.js +24 -24
- package/lib/module/utils/auth.js +18 -18
- package/lib/module/utils/crypto.js +13 -13
- package/lib/module/utils/encryption.js +12 -12
- package/lib/module/utils/eventUtils.js +52 -52
- package/lib/module/utils/programmaticFlow.js +16 -16
- package/lib/module/utils/retryHelper.js +27 -27
- package/lib/typescript/components/ModalSheet.d.ts.map +1 -1
- package/lib/typescript/components/OnairosButton.d.ts +37 -0
- package/lib/typescript/components/OnairosButton.d.ts.map +1 -0
- package/lib/typescript/components/OnairosSignInButton.d.ts.map +1 -1
- package/lib/typescript/components/WelcomeScreen.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +3 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/package.json +145 -163
- package/src/api/index.ts +151 -151
- package/src/assets/images/Checkbox.svg +3 -3
- package/src/assets/images/EnochE.svg +19 -19
- package/src/assets/images/Personalityprofile.svg +3 -3
- package/src/assets/images/Personalitytraits.svg +3 -3
- package/src/assets/images/Userpreferences.svg +3 -3
- package/src/assets/images/arrow.svg +20 -20
- package/src/assets/images/basicproficon.svg +43 -43
- package/src/assets/images/basicprofile.svg +3 -3
- package/src/assets/images/checkmark.svg +4 -4
- package/src/assets/images/contentanalysis.svg +3 -3
- package/src/assets/images/contenticon.svg +23 -23
- package/src/assets/images/personalityicon.svg +18 -18
- package/src/assets/images/x-close.svg +3 -3
- package/src/components/BodyText.tsx +33 -33
- package/src/components/BrandMark.tsx +62 -62
- package/src/components/CodeInput.tsx +32 -32
- package/src/components/DataRequestScreen.tsx +355 -355
- package/src/components/EmailInput.tsx +31 -31
- package/src/components/EmailVerificationModal.tsx +363 -363
- package/src/components/ExistingUserDataConfirmation.tsx +506 -506
- package/src/components/GoogleButton.tsx +55 -55
- package/src/components/HeadingGroup.tsx +49 -49
- package/src/components/ModalHeader.tsx +125 -125
- package/src/components/ModalSheet.tsx +59 -57
- package/src/components/Onairos.tsx +422 -422
- package/src/components/OnairosButton.tsx +339 -0
- package/src/components/OnairosSignInButton.tsx +31 -9
- package/src/components/Overlay.tsx +506 -506
- package/src/components/PersonaImage.tsx +79 -79
- package/src/components/PersonaLoadingScreen.tsx +201 -201
- package/src/components/PersonalizationConsentScreen.tsx +410 -410
- package/src/components/PinCreationScreen.tsx +492 -492
- package/src/components/PinInput.tsx +555 -555
- package/src/components/PlatformConnectorsStep.tsx +891 -891
- package/src/components/PlatformList.tsx +144 -144
- package/src/components/PlatformToggle.tsx +226 -226
- package/src/components/PrimaryButton.tsx +213 -213
- package/src/components/SignInMatchAnimation.tsx +225 -225
- package/src/components/SignInStep.tsx +217 -217
- package/src/components/TrainingModal.tsx +1047 -1047
- package/src/components/UniversalOnboarding.tsx +2887 -2887
- package/src/components/VerificationStep.tsx +198 -198
- package/src/components/WelcomeScreen.tsx +490 -473
- package/src/components/icons/Basicproficon.tsx +30 -30
- package/src/components/icons/Basicprofile.tsx +17 -17
- package/src/components/icons/Checkbox.tsx +17 -17
- package/src/components/icons/Checkmark.tsx +24 -24
- package/src/components/icons/Contentanalysis.tsx +17 -17
- package/src/components/icons/Contenticon.tsx +30 -30
- package/src/components/icons/EnochE.tsx +39 -39
- package/src/components/icons/Personalityicon.tsx +22 -22
- package/src/components/icons/Personalityprofile.tsx +17 -17
- package/src/components/icons/Personalitytraits.tsx +17 -17
- package/src/components/icons/Userpreferences.tsx +17 -17
- package/src/components/icons/index.ts +12 -12
- package/src/components/onboarding/OAuthWebView.tsx +232 -232
- package/src/config/api.ts +25 -25
- package/src/context/AuthContext.tsx +393 -393
- package/src/hooks/useConnectedAccounts.ts +138 -138
- package/src/hooks/useConnections.ts +161 -161
- package/src/hooks/useCredentials.ts +174 -174
- package/src/hooks/useUserConnections.ts +165 -165
- package/src/index.js +14 -0
- package/src/index.ts +99 -96
- package/src/services/apiClient.ts +336 -336
- package/src/services/apiKeyService.ts +919 -919
- package/src/services/authService.ts +1008 -1008
- package/src/services/biometricPinService.ts +192 -192
- package/src/services/connectedAccountsService.ts +289 -289
- package/src/services/googleAuthService.ts +279 -279
- package/src/services/imageCompressionService.ts +302 -302
- package/src/services/jwtStorageService.ts +256 -256
- package/src/services/mobileTrainingService.ts +203 -203
- package/src/services/pinEncryptionService.ts +75 -75
- package/src/services/pinStorageUtils.ts +96 -96
- package/src/services/platformAuthService.ts +1346 -1346
- package/src/services/storageService.ts +451 -451
- package/src/services/trainingApiHelpers.ts +66 -66
- package/src/services/userConnectionsService.ts +556 -556
- package/src/services/youtubeMigrationService.ts +453 -453
- package/src/theme/index.ts +239 -239
- package/src/types/ambient.d.ts +28 -28
- package/src/types/index.ts +265 -265
- package/src/types/node-fix.d.ts +18 -18
- package/src/types/node-override.d.ts +23 -23
- package/src/types/opacity.d.ts +15 -15
- package/src/types/types.d.ts +17 -17
- package/src/utils/Portal.tsx +82 -82
- package/src/utils/api.js +111 -111
- package/src/utils/auth.js +103 -103
- package/src/utils/crypto.js +59 -59
- package/src/utils/encryption.ts +68 -68
- package/src/utils/eventUtils.ts +302 -302
- package/src/utils/haptics.ts +58 -58
- package/src/utils/imagePreloader.ts +2 -2
- package/src/utils/programmaticFlow.ts +112 -112
- package/src/utils/retryHelper.ts +274 -274
|
@@ -1,257 +1,257 @@
|
|
|
1
|
-
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
2
|
-
import { Buffer } from 'buffer';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* JWT Token Storage Service - CORRECTED APPROACH
|
|
6
|
-
* Manages 3 DISTINCT JWT token types for different route families
|
|
7
|
-
*
|
|
8
|
-
* TOKEN TYPES:
|
|
9
|
-
* 1. Enoch JWT (enoch_token) - For /enoch/*, /api/auth/*, /mobile-training/enoch
|
|
10
|
-
* 2. Onairos JWT (onairos_jwt_token) - For /youtube/*, /gmail/*, social connections
|
|
11
|
-
* 3. Auth Token (auth_token) - For context-specific auth flows
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
export enum TokenType {
|
|
15
|
-
ENOCH = 'enoch_token',
|
|
16
|
-
ONAIROS = 'onairos_jwt_token',
|
|
17
|
-
AUTH = 'auth_token'
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Route-based token mapping
|
|
22
|
-
* Determines which token type to use for which routes
|
|
23
|
-
*/
|
|
24
|
-
export const getTokenTypeForRoute = (route: string): TokenType => {
|
|
25
|
-
const cleanRoute = route.toLowerCase();
|
|
26
|
-
|
|
27
|
-
// Enoch routes - use Enoch JWT
|
|
28
|
-
if (cleanRoute.includes('/enoch/') ||
|
|
29
|
-
cleanRoute.includes('/api/auth/') ||
|
|
30
|
-
cleanRoute.includes('/mobile-training/enoch')) {
|
|
31
|
-
return TokenType.ENOCH;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Onairos routes - use Onairos JWT
|
|
35
|
-
if (cleanRoute.includes('/youtube/') ||
|
|
36
|
-
cleanRoute.includes('/gmail/') ||
|
|
37
|
-
cleanRoute.includes('/connectedaccounts') ||
|
|
38
|
-
cleanRoute.includes('/social/')) {
|
|
39
|
-
return TokenType.ONAIROS;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Default to auth token for other routes
|
|
43
|
-
return TokenType.AUTH;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Store JWT token of specific type
|
|
48
|
-
* @param tokenType - Type of token to store
|
|
49
|
-
* @param token - JWT token to store
|
|
50
|
-
* @returns Promise<boolean> - Success status
|
|
51
|
-
*/
|
|
52
|
-
export const storeJWT = async (tokenType: TokenType, token: string): Promise<boolean> => {
|
|
53
|
-
try {
|
|
54
|
-
if (!token || token.trim() === '') {
|
|
55
|
-
console.warn(`⚠️ [JWT Storage] Attempted to store empty/null ${tokenType} token`);
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Validate JWT format (should have 3 parts separated by dots)
|
|
60
|
-
const parts = token.split('.');
|
|
61
|
-
if (parts.length !== 3) {
|
|
62
|
-
console.warn(`⚠️ [JWT Storage] Invalid JWT format for ${tokenType} - token should have 3 parts`);
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
await AsyncStorage.setItem(tokenType, token);
|
|
67
|
-
console.log(`✅ [JWT Storage] ${tokenType} token stored successfully`);
|
|
68
|
-
return true;
|
|
69
|
-
} catch (error) {
|
|
70
|
-
console.error(`❌ [JWT Storage] Failed to store ${tokenType} token:`, error);
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Retrieve JWT token of specific type
|
|
77
|
-
* @param tokenType - Type of token to retrieve
|
|
78
|
-
* @returns Promise<string | null> - JWT token or null if not found
|
|
79
|
-
*/
|
|
80
|
-
export const getJWT = async (tokenType: TokenType): Promise<string | null> => {
|
|
81
|
-
try {
|
|
82
|
-
const token = await AsyncStorage.getItem(tokenType);
|
|
83
|
-
|
|
84
|
-
if (!token) {
|
|
85
|
-
console.log(`📭 [JWT Storage] No ${tokenType} token found in storage`);
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Validate JWT format
|
|
90
|
-
if (!isValidJWTFormat(token)) {
|
|
91
|
-
console.warn(`⚠️ [JWT Storage] Invalid JWT format found for ${tokenType}, removing`);
|
|
92
|
-
await clearJWT(tokenType);
|
|
93
|
-
return null;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
console.log(`🔐 [JWT Storage] ${tokenType} token retrieved successfully`);
|
|
97
|
-
return token;
|
|
98
|
-
} catch (error) {
|
|
99
|
-
console.error(`❌ [JWT Storage] Failed to retrieve ${tokenType} token:`, error);
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Get JWT token for specific route
|
|
106
|
-
* @param route - API route to get token for
|
|
107
|
-
* @returns Promise<string | null> - Appropriate JWT token or null
|
|
108
|
-
*/
|
|
109
|
-
export const getJWTForRoute = async (route: string): Promise<string | null> => {
|
|
110
|
-
const tokenType = getTokenTypeForRoute(route);
|
|
111
|
-
const token = await getJWT(tokenType);
|
|
112
|
-
|
|
113
|
-
if (token) {
|
|
114
|
-
console.log(`🎯 [JWT Storage] Using ${tokenType} token for route: ${route}`);
|
|
115
|
-
} else {
|
|
116
|
-
console.warn(`⚠️ [JWT Storage] No ${tokenType} token available for route: ${route}`);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return token;
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Clear JWT token of specific type
|
|
124
|
-
* @param tokenType - Type of token to clear
|
|
125
|
-
* @returns Promise<boolean> - Success status
|
|
126
|
-
*/
|
|
127
|
-
export const clearJWT = async (tokenType: TokenType): Promise<boolean> => {
|
|
128
|
-
try {
|
|
129
|
-
await AsyncStorage.removeItem(tokenType);
|
|
130
|
-
console.log(`✅ [JWT Storage] ${tokenType} token cleared successfully`);
|
|
131
|
-
return true;
|
|
132
|
-
} catch (error) {
|
|
133
|
-
console.error(`❌ [JWT Storage] Failed to clear ${tokenType} token:`, error);
|
|
134
|
-
return false;
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Clear all JWT tokens
|
|
140
|
-
* @returns Promise<boolean> - Success status
|
|
141
|
-
*/
|
|
142
|
-
export const clearAllJWT = async (): Promise<boolean> => {
|
|
143
|
-
try {
|
|
144
|
-
await Promise.all([
|
|
145
|
-
clearJWT(TokenType.ENOCH),
|
|
146
|
-
clearJWT(TokenType.ONAIROS),
|
|
147
|
-
clearJWT(TokenType.AUTH)
|
|
148
|
-
]);
|
|
149
|
-
console.log('✅ [JWT Storage] All JWT tokens cleared successfully');
|
|
150
|
-
return true;
|
|
151
|
-
} catch (error) {
|
|
152
|
-
console.error('❌ [JWT Storage] Failed to clear all JWT tokens:', error);
|
|
153
|
-
return false;
|
|
154
|
-
}
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Replace JWT token after verification - route-aware
|
|
159
|
-
* @param tokenType - Type of token being replaced
|
|
160
|
-
* @param newToken - New JWT token from verification response
|
|
161
|
-
* @returns Promise<boolean> - Success status
|
|
162
|
-
*/
|
|
163
|
-
export const replaceJWTAfterVerification = async (tokenType: TokenType, newToken: string): Promise<boolean> => {
|
|
164
|
-
try {
|
|
165
|
-
console.log(`🔄 [JWT Storage] Replacing ${tokenType} token after verification`);
|
|
166
|
-
|
|
167
|
-
if (!newToken || !isValidJWTFormat(newToken)) {
|
|
168
|
-
console.error(`❌ [JWT Storage] Invalid ${tokenType} token provided for replacement`);
|
|
169
|
-
return false;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Clear old token first, then store new one
|
|
173
|
-
await clearJWT(tokenType);
|
|
174
|
-
const stored = await storeJWT(tokenType, newToken);
|
|
175
|
-
|
|
176
|
-
if (stored) {
|
|
177
|
-
console.log(`✅ [JWT Storage] ${tokenType} token successfully replaced after verification`);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return stored;
|
|
181
|
-
} catch (error) {
|
|
182
|
-
console.error(`❌ [JWT Storage] Failed to replace ${tokenType} token after verification:`, error);
|
|
183
|
-
return false;
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Store Enoch JWT token (from email verification)
|
|
189
|
-
* @param token - Enoch JWT token
|
|
190
|
-
* @returns Promise<boolean> - Success status
|
|
191
|
-
*/
|
|
192
|
-
export const storeEnochJWT = async (token: string): Promise<boolean> => {
|
|
193
|
-
return await storeJWT(TokenType.ENOCH, token);
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Store Onairos JWT token (from sign-in/registration)
|
|
198
|
-
* @param token - Onairos JWT token
|
|
199
|
-
* @returns Promise<boolean> - Success status
|
|
200
|
-
*/
|
|
201
|
-
export const storeOnairosJWT = async (token: string): Promise<boolean> => {
|
|
202
|
-
return await storeJWT(TokenType.ONAIROS, token);
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Store Auth token (for context-specific flows)
|
|
207
|
-
* @param token - Auth token
|
|
208
|
-
* @returns Promise<boolean> - Success status
|
|
209
|
-
*/
|
|
210
|
-
export const storeAuthToken = async (token: string): Promise<boolean> => {
|
|
211
|
-
return await storeJWT(TokenType.AUTH, token);
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Validate JWT format
|
|
216
|
-
* @param token - Token to validate
|
|
217
|
-
* @returns boolean - True if valid JWT format
|
|
218
|
-
*/
|
|
219
|
-
const isValidJWTFormat = (token: string): boolean => {
|
|
220
|
-
if (!token || token.length < 20) return false;
|
|
221
|
-
|
|
222
|
-
// Check if it's an email address (invalid JWT)
|
|
223
|
-
if (token.includes('@') && token.includes('.') && !token.includes('Bearer') && token.length < 100) {
|
|
224
|
-
return false;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// Check if it has JWT structure (3 parts separated by dots)
|
|
228
|
-
const tokenParts = token.split('.');
|
|
229
|
-
if (tokenParts.length !== 3) return false;
|
|
230
|
-
|
|
231
|
-
// Additional validation - JWT should be longer than 50 characters typically
|
|
232
|
-
if (token.length < 50) return false;
|
|
233
|
-
|
|
234
|
-
return true;
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* Check if JWT token of specific type exists and is valid
|
|
239
|
-
* @param tokenType - Type of token to check
|
|
240
|
-
* @returns Promise<boolean> - True if valid token exists
|
|
241
|
-
*/
|
|
242
|
-
export const hasValidJWT = async (tokenType: TokenType): Promise<boolean> => {
|
|
243
|
-
const token = await getJWT(tokenType);
|
|
244
|
-
return token !== null;
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Get all available tokens (for debugging)
|
|
249
|
-
* @returns Promise<Record<TokenType, string | null>> - All tokens
|
|
250
|
-
*/
|
|
251
|
-
export const getAllTokens = async (): Promise<Record<TokenType, string | null>> => {
|
|
252
|
-
return {
|
|
253
|
-
[TokenType.ENOCH]: await getJWT(TokenType.ENOCH),
|
|
254
|
-
[TokenType.ONAIROS]: await getJWT(TokenType.ONAIROS),
|
|
255
|
-
[TokenType.AUTH]: await getJWT(TokenType.AUTH)
|
|
256
|
-
};
|
|
1
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
2
|
+
import { Buffer } from 'buffer';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* JWT Token Storage Service - CORRECTED APPROACH
|
|
6
|
+
* Manages 3 DISTINCT JWT token types for different route families
|
|
7
|
+
*
|
|
8
|
+
* TOKEN TYPES:
|
|
9
|
+
* 1. Enoch JWT (enoch_token) - For /enoch/*, /api/auth/*, /mobile-training/enoch
|
|
10
|
+
* 2. Onairos JWT (onairos_jwt_token) - For /youtube/*, /gmail/*, social connections
|
|
11
|
+
* 3. Auth Token (auth_token) - For context-specific auth flows
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export enum TokenType {
|
|
15
|
+
ENOCH = 'enoch_token',
|
|
16
|
+
ONAIROS = 'onairos_jwt_token',
|
|
17
|
+
AUTH = 'auth_token'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Route-based token mapping
|
|
22
|
+
* Determines which token type to use for which routes
|
|
23
|
+
*/
|
|
24
|
+
export const getTokenTypeForRoute = (route: string): TokenType => {
|
|
25
|
+
const cleanRoute = route.toLowerCase();
|
|
26
|
+
|
|
27
|
+
// Enoch routes - use Enoch JWT
|
|
28
|
+
if (cleanRoute.includes('/enoch/') ||
|
|
29
|
+
cleanRoute.includes('/api/auth/') ||
|
|
30
|
+
cleanRoute.includes('/mobile-training/enoch')) {
|
|
31
|
+
return TokenType.ENOCH;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Onairos routes - use Onairos JWT
|
|
35
|
+
if (cleanRoute.includes('/youtube/') ||
|
|
36
|
+
cleanRoute.includes('/gmail/') ||
|
|
37
|
+
cleanRoute.includes('/connectedaccounts') ||
|
|
38
|
+
cleanRoute.includes('/social/')) {
|
|
39
|
+
return TokenType.ONAIROS;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Default to auth token for other routes
|
|
43
|
+
return TokenType.AUTH;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Store JWT token of specific type
|
|
48
|
+
* @param tokenType - Type of token to store
|
|
49
|
+
* @param token - JWT token to store
|
|
50
|
+
* @returns Promise<boolean> - Success status
|
|
51
|
+
*/
|
|
52
|
+
export const storeJWT = async (tokenType: TokenType, token: string): Promise<boolean> => {
|
|
53
|
+
try {
|
|
54
|
+
if (!token || token.trim() === '') {
|
|
55
|
+
console.warn(`⚠️ [JWT Storage] Attempted to store empty/null ${tokenType} token`);
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Validate JWT format (should have 3 parts separated by dots)
|
|
60
|
+
const parts = token.split('.');
|
|
61
|
+
if (parts.length !== 3) {
|
|
62
|
+
console.warn(`⚠️ [JWT Storage] Invalid JWT format for ${tokenType} - token should have 3 parts`);
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
await AsyncStorage.setItem(tokenType, token);
|
|
67
|
+
console.log(`✅ [JWT Storage] ${tokenType} token stored successfully`);
|
|
68
|
+
return true;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error(`❌ [JWT Storage] Failed to store ${tokenType} token:`, error);
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Retrieve JWT token of specific type
|
|
77
|
+
* @param tokenType - Type of token to retrieve
|
|
78
|
+
* @returns Promise<string | null> - JWT token or null if not found
|
|
79
|
+
*/
|
|
80
|
+
export const getJWT = async (tokenType: TokenType): Promise<string | null> => {
|
|
81
|
+
try {
|
|
82
|
+
const token = await AsyncStorage.getItem(tokenType);
|
|
83
|
+
|
|
84
|
+
if (!token) {
|
|
85
|
+
console.log(`📭 [JWT Storage] No ${tokenType} token found in storage`);
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Validate JWT format
|
|
90
|
+
if (!isValidJWTFormat(token)) {
|
|
91
|
+
console.warn(`⚠️ [JWT Storage] Invalid JWT format found for ${tokenType}, removing`);
|
|
92
|
+
await clearJWT(tokenType);
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
console.log(`🔐 [JWT Storage] ${tokenType} token retrieved successfully`);
|
|
97
|
+
return token;
|
|
98
|
+
} catch (error) {
|
|
99
|
+
console.error(`❌ [JWT Storage] Failed to retrieve ${tokenType} token:`, error);
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get JWT token for specific route
|
|
106
|
+
* @param route - API route to get token for
|
|
107
|
+
* @returns Promise<string | null> - Appropriate JWT token or null
|
|
108
|
+
*/
|
|
109
|
+
export const getJWTForRoute = async (route: string): Promise<string | null> => {
|
|
110
|
+
const tokenType = getTokenTypeForRoute(route);
|
|
111
|
+
const token = await getJWT(tokenType);
|
|
112
|
+
|
|
113
|
+
if (token) {
|
|
114
|
+
console.log(`🎯 [JWT Storage] Using ${tokenType} token for route: ${route}`);
|
|
115
|
+
} else {
|
|
116
|
+
console.warn(`⚠️ [JWT Storage] No ${tokenType} token available for route: ${route}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return token;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Clear JWT token of specific type
|
|
124
|
+
* @param tokenType - Type of token to clear
|
|
125
|
+
* @returns Promise<boolean> - Success status
|
|
126
|
+
*/
|
|
127
|
+
export const clearJWT = async (tokenType: TokenType): Promise<boolean> => {
|
|
128
|
+
try {
|
|
129
|
+
await AsyncStorage.removeItem(tokenType);
|
|
130
|
+
console.log(`✅ [JWT Storage] ${tokenType} token cleared successfully`);
|
|
131
|
+
return true;
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error(`❌ [JWT Storage] Failed to clear ${tokenType} token:`, error);
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Clear all JWT tokens
|
|
140
|
+
* @returns Promise<boolean> - Success status
|
|
141
|
+
*/
|
|
142
|
+
export const clearAllJWT = async (): Promise<boolean> => {
|
|
143
|
+
try {
|
|
144
|
+
await Promise.all([
|
|
145
|
+
clearJWT(TokenType.ENOCH),
|
|
146
|
+
clearJWT(TokenType.ONAIROS),
|
|
147
|
+
clearJWT(TokenType.AUTH)
|
|
148
|
+
]);
|
|
149
|
+
console.log('✅ [JWT Storage] All JWT tokens cleared successfully');
|
|
150
|
+
return true;
|
|
151
|
+
} catch (error) {
|
|
152
|
+
console.error('❌ [JWT Storage] Failed to clear all JWT tokens:', error);
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Replace JWT token after verification - route-aware
|
|
159
|
+
* @param tokenType - Type of token being replaced
|
|
160
|
+
* @param newToken - New JWT token from verification response
|
|
161
|
+
* @returns Promise<boolean> - Success status
|
|
162
|
+
*/
|
|
163
|
+
export const replaceJWTAfterVerification = async (tokenType: TokenType, newToken: string): Promise<boolean> => {
|
|
164
|
+
try {
|
|
165
|
+
console.log(`🔄 [JWT Storage] Replacing ${tokenType} token after verification`);
|
|
166
|
+
|
|
167
|
+
if (!newToken || !isValidJWTFormat(newToken)) {
|
|
168
|
+
console.error(`❌ [JWT Storage] Invalid ${tokenType} token provided for replacement`);
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Clear old token first, then store new one
|
|
173
|
+
await clearJWT(tokenType);
|
|
174
|
+
const stored = await storeJWT(tokenType, newToken);
|
|
175
|
+
|
|
176
|
+
if (stored) {
|
|
177
|
+
console.log(`✅ [JWT Storage] ${tokenType} token successfully replaced after verification`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return stored;
|
|
181
|
+
} catch (error) {
|
|
182
|
+
console.error(`❌ [JWT Storage] Failed to replace ${tokenType} token after verification:`, error);
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Store Enoch JWT token (from email verification)
|
|
189
|
+
* @param token - Enoch JWT token
|
|
190
|
+
* @returns Promise<boolean> - Success status
|
|
191
|
+
*/
|
|
192
|
+
export const storeEnochJWT = async (token: string): Promise<boolean> => {
|
|
193
|
+
return await storeJWT(TokenType.ENOCH, token);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Store Onairos JWT token (from sign-in/registration)
|
|
198
|
+
* @param token - Onairos JWT token
|
|
199
|
+
* @returns Promise<boolean> - Success status
|
|
200
|
+
*/
|
|
201
|
+
export const storeOnairosJWT = async (token: string): Promise<boolean> => {
|
|
202
|
+
return await storeJWT(TokenType.ONAIROS, token);
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Store Auth token (for context-specific flows)
|
|
207
|
+
* @param token - Auth token
|
|
208
|
+
* @returns Promise<boolean> - Success status
|
|
209
|
+
*/
|
|
210
|
+
export const storeAuthToken = async (token: string): Promise<boolean> => {
|
|
211
|
+
return await storeJWT(TokenType.AUTH, token);
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Validate JWT format
|
|
216
|
+
* @param token - Token to validate
|
|
217
|
+
* @returns boolean - True if valid JWT format
|
|
218
|
+
*/
|
|
219
|
+
const isValidJWTFormat = (token: string): boolean => {
|
|
220
|
+
if (!token || token.length < 20) return false;
|
|
221
|
+
|
|
222
|
+
// Check if it's an email address (invalid JWT)
|
|
223
|
+
if (token.includes('@') && token.includes('.') && !token.includes('Bearer') && token.length < 100) {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Check if it has JWT structure (3 parts separated by dots)
|
|
228
|
+
const tokenParts = token.split('.');
|
|
229
|
+
if (tokenParts.length !== 3) return false;
|
|
230
|
+
|
|
231
|
+
// Additional validation - JWT should be longer than 50 characters typically
|
|
232
|
+
if (token.length < 50) return false;
|
|
233
|
+
|
|
234
|
+
return true;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Check if JWT token of specific type exists and is valid
|
|
239
|
+
* @param tokenType - Type of token to check
|
|
240
|
+
* @returns Promise<boolean> - True if valid token exists
|
|
241
|
+
*/
|
|
242
|
+
export const hasValidJWT = async (tokenType: TokenType): Promise<boolean> => {
|
|
243
|
+
const token = await getJWT(tokenType);
|
|
244
|
+
return token !== null;
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Get all available tokens (for debugging)
|
|
249
|
+
* @returns Promise<Record<TokenType, string | null>> - All tokens
|
|
250
|
+
*/
|
|
251
|
+
export const getAllTokens = async (): Promise<Record<TokenType, string | null>> => {
|
|
252
|
+
return {
|
|
253
|
+
[TokenType.ENOCH]: await getJWT(TokenType.ENOCH),
|
|
254
|
+
[TokenType.ONAIROS]: await getJWT(TokenType.ONAIROS),
|
|
255
|
+
[TokenType.AUTH]: await getJWT(TokenType.AUTH)
|
|
256
|
+
};
|
|
257
257
|
};
|