@oxyhq/services 5.16.35 → 5.16.37
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 +8 -26
- package/lib/commonjs/core/OxyServices.base.js.map +1 -1
- package/lib/commonjs/core/mixins/OxyServices.user.js.map +1 -1
- package/lib/commonjs/core/mixins/OxyServices.utility.js.map +1 -1
- package/lib/commonjs/crypto/README.md +142 -0
- package/lib/commonjs/crypto/core.js +147 -0
- package/lib/commonjs/crypto/core.js.map +1 -0
- package/lib/commonjs/crypto/index.js +16 -0
- package/lib/commonjs/crypto/index.js.map +1 -1
- package/lib/commonjs/crypto/keyManager.js +19 -22
- package/lib/commonjs/crypto/keyManager.js.map +1 -1
- package/lib/commonjs/crypto/signatureService.js +116 -28
- package/lib/commonjs/crypto/signatureService.js.map +1 -1
- package/lib/commonjs/index.js +0 -12
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/interfaces.js +10 -11
- package/lib/commonjs/models/interfaces.js.map +1 -1
- package/lib/commonjs/node/index.js +10 -1
- package/lib/commonjs/node/index.js.map +1 -1
- package/lib/commonjs/node/signatureService.js +107 -0
- package/lib/commonjs/node/signatureService.js.map +1 -0
- package/lib/commonjs/ui/context/OxyContext.js +23 -0
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +29 -2
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useLanguageManagement.js.map +1 -1
- package/lib/commonjs/ui/hooks/useLanguageManagement.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/commonjs/ui/index.js +0 -2
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/OxyAuthScreen.js +11 -2
- package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/module/core/OxyServices.base.js.map +1 -1
- package/lib/module/core/mixins/OxyServices.user.js.map +1 -1
- package/lib/module/core/mixins/OxyServices.utility.js.map +1 -1
- package/lib/module/crypto/README.md +142 -0
- package/lib/module/crypto/core.js +133 -0
- package/lib/module/crypto/core.js.map +1 -0
- package/lib/module/crypto/index.js +3 -9
- package/lib/module/crypto/index.js.map +1 -1
- package/lib/module/crypto/keyManager.js +19 -22
- package/lib/module/crypto/keyManager.js.map +1 -1
- package/lib/module/crypto/signatureService.js +113 -23
- package/lib/module/crypto/signatureService.js.map +1 -1
- package/lib/module/index.js +0 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/interfaces.js +10 -11
- package/lib/module/models/interfaces.js.map +1 -1
- package/lib/module/node/index.js +3 -0
- package/lib/module/node/index.js.map +1 -1
- package/lib/module/node/signatureService.js +101 -0
- package/lib/module/node/signatureService.js.map +1 -0
- package/lib/module/ui/context/OxyContext.js +23 -0
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +29 -2
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/context/hooks/useLanguageManagement.js.map +1 -1
- package/lib/module/ui/hooks/useLanguageManagement.js.map +1 -1
- package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/module/ui/index.js +0 -1
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/OxyAuthScreen.js +11 -2
- package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/typescript/core/OxyServices.base.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.analytics.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.assets.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.auth.d.ts +1 -1
- package/lib/typescript/core/mixins/OxyServices.auth.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.developer.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.devices.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.karma.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.language.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.location.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.payment.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.privacy.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.security.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.user.d.ts +1 -2
- package/lib/typescript/core/mixins/OxyServices.user.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.utility.d.ts.map +1 -1
- package/lib/typescript/core/mixins/index.d.ts +13 -13
- package/lib/typescript/core/mixins/index.d.ts.map +1 -1
- package/lib/typescript/core/services/SessionService.d.ts +1 -1
- package/lib/typescript/core/services/SessionService.d.ts.map +1 -1
- package/lib/typescript/crypto/core.d.ts +56 -0
- package/lib/typescript/crypto/core.d.ts.map +1 -0
- package/lib/typescript/crypto/index.d.ts +1 -9
- package/lib/typescript/crypto/index.d.ts.map +1 -1
- package/lib/typescript/crypto/keyManager.d.ts +13 -1
- package/lib/typescript/crypto/keyManager.d.ts.map +1 -1
- package/lib/typescript/crypto/signatureService.d.ts +15 -9
- package/lib/typescript/crypto/signatureService.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +1 -2
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/models/interfaces.d.ts +68 -15
- package/lib/typescript/models/interfaces.d.ts.map +1 -1
- package/lib/typescript/node/index.d.ts +1 -0
- package/lib/typescript/node/index.d.ts.map +1 -1
- package/lib/typescript/node/signatureService.d.ts +55 -0
- package/lib/typescript/node/signatureService.d.ts.map +1 -0
- package/lib/typescript/ui/context/OxyContext.d.ts +1 -2
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts +1 -2
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useLanguageManagement.d.ts +1 -2
- package/lib/typescript/ui/context/hooks/useLanguageManagement.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts +1 -1
- package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts +1 -1
- package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useLanguageManagement.d.ts +1 -2
- package/lib/typescript/ui/hooks/useLanguageManagement.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useSessionManagement.d.ts +1 -2
- package/lib/typescript/ui/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/ui/index.d.ts +1 -1
- package/lib/typescript/ui/index.d.ts.map +1 -1
- package/lib/typescript/ui/screens/OxyAuthScreen.d.ts.map +1 -1
- package/lib/typescript/ui/stores/authStore.d.ts +1 -1
- package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
- package/lib/typescript/ui/utils/avatarUtils.d.ts +1 -1
- package/lib/typescript/ui/utils/avatarUtils.d.ts.map +1 -1
- package/package.json +6 -1
- package/src/core/OxyServices.base.ts +1 -2
- package/src/core/mixins/OxyServices.auth.ts +1 -1
- package/src/core/mixins/OxyServices.user.ts +1 -2
- package/src/core/mixins/OxyServices.utility.ts +1 -2
- package/src/core/services/SessionService.ts +1 -1
- package/src/crypto/README.md +142 -0
- package/src/crypto/__tests__/core.test.ts +203 -0
- package/src/crypto/core.ts +142 -0
- package/src/crypto/index.ts +3 -10
- package/src/crypto/keyManager.ts +25 -21
- package/src/crypto/signatureService.ts +137 -36
- package/src/index.ts +2 -3
- package/src/models/interfaces.ts +73 -21
- package/src/node/index.ts +3 -0
- package/src/node/signatureService.ts +126 -0
- package/src/ui/context/OxyContext.tsx +26 -2
- package/src/ui/context/hooks/useAuthOperations.ts +33 -4
- package/src/ui/context/hooks/useLanguageManagement.ts +1 -2
- package/src/ui/hooks/auth/index.ts +2 -0
- package/src/ui/hooks/mutations/useAccountMutations.ts +1 -1
- package/src/ui/hooks/mutations/useServicesMutations.ts +1 -1
- package/src/ui/hooks/queries/useAccountQueries.ts +1 -1
- package/src/ui/hooks/useLanguageManagement.ts +1 -2
- package/src/ui/hooks/useSessionManagement.ts +1 -2
- package/src/ui/index.ts +1 -2
- package/src/ui/screens/AccountSettingsScreen.tsx +6 -6
- package/src/ui/screens/AccountSwitcherScreen.tsx +1 -1
- package/src/ui/screens/OxyAuthScreen.tsx +11 -2
- package/src/ui/screens/ProfileScreen.tsx +1 -1
- package/src/ui/stores/authStore.ts +1 -1
- package/src/ui/types/navigation.ts +1 -1
- package/src/ui/utils/avatarUtils.ts +1 -1
- package/lib/commonjs/core/services/AuthService.js +0 -156
- package/lib/commonjs/core/services/AuthService.js.map +0 -1
- package/lib/commonjs/core/services/SessionTransportService.js +0 -64
- package/lib/commonjs/core/services/SessionTransportService.js.map +0 -1
- package/lib/commonjs/core/services/UserService.js +0 -123
- package/lib/commonjs/core/services/UserService.js.map +0 -1
- package/lib/commonjs/core/services/index.js +0 -34
- package/lib/commonjs/core/services/index.js.map +0 -1
- package/lib/commonjs/shared/crypto/messageBuilders.js +0 -79
- package/lib/commonjs/shared/crypto/messageBuilders.js.map +0 -1
- package/lib/commonjs/shared/crypto/platform.js +0 -118
- package/lib/commonjs/shared/crypto/platform.js.map +0 -1
- package/lib/commonjs/shared/crypto/signature.js +0 -191
- package/lib/commonjs/shared/crypto/signature.js.map +0 -1
- package/lib/commonjs/shared/index.js +0 -94
- package/lib/commonjs/shared/index.js.map +0 -1
- package/lib/commonjs/shared/models/index.js +0 -2
- package/lib/commonjs/shared/models/index.js.map +0 -1
- package/lib/commonjs/shared/transport/index.js +0 -260
- package/lib/commonjs/shared/transport/index.js.map +0 -1
- package/lib/commonjs/shared/utils/index.js +0 -82
- package/lib/commonjs/shared/utils/index.js.map +0 -1
- package/lib/module/core/services/AuthService.js +0 -151
- package/lib/module/core/services/AuthService.js.map +0 -1
- package/lib/module/core/services/SessionTransportService.js +0 -59
- package/lib/module/core/services/SessionTransportService.js.map +0 -1
- package/lib/module/core/services/UserService.js +0 -118
- package/lib/module/core/services/UserService.js.map +0 -1
- package/lib/module/core/services/index.js +0 -16
- package/lib/module/core/services/index.js.map +0 -1
- package/lib/module/shared/crypto/messageBuilders.js +0 -70
- package/lib/module/shared/crypto/messageBuilders.js.map +0 -1
- package/lib/module/shared/crypto/platform.js +0 -112
- package/lib/module/shared/crypto/platform.js.map +0 -1
- package/lib/module/shared/crypto/signature.js +0 -186
- package/lib/module/shared/crypto/signature.js.map +0 -1
- package/lib/module/shared/index.js +0 -30
- package/lib/module/shared/index.js.map +0 -1
- package/lib/module/shared/models/index.js +0 -2
- package/lib/module/shared/models/index.js.map +0 -1
- package/lib/module/shared/transport/index.js +0 -254
- package/lib/module/shared/transport/index.js.map +0 -1
- package/lib/module/shared/utils/index.js +0 -74
- package/lib/module/shared/utils/index.js.map +0 -1
- package/lib/typescript/core/services/AuthService.d.ts +0 -50
- package/lib/typescript/core/services/AuthService.d.ts.map +0 -1
- package/lib/typescript/core/services/SessionTransportService.d.ts +0 -31
- package/lib/typescript/core/services/SessionTransportService.d.ts.map +0 -1
- package/lib/typescript/core/services/UserService.d.ts +0 -39
- package/lib/typescript/core/services/UserService.d.ts.map +0 -1
- package/lib/typescript/core/services/index.d.ts +0 -13
- package/lib/typescript/core/services/index.d.ts.map +0 -1
- package/lib/typescript/shared/crypto/messageBuilders.d.ts +0 -38
- package/lib/typescript/shared/crypto/messageBuilders.d.ts.map +0 -1
- package/lib/typescript/shared/crypto/platform.d.ts +0 -54
- package/lib/typescript/shared/crypto/platform.d.ts.map +0 -1
- package/lib/typescript/shared/crypto/signature.d.ts +0 -72
- package/lib/typescript/shared/crypto/signature.d.ts.map +0 -1
- package/lib/typescript/shared/index.d.ts +0 -20
- package/lib/typescript/shared/index.d.ts.map +0 -1
- package/lib/typescript/shared/models/index.d.ts +0 -163
- package/lib/typescript/shared/models/index.d.ts.map +0 -1
- package/lib/typescript/shared/transport/index.d.ts +0 -73
- package/lib/typescript/shared/transport/index.d.ts.map +0 -1
- package/lib/typescript/shared/utils/index.d.ts +0 -28
- package/lib/typescript/shared/utils/index.d.ts.map +0 -1
- package/src/core/services/AuthService.ts +0 -153
- package/src/core/services/SessionTransportService.ts +0 -69
- package/src/core/services/UserService.ts +0 -125
- package/src/core/services/index.ts +0 -14
- package/src/shared/crypto/messageBuilders.ts +0 -89
- package/src/shared/crypto/platform.ts +0 -140
- package/src/shared/crypto/signature.ts +0 -235
- package/src/shared/index.ts +0 -28
- package/src/shared/models/index.ts +0 -173
- package/src/shared/transport/index.ts +0 -349
- package/src/shared/utils/index.ts +0 -73
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js Signature Service
|
|
3
|
+
*
|
|
4
|
+
* Provides synchronous signature operations for Node.js backend.
|
|
5
|
+
* Uses Node's crypto module for hashing and the shared core for verification.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import crypto from 'crypto';
|
|
9
|
+
import {
|
|
10
|
+
verifySignatureCore,
|
|
11
|
+
isValidPublicKey,
|
|
12
|
+
isTimestampFresh,
|
|
13
|
+
buildAuthMessage,
|
|
14
|
+
buildRegistrationMessage,
|
|
15
|
+
buildRequestMessage,
|
|
16
|
+
shortenPublicKey,
|
|
17
|
+
CHALLENGE_TTL_MS,
|
|
18
|
+
MAX_SIGNATURE_AGE_MS,
|
|
19
|
+
} from '../crypto/core';
|
|
20
|
+
|
|
21
|
+
export class SignatureService {
|
|
22
|
+
/**
|
|
23
|
+
* Generate a random challenge string
|
|
24
|
+
*/
|
|
25
|
+
static generateChallenge(): string {
|
|
26
|
+
return crypto.randomBytes(32).toString('hex');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Compute SHA-256 hash of a message (synchronous)
|
|
31
|
+
*/
|
|
32
|
+
static hashMessage(message: string): string {
|
|
33
|
+
return crypto.createHash('sha256').update(message).digest('hex');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Verify an ECDSA signature (synchronous)
|
|
38
|
+
*
|
|
39
|
+
* @param message - The original message that was signed
|
|
40
|
+
* @param signature - The signature in DER format (hex encoded)
|
|
41
|
+
* @param publicKey - The public key (hex encoded, uncompressed)
|
|
42
|
+
* @returns true if the signature is valid
|
|
43
|
+
*/
|
|
44
|
+
static verifySignature(message: string, signature: string, publicKey: string): boolean {
|
|
45
|
+
const messageHash = SignatureService.hashMessage(message);
|
|
46
|
+
return verifySignatureCore(messageHash, signature, publicKey);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Verify an authentication challenge response
|
|
51
|
+
*
|
|
52
|
+
* @param publicKey - The user's public key
|
|
53
|
+
* @param challenge - The original challenge string
|
|
54
|
+
* @param signature - The signature of the auth message
|
|
55
|
+
* @param timestamp - The timestamp when the signature was created
|
|
56
|
+
* @returns true if the challenge response is valid
|
|
57
|
+
*/
|
|
58
|
+
static verifyChallengeResponse(
|
|
59
|
+
publicKey: string,
|
|
60
|
+
challenge: string,
|
|
61
|
+
signature: string,
|
|
62
|
+
timestamp: number
|
|
63
|
+
): boolean {
|
|
64
|
+
// Check timestamp is not too old
|
|
65
|
+
if (!isTimestampFresh(timestamp, CHALLENGE_TTL_MS)) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Build the message and verify signature
|
|
70
|
+
const message = buildAuthMessage(publicKey, challenge, timestamp);
|
|
71
|
+
return SignatureService.verifySignature(message, signature, publicKey);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Verify a registration signature
|
|
76
|
+
* Signature format: oxy:register:{publicKey}:{timestamp}
|
|
77
|
+
*/
|
|
78
|
+
static verifyRegistrationSignature(
|
|
79
|
+
publicKey: string,
|
|
80
|
+
signature: string,
|
|
81
|
+
timestamp: number
|
|
82
|
+
): boolean {
|
|
83
|
+
// Check timestamp freshness
|
|
84
|
+
if (!isTimestampFresh(timestamp, MAX_SIGNATURE_AGE_MS)) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const message = buildRegistrationMessage(publicKey, timestamp);
|
|
89
|
+
return SignatureService.verifySignature(message, signature, publicKey);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Verify a signed request
|
|
94
|
+
* Used for authenticated API operations
|
|
95
|
+
*/
|
|
96
|
+
static verifyRequestSignature(
|
|
97
|
+
publicKey: string,
|
|
98
|
+
data: Record<string, unknown>,
|
|
99
|
+
signature: string,
|
|
100
|
+
timestamp: number
|
|
101
|
+
): boolean {
|
|
102
|
+
// Check timestamp freshness
|
|
103
|
+
if (!isTimestampFresh(timestamp, MAX_SIGNATURE_AGE_MS)) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const message = buildRequestMessage(publicKey, timestamp, data);
|
|
108
|
+
return SignatureService.verifySignature(message, signature, publicKey);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Validate that a string is a valid public key
|
|
113
|
+
*/
|
|
114
|
+
static isValidPublicKey(publicKey: string): boolean {
|
|
115
|
+
return isValidPublicKey(publicKey);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Get a shortened display version of a public key
|
|
120
|
+
*/
|
|
121
|
+
static shortenPublicKey(publicKey: string): string {
|
|
122
|
+
return shortenPublicKey(publicKey);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export default SignatureService;
|
|
@@ -11,8 +11,7 @@ import {
|
|
|
11
11
|
} from 'react';
|
|
12
12
|
import { Platform } from 'react-native';
|
|
13
13
|
import { OxyServices } from '../../core';
|
|
14
|
-
import type { ApiError } from '../../models/interfaces';
|
|
15
|
-
import type { User } from '../../shared';
|
|
14
|
+
import type { User, ApiError } from '../../models/interfaces';
|
|
16
15
|
import type { ClientSession } from '../../models/session';
|
|
17
16
|
import { toast } from '../../lib/sonner';
|
|
18
17
|
import { useAuthStore, type AuthState } from '../stores/authStore';
|
|
@@ -581,10 +580,23 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
581
580
|
setTokenReady(false);
|
|
582
581
|
|
|
583
582
|
try {
|
|
583
|
+
// CRITICAL: Get current identity's public key first
|
|
584
|
+
// Only restore sessions that belong to this identity
|
|
585
|
+
const currentPublicKey = await KeyManager.getPublicKey().catch(() => null);
|
|
586
|
+
|
|
584
587
|
const storedSessionIdsJson = await storage.getItem(storageKeys.sessionIds);
|
|
585
588
|
const storedSessionIds: string[] = storedSessionIdsJson ? JSON.parse(storedSessionIdsJson) : [];
|
|
586
589
|
const storedActiveSessionId = await storage.getItem(storageKeys.activeSessionId);
|
|
587
590
|
|
|
591
|
+
// If no identity exists, clear all sessions and return
|
|
592
|
+
if (!currentPublicKey) {
|
|
593
|
+
if (storedSessionIds.length > 0 || storedActiveSessionId) {
|
|
594
|
+
await clearSessionState();
|
|
595
|
+
}
|
|
596
|
+
setTokenReady(true);
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
|
|
588
600
|
const validSessions: ClientSession[] = [];
|
|
589
601
|
|
|
590
602
|
if (storedSessionIds.length > 0) {
|
|
@@ -592,6 +604,18 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
592
604
|
try {
|
|
593
605
|
const validation = await oxyServices.validateSession(sessionId, { useHeaderValidation: true });
|
|
594
606
|
if (validation?.valid && validation.user) {
|
|
607
|
+
// CRITICAL: Verify session belongs to current identity
|
|
608
|
+
// IMPORTANT: In OxyAccounts, user.id is set to the publicKey (as confirmed by line 754 comment below)
|
|
609
|
+
// This is different from the JWT's userId field which contains MongoDB ObjectId
|
|
610
|
+
// We compare user.id (publicKey) to currentPublicKey to ensure session ownership
|
|
611
|
+
if (validation.user.id !== currentPublicKey) {
|
|
612
|
+
// Session belongs to different identity - skip it
|
|
613
|
+
if (__DEV__) {
|
|
614
|
+
logger('Skipping session from different identity during restoration');
|
|
615
|
+
}
|
|
616
|
+
continue;
|
|
617
|
+
}
|
|
618
|
+
|
|
595
619
|
const now = new Date();
|
|
596
620
|
validSessions.push({
|
|
597
621
|
sessionId,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useCallback } from 'react';
|
|
2
|
-
import type { ApiError } from '../../../models/interfaces';
|
|
3
|
-
import type { User } from '../../../shared';
|
|
2
|
+
import type { ApiError, User } from '../../../models/interfaces';
|
|
4
3
|
import type { AuthState } from '../../stores/authStore';
|
|
5
4
|
import type { ClientSession, SessionLoginResponse } from '../../../models/session';
|
|
6
5
|
import { DeviceManager } from '../../../utils/deviceManager';
|
|
@@ -85,6 +84,22 @@ export const useAuthOperations = ({
|
|
|
85
84
|
logger,
|
|
86
85
|
}: UseAuthOperationsOptions): UseAuthOperationsResult => {
|
|
87
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Clear session data if identity has changed
|
|
89
|
+
* Internal helper to avoid code duplication
|
|
90
|
+
*/
|
|
91
|
+
const clearSessionsIfIdentityChanged = useCallback(
|
|
92
|
+
async (oldPublicKey: string | null, newPublicKey: string): Promise<void> => {
|
|
93
|
+
if (oldPublicKey && oldPublicKey !== newPublicKey) {
|
|
94
|
+
// Clear all session state to prevent old identity's data from showing up
|
|
95
|
+
await clearSessionState();
|
|
96
|
+
// Logout from auth store
|
|
97
|
+
logoutStore();
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
[clearSessionState, logoutStore]
|
|
101
|
+
);
|
|
102
|
+
|
|
88
103
|
/**
|
|
89
104
|
* Internal function to perform challenge-response sign in (works offline)
|
|
90
105
|
*/
|
|
@@ -293,10 +308,17 @@ export const useAuthOperations = ({
|
|
|
293
308
|
setAuthState({ isLoading: true, error: null });
|
|
294
309
|
|
|
295
310
|
try {
|
|
311
|
+
// CRITICAL: Get old public key before creating new identity
|
|
312
|
+
// If identity changes, we must clear all session data to prevent data leakage
|
|
313
|
+
const oldPublicKey = await KeyManager.getPublicKey().catch(() => null);
|
|
314
|
+
|
|
296
315
|
// Generate new key pair directly (works offline)
|
|
297
316
|
const { publicKey, privateKey } = await KeyManager.generateKeyPair();
|
|
298
317
|
await KeyManager.importKeyPair(privateKey);
|
|
299
318
|
|
|
319
|
+
// Clear sessions if identity changed (prevents data leakage)
|
|
320
|
+
await clearSessionsIfIdentityChanged(oldPublicKey, publicKey);
|
|
321
|
+
|
|
300
322
|
// Mark as not synced
|
|
301
323
|
await storage.setItem('oxy_identity_synced', 'false');
|
|
302
324
|
setIdentitySynced(false);
|
|
@@ -359,7 +381,7 @@ export const useAuthOperations = ({
|
|
|
359
381
|
setAuthState({ isLoading: false });
|
|
360
382
|
}
|
|
361
383
|
},
|
|
362
|
-
[oxyServices, storage, setAuthState, loginFailure, onError, logger, setIdentitySynced],
|
|
384
|
+
[oxyServices, storage, setAuthState, loginFailure, onError, logger, setIdentitySynced, clearSessionsIfIdentityChanged],
|
|
363
385
|
);
|
|
364
386
|
|
|
365
387
|
/**
|
|
@@ -464,6 +486,10 @@ export const useAuthOperations = ({
|
|
|
464
486
|
setAuthState({ isLoading: true, error: null });
|
|
465
487
|
|
|
466
488
|
try {
|
|
489
|
+
// CRITICAL: Get old public key before importing new identity
|
|
490
|
+
// If identity changes, we must clear all session data to prevent data leakage
|
|
491
|
+
const oldPublicKey = await KeyManager.getPublicKey().catch(() => null);
|
|
492
|
+
|
|
467
493
|
// Decrypt private key from backup data
|
|
468
494
|
const Crypto = await import('expo-crypto');
|
|
469
495
|
|
|
@@ -505,6 +531,9 @@ export const useAuthOperations = ({
|
|
|
505
531
|
throw new Error('Backup file is corrupted or password is incorrect');
|
|
506
532
|
}
|
|
507
533
|
|
|
534
|
+
// Clear sessions if identity changed (prevents data leakage)
|
|
535
|
+
await clearSessionsIfIdentityChanged(oldPublicKey, publicKey);
|
|
536
|
+
|
|
508
537
|
// Mark as not synced
|
|
509
538
|
await storage.setItem('oxy_identity_synced', 'false');
|
|
510
539
|
setIdentitySynced(false);
|
|
@@ -549,7 +578,7 @@ export const useAuthOperations = ({
|
|
|
549
578
|
setAuthState({ isLoading: false });
|
|
550
579
|
}
|
|
551
580
|
},
|
|
552
|
-
[oxyServices, storage, setAuthState, loginFailure, onError, logger, setIdentitySynced],
|
|
581
|
+
[oxyServices, storage, setAuthState, loginFailure, onError, logger, setIdentitySynced, clearSessionsIfIdentityChanged],
|
|
553
582
|
);
|
|
554
583
|
|
|
555
584
|
/**
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
-
import type { ApiError } from '../../../models/interfaces';
|
|
3
|
-
import type { User } from '../../../shared';
|
|
2
|
+
import type { ApiError, User } from '../../../models/interfaces';
|
|
4
3
|
import {
|
|
5
4
|
getLanguageMetadata,
|
|
6
5
|
getLanguageName,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
2
|
-
import type { User } from '../../../
|
|
2
|
+
import type { User } from '../../../models/interfaces';
|
|
3
3
|
import { queryKeys, invalidateAccountQueries, invalidateUserQueries } from '../queries/queryKeys';
|
|
4
4
|
import { useOxy } from '../../context/OxyContext';
|
|
5
5
|
import { toast } from '../../../lib/sonner';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
2
|
-
import type { User } from '../../../
|
|
2
|
+
import type { User } from '../../../models/interfaces';
|
|
3
3
|
import { queryKeys, invalidateSessionQueries } from '../queries/queryKeys';
|
|
4
4
|
import { useOxy } from '../../context/OxyContext';
|
|
5
5
|
import { toast } from '../../../lib/sonner';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useQuery, useQueries } from '@tanstack/react-query';
|
|
2
|
-
import type { User } from '../../../
|
|
2
|
+
import type { User } from '../../../models/interfaces';
|
|
3
3
|
import type { OxyServices } from '../../../core';
|
|
4
4
|
import { queryKeys } from './queryKeys';
|
|
5
5
|
import { useOxy } from '../../context/OxyContext';
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
-
import type { ApiError } from '../../models/interfaces';
|
|
3
|
-
import type { User } from '../../shared';
|
|
2
|
+
import type { ApiError, User } from '../../models/interfaces';
|
|
4
3
|
import {
|
|
5
4
|
getLanguageMetadata,
|
|
6
5
|
getLanguageName,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import type { ApiError } from '../../models/interfaces';
|
|
3
|
-
import type { User } from '../../shared';
|
|
2
|
+
import type { ApiError, User } from '../../models/interfaces';
|
|
4
3
|
import type { ClientSession } from '../../models/session';
|
|
5
4
|
import { mergeSessions, normalizeAndSortSessions, sessionsArraysEqual } from '../../utils/sessionUtils';
|
|
6
5
|
import { fetchSessionsWithFallback, mapSessionsToClient, validateSessionBatch } from '../utils/sessionHelpers';
|
package/src/ui/index.ts
CHANGED
|
@@ -81,5 +81,4 @@ export {
|
|
|
81
81
|
|
|
82
82
|
// Re-export core services for convenience in UI context
|
|
83
83
|
export { OxyServices } from '../core';
|
|
84
|
-
|
|
85
|
-
export type { ApiError } from '../models/interfaces';
|
|
84
|
+
export type { User, LoginResponse, ApiError } from '../models/interfaces';
|
|
@@ -233,7 +233,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
|
|
|
233
233
|
|
|
234
234
|
// Handle locations - convert single location to array format
|
|
235
235
|
if (finalUser.locations && Array.isArray(finalUser.locations)) {
|
|
236
|
-
setLocations(finalUser.locations.map((loc
|
|
236
|
+
setLocations(finalUser.locations.map((loc, index) => ({
|
|
237
237
|
id: loc.id || `existing-${index}`,
|
|
238
238
|
name: loc.name,
|
|
239
239
|
label: loc.label,
|
|
@@ -252,17 +252,17 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
|
|
|
252
252
|
|
|
253
253
|
// Handle links - simple and direct like other fields
|
|
254
254
|
if (finalUser.linksMetadata && Array.isArray(finalUser.linksMetadata)) {
|
|
255
|
-
const urls = finalUser.linksMetadata.map(
|
|
255
|
+
const urls = finalUser.linksMetadata.map(l => l.url);
|
|
256
256
|
setLinks(urls);
|
|
257
|
-
const metadataWithIds = finalUser.linksMetadata.map((link
|
|
257
|
+
const metadataWithIds = finalUser.linksMetadata.map((link, index) => ({
|
|
258
258
|
...link,
|
|
259
259
|
id: link.id || `existing-${index}`
|
|
260
260
|
}));
|
|
261
261
|
setLinksMetadata(metadataWithIds);
|
|
262
262
|
} else if (Array.isArray(finalUser.links)) {
|
|
263
|
-
const simpleLinks = finalUser.links.map(
|
|
263
|
+
const simpleLinks = finalUser.links.map(l => typeof l === 'string' ? l : l.link).filter(Boolean);
|
|
264
264
|
setLinks(simpleLinks);
|
|
265
|
-
const linksWithMetadata = simpleLinks.map((url
|
|
265
|
+
const linksWithMetadata = simpleLinks.map((url, index) => ({
|
|
266
266
|
url,
|
|
267
267
|
title: url.replace(/^https?:\/\//, '').replace(/\/$/, ''),
|
|
268
268
|
description: `Link to ${url}`,
|
|
@@ -553,7 +553,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
|
|
|
553
553
|
}
|
|
554
554
|
|
|
555
555
|
if (currentUser.linksMetadata && Array.isArray(currentUser.linksMetadata)) {
|
|
556
|
-
setLinksMetadata(currentUser.linksMetadata.map((link
|
|
556
|
+
setLinksMetadata(currentUser.linksMetadata.map((link, index) => ({
|
|
557
557
|
...link,
|
|
558
558
|
id: link.id || `existing-${index}`
|
|
559
559
|
})));
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import type { BaseScreenProps } from '../types/navigation';
|
|
16
16
|
import type { ClientSession } from '../../models/session';
|
|
17
17
|
import { fontFamilies } from '../styles/fonts';
|
|
18
|
-
import type { User } from '../../
|
|
18
|
+
import type { User } from '../../models/interfaces';
|
|
19
19
|
import { toast } from '../../lib/sonner';
|
|
20
20
|
import { confirmAction } from '../utils/confirmAction';
|
|
21
21
|
import OxyIcon from '../components/icon/OxyIcon';
|
|
@@ -28,7 +28,6 @@ import { useThemeColors } from '../styles';
|
|
|
28
28
|
import { useOxy } from '../context/OxyContext';
|
|
29
29
|
import QRCode from 'react-native-qrcode-svg';
|
|
30
30
|
import OxyLogo from '../components/OxyLogo';
|
|
31
|
-
import { generateSessionToken } from '../../shared';
|
|
32
31
|
|
|
33
32
|
// Deep link scheme for Oxy Accounts app
|
|
34
33
|
const OXY_ACCOUNTS_SCHEME = 'oxyaccounts://';
|
|
@@ -221,7 +220,7 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
|
|
|
221
220
|
|
|
222
221
|
try {
|
|
223
222
|
// Generate a unique session token for this auth request
|
|
224
|
-
const sessionToken =
|
|
223
|
+
const sessionToken = generateSessionToken();
|
|
225
224
|
const expiresAt = Date.now() + AUTH_SESSION_EXPIRY_MS;
|
|
226
225
|
|
|
227
226
|
// Register the auth session with the server
|
|
@@ -243,6 +242,16 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
|
|
|
243
242
|
}
|
|
244
243
|
}, [oxyServices, connectSocket]);
|
|
245
244
|
|
|
245
|
+
// Generate a random session token
|
|
246
|
+
const generateSessionToken = (): string => {
|
|
247
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
248
|
+
let result = '';
|
|
249
|
+
for (let i = 0; i < 32; i++) {
|
|
250
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
251
|
+
}
|
|
252
|
+
return result;
|
|
253
|
+
};
|
|
254
|
+
|
|
246
255
|
// Clean up on unmount
|
|
247
256
|
useEffect(() => {
|
|
248
257
|
return () => {
|
|
@@ -10,7 +10,7 @@ import { Ionicons } from '@expo/vector-icons';
|
|
|
10
10
|
import { useI18n } from '../hooks/useI18n';
|
|
11
11
|
import { useOxy } from '../context/OxyContext';
|
|
12
12
|
import { logger } from '../../utils/loggerUtils';
|
|
13
|
-
import type { User } from '../../
|
|
13
|
+
import type { User } from '../../models/interfaces';
|
|
14
14
|
import { extractErrorMessage } from '../utils/errorHandlers';
|
|
15
15
|
|
|
16
16
|
interface ProfileScreenProps extends BaseScreenProps {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode, RefObject } from 'react';
|
|
2
2
|
import type { QueryClient } from '@tanstack/react-query';
|
|
3
3
|
import type { RouteName } from '../navigation/routes';
|
|
4
|
-
import type { User } from '../../
|
|
4
|
+
import type { User } from '../../models/interfaces';
|
|
5
5
|
import type { ClientSession } from '../../models/session';
|
|
6
6
|
|
|
7
7
|
// Re-export RouteName from routes for convenience
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { OxyServices } from '../../core';
|
|
2
|
-
import type { User } from '../../
|
|
2
|
+
import type { User } from '../../models/interfaces';
|
|
3
3
|
import { useAccountStore } from '../stores/accountStore';
|
|
4
4
|
import { useAuthStore } from '../stores/authStore';
|
|
5
5
|
import { QueryClient } from '@tanstack/react-query';
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.AuthService = void 0;
|
|
7
|
-
var _HttpService = require("../HttpService");
|
|
8
|
-
var _signatureService = require("../../crypto/signatureService");
|
|
9
|
-
/**
|
|
10
|
-
* Auth Service
|
|
11
|
-
*
|
|
12
|
-
* Handles authentication operations:
|
|
13
|
-
* - Challenge retrieval
|
|
14
|
-
* - Signing orchestration (delegated to Accounts/KeyManager)
|
|
15
|
-
* - Session verification
|
|
16
|
-
* - Access token retrieval
|
|
17
|
-
* - Registration
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
class AuthService {
|
|
21
|
-
constructor(config) {
|
|
22
|
-
this.httpService = new _HttpService.HttpService(config);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Check if a public key is registered on the server
|
|
27
|
-
*/
|
|
28
|
-
async checkPublicKeyRegistered(publicKey) {
|
|
29
|
-
try {
|
|
30
|
-
return await this.httpService.request({
|
|
31
|
-
method: 'GET',
|
|
32
|
-
url: `/api/auth/check-publickey?publicKey=${encodeURIComponent(publicKey)}`,
|
|
33
|
-
cache: true,
|
|
34
|
-
cacheTTL: 2 * 60 * 1000
|
|
35
|
-
});
|
|
36
|
-
} catch (error) {
|
|
37
|
-
throw error;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Request an authentication challenge
|
|
43
|
-
*/
|
|
44
|
-
async requestChallenge(publicKey) {
|
|
45
|
-
try {
|
|
46
|
-
return await this.httpService.request({
|
|
47
|
-
method: 'POST',
|
|
48
|
-
url: '/api/auth/challenge',
|
|
49
|
-
data: {
|
|
50
|
-
publicKey
|
|
51
|
-
},
|
|
52
|
-
cache: false
|
|
53
|
-
});
|
|
54
|
-
} catch (error) {
|
|
55
|
-
throw error;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Verify a challenge and authenticate (creates session)
|
|
61
|
-
* This orchestrates signing via SignatureService (which uses KeyManager)
|
|
62
|
-
*/
|
|
63
|
-
async verifyChallenge(challenge) {
|
|
64
|
-
try {
|
|
65
|
-
// Sign the challenge using SignatureService (requires private key)
|
|
66
|
-
const signedChallenge = await _signatureService.SignatureService.signChallenge(challenge);
|
|
67
|
-
|
|
68
|
-
// Verify challenge and get session
|
|
69
|
-
return await this.httpService.request({
|
|
70
|
-
method: 'POST',
|
|
71
|
-
url: '/api/auth/verify',
|
|
72
|
-
data: {
|
|
73
|
-
publicKey: signedChallenge.publicKey,
|
|
74
|
-
challenge: challenge,
|
|
75
|
-
signature: signedChallenge.challenge,
|
|
76
|
-
timestamp: signedChallenge.timestamp
|
|
77
|
-
},
|
|
78
|
-
cache: false
|
|
79
|
-
});
|
|
80
|
-
} catch (error) {
|
|
81
|
-
throw error;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Register a new identity with the server
|
|
87
|
-
*/
|
|
88
|
-
async register(publicKey, signature, timestamp, username, email) {
|
|
89
|
-
try {
|
|
90
|
-
return await this.httpService.request({
|
|
91
|
-
method: 'POST',
|
|
92
|
-
url: '/api/auth/register',
|
|
93
|
-
data: {
|
|
94
|
-
publicKey,
|
|
95
|
-
signature,
|
|
96
|
-
timestamp,
|
|
97
|
-
username,
|
|
98
|
-
email
|
|
99
|
-
},
|
|
100
|
-
cache: false
|
|
101
|
-
});
|
|
102
|
-
} catch (error) {
|
|
103
|
-
throw error;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Register using current identity (signs automatically)
|
|
109
|
-
*/
|
|
110
|
-
async registerCurrentIdentity(username, email) {
|
|
111
|
-
try {
|
|
112
|
-
const {
|
|
113
|
-
signature,
|
|
114
|
-
publicKey,
|
|
115
|
-
timestamp
|
|
116
|
-
} = await _signatureService.SignatureService.createRegistrationSignature();
|
|
117
|
-
return this.register(publicKey, signature, timestamp, username, email);
|
|
118
|
-
} catch (error) {
|
|
119
|
-
throw error;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Get user by public key
|
|
125
|
-
*/
|
|
126
|
-
async getUserByPublicKey(publicKey) {
|
|
127
|
-
try {
|
|
128
|
-
return await this.httpService.request({
|
|
129
|
-
method: 'GET',
|
|
130
|
-
url: `/api/auth/user/${encodeURIComponent(publicKey)}`,
|
|
131
|
-
cache: true,
|
|
132
|
-
cacheTTL: 2 * 60 * 1000
|
|
133
|
-
});
|
|
134
|
-
} catch (error) {
|
|
135
|
-
throw error;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Get user by session ID
|
|
141
|
-
*/
|
|
142
|
-
async getUserBySession(sessionId) {
|
|
143
|
-
try {
|
|
144
|
-
return await this.httpService.request({
|
|
145
|
-
method: 'GET',
|
|
146
|
-
url: `/api/auth/user/session/${encodeURIComponent(sessionId)}`,
|
|
147
|
-
cache: true,
|
|
148
|
-
cacheTTL: 2 * 60 * 1000
|
|
149
|
-
});
|
|
150
|
-
} catch (error) {
|
|
151
|
-
throw error;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
exports.AuthService = AuthService;
|
|
156
|
-
//# sourceMappingURL=AuthService.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["_HttpService","require","_signatureService","AuthService","constructor","config","httpService","HttpService","checkPublicKeyRegistered","publicKey","request","method","url","encodeURIComponent","cache","cacheTTL","error","requestChallenge","data","verifyChallenge","challenge","signedChallenge","SignatureService","signChallenge","signature","timestamp","register","username","email","registerCurrentIdentity","createRegistrationSignature","getUserByPublicKey","getUserBySession","sessionId","exports"],"sourceRoot":"../../../../src","sources":["core/services/AuthService.ts"],"mappings":"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","ignoreList":[]}
|