@onairos/react-native 3.0.74 → 3.1.0

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.
Files changed (49) hide show
  1. package/lib/commonjs/components/EmailVerificationModal.js +7 -5
  2. package/lib/commonjs/components/EmailVerificationModal.js.map +1 -1
  3. package/lib/commonjs/components/UniversalOnboarding.js +10 -1
  4. package/lib/commonjs/components/UniversalOnboarding.js.map +1 -1
  5. package/lib/commonjs/index.js +0 -6
  6. package/lib/commonjs/index.js.map +1 -1
  7. package/lib/commonjs/services/apiKeyService.js +278 -27
  8. package/lib/commonjs/services/apiKeyService.js.map +1 -1
  9. package/lib/commonjs/services/platformAuthService.js +127 -290
  10. package/lib/commonjs/services/platformAuthService.js.map +1 -1
  11. package/lib/commonjs/utils/onairosApi.js +143 -71
  12. package/lib/commonjs/utils/onairosApi.js.map +1 -1
  13. package/lib/commonjs/utils/secureStorage.js +123 -1
  14. package/lib/commonjs/utils/secureStorage.js.map +1 -1
  15. package/lib/module/components/EmailVerificationModal.js +7 -5
  16. package/lib/module/components/EmailVerificationModal.js.map +1 -1
  17. package/lib/module/components/UniversalOnboarding.js +11 -2
  18. package/lib/module/components/UniversalOnboarding.js.map +1 -1
  19. package/lib/module/index.js +3 -1
  20. package/lib/module/index.js.map +1 -1
  21. package/lib/module/services/apiKeyService.js +264 -22
  22. package/lib/module/services/apiKeyService.js.map +1 -1
  23. package/lib/module/services/platformAuthService.js +125 -287
  24. package/lib/module/services/platformAuthService.js.map +1 -1
  25. package/lib/module/utils/onairosApi.js +139 -70
  26. package/lib/module/utils/onairosApi.js.map +1 -1
  27. package/lib/module/utils/secureStorage.js +116 -0
  28. package/lib/module/utils/secureStorage.js.map +1 -1
  29. package/lib/typescript/components/EmailVerificationModal.d.ts.map +1 -1
  30. package/lib/typescript/components/UniversalOnboarding.d.ts.map +1 -1
  31. package/lib/typescript/index.d.ts +1 -1
  32. package/lib/typescript/index.d.ts.map +1 -1
  33. package/lib/typescript/services/apiKeyService.d.ts +50 -2
  34. package/lib/typescript/services/apiKeyService.d.ts.map +1 -1
  35. package/lib/typescript/services/platformAuthService.d.ts +29 -14
  36. package/lib/typescript/services/platformAuthService.d.ts.map +1 -1
  37. package/lib/typescript/utils/onairosApi.d.ts +24 -10
  38. package/lib/typescript/utils/onairosApi.d.ts.map +1 -1
  39. package/lib/typescript/utils/secureStorage.d.ts +31 -0
  40. package/lib/typescript/utils/secureStorage.d.ts.map +1 -1
  41. package/package.json +1 -1
  42. package/src/components/EmailVerificationModal.tsx +9 -5
  43. package/src/components/UniversalOnboarding.tsx +11 -1
  44. package/src/index.ts +1 -1
  45. package/src/services/apiKeyService.ts +282 -18
  46. package/src/services/platformAuthService.ts +216 -412
  47. package/src/types/index.d.ts +6 -5
  48. package/src/utils/onairosApi.ts +151 -74
  49. package/src/utils/secureStorage.ts +122 -0
@@ -1,52 +1,33 @@
1
1
  import AsyncStorage from '@react-native-async-storage/async-storage';
2
- import { makeAuthenticatedRequest } from './apiKeyService';
2
+ import { makeDeveloperRequest, getApiConfig, storeJWT } from './apiKeyService';
3
3
 
4
- // 🔑 CRITICAL: Initialize API key service for authentication
5
- let isApiKeyInitialized = false;
4
+ // 🔑 CRITICAL: Use two-tier authentication system
5
+ // - Developer API key for email verification requests
6
+ // - JWT tokens for user-authenticated requests after email verification
6
7
 
