@oobit/react-native-sdk 1.0.3 → 1.0.5
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/WidgetSDK.d.ts.map +1 -1
- package/dist/WidgetSDK.js +60 -3
- package/dist/WidgetSDK.js.map +1 -1
- package/dist/biometricUtils.d.ts +66 -0
- package/dist/biometricUtils.d.ts.map +1 -0
- package/dist/biometricUtils.js +179 -0
- package/dist/biometricUtils.js.map +1 -0
- package/dist/config.d.ts +2 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/cryptoUtils.d.ts +67 -0
- package/dist/cryptoUtils.d.ts.map +1 -0
- package/dist/cryptoUtils.js +143 -0
- package/dist/cryptoUtils.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +41 -18
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +18 -15
- package/dist/types.js.map +1 -1
- package/package.json +7 -7
- package/src/WidgetSDK.tsx +108 -7
- package/src/biometricUtils.ts +189 -0
- package/src/config.ts +5 -3
- package/src/cryptoUtils.ts +160 -0
- package/src/index.ts +20 -0
- package/src/types.ts +80 -44
package/dist/WidgetSDK.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetSDK.d.ts","sourceRoot":"","sources":["../src/WidgetSDK.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAON,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"WidgetSDK.d.ts","sourceRoot":"","sources":["../src/WidgetSDK.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAON,MAAM,OAAO,CAAC;AAaf,OAAO,EAIL,eAAe,EAChB,MAAM,SAAS,CAAC;AAGjB,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,eAAO,MAAM,SAAS,sFAqVrB,CAAC"}
|
package/dist/WidgetSDK.js
CHANGED
|
@@ -41,7 +41,9 @@ exports.WidgetSDK = void 0;
|
|
|
41
41
|
const react_1 = __importStar(require("react"));
|
|
42
42
|
const react_native_1 = require("react-native");
|
|
43
43
|
const react_native_webview_1 = require("react-native-webview");
|
|
44
|
+
const biometricUtils_1 = require("./biometricUtils");
|
|
44
45
|
const config_1 = require("./config");
|
|
46
|
+
const cryptoUtils_1 = require("./cryptoUtils");
|
|
45
47
|
const walletUtils_1 = require("./walletUtils");
|
|
46
48
|
exports.WidgetSDK = (0, react_1.forwardRef)(({ accessToken, userWalletAddress, environment, onReady, onCardCreated, onError, onClose, onTransactionRequested, }, ref) => {
|
|
47
49
|
const webViewRef = (0, react_1.useRef)(null);
|
|
@@ -108,6 +110,9 @@ exports.WidgetSDK = (0, react_1.forwardRef)(({ accessToken, userWalletAddress, e
|
|
|
108
110
|
console.error("[WidgetSDK] Access token expired");
|
|
109
111
|
onError?.("TOKEN_EXPIRED", "Access token has expired");
|
|
110
112
|
break;
|
|
113
|
+
case "widget:request-card-details-session":
|
|
114
|
+
handleCardDetailsRequest(message);
|
|
115
|
+
break;
|
|
111
116
|
default:
|
|
112
117
|
console.warn("[WidgetSDK] Unknown message type:", message);
|
|
113
118
|
}
|
|
@@ -168,6 +173,58 @@ exports.WidgetSDK = (0, react_1.forwardRef)(({ accessToken, userWalletAddress, e
|
|
|
168
173
|
});
|
|
169
174
|
onTransactionRequested?.(token, cryptoAmount, depositAddress, depositAddressTag);
|
|
170
175
|
};
|
|
176
|
+
/**
|
|
177
|
+
* Handle card details session request from widget
|
|
178
|
+
* 1. Show biometric prompt for user authentication
|
|
179
|
+
* 2. Generate cryptographically linked sessionId + secretKey pair
|
|
180
|
+
* 3. Send credentials back to widget for API call and decryption
|
|
181
|
+
*/
|
|
182
|
+
const handleCardDetailsRequest = async (message) => {
|
|
183
|
+
if (message.type !== "widget:request-card-details-session")
|
|
184
|
+
return;
|
|
185
|
+
const { publicKey } = message.payload;
|
|
186
|
+
console.log("[WidgetSDK] Card details requested, initiating biometric auth...");
|
|
187
|
+
// Step 1: Authenticate with biometrics
|
|
188
|
+
const biometricResult = await (0, biometricUtils_1.authenticateWithBiometrics)("Authenticate to view card details");
|
|
189
|
+
if (!biometricResult.success) {
|
|
190
|
+
console.log("[WidgetSDK] Biometric auth failed:", biometricResult.error);
|
|
191
|
+
const failedMessage = {
|
|
192
|
+
type: "native:biometric-failed",
|
|
193
|
+
payload: {
|
|
194
|
+
reason: biometricResult.error?.reason || "failed",
|
|
195
|
+
message: biometricResult.error?.message,
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
sendMessageToWidget(failedMessage);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
// Step 2: Generate session credentials
|
|
202
|
+
try {
|
|
203
|
+
console.log("[WidgetSDK] Biometric auth successful, generating session credentials...");
|
|
204
|
+
const { secretKeyHex, sessionId } = await (0, cryptoUtils_1.generateSessionCredentials)(publicKey);
|
|
205
|
+
console.log("[WidgetSDK] Session credentials generated successfully");
|
|
206
|
+
// Step 3: Send credentials to widget
|
|
207
|
+
const sessionMessage = {
|
|
208
|
+
type: "native:card-details-session",
|
|
209
|
+
payload: {
|
|
210
|
+
sessionId,
|
|
211
|
+
secretKey: secretKeyHex,
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
sendMessageToWidget(sessionMessage);
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
console.error("[WidgetSDK] Failed to generate session credentials:", error);
|
|
218
|
+
const failedMessage = {
|
|
219
|
+
type: "native:biometric-failed",
|
|
220
|
+
payload: {
|
|
221
|
+
reason: "failed",
|
|
222
|
+
message: "Failed to generate secure session",
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
sendMessageToWidget(failedMessage);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
171
228
|
/**
|
|
172
229
|
* Send message to the web widget
|
|
173
230
|
*/
|
|
@@ -241,9 +298,9 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
241
298
|
},
|
|
242
299
|
loadingOverlay: {
|
|
243
300
|
...react_native_1.StyleSheet.absoluteFillObject,
|
|
244
|
-
backgroundColor:
|
|
245
|
-
justifyContent:
|
|
246
|
-
alignItems:
|
|
301
|
+
backgroundColor: "rgba(255, 255, 255, 0.9)",
|
|
302
|
+
justifyContent: "center",
|
|
303
|
+
alignItems: "center",
|
|
247
304
|
},
|
|
248
305
|
});
|
|
249
306
|
//# sourceMappingURL=WidgetSDK.js.map
|
package/dist/WidgetSDK.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetSDK.js","sourceRoot":"","sources":["../src/WidgetSDK.tsx"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,+CAOe;AACf,+
|
|
1
|
+
{"version":3,"file":"WidgetSDK.js","sourceRoot":"","sources":["../src/WidgetSDK.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Biometric Authentication Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides cross-platform biometric authentication for card details access.
|
|
5
|
+
* Supports Face ID, Touch ID, and Android biometrics.
|
|
6
|
+
*
|
|
7
|
+
* @requires react-native-biometrics - npm install react-native-biometrics
|
|
8
|
+
*/
|
|
9
|
+
import { BiometryTypes, type BiometryType } from 'react-native-biometrics';
|
|
10
|
+
/**
|
|
11
|
+
* Result of a biometric authentication attempt
|
|
12
|
+
*/
|
|
13
|
+
export interface BiometricResult {
|
|
14
|
+
/** Whether authentication was successful */
|
|
15
|
+
success: boolean;
|
|
16
|
+
/** Error details if authentication failed */
|
|
17
|
+
error?: {
|
|
18
|
+
reason: 'cancelled' | 'failed' | 'not_available' | 'not_enrolled';
|
|
19
|
+
message?: string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Information about biometric capabilities on the device
|
|
24
|
+
*/
|
|
25
|
+
export interface BiometricAvailability {
|
|
26
|
+
/** Whether any biometric authentication is available */
|
|
27
|
+
available: boolean;
|
|
28
|
+
/** The type of biometry available (FaceID, TouchID, Biometrics, or null) */
|
|
29
|
+
biometryType: BiometryType | null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Checks if biometric authentication is available on the device
|
|
33
|
+
*
|
|
34
|
+
* @returns Object containing availability status and biometry type
|
|
35
|
+
*/
|
|
36
|
+
export declare function isBiometricAvailable(): Promise<BiometricAvailability>;
|
|
37
|
+
/**
|
|
38
|
+
* Prompts the user for biometric authentication
|
|
39
|
+
*
|
|
40
|
+
* This function should be called before generating session credentials
|
|
41
|
+
* for viewing card details. It ensures proper user verification before
|
|
42
|
+
* accessing sensitive payment card information.
|
|
43
|
+
*
|
|
44
|
+
* @param promptMessage - Message to display in the biometric prompt
|
|
45
|
+
* @returns Result indicating success or failure with reason
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* const result = await authenticateWithBiometrics('Authenticate to view card details');
|
|
50
|
+
* if (result.success) {
|
|
51
|
+
* // Proceed with generating session credentials
|
|
52
|
+
* } else {
|
|
53
|
+
* // Handle failure based on result.error.reason
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function authenticateWithBiometrics(promptMessage?: string): Promise<BiometricResult>;
|
|
58
|
+
/**
|
|
59
|
+
* Gets a user-friendly description of the biometric type
|
|
60
|
+
*
|
|
61
|
+
* @param biometryType - The biometry type from the device
|
|
62
|
+
* @returns Human-readable string for the biometry type
|
|
63
|
+
*/
|
|
64
|
+
export declare function getBiometryTypeLabel(biometryType: BiometryType | null): string;
|
|
65
|
+
export { BiometryTypes };
|
|
66
|
+
//# sourceMappingURL=biometricUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"biometricUtils.d.ts","sourceRoot":"","sources":["../src/biometricUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAA8B,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAElG;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,4CAA4C;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,6CAA6C;IAC7C,KAAK,CAAC,EAAE;QACN,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,eAAe,GAAG,cAAc,CAAC;QAClE,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,wDAAwD;IACxD,SAAS,EAAE,OAAO,CAAC;IACnB,4EAA4E;IAC5E,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC;AAOD;;;;GAIG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAe3E;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,0BAA0B,CAC9C,aAAa,GAAE,MAA4C,GAC1D,OAAO,CAAC,eAAe,CAAC,CAmF1B;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,GAAG,MAAM,CAW9E;AAGD,OAAO,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Biometric Authentication Utilities
|
|
4
|
+
*
|
|
5
|
+
* Provides cross-platform biometric authentication for card details access.
|
|
6
|
+
* Supports Face ID, Touch ID, and Android biometrics.
|
|
7
|
+
*
|
|
8
|
+
* @requires react-native-biometrics - npm install react-native-biometrics
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.BiometryTypes = void 0;
|
|
45
|
+
exports.isBiometricAvailable = isBiometricAvailable;
|
|
46
|
+
exports.authenticateWithBiometrics = authenticateWithBiometrics;
|
|
47
|
+
exports.getBiometryTypeLabel = getBiometryTypeLabel;
|
|
48
|
+
const react_native_biometrics_1 = __importStar(require("react-native-biometrics"));
|
|
49
|
+
Object.defineProperty(exports, "BiometryTypes", { enumerable: true, get: function () { return react_native_biometrics_1.BiometryTypes; } });
|
|
50
|
+
// Singleton instance of ReactNativeBiometrics
|
|
51
|
+
const rnBiometrics = new react_native_biometrics_1.default({
|
|
52
|
+
allowDeviceCredentials: false, // Only allow biometric, not PIN/password fallback
|
|
53
|
+
});
|
|
54
|
+
/**
|
|
55
|
+
* Checks if biometric authentication is available on the device
|
|
56
|
+
*
|
|
57
|
+
* @returns Object containing availability status and biometry type
|
|
58
|
+
*/
|
|
59
|
+
async function isBiometricAvailable() {
|
|
60
|
+
try {
|
|
61
|
+
const { available, biometryType } = await rnBiometrics.isSensorAvailable();
|
|
62
|
+
return {
|
|
63
|
+
available,
|
|
64
|
+
biometryType: biometryType || null,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.error('[BiometricUtils] Error checking biometric availability:', error);
|
|
69
|
+
return {
|
|
70
|
+
available: false,
|
|
71
|
+
biometryType: null,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Prompts the user for biometric authentication
|
|
77
|
+
*
|
|
78
|
+
* This function should be called before generating session credentials
|
|
79
|
+
* for viewing card details. It ensures proper user verification before
|
|
80
|
+
* accessing sensitive payment card information.
|
|
81
|
+
*
|
|
82
|
+
* @param promptMessage - Message to display in the biometric prompt
|
|
83
|
+
* @returns Result indicating success or failure with reason
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const result = await authenticateWithBiometrics('Authenticate to view card details');
|
|
88
|
+
* if (result.success) {
|
|
89
|
+
* // Proceed with generating session credentials
|
|
90
|
+
* } else {
|
|
91
|
+
* // Handle failure based on result.error.reason
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
async function authenticateWithBiometrics(promptMessage = 'Authenticate to view card details') {
|
|
96
|
+
try {
|
|
97
|
+
// First check if biometrics are available
|
|
98
|
+
const { available, biometryType } = await rnBiometrics.isSensorAvailable();
|
|
99
|
+
if (!available) {
|
|
100
|
+
console.log('[BiometricUtils] Biometrics not available on device');
|
|
101
|
+
return {
|
|
102
|
+
success: false,
|
|
103
|
+
error: {
|
|
104
|
+
reason: 'not_available',
|
|
105
|
+
message: 'Biometric authentication is not available on this device',
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
// Check if biometrics are enrolled
|
|
110
|
+
const { keysExist } = await rnBiometrics.biometricKeysExist();
|
|
111
|
+
// Note: Even without keys, simplePrompt should work for basic authentication
|
|
112
|
+
// The keysExist check is more for cryptographic operations
|
|
113
|
+
console.log(`[BiometricUtils] Attempting biometric auth. Type: ${biometryType}, Keys exist: ${keysExist}`);
|
|
114
|
+
// Perform the biometric authentication
|
|
115
|
+
const { success, error } = await rnBiometrics.simplePrompt({
|
|
116
|
+
promptMessage,
|
|
117
|
+
cancelButtonText: 'Cancel',
|
|
118
|
+
});
|
|
119
|
+
if (success) {
|
|
120
|
+
console.log('[BiometricUtils] Biometric authentication successful');
|
|
121
|
+
return { success: true };
|
|
122
|
+
}
|
|
123
|
+
// Handle various failure reasons
|
|
124
|
+
console.log('[BiometricUtils] Biometric authentication failed:', error);
|
|
125
|
+
// Parse the error message to determine the reason
|
|
126
|
+
const errorMessage = error || 'Authentication failed';
|
|
127
|
+
let reason = 'failed';
|
|
128
|
+
if (errorMessage.toLowerCase().includes('cancel') ||
|
|
129
|
+
errorMessage.toLowerCase().includes('user cancel')) {
|
|
130
|
+
reason = 'cancelled';
|
|
131
|
+
}
|
|
132
|
+
else if (errorMessage.toLowerCase().includes('not enrolled') ||
|
|
133
|
+
errorMessage.toLowerCase().includes('no fingerprint') ||
|
|
134
|
+
errorMessage.toLowerCase().includes('no face')) {
|
|
135
|
+
reason = 'not_enrolled';
|
|
136
|
+
}
|
|
137
|
+
else if (errorMessage.toLowerCase().includes('not available') ||
|
|
138
|
+
errorMessage.toLowerCase().includes('not supported')) {
|
|
139
|
+
reason = 'not_available';
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
success: false,
|
|
143
|
+
error: {
|
|
144
|
+
reason,
|
|
145
|
+
message: errorMessage,
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
console.error('[BiometricUtils] Biometric authentication error:', error);
|
|
151
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
152
|
+
return {
|
|
153
|
+
success: false,
|
|
154
|
+
error: {
|
|
155
|
+
reason: 'failed',
|
|
156
|
+
message: errorMessage,
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Gets a user-friendly description of the biometric type
|
|
163
|
+
*
|
|
164
|
+
* @param biometryType - The biometry type from the device
|
|
165
|
+
* @returns Human-readable string for the biometry type
|
|
166
|
+
*/
|
|
167
|
+
function getBiometryTypeLabel(biometryType) {
|
|
168
|
+
switch (biometryType) {
|
|
169
|
+
case react_native_biometrics_1.BiometryTypes.FaceID:
|
|
170
|
+
return 'Face ID';
|
|
171
|
+
case react_native_biometrics_1.BiometryTypes.TouchID:
|
|
172
|
+
return 'Touch ID';
|
|
173
|
+
case react_native_biometrics_1.BiometryTypes.Biometrics:
|
|
174
|
+
return 'Biometrics';
|
|
175
|
+
default:
|
|
176
|
+
return 'Biometric Authentication';
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=biometricUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"biometricUtils.js","sourceRoot":"","sources":["../src/biometricUtils.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* Widget SDK Configuration
|
|
3
3
|
* Environment-based configuration for the widget URL
|
|
4
4
|
*/
|
|
5
|
-
import { WidgetEnvironment } from
|
|
5
|
+
import { WidgetEnvironment } from "./types";
|
|
6
6
|
/**
|
|
7
7
|
* Widget URLs by environment
|
|
8
8
|
*/
|
|
9
9
|
export declare const WIDGET_URLS: {
|
|
10
10
|
readonly development: "https://oobit-widget-dev.web.app";
|
|
11
|
-
readonly production: "https://widget.
|
|
11
|
+
readonly production: "https://oobit-widget.web.app";
|
|
12
12
|
};
|
|
13
13
|
/**
|
|
14
14
|
* Get the widget URL for the specified environment
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE5C;;GAEG;AACH,eAAO,MAAM,WAAW;;;CAGd,CAAC;AAEX;;;;GAIG;AACH,wBAAgB,YAAY,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE5C;;GAEG;AACH,eAAO,MAAM,WAAW;;;CAGd,CAAC;AAEX;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,WAAW,GAAE,iBAAgC,GAC5C,MAAM,CAER"}
|
package/dist/config.js
CHANGED
|
@@ -11,14 +11,14 @@ exports.getWidgetUrl = getWidgetUrl;
|
|
|
11
11
|
*/
|
|
12
12
|
exports.WIDGET_URLS = {
|
|
13
13
|
development: "https://oobit-widget-dev.web.app",
|
|
14
|
-
production: "https://widget.
|
|
14
|
+
production: "https://oobit-widget.web.app",
|
|
15
15
|
};
|
|
16
16
|
/**
|
|
17
17
|
* Get the widget URL for the specified environment
|
|
18
18
|
* @param environment - The environment to use (defaults to 'production')
|
|
19
19
|
* @returns The widget URL for the specified environment
|
|
20
20
|
*/
|
|
21
|
-
function getWidgetUrl(environment =
|
|
21
|
+
function getWidgetUrl(environment = "production") {
|
|
22
22
|
return exports.WIDGET_URLS[environment];
|
|
23
23
|
}
|
|
24
24
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAiBH,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAiBH,oCAIC;AAjBD;;GAEG;AACU,QAAA,WAAW,GAAG;IACzB,WAAW,EAAE,kCAAkC;IAC/C,UAAU,EAAE,8BAA8B;CAClC,CAAC;AAEX;;;;GAIG;AACH,SAAgB,YAAY,CAC1B,cAAiC,YAAY;IAE7C,OAAO,mBAAW,CAAC,WAAW,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crypto Utilities for Card Details Session Generation
|
|
3
|
+
*
|
|
4
|
+
* CRITICAL: This implementation MUST match Android's PublicKeyCryptoHelper.kt exactly:
|
|
5
|
+
* - RSA Algorithm: RSA/ECB/OAEPWithSHA-1AndMGF1Padding
|
|
6
|
+
* - Secret Key: UUID without dashes (32 hex chars = 16 bytes = 128-bit)
|
|
7
|
+
* - Input to RSA: secretKey as Base64 string
|
|
8
|
+
* - Output: encrypted sessionId as Base64 string
|
|
9
|
+
*
|
|
10
|
+
* Uses react-native-quick-crypto for native RSA-OAEP encryption
|
|
11
|
+
* (OpenSSL on Android, CommonCrypto on iOS)
|
|
12
|
+
*
|
|
13
|
+
* @requires react-native-quick-crypto - npm install react-native-quick-crypto
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Generates a random hex key matching Android's generateRandomHexKey()
|
|
17
|
+
*
|
|
18
|
+
* Creates a UUID v4 without dashes = 32 hex characters = 16 bytes = 128-bit key
|
|
19
|
+
* This matches the format used in Android's PublicKeyCryptoHelper
|
|
20
|
+
*
|
|
21
|
+
* @returns 32-character hexadecimal string
|
|
22
|
+
*/
|
|
23
|
+
export declare function generateRandomHexKey(): string;
|
|
24
|
+
/**
|
|
25
|
+
* Converts a hex string to Base64 encoding
|
|
26
|
+
* Matches Android's hexToBase64() method
|
|
27
|
+
*
|
|
28
|
+
* @param hexString - Hexadecimal string (must have even length)
|
|
29
|
+
* @returns Base64 encoded string
|
|
30
|
+
*/
|
|
31
|
+
export declare function hexToBase64(hexString: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Encrypts data using RSA with OAEP-SHA1 padding (native implementation)
|
|
34
|
+
*
|
|
35
|
+
* MUST match Android's RSA/ECB/OAEPWithSHA-1AndMGF1Padding algorithm
|
|
36
|
+
* Uses native crypto (OpenSSL on Android, CommonCrypto on iOS)
|
|
37
|
+
*
|
|
38
|
+
* @param data - Plain text data to encrypt (Base64 string of the secret key)
|
|
39
|
+
* @param publicKeyPem - RSA public key in PEM format
|
|
40
|
+
* @returns Encrypted data as Base64 string
|
|
41
|
+
* @throws Error if encryption fails
|
|
42
|
+
*/
|
|
43
|
+
export declare function encryptWithRSA(data: string, publicKeyPem: string): string;
|
|
44
|
+
/**
|
|
45
|
+
* Generates session credentials for card details API request
|
|
46
|
+
*
|
|
47
|
+
* This is the main function that creates the cryptographically linked
|
|
48
|
+
* sessionId + secretKey pair, matching Android's PublicKeyCryptoHelper.generateSessionId()
|
|
49
|
+
*
|
|
50
|
+
* Flow:
|
|
51
|
+
* 1. Generate random secretKeyHex (UUID without dashes)
|
|
52
|
+
* 2. Convert secretKeyHex to Base64
|
|
53
|
+
* 3. Encrypt Base64 key with RSA public key → sessionId
|
|
54
|
+
* 4. Return both secretKeyHex (for client-side decryption) and sessionId (for API header)
|
|
55
|
+
*
|
|
56
|
+
* @param publicKeyPem - RSA public key in PEM format (from widget)
|
|
57
|
+
* @returns Object containing:
|
|
58
|
+
* - secretKeyHex: Keep on device for AES-GCM decryption (32 hex chars)
|
|
59
|
+
* - sessionId: Send to API as SessionId header (RSA-encrypted, Base64)
|
|
60
|
+
* @throws Error if key generation or encryption fails
|
|
61
|
+
*/
|
|
62
|
+
export declare function generateSessionCredentials(publicKeyPem: string): SessionCredentials;
|
|
63
|
+
export interface SessionCredentials {
|
|
64
|
+
secretKeyHex: string;
|
|
65
|
+
sessionId: string;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=cryptoUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cryptoUtils.d.ts","sourceRoot":"","sources":["../src/cryptoUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAU7C;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAkCrD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAqBzE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,0BAA0B,CAAC,YAAY,EAAE,MAAM,GAAG,kBAAkB,CAqBnF;AAGD,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Crypto Utilities for Card Details Session Generation
|
|
4
|
+
*
|
|
5
|
+
* CRITICAL: This implementation MUST match Android's PublicKeyCryptoHelper.kt exactly:
|
|
6
|
+
* - RSA Algorithm: RSA/ECB/OAEPWithSHA-1AndMGF1Padding
|
|
7
|
+
* - Secret Key: UUID without dashes (32 hex chars = 16 bytes = 128-bit)
|
|
8
|
+
* - Input to RSA: secretKey as Base64 string
|
|
9
|
+
* - Output: encrypted sessionId as Base64 string
|
|
10
|
+
*
|
|
11
|
+
* Uses react-native-quick-crypto for native RSA-OAEP encryption
|
|
12
|
+
* (OpenSSL on Android, CommonCrypto on iOS)
|
|
13
|
+
*
|
|
14
|
+
* @requires react-native-quick-crypto - npm install react-native-quick-crypto
|
|
15
|
+
*/
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.generateRandomHexKey = generateRandomHexKey;
|
|
21
|
+
exports.hexToBase64 = hexToBase64;
|
|
22
|
+
exports.encryptWithRSA = encryptWithRSA;
|
|
23
|
+
exports.generateSessionCredentials = generateSessionCredentials;
|
|
24
|
+
const react_native_quick_crypto_1 = __importDefault(require("react-native-quick-crypto"));
|
|
25
|
+
/**
|
|
26
|
+
* Generates a random hex key matching Android's generateRandomHexKey()
|
|
27
|
+
*
|
|
28
|
+
* Creates a UUID v4 without dashes = 32 hex characters = 16 bytes = 128-bit key
|
|
29
|
+
* This matches the format used in Android's PublicKeyCryptoHelper
|
|
30
|
+
*
|
|
31
|
+
* @returns 32-character hexadecimal string
|
|
32
|
+
*/
|
|
33
|
+
function generateRandomHexKey() {
|
|
34
|
+
// Generate UUID v4 pattern and remove dashes
|
|
35
|
+
// This matches Android's java.util.UUID.randomUUID().toString().replace("-", "")
|
|
36
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
|
|
37
|
+
.replace(/[xy]/g, (c) => {
|
|
38
|
+
const r = (Math.random() * 16) | 0;
|
|
39
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
40
|
+
return v.toString(16);
|
|
41
|
+
})
|
|
42
|
+
.replace(/-/g, '');
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Converts a hex string to Base64 encoding
|
|
46
|
+
* Matches Android's hexToBase64() method
|
|
47
|
+
*
|
|
48
|
+
* @param hexString - Hexadecimal string (must have even length)
|
|
49
|
+
* @returns Base64 encoded string
|
|
50
|
+
*/
|
|
51
|
+
function hexToBase64(hexString) {
|
|
52
|
+
// Convert hex string to binary string
|
|
53
|
+
let binaryString = '';
|
|
54
|
+
for (let i = 0; i < hexString.length; i += 2) {
|
|
55
|
+
const byte = parseInt(hexString.substring(i, i + 2), 16);
|
|
56
|
+
binaryString += String.fromCharCode(byte);
|
|
57
|
+
}
|
|
58
|
+
// Use btoa for Base64 encoding (available in React Native with Hermes)
|
|
59
|
+
if (typeof btoa === 'function') {
|
|
60
|
+
return btoa(binaryString);
|
|
61
|
+
}
|
|
62
|
+
// Fallback: manual Base64 encoding
|
|
63
|
+
const base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
64
|
+
let result = '';
|
|
65
|
+
let i = 0;
|
|
66
|
+
while (i < binaryString.length) {
|
|
67
|
+
const a = binaryString.charCodeAt(i++);
|
|
68
|
+
const b = binaryString.charCodeAt(i++);
|
|
69
|
+
const c = binaryString.charCodeAt(i++);
|
|
70
|
+
const triplet = (a << 16) | ((b || 0) << 8) | (c || 0);
|
|
71
|
+
result +=
|
|
72
|
+
base64Chars[(triplet >> 18) & 0x3f] +
|
|
73
|
+
base64Chars[(triplet >> 12) & 0x3f] +
|
|
74
|
+
(isNaN(b) ? '=' : base64Chars[(triplet >> 6) & 0x3f]) +
|
|
75
|
+
(isNaN(c) ? '=' : base64Chars[triplet & 0x3f]);
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Encrypts data using RSA with OAEP-SHA1 padding (native implementation)
|
|
81
|
+
*
|
|
82
|
+
* MUST match Android's RSA/ECB/OAEPWithSHA-1AndMGF1Padding algorithm
|
|
83
|
+
* Uses native crypto (OpenSSL on Android, CommonCrypto on iOS)
|
|
84
|
+
*
|
|
85
|
+
* @param data - Plain text data to encrypt (Base64 string of the secret key)
|
|
86
|
+
* @param publicKeyPem - RSA public key in PEM format
|
|
87
|
+
* @returns Encrypted data as Base64 string
|
|
88
|
+
* @throws Error if encryption fails
|
|
89
|
+
*/
|
|
90
|
+
function encryptWithRSA(data, publicKeyPem) {
|
|
91
|
+
try {
|
|
92
|
+
// Convert string to Buffer
|
|
93
|
+
const dataBuffer = Buffer.from(data, 'utf8');
|
|
94
|
+
// Encrypt using RSA-OAEP with SHA-1 (matches Android's OAEPWithSHA-1AndMGF1Padding)
|
|
95
|
+
const encrypted = react_native_quick_crypto_1.default.publicEncrypt({
|
|
96
|
+
key: publicKeyPem,
|
|
97
|
+
padding: react_native_quick_crypto_1.default.constants.RSA_PKCS1_OAEP_PADDING,
|
|
98
|
+
oaepHash: 'sha1',
|
|
99
|
+
}, dataBuffer);
|
|
100
|
+
// Return as Base64 string
|
|
101
|
+
return encrypted.toString('base64');
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
console.error('[CryptoUtils] RSA encryption failed:', error);
|
|
105
|
+
throw new Error('Failed to encrypt session data');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Generates session credentials for card details API request
|
|
110
|
+
*
|
|
111
|
+
* This is the main function that creates the cryptographically linked
|
|
112
|
+
* sessionId + secretKey pair, matching Android's PublicKeyCryptoHelper.generateSessionId()
|
|
113
|
+
*
|
|
114
|
+
* Flow:
|
|
115
|
+
* 1. Generate random secretKeyHex (UUID without dashes)
|
|
116
|
+
* 2. Convert secretKeyHex to Base64
|
|
117
|
+
* 3. Encrypt Base64 key with RSA public key → sessionId
|
|
118
|
+
* 4. Return both secretKeyHex (for client-side decryption) and sessionId (for API header)
|
|
119
|
+
*
|
|
120
|
+
* @param publicKeyPem - RSA public key in PEM format (from widget)
|
|
121
|
+
* @returns Object containing:
|
|
122
|
+
* - secretKeyHex: Keep on device for AES-GCM decryption (32 hex chars)
|
|
123
|
+
* - sessionId: Send to API as SessionId header (RSA-encrypted, Base64)
|
|
124
|
+
* @throws Error if key generation or encryption fails
|
|
125
|
+
*/
|
|
126
|
+
function generateSessionCredentials(publicKeyPem) {
|
|
127
|
+
// Validate public key
|
|
128
|
+
if (!publicKeyPem || !publicKeyPem.includes('BEGIN PUBLIC KEY')) {
|
|
129
|
+
throw new Error('Invalid RSA public key format');
|
|
130
|
+
}
|
|
131
|
+
// Step 1: Generate random secret key (matches Android's generateRandomHexKey)
|
|
132
|
+
const secretKeyHex = generateRandomHexKey();
|
|
133
|
+
// Step 2: Convert to Base64 (matches Android's hexToBase64)
|
|
134
|
+
const secretKeyBase64 = hexToBase64(secretKeyHex);
|
|
135
|
+
// Step 3: Encrypt with RSA public key (matches Android's encryptWithPublicKey)
|
|
136
|
+
const sessionId = encryptWithRSA(secretKeyBase64, publicKeyPem);
|
|
137
|
+
console.log('[CryptoUtils] Session credentials generated successfully');
|
|
138
|
+
return {
|
|
139
|
+
secretKeyHex,
|
|
140
|
+
sessionId,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=cryptoUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cryptoUtils.js","sourceRoot":"","sources":["../src/cryptoUtils.ts"],"names":[],"mappings":"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"}
|