@trust-proto/auth-node 0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Liberion
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,138 @@
1
+ # @trust-proto/auth-node
2
+
3
+ Backend SDK for Liberion decentralized authentication system. This package provides a WebSocket server that handles browser-wallet authentication flow.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @trust-proto/auth-node
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { LiberionAuth, createWinstonAdapter } from '@trust-proto/auth-node';
15
+
16
+ const auth = new LiberionAuth({
17
+ projectId: 'your-project-uuid',
18
+ secretCode: 'your-secret-code',
19
+ port: 31313, // optional, default: 31313
20
+
21
+ // Check if user exists in your database
22
+ onHello: async (address) => {
23
+ return await userExists(address);
24
+ },
25
+
26
+ // Generate JWT token after successful authentication
27
+ onSuccess: async ({ address, fields }) => {
28
+ const token = generateJWT(address);
29
+ return { token };
30
+ },
31
+
32
+ // Handle declined authorization (optional)
33
+ onDecline: async ({ address, reason, message }) => {
34
+ console.log(`Auth declined: ${reason}`);
35
+ },
36
+ });
37
+ ```
38
+
39
+ ## Configuration
40
+
41
+ | Option | Type | Required | Default | Description |
42
+ |--------|------|----------|---------|-------------|
43
+ | `projectId` | `string` | Yes | - | Project UUID from Liberion dashboard |
44
+ | `secretCode` | `string` | Yes | - | Secret code for encryption |
45
+ | `port` | `number` | No | `31313` | WebSocket server port |
46
+ | `ssl` | `{ key: string; cert: string }` | No | - | SSL credentials for HTTPS |
47
+ | `debug` | `boolean` | No | `false` | Enable debug logging |
48
+ | `logger` | `ILogger` | No | `NoOpLogger` | Custom logger instance |
49
+ | `onHello` | `(address: string) => Promise<boolean>` | No | - | Called when wallet activates |
50
+ | `onSuccess` | `(payload: AuthPayload) => Promise<AuthResult>` | No | - | Called on successful auth |
51
+ | `onDecline` | `(info: DeclineInfo) => Promise<void>` | No | - | Called when auth is declined |
52
+
53
+ ## Logger Integration
54
+
55
+ ### Using Winston
56
+
57
+ ```typescript
58
+ import { createWinstonAdapter } from '@trust-proto/auth-node';
59
+ import winston from 'winston';
60
+
61
+ const logger = winston.createLogger({ /* your config */ });
62
+
63
+ const auth = new LiberionAuth({
64
+ projectId: 'your-project-uuid',
65
+ secretCode: 'your-secret-code',
66
+ logger: createWinstonAdapter(logger),
67
+ });
68
+ ```
69
+
70
+ ### Using Console Logger
71
+
72
+ ```typescript
73
+ import { ConsoleLogger } from '@trust-proto/auth-node';
74
+
75
+ const auth = new LiberionAuth({
76
+ projectId: 'your-project-uuid',
77
+ secretCode: 'your-secret-code',
78
+ logger: new ConsoleLogger('[MyApp]'),
79
+ });
80
+ ```
81
+
82
+ ### Custom Logger
83
+
84
+ Implement the `ILogger` interface:
85
+
86
+ ```typescript
87
+ const customLogger: ILogger = {
88
+ info: (message, meta) => { /* ... */ },
89
+ warn: (message, meta) => { /* ... */ },
90
+ error: (message, meta) => { /* ... */ },
91
+ };
92
+ ```
93
+
94
+ ## Authentication Flow
95
+
96
+ 1. **Browser** connects to WebSocket server and sends `auth_init`
97
+ 2. **Server** creates authorization task via Trust Gate
98
+ 3. **Server** returns QR code link to browser
99
+ 4. **User** scans QR code with Liberion Wallet
100
+ 5. **Wallet** sends activation request with encrypted session data
101
+ 6. **Server** calls `onHello` callback, sends ACTIVATED to browser
102
+ 7. **Wallet** sends signed auth data with KYC fields
103
+ 8. **Server** verifies ML-DSA-87 signature, calls `onSuccess`
104
+ 9. **Server** sends JWT token to browser, closes connections
105
+
106
+ ## Security Features
107
+
108
+ - **Post-Quantum Cryptography**: ML-KEM-1024 + ML-DSA-87 (FIPS 203/204)
109
+ - **AES-256-CBC**: Session encryption with project secret
110
+ - **Signature Verification**: All auth data is cryptographically signed
111
+ - **Session Timeout**: 10-minute authorization window
112
+ - **WebSocket Ping/Pong**: Keep-alive with 30-second interval
113
+
114
+ ## Types
115
+
116
+ ```typescript
117
+ interface AuthPayload {
118
+ address: string;
119
+ fields: Record<string, unknown>;
120
+ }
121
+
122
+ interface AuthResult {
123
+ token?: string;
124
+ error?: string;
125
+ }
126
+
127
+ interface DeclineInfo {
128
+ address: string | null;
129
+ reason: 'user_declined' | 'timeout' | 'error' | 'unknown';
130
+ message: string;
131
+ declinedBy: 'wallet' | 'browser';
132
+ sessionId: string;
133
+ }
134
+ ```
135
+
136
+ ## License
137
+
138
+ MIT
@@ -0,0 +1,423 @@
1
+ /**
2
+ * Blockchain configuration constants
3
+ * Supports production and development environments
4
+ */
5
+ /** Environment type */
6
+ type Environment = 'production' | 'development';
7
+ /** Network configuration interface */
8
+ interface NetworkConfig {
9
+ RPC_ENDPOINT: string;
10
+ USER_CONTRACT_ADDRESS: string;
11
+ IPFS_GATEWAY: string;
12
+ TRUST_GATE_URL: string;
13
+ }
14
+ /**
15
+ * Get network configuration for specified environment
16
+ * @param env - Environment ('production' | 'development'), default: 'production'
17
+ * @returns Network configuration object
18
+ */
19
+ declare function getNetworkConfig(env?: Environment): NetworkConfig;
20
+ /** User contract ABI (minimal for tokenURI) */
21
+ declare const USER_CONTRACT_ABI: readonly [{
22
+ readonly inputs: readonly [{
23
+ readonly internalType: "address";
24
+ readonly name: "tokenId";
25
+ readonly type: "address";
26
+ }];
27
+ readonly name: "tokenURI";
28
+ readonly outputs: readonly [{
29
+ readonly internalType: "string";
30
+ readonly name: "";
31
+ readonly type: "string";
32
+ }];
33
+ readonly stateMutability: "view";
34
+ readonly type: "function";
35
+ }];
36
+
37
+ /**
38
+ * Liberion Auth Backend SDK Types
39
+ */
40
+
41
+ /**
42
+ * Logger interface for dependency injection
43
+ */
44
+ interface ILogger {
45
+ info(message: string, meta?: Record<string, unknown>): void;
46
+ warn(message: string, meta?: Record<string, unknown>): void;
47
+ error(message: string, meta?: Record<string, unknown>): void;
48
+ }
49
+ /**
50
+ * User SNFT token structure from IPFS
51
+ */
52
+ interface UserToken {
53
+ /** ML-DSA-87 public key (base64 encoded, 2592 bytes decoded) */
54
+ publicKeySign: string;
55
+ /** ML-KEM-1024 public key (base64 encoded, 1568 bytes decoded) */
56
+ publicKeyEncrypt: string;
57
+ /** Optional KYC assets */
58
+ assets?: Record<string, unknown>;
59
+ /** Additional token properties */
60
+ [key: string]: unknown;
61
+ }
62
+ /**
63
+ * SSL credentials for HTTPS server
64
+ */
65
+ interface SSLCredentials {
66
+ key: string;
67
+ cert: string;
68
+ }
69
+ /**
70
+ * Decline reason categories
71
+ */
72
+ type DeclineReason = 'user_declined' | 'timeout' | 'error' | 'unknown';
73
+ /**
74
+ * Information about declined authorization
75
+ */
76
+ interface DeclineInfo {
77
+ /** User wallet address (null if declined before activation) */
78
+ address: string | null;
79
+ /** Standardized decline reason */
80
+ reason: DeclineReason;
81
+ /** Detailed message */
82
+ message: string;
83
+ /** Who initiated the decline */
84
+ declinedBy: 'wallet' | 'browser';
85
+ /** Session identifier */
86
+ sessionId: string;
87
+ }
88
+ /**
89
+ * Payload received on successful authorization
90
+ */
91
+ interface AuthPayload {
92
+ /** User wallet address */
93
+ address: string;
94
+ /** KYC fields provided by user */
95
+ fields: Record<string, unknown>;
96
+ }
97
+ /**
98
+ * Result returned from onSuccess callback
99
+ */
100
+ interface AuthResult {
101
+ /** JWT token for authenticated user */
102
+ token?: string;
103
+ /** Error message if authentication failed */
104
+ error?: string;
105
+ }
106
+ /**
107
+ * Main configuration for LiberionAuth
108
+ */
109
+ interface LiberionAuthConfig {
110
+ /** Project UUID from Liberion dashboard */
111
+ projectId: string;
112
+ /** Secret code for AES-256-CBC encryption */
113
+ secretCode: string;
114
+ /** WebSocket server port (default: 31313) */
115
+ port?: number;
116
+ /** Enable debug logging (default: false) */
117
+ debug?: boolean;
118
+ /** SSL credentials for HTTPS (default: undefined, use HTTP) */
119
+ ssl?: SSLCredentials;
120
+ /** Environment: 'production' or 'development' (default: 'production') */
121
+ environment?: Environment;
122
+ /** Logger instance (default: NoOpLogger) */
123
+ logger?: ILogger;
124
+ /**
125
+ * Called when wallet activates (scans QR)
126
+ * @param address - User wallet address
127
+ * @returns true if user is registered, false otherwise
128
+ */
129
+ onHello?: (address: string) => Promise<boolean>;
130
+ /**
131
+ * Called on successful authorization
132
+ * @param payload - Contains address and KYC fields
133
+ * @returns Object with token or error
134
+ */
135
+ onSuccess?: (payload: AuthPayload) => Promise<AuthResult>;
136
+ /**
137
+ * Called when authorization is declined
138
+ * @param info - Decline details including reason and who declined
139
+ */
140
+ onDecline?: (info: DeclineInfo) => Promise<void>;
141
+ }
142
+ /**
143
+ * Session data stored for each connected client
144
+ */
145
+ interface Session {
146
+ /** WebSocket client reference */
147
+ client: unknown;
148
+ /** Session UUID (for browser-wallet linking) */
149
+ sessionId: string | null;
150
+ /** User wallet address (set after activation) */
151
+ address: string | null;
152
+ /** Client session ID (for wallet auth) */
153
+ clientSessionId: string | null;
154
+ /** True if this is a browser session */
155
+ isBrowserSession: boolean;
156
+ /** Stored auth result for reconnect scenario */
157
+ authResult?: {
158
+ token: string;
159
+ };
160
+ /** Stored decline result for reconnect scenario */
161
+ declineResult?: {
162
+ message: string;
163
+ };
164
+ /** Authorization timeout handle */
165
+ timeout?: NodeJS.Timeout;
166
+ }
167
+ /**
168
+ * Crypto instance for signature verification
169
+ */
170
+ interface CryptoInstance {
171
+ /** ML-DSA-87 public key */
172
+ dsaPublicKey: Uint8Array;
173
+ /** ML-KEM-1024 public key (optional) */
174
+ kemPublicKey: Uint8Array | null;
175
+ /** Algorithm identifier */
176
+ algorithm: string;
177
+ /** Original user token */
178
+ userToken: UserToken;
179
+ /**
180
+ * Verify ML-DSA-87 signature
181
+ * @param msg - Message that was signed
182
+ * @param signature - ML-DSA-87 signature
183
+ * @returns true if signature is valid
184
+ */
185
+ verifySignature: (msg: Buffer | Uint8Array, sig: Buffer | Uint8Array) => boolean;
186
+ }
187
+
188
+ /**
189
+ * LiberionAuth - Main SDK class for Liberion authentication
190
+ * Creates a WebSocket server that handles browser and wallet connections
191
+ */
192
+
193
+ declare class LiberionAuth {
194
+ private logger;
195
+ private projectId;
196
+ private secretCode;
197
+ private networkConfig;
198
+ private sessions;
199
+ private interval;
200
+ private onHello?;
201
+ private onSuccess?;
202
+ private onDecline?;
203
+ static readonly COMMAND_AUTH = "auth";
204
+ static readonly COMMAND_READY = "ready";
205
+ constructor(config: LiberionAuthConfig);
206
+ private encode;
207
+ private decode;
208
+ private request;
209
+ private send;
210
+ private readMessage;
211
+ private newClient;
212
+ private handleClose;
213
+ private responseInit;
214
+ private responseActivate;
215
+ private responseAuth;
216
+ private responseDeclined;
217
+ private responseReconnect;
218
+ private responseFailed;
219
+ private errorResponse;
220
+ private finalResponse;
221
+ private finalizeSession;
222
+ private closeClient;
223
+ private findSession;
224
+ }
225
+
226
+ /**
227
+ * Logger adapters for dependency injection
228
+ */
229
+
230
+ /**
231
+ * No-operation logger - default when no logger provided
232
+ * Silently ignores all log calls
233
+ */
234
+ declare class NoOpLogger implements ILogger {
235
+ info(): void;
236
+ warn(): void;
237
+ error(): void;
238
+ }
239
+ /**
240
+ * Console logger for development/debugging
241
+ * Outputs to stdout/stderr with timestamps
242
+ */
243
+ declare class ConsoleLogger implements ILogger {
244
+ private readonly prefix;
245
+ constructor(prefix?: string);
246
+ info(message: string, meta?: Record<string, unknown>): void;
247
+ warn(message: string, meta?: Record<string, unknown>): void;
248
+ error(message: string, meta?: Record<string, unknown>): void;
249
+ }
250
+ /**
251
+ * Create a logger adapter from Winston logger instance
252
+ * @param winston - Winston logger instance
253
+ * @returns ILogger compatible adapter
254
+ *
255
+ * @example
256
+ * ```typescript
257
+ * import { createWinstonAdapter } from '@trust-proto/auth-node';
258
+ * import { logger } from './my-winston-logger';
259
+ *
260
+ * const auth = new LiberionAuth({
261
+ * logger: createWinstonAdapter(logger),
262
+ * // ...
263
+ * });
264
+ * ```
265
+ */
266
+ declare function createWinstonAdapter(winston: {
267
+ info: (message: string, meta?: Record<string, unknown>) => void;
268
+ warn: (message: string, meta?: Record<string, unknown>) => void;
269
+ error: (message: string, meta?: Record<string, unknown>) => void;
270
+ }): ILogger;
271
+ /**
272
+ * Shorten blockchain address for logging (privacy protection)
273
+ * @param address - Full blockchain address
274
+ * @returns Shortened address like "0x1234...abcd"
275
+ */
276
+ declare function shortenAddress(address: string | null | undefined): string;
277
+
278
+ /**
279
+ * AES-256-CBC encryption utilities
280
+ */
281
+ /**
282
+ * Encrypt buffer using AES-256-CBC
283
+ * @param buffer - Data to encrypt
284
+ * @param key - Encryption key (will be hashed to 32 bytes)
285
+ * @returns Encrypted buffer with IV prepended (16 bytes IV + encrypted data)
286
+ */
287
+ declare function encryptBuffer(buffer: Buffer, key: string): Buffer;
288
+ /**
289
+ * Decrypt buffer using AES-256-CBC
290
+ * @param data - Encrypted data (16 bytes IV + encrypted data)
291
+ * @param key - Decryption key (will be hashed to 32 bytes)
292
+ * @returns Decrypted buffer
293
+ */
294
+ declare function decryptBuffer(data: Buffer, key: string): Buffer;
295
+
296
+ /**
297
+ * Post-Quantum Cryptography utility class
298
+ * Implements hybrid encryption: ML-KEM-1024 + XChaCha20-Poly1305 + ML-DSA-87
299
+ */
300
+
301
+ /**
302
+ * Post-Quantum Cryptography utility class
303
+ * Used by Trust Gate to:
304
+ * 1. Generate temporary session keys
305
+ * 2. Encrypt data for Wallet using user's public keys
306
+ * 3. Sign KEM ciphertext for authenticity
307
+ *
308
+ * Format matches client (cipher.js):
309
+ * version (1) + header (4) + sigLen (4) + signature + cipherText + nonce (24) + ct
310
+ */
311
+ declare class PQCrypto {
312
+ private logger;
313
+ private _kemPrivateKey;
314
+ private kemPublicKey;
315
+ private dsaPrivateKey;
316
+ private dsaPublicKey;
317
+ private peerKEMPublicKey;
318
+ private peerDSAPublicKey;
319
+ constructor(logger?: ILogger);
320
+ /**
321
+ * Generate Trust Gate session keys from cryptographic seed
322
+ * @param seed - Random seed (at least 96 bytes: 64 for ML-KEM + 32 for ML-DSA)
323
+ */
324
+ generateKeysFromSeed(seed: Uint8Array): Promise<void>;
325
+ /**
326
+ * Import peer's (user) public keys for encryption and verification
327
+ * @param kemPublicKey - ML-KEM-1024 public key (1568 bytes)
328
+ * @param dsaPublicKey - ML-DSA-87 public key (2592 bytes)
329
+ */
330
+ importPeerPublicKeys(kemPublicKey: Uint8Array | Buffer, dsaPublicKey: Uint8Array | Buffer): void;
331
+ /**
332
+ * Hybrid encryption: ML-KEM + XChaCha20-Poly1305 + ML-DSA signature
333
+ * Matches client format: version + header + sigLen + signature + cipherText + nonce + ct
334
+ * @param message - Data to encrypt
335
+ * @returns Encrypted package in client-compatible format
336
+ */
337
+ encrypt(message: ArrayBuffer | Uint8Array | Buffer): Promise<Buffer>;
338
+ /**
339
+ * Check if keys have been generated
340
+ */
341
+ hasKeys(): boolean;
342
+ /**
343
+ * Export Trust Gate public keys (for sending to client)
344
+ * @returns Object with publicKeyEncrypt and publicKeySign as Buffers
345
+ */
346
+ exportKeys(): {
347
+ publicKeyEncrypt: Buffer;
348
+ publicKeySign: Buffer;
349
+ };
350
+ }
351
+
352
+ /**
353
+ * ML-DSA-87 signature verification utilities
354
+ */
355
+
356
+ /**
357
+ * Initialize user crypto instance from SNFT token
358
+ * Parses ML-DSA-87 and ML-KEM-1024 public keys from base64-encoded token
359
+ *
360
+ * @param userToken - SNFT token with publicKeySign and publicKeyEncrypt (base64)
361
+ * @param logger - Optional logger instance
362
+ * @returns Crypto instance for signature verification
363
+ */
364
+ declare function initUserCrypto(userToken: UserToken, logger?: ILogger): CryptoInstance;
365
+ /**
366
+ * Verify ML-DSA-87 signature of data
367
+ *
368
+ * @param crypto - Crypto instance from initUserCrypto
369
+ * @param data - Data that was signed
370
+ * @param signature - ML-DSA-87 signature (~4595 bytes)
371
+ * @param logger - Optional logger instance
372
+ * @returns true if signature is valid
373
+ * @throws Error if verification fails
374
+ */
375
+ declare function checkSignature(crypto: CryptoInstance, data: Buffer | Uint8Array | ArrayBuffer | string, signature: Buffer | Uint8Array | ArrayBuffer | string, logger?: ILogger): boolean;
376
+
377
+ /**
378
+ * Token Provider - Fetches user SNFT tokens from blockchain and IPFS
379
+ */
380
+
381
+ /**
382
+ * Extract IPFS hash from tokenURI
383
+ * Handles multiple formats:
384
+ * - ipfs://QmHash...
385
+ * - https://gateway.pinata.cloud/ipfs/QmHash...
386
+ * - https://secure.liberion.com/QmHash...
387
+ * - QmHash... (raw hash)
388
+ */
389
+ declare function extractIpfsHash(tokenURI: string): string;
390
+ /**
391
+ * Get SNFT token from IPFS by user address
392
+ *
393
+ * @param address - User blockchain address
394
+ * @param logger - Optional logger instance
395
+ * @param networkConfig - Optional network configuration (defaults to production)
396
+ * @returns SNFT token object from IPFS
397
+ */
398
+ declare function getTokenFromIPFS(address: string, logger?: ILogger, networkConfig?: NetworkConfig): Promise<UserToken>;
399
+ /**
400
+ * Clear the token cache (for testing or manual invalidation)
401
+ */
402
+ declare function clearTokenCache(): void;
403
+
404
+ declare const COMMAND_READY = "ready";
405
+ declare const COMMAND_AUTH = "auth";
406
+ declare const COMMAND_AUTH_RESULT = "auth_result";
407
+ declare const COMMAND_ACTIVATED = "activated";
408
+ declare const COMMAND_AUTH_DECLINED = "declined";
409
+ declare const COMMAND_AUTH_TIMEOUT = "timeout";
410
+ declare const COMMAND_ERROR = "error";
411
+ declare const DEFAULT_PORT = 31313;
412
+ declare const STATUS: {
413
+ readonly OK: "ok";
414
+ readonly FAILED: "error";
415
+ };
416
+ declare const DECLINE_REASON: {
417
+ readonly USER: "user_declined";
418
+ readonly TIMEOUT: "timeout";
419
+ readonly ERROR: "error";
420
+ readonly UNKNOWN: "unknown";
421
+ };
422
+
423
+ export { type AuthPayload, type AuthResult, COMMAND_ACTIVATED, COMMAND_AUTH, COMMAND_AUTH_DECLINED, COMMAND_AUTH_RESULT, COMMAND_AUTH_TIMEOUT, COMMAND_ERROR, COMMAND_READY, ConsoleLogger, type CryptoInstance, DECLINE_REASON, DEFAULT_PORT, type DeclineInfo, type DeclineReason, type Environment, type ILogger, LiberionAuth, type LiberionAuthConfig, type NetworkConfig, NoOpLogger, PQCrypto, type SSLCredentials, STATUS, type Session, USER_CONTRACT_ABI, type UserToken, checkSignature, clearTokenCache, createWinstonAdapter, decryptBuffer, encryptBuffer, extractIpfsHash, getNetworkConfig, getTokenFromIPFS, initUserCrypto, shortenAddress };