7
8
  /**
8
- * Initialize the API key service with the admin key for testing
9
- * This ensures all API requests include proper authentication headers
9
+ * Initialize the platform auth service
10
+ * This service now uses the two-tier authentication system
10
11
  */
11
12
  export const initializePlatformAuthService = async () => {
12
- if (isApiKeyInitialized) {
13
- console.log('🔑 API key service already initialized');
14
- return;
15
- }
16
13
  try {
17
- // Import the initialization function
18
- const {
19
- initializeApiKey,
20
- ADMIN_API_KEY
21
- } = await import('./apiKeyService');
22
-
23
- // Initialize with admin key for production email service
24
- await initializeApiKey({
25
- apiKey: ADMIN_API_KEY,
26
- // 'OnairosIsAUnicorn2025'
27
- environment: 'production',
28
- // Use production for email verification
29
- enableLogging: true,
30
- timeout: 30000
31
- });
32
- isApiKeyInitialized = true;
33
- console.log('✅ Platform auth service initialized with admin key (production)');
14
+ // Check if app is already initialized with API key
15
+ const existingConfig = getApiConfig();
16
+ if (existingConfig && existingConfig.apiKey) {
17
+ console.log('🔑 Platform auth service using existing app configuration');
18
+ console.log(`✅ Environment: ${existingConfig.environment}`);
19
+ return;
20
+ }
21
+
22
+ // If no app initialization, we can't proceed
23
+ console.error('❌ Platform auth service requires app-level API key initialization');
24
+ throw new Error('Platform auth service requires app-level API key initialization. Please call initializeApiKey() first.');
34
25
  } catch (error) {
35
26
  console.error('❌ Failed to initialize platform auth service:', error);
36
27
  throw error;
37
28
  }
38
29
  };
39
30
 
40
- /**
41
- * Ensure API key is initialized before making authenticated requests
42
- */
43
- const ensureApiKeyInitialized = async () => {
44
- if (!isApiKeyInitialized) {
45
- console.log('🔑 API key not initialized, initializing now...');
46
- await initializePlatformAuthService();
47
- }
48
- };
49
-
50
31
  // Configuration for each platform's authentication
51
32
  let PLATFORM_AUTH_CONFIG = {
52
33
  instagram: {
@@ -154,7 +135,7 @@ export const initiateOAuth = async (platform, username, appName) => {
154
135
  }
155
136
  };
156
137
  console.log('📤 Sending Instagram OAuth request:', jsonData);
157
- const response = await makeAuthenticatedRequest(PLATFORM_AUTH_CONFIG[platform].authEndpoint, {
138
+ const response = await makeDeveloperRequest(PLATFORM_AUTH_CONFIG[platform].authEndpoint, {
158
139
  method: 'POST',
159
140
  body: JSON.stringify(jsonData)
160
141
  });
@@ -192,7 +173,7 @@ export const initiateOAuth = async (platform, username, appName) => {
192
173
  console.log(`📤 Sending ${platform} OAuth request:`, jsonData);
193
174
 
194
175
  // Make the authenticated request to get the OAuth URL
195
- const response = await makeAuthenticatedRequest(PLATFORM_AUTH_CONFIG[platform].authEndpoint, {
176
+ const response = await makeDeveloperRequest(PLATFORM_AUTH_CONFIG[platform].authEndpoint, {
196
177
  method: 'POST',
197
178
  body: JSON.stringify(jsonData)
198
179
  });
@@ -793,355 +774,212 @@ export const updateGoogleClientIds = config => {
793
774
  };
794
775
 
795
776
  /**
796
- * 📧 EMAIL VERIFICATION FUNCTIONS
797
- * Using the correct Onairos email verification endpoints
777
+ * Request email verification using developer API key
778
+ * @param email Email address to verify
779
+ * @param testMode Whether to use test mode
780
+ * @returns Promise with verification result
798
781
  */
799
782
  export const requestEmailVerification = async (email, testMode = false) => {
800
783
  try {
801
784
  console.log('📧 Requesting email verification for:', email);
802
- console.log('🧪 Test mode:', testMode);
803
- if (!email || !email.includes('@')) {
804
- return {
805
- success: false,
806
- error: 'Valid email address is required'
807
- };
808
- }
809
-
810
- // In test mode, always return success with mock request ID
811
- if (testMode) {
812
- console.log('🧪 Test mode: Always returning success with mock request ID');
813
- const mockRequestId = 'test-request-' + Date.now();
814
-
815
- // Store request info for tracking
816
- await AsyncStorage.setItem('email_verification_request_id', mockRequestId);
817
- await AsyncStorage.setItem('email_verification_request_email', email);
785
+ const response = await makeDeveloperRequest('/email/verification', {
786
+ method: 'POST',
787
+ body: JSON.stringify({
788
+ email,
789
+ action: 'request',
790
+ testMode
791
+ })
792
+ });
793
+ const data = await response.json();
794
+ if (response.ok && data.success) {
795
+ console.log(' Email verification requested successfully');
818
796
  return {
819
797
  success: true,
820
- message: 'Email verification sent successfully (test mode)',
821
- requestId: mockRequestId
798
+ message: data.message || 'Verification code sent to your email'
822
799
  };
823
- }
824
-
825
- // Production mode: Make real API call with API key authentication
826
- try {
827
- // 🔑 Ensure API key is initialized before making authenticated requests
828
- await ensureApiKeyInitialized();
829
- const response = await makeAuthenticatedRequest('/email/verification', {
830
- method: 'POST',
831
- body: JSON.stringify({
832
- email,
833
- action: 'request'
834
- })
835
- });
836
- const result = await response.json();
837
- console.log('📡 Email verification API response:', result);
838
- if (response.ok && result.success) {
839
- console.log('✅ Email verification request sent');
840
-
841
- // Store request info for tracking
842
- const requestId = result.requestId || result.id || 'req-' + Date.now();
843
- await AsyncStorage.setItem('email_verification_request_id', requestId);
844
- await AsyncStorage.setItem('email_verification_request_email', email);
845
- return {
846
- success: true,
847
- message: result.message || 'Email verification sent successfully',
848
- requestId: requestId
849
- };
850
- } else {
851
- console.error('❌ Email verification request failed:', result.error);
852
- return {
853
- success: false,
854
- error: result.error || 'Failed to send verification email'
855
- };
856
- }
857
- } catch (apiError) {
858
- console.error('❌ Email verification API call failed:', apiError);
800
+ } else {
801
+ console.error('❌ Email verification request failed:', data.error);
859
802
  return {
860
803
  success: false,
861
- error: 'Network error while sending verification email'
804
+ error: data.error || 'Failed to send verification code'
862
805
  };
863
806
  }
864
807
  } catch (error) {
865
- console.error('❌ Email verification request error:', error);
808
+ console.error('❌ Error requesting email verification:', error);
866
809
  return {
867
810
  success: false,
868
- error: error instanceof Error ? error.message : 'Unknown error'
811
+ error: error instanceof Error ? error.message : 'Network error'
869
812
  };
870
813
  }
871
814
  };
815
+
816
+ /**
817
+ * Verify email code and store JWT token
818
+ * @param email Email address
819
+ * @param code Verification code
820
+ * @param testMode Whether to use test mode
821
+ * @returns Promise with verification result and JWT token
822
+ */
872
823
  export const verifyEmailCode = async (email, code, testMode = false) => {
873
824
  try {
874
825
  console.log('🔍 Verifying email code for:', email);
875
- console.log('🔑 Code length:', code.length);
876
- console.log('🧪 Test mode:', testMode);
877
- if (!email || !email.includes('@')) {
878
- return {
879
- success: false,
880
- error: 'Valid email address is required'
881
- };
882
- }
883
- if (!code || code.length < 4) {
884
- return {
885
- success: false,
886
- error: 'Valid verification code is required'
887
- };
888
- }
889
-
890
- // In test mode, always return success with mock JWT token
891
- if (testMode) {
892
- console.log('🧪 Test mode: Always returning success with mock JWT token');
893
- const mockToken = 'test-jwt-token-' + Date.now();
894
-
895
- // Store mock token for API requests
896
- await AsyncStorage.setItem('email_verification_token', mockToken);
897
- await AsyncStorage.setItem('onairos_jwt_token', mockToken);
898
- await AsyncStorage.setItem('email_verification_email', email);
826
+ const response = await makeDeveloperRequest('/email/verification', {
827
+ method: 'POST',
828
+ body: JSON.stringify({
829
+ email,
830
+ action: 'verify',
831
+ code,
832
+ testMode
833
+ })
834
+ });
835
+ const data = await response.json();
836
+ if (response.ok && data.success) {
837
+ console.log(' Email verification successful');
838
+
839
+ // Store JWT token if received
840
+ if (data.token || data.jwtToken) {
841
+ const jwtToken = data.token || data.jwtToken;
842
+ await storeJWT(jwtToken);
843
+ console.log('🎫 JWT token stored successfully');
844
+ }
899
845
  return {
900
846
  success: true,
901
- message: 'Email verification successful (test mode)',
902
- existingUser: false,
903
- jwtToken: mockToken
847
+ message: data.message || 'Email verified successfully',
848
+ existingUser: data.existingUser || false,
849
+ token: data.token || data.jwtToken
904
850
  };
905
- }
906
-
907
- // Production mode: Make real API call with API key authentication
908
- try {
909
- // 🔑 Ensure API key is initialized before making authenticated requests
910
- await ensureApiKeyInitialized();
911
- const response = await makeAuthenticatedRequest('/email/verification', {
912
- method: 'POST',
913
- body: JSON.stringify({
914
- email,
915
- code,
916
- action: 'verify'
917
- })
918
- });
919
- const result = await response.json();
920
- console.log('📡 Email verification API response:', result);
921
- if (response.ok && result.success) {
922
- console.log('✅ Email verification successful');
923
-
924
- // 🎫 CRITICAL: Store JWT token from email verification response
925
- const jwtToken = result.token || result.jwtToken || result.jwt || result.authToken;
926
- if (jwtToken) {
927
- console.log('🎫 Storing JWT token from email verification response');
928
- await AsyncStorage.setItem('email_verification_token', jwtToken);
929
- await AsyncStorage.setItem('onairos_jwt_token', jwtToken);
930
- await AsyncStorage.setItem('enoch_token', jwtToken);
931
- await AsyncStorage.setItem('auth_token', jwtToken);
932
- await AsyncStorage.setItem('email_verification_email', email);
933
- await AsyncStorage.setItem('token_timestamp', Date.now().toString());
934
- } else {
935
- console.warn('⚠️ No JWT token received from email verification API');
936
- }
937
- return {
938
- success: true,
939
- message: result.message || 'Email verification successful',
940
- existingUser: result.existingUser || false,
941
- jwtToken: jwtToken
942
- };
943
- } else {
944
- console.error('❌ Email verification failed:', result.error);
945
- return {
946
- success: false,
947
- error: result.error || 'Email verification failed'
948
- };
949
- }
950
- } catch (apiError) {
951
- console.error('❌ Email verification API call failed:', apiError);
851
+ } else {
852
+ console.error('❌ Email verification failed:', data.error);
952
853
  return {
953
854
  success: false,
954
- error: 'Network error during email verification'
855
+ error: data.error || 'Invalid verification code'
955
856
  };
956
857
  }
957
858
  } catch (error) {
958
- console.error('❌ Email verification error:', error);
859
+ console.error('❌ Error verifying email code:', error);
959
860
  return {
960
861
  success: false,
961
- error: error instanceof Error ? error.message : 'Unknown error'
862
+ error: error instanceof Error ? error.message : 'Network error'
962
863
  };
963
864
  }
964
865
  };
866
+
867
+ /**
868
+ * Check email verification status
869
+ * @param email Email address
870
+ * @param testMode Whether to use test mode
871
+ * @returns Promise with status result
872
+ */
965
873
  export const checkEmailVerificationStatus = async (email, testMode = false) => {
966
874
  try {
967
875
  console.log('🔍 Checking email verification status for:', email);
968
- console.log('🔍 Test mode:', testMode);
969
-
970
- // In test mode, always return no pending verification
971
- if (testMode) {
972
- console.log('🧪 Test mode: Always returning no pending verification');
876
+ const response = await makeDeveloperRequest('/email/verification/status', {
877
+ method: 'POST',
878
+ body: JSON.stringify({
879
+ email,
880
+ testMode
881
+ })
882
+ });
883
+ const data = await response.json();
884
+ if (response.ok && data.success) {
973
885
  return {
974
886
  success: true,
975
- isPending: false,
976
- message: 'Status retrieved successfully (test mode)'
887
+ isPending: data.isPending || false
977
888
  };
978
- }
979
-
980
- // Production mode: Make real API call with API key authentication
981
- try {
982
- // 🔑 Ensure API key is initialized before making authenticated requests
983
- await ensureApiKeyInitialized();
984
- const response = await makeAuthenticatedRequest(`/email/verify/status/${encodeURIComponent(email)}`, {
985
- method: 'GET'
986
- });
987
- const result = await response.json();
988
- console.log('📡 Email verification status API response:', result);
989
- if (response.ok && result.success) {
990
- console.log('✅ Email verification status retrieved');
991
- return {
992
- success: true,
993
- isPending: result.isPending || false,
994
- message: result.message || 'Status retrieved successfully'
995
- };
996
- } else {
997
- console.error('❌ Email verification status failed:', result.error);
998
- return {
999
- success: false,
1000
- error: result.error || 'Failed to check verification status'
1001
- };
1002
- }
1003
- } catch (apiError) {
1004
- console.error('❌ Email verification status API call failed:', apiError);
889
+ } else {
1005
890
  return {
1006
891
  success: false,
1007
- error: 'Network error while checking status'
892
+ error: data.error || 'Failed to check verification status'
1008
893
  };
1009
894
  }
1010
895
  } catch (error) {
1011
- console.error('❌ Email verification status error:', error);
896
+ console.error('❌ Error checking email verification status:', error);
1012
897
  return {
1013
898
  success: false,
1014
- error: error instanceof Error ? error.message : 'Unknown error'
899
+ error: error instanceof Error ? error.message : 'Network error'
1015
900
  };
1016
901
  }
1017
902
  };
1018
903
 
1019
904
  /**
1020
- * 🔌 UNIVERSAL PLATFORM DISCONNECTION
1021
- * Backend confirmed this endpoint is fully implemented
905
+ * Disconnect a platform (uses developer API key)
906
+ * @param platform Platform to disconnect
907
+ * @param username Username associated with the platform
908
+ * @returns Promise with disconnect result
1022
909
  */
1023
910
  export const disconnectPlatform = async (platform, username) => {
1024
911
  try {
1025
912
  console.log('🔌 Disconnecting platform:', platform, 'for user:', username);
1026
- if (!platform || !username) {
1027
- return {
1028
- success: false,
1029
- error: 'Platform and username are required'
1030
- };
1031
- }
1032
913
 
1033
914
  // Make authenticated API call to disconnect platform
1034
- const response = await makeAuthenticatedRequest('/revoke', {
915
+ const response = await makeDeveloperRequest('/revoke', {
1035
916
  method: 'POST',
1036
917
  body: JSON.stringify({
1037
918
  platform,
1038
919
  username
1039
920
  })
1040
921
  });
1041
- const result = await response.json();
1042
- console.log('📡 Platform disconnect API response:', result);
1043
- if (response.ok && result.success) {
1044
- console.log('✅ Platform disconnected successfully');
922
+ const data = await response.json();
923
+ if (response.ok && data.success) {
924
+ console.log(`✅ ${platform} disconnected successfully`);
1045
925
  return {
1046
- success: true,
1047
- message: result.message || 'Platform disconnected successfully'
926
+ success: true
1048
927
  };
1049
928
  } else {
1050
- console.error('❌ Platform disconnect failed:', result.error);
929
+ console.error(`❌ Failed to disconnect ${platform}:`, data.error);
1051
930
  return {
1052
931
  success: false,
1053
- error: result.error || 'Failed to disconnect platform'
932
+ error: data.error || 'Failed to disconnect platform'
1054
933
  };
1055
934
  }
1056
935
  } catch (error) {
1057
- console.error('❌ Platform disconnect error:', error);
936
+ console.error(`❌ Error disconnecting ${platform}:`, error);
1058
937
  return {
1059
938
  success: false,
1060
- error: error instanceof Error ? error.message : 'Platform disconnect failed'
939
+ error: error instanceof Error ? error.message : 'Network error'
1061
940
  };
1062
941
  }
1063
942
  };
1064
943
 
1065
944
  /**
1066
- * 🔐 STORE PIN AFTER BIOMETRIC AUTHENTICATION
1067
- * Send PIN separately to /store-pin/web endpoint after biometric Face ID verification
945
+ * Store PIN for user (uses developer API key for now, should be JWT in future)
946
+ * @param username Username
947
+ * @param pin User PIN
948
+ * @returns Promise with result
1068
949
  */
1069
- export const storePinAfterBiometric = async (username, pin, jwtToken) => {
950
+ export const storePIN = async (username, pin) => {
1070
951
  try {
1071
- console.log('🔐 Storing PIN after biometric authentication for user:', username);
1072
- console.log('🔑 PIN length:', pin.length);
1073
- console.log('🎫 JWT token provided:', !!jwtToken);
1074
- if (!username || !pin) {
1075
- return {
1076
- success: false,
1077
- error: 'Username and PIN are required'
1078
- };
1079
- }
1080
- if (pin.length < 4) {
1081
- return {
1082
- success: false,
1083
- error: 'PIN must be at least 4 digits'
1084
- };
1085
- }
1086
-
1087
- // Get JWT token from storage if not provided
1088
- let authToken = jwtToken;
1089
- if (!authToken) {
1090
- authToken = (await AsyncStorage.getItem('onairos_jwt_token')) || (await AsyncStorage.getItem('enoch_token')) || (await AsyncStorage.getItem('auth_token')) || (await AsyncStorage.getItem('email_verification_token'));
1091
- }
1092
- if (!authToken) {
1093
- console.warn('⚠️ No JWT token available for PIN storage');
1094
- return {
1095
- success: false,
1096
- error: 'No authentication token available'
1097
- };
1098
- }
1099
- console.log('📤 Sending PIN to /store-pin/web endpoint');
952
+ console.log('🔐 Storing PIN for user:', username);
1100
953
 
1101
954
  // Make authenticated request to store PIN
1102
- const response = await makeAuthenticatedRequest('/store-pin/web', {
955
+ const response = await makeDeveloperRequest('/store-pin/web', {
1103
956
  method: 'POST',
1104
957
  headers: {
1105
- 'Authorization': `Bearer ${authToken}`
958
+ 'Content-Type': 'application/json'
1106
959
  },
1107
960
  body: JSON.stringify({
1108
961
  username,
1109
962
  pin
1110
963
  })
1111
964
  });
1112
- console.log('📡 PIN storage response status:', response.status);
1113
- if (!response.ok) {
1114
- const errorText = await response.text();
1115
- console.error('❌ PIN storage failed:', errorText);
1116
- return {
1117
- success: false,
1118
- error: `PIN storage failed: ${response.status} - ${errorText}`
1119
- };
1120
- }
1121
- const result = await response.json();
1122
- console.log('📥 PIN storage response:', result);
1123
- if (result.success) {
1124
- console.log('✅ PIN stored successfully after biometric authentication');
1125
-
1126
- // Store PIN locally for future use
1127
- await AsyncStorage.setItem('user_pin_stored', 'true');
1128
- await AsyncStorage.setItem('pin_storage_timestamp', Date.now().toString());
965
+ const data = await response.json();
966
+ if (response.ok && data.success) {
967
+ console.log('✅ PIN stored successfully');
1129
968
  return {
1130
- success: true,
1131
- message: result.message || 'PIN stored successfully'
969
+ success: true
1132
970
  };
1133
971
  } else {
1134
- console.error('❌ PIN storage API returned error:', result.error);
972
+ console.error('❌ Failed to store PIN:', data.error);
1135
973
  return {
1136
974
  success: false,
1137
- error: result.error || 'PIN storage failed'
975
+ error: data.error || 'Failed to store PIN'
1138
976
  };
1139
977
  }
1140
978
  } catch (error) {
1141
- console.error('❌ Error storing PIN after biometric authentication:', error);
979
+ console.error('❌ Error storing PIN:', error);
1142
980
  return {
1143
981
  success: false,
1144
- error: error instanceof Error ? error.message : 'PIN storage failed'
982
+ error: error instanceof Error ? error.message : 'Network error'
1145
983
  };
1146
984
  }
1147
985
  };