nostr-auth-middleware 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +216 -0
  3. package/dist/__tests__/nostr-auth.middleware.test.d.ts +1 -0
  4. package/dist/__tests__/nostr-auth.middleware.test.js +104 -0
  5. package/dist/config/index.d.ts +7 -0
  6. package/dist/config/index.js +148 -0
  7. package/dist/config/index.js.map +1 -0
  8. package/dist/config.d.ts +3 -0
  9. package/dist/config.js +68 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/index.d.ts +33 -0
  12. package/dist/index.js +39 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/interfaces/nostr.interface.d.ts +29 -0
  15. package/dist/interfaces/nostr.interface.js +1 -0
  16. package/dist/middleware/nostr-auth.middleware.d.ts +14 -0
  17. package/dist/middleware/nostr-auth.middleware.js +102 -0
  18. package/dist/middleware/nostr-auth.middleware.js.map +1 -0
  19. package/dist/middleware/security.middleware.d.ts +5 -0
  20. package/dist/middleware/security.middleware.js +55 -0
  21. package/dist/middleware/security.middleware.js.map +1 -0
  22. package/dist/models/nostr-profile.d.ts +9 -0
  23. package/dist/models/nostr-profile.js +1 -0
  24. package/dist/scripts/generate-keypair.js +15 -0
  25. package/dist/scripts/tests/create-test-user.js +19 -0
  26. package/dist/scripts/tests/test-auth-live.js +156 -0
  27. package/dist/server.d.ts +1 -0
  28. package/dist/server.js +67 -0
  29. package/dist/server.js.map +1 -0
  30. package/dist/services/nostr.service.d.ts +11 -0
  31. package/dist/services/nostr.service.js +110 -0
  32. package/dist/services/nostr.service.js.map +1 -0
  33. package/dist/src/config/index.js +148 -0
  34. package/dist/src/config.js +60 -0
  35. package/dist/src/index.js +39 -0
  36. package/dist/src/middleware/nostr-auth.middleware.js +120 -0
  37. package/dist/src/middleware/security.middleware.js +55 -0
  38. package/dist/src/server.js +67 -0
  39. package/dist/src/services/nostr.service.js +287 -0
  40. package/dist/src/types/index.js +1 -0
  41. package/dist/src/utils/api-key.utils.js +72 -0
  42. package/dist/src/utils/crypto.utils.js +81 -0
  43. package/dist/src/utils/domain.utils.js +67 -0
  44. package/dist/src/utils/logger.js +25 -0
  45. package/dist/src/utils/types.js +1 -0
  46. package/dist/src/validators/event.validator.js +144 -0
  47. package/dist/types/index.d.ts +58 -0
  48. package/dist/types/index.js +1 -0
  49. package/dist/types/index.js.map +1 -0
  50. package/dist/types.d.ts +57 -0
  51. package/dist/types.js +1 -0
  52. package/dist/utils/api-key.utils.d.ts +10 -0
  53. package/dist/utils/api-key.utils.js +65 -0
  54. package/dist/utils/api-key.utils.js.map +1 -0
  55. package/dist/utils/crypto.utils.d.ts +9 -0
  56. package/dist/utils/crypto.utils.js +80 -0
  57. package/dist/utils/crypto.utils.js.map +1 -0
  58. package/dist/utils/domain.utils.d.ts +31 -0
  59. package/dist/utils/domain.utils.js +67 -0
  60. package/dist/utils/domain.utils.js.map +1 -0
  61. package/dist/utils/jwt.utils.d.ts +4 -0
  62. package/dist/utils/jwt.utils.js +22 -0
  63. package/dist/utils/logger.d.ts +2 -0
  64. package/dist/utils/logger.js +25 -0
  65. package/dist/utils/logger.js.map +1 -0
  66. package/dist/utils/types.d.ts +14 -0
  67. package/dist/utils/types.js +1 -0
  68. package/dist/utils/types.js.map +1 -0
  69. package/dist/validators/event.validator.d.ts +14 -0
  70. package/dist/validators/event.validator.js +137 -0
  71. package/dist/validators/event.validator.js.map +1 -0
  72. package/dist/validators/nostr-event.validator.d.ts +4 -0
  73. package/dist/validators/nostr-event.validator.js +14 -0
  74. package/package.json +120 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 MaiQR.app
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,216 @@
1
+ # Nostr Auth Middleware
2
+
3
+ A focused, security-first authentication middleware for Nostr applications.
4
+
5
+ ⚠️ **Important Security Notice**
6
+
7
+ This library handles cryptographic keys and authentication tokens that are critical for securing your Nostr application and user data. Any private keys (`nsec`) or authentication tokens must be stored and managed with the utmost security and care.
8
+
9
+ Developers using this middleware must inform their users about the critical nature of managing private keys and tokens. It is the user's responsibility to securely store and manage these credentials. The library and its authors disclaim any responsibility or liability for lost keys, compromised tokens, or data resulting from mismanagement.
10
+
11
+ ## Project Philosophy
12
+
13
+ This middleware follows key principles that promote security, auditability, and simplicity:
14
+
15
+ ### 1. Single Responsibility
16
+ - **Authentication Only**: Handles only Nostr key-based authentication
17
+ - **No Business Logic**: Business rules, user tiers, and application logic belong in your API layer
18
+ - **Simple JWT**: Issues basic JWTs with minimal claims (npub, timestamp)
19
+
20
+ ### 2. Security First
21
+ - **Open Source**: Fully auditable security-critical code
22
+ - **Transparent**: Clear, readable implementation
23
+ - **Focused Scope**: Does one thing well - Nostr authentication
24
+
25
+ ### 3. Integration Ready
26
+ ```plaintext
27
+ ┌─────────────────┐
28
+ │ Client App │
29
+ └────────┬────────┘
30
+
31
+
32
+ ┌─────────────────┐
33
+ │ Nostr Auth │ ◄── This Service
34
+ │ Service │ Simple Auth Only
35
+ └────────┬────────┘
36
+
37
+
38
+ ┌─────────────────┐
39
+ │ App Platform │ ◄── Your Business Logic
40
+ │ API │ User Tiers
41
+ └─────────────────┘ Rate Limits
42
+ ```
43
+
44
+ ## Core Features
45
+
46
+ - 🔑 NIP-07 Compatible Authentication
47
+ - 📝 Secure User Enrollment with Nostr
48
+ - ⚡ Comprehensive Event Validation
49
+ - 🔒 Advanced Cryptographic Operations
50
+ - 🗄️ Supabase Integration for Data Persistence
51
+ - 🎫 JWT-based Session Management
52
+ - 🔄 Profile Management & Synchronization
53
+ - 📊 Detailed Logging and Monitoring
54
+ - 🔐 Automatic Key Management
55
+ - 🚀 Environment-Aware Deployment
56
+ - 🛠️ Development & Production Modes
57
+ - 📁 Automated Directory Management
58
+
59
+ ## Documentation
60
+
61
+ - [Architecture Guide](docs/architecture-guide.md) - Understanding the service architecture
62
+ - [Key Management Guide](docs/key-management.md) - Comprehensive key management documentation
63
+ - [Deployment Guide](docs/deployment-guide.md) - Environment-specific deployment instructions
64
+ - [Getting Started](docs/getting-started.md) - Quick start guide
65
+ - [Authentication Flow](docs/authentication-flow.md) - Detailed authentication process
66
+ - [Troubleshooting Guide](docs/troubleshooting.md) - Common issues and solutions
67
+ - [API Documentation](docs/api.md) - API endpoints and usage
68
+ - [Security Guide](docs/security.md) - Security best practices and considerations
69
+ - [Automated Tests](docs/automated-tests.md) - Comprehensive test suite documentation
70
+
71
+ ## Testing
72
+
73
+ The middleware includes comprehensive test coverage for all core functionality:
74
+
75
+ - ✅ Challenge Generation & Verification
76
+ - ✅ Profile Fetching
77
+ - ✅ Enrollment & Verification
78
+ - ✅ Error Handling
79
+ - ✅ Router Integration
80
+
81
+ Current test coverage: 94.8%
82
+
83
+ For detailed information about the test suite, please see our [Automated Tests Documentation](docs/automated-tests.md).
84
+
85
+ To run the tests:
86
+
87
+ ```bash
88
+ npm test
89
+ ```
90
+
91
+ For live testing with actual Nostr relays:
92
+
93
+ ```bash
94
+ npm run test:live
95
+ ```
96
+
97
+ For testing authentication flow:
98
+
99
+ ```bash
100
+ npm run test:auth
101
+ ```
102
+
103
+ ## Quick Start
104
+
105
+ 1. Clone the repository
106
+ 2. Copy `.env.example` to `.env`
107
+ 3. Run `./scripts/startup.sh`
108
+
109
+ The server will automatically:
110
+ - Configure itself based on the environment (development/production)
111
+ - Generate server keys if none exist
112
+ - Create necessary directories with proper permissions
113
+ - Start the service with appropriate settings
114
+
115
+ ## Development Mode
116
+
117
+ ```bash
118
+ # Start the service in development mode
119
+ NODE_ENV=development ./scripts/startup.sh
120
+
121
+ # Stop the service
122
+ ./scripts/shutdown.sh
123
+ ```
124
+
125
+ Development mode features:
126
+ - Local directory structure
127
+ - Auto-generated test keys
128
+ - In-memory data storage option
129
+ - Hot-reloading enabled
130
+ - Detailed logging
131
+ - No root permissions required
132
+
133
+ ## Production Mode
134
+
135
+ ```bash
136
+ # Start the service in production mode
137
+ sudo NODE_ENV=production ./scripts/startup.sh
138
+
139
+ # Stop the service
140
+ sudo ./scripts/shutdown.sh
141
+ ```
142
+
143
+ Production mode features:
144
+ - System-level directory structure
145
+ - Secure key management via Supabase
146
+ - Proper file permissions
147
+ - Log rotation and compression
148
+ - Automatic backups
149
+ - Rate limiting
150
+ - IP whitelisting
151
+
152
+ ## Configuration
153
+
154
+ ### Environment Variables
155
+
156
+ ```bash
157
+ # Core Configuration
158
+ NODE_ENV=development # development or production
159
+ DOMAIN=nostr-platform.app # your domain
160
+ SERVICE_NAME=auth # service identifier
161
+
162
+ # Service URLs (auto-configured in production)
163
+ AUTH_SERVICE_URL=http://localhost:3002 # becomes https://auth.your-domain.app
164
+ IPFS_SERVICE_URL=http://localhost:3001 # becomes https://ipfs.your-domain.app
165
+ RELAY_SERVICE_URL=http://localhost:3000 # becomes https://relay.your-domain.app
166
+
167
+ # Security Configuration
168
+ SERVER_PRIVATE_KEY= # auto-generated if not provided
169
+ SERVER_PUBLIC_KEY= # auto-generated if not provided
170
+ JWT_SECRET=your_jwt_secret # required in production
171
+
172
+ # Supabase Configuration
173
+ SUPABASE_PROJECT=your-project # project identifier
174
+ SUPABASE_URL=your_supabase_url # required in production
175
+ SUPABASE_KEY=your_supabase_key # required in production
176
+
177
+ # Service Configuration
178
+ SERVICE_USER=nostr # service user (production)
179
+ SERVICE_GROUP=nostr # service group (production)
180
+ DEPLOY_DIR=/opt/nostr-platform/auth # deployment directory (production)
181
+ BACKUP_DIR=/opt/backups/nostr # backup directory (production)
182
+ LOG_DIR=/var/log/nostr-platform # log directory (production)
183
+ ```
184
+
185
+ ## Scripts
186
+
187
+ The `scripts` directory contains utilities for managing the service:
188
+
189
+ - `startup.sh`: Service initialization and startup
190
+ - Environment detection
191
+ - Directory creation
192
+ - Permission setting
193
+ - Service startup
194
+
195
+ - `shutdown.sh`: Clean service shutdown
196
+ - Process termination
197
+ - Log rotation
198
+ - Cleanup operations
199
+
200
+ - `config.sh`: Configuration management
201
+ - Environment detection
202
+ - Directory structure
203
+ - Permissions handling
204
+ - Logging utilities
205
+
206
+ ## Contributing
207
+
208
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
209
+
210
+ ## Security
211
+
212
+ Security is our top priority. For details about our security practices and how to report security issues, see our [Security Guide](docs/security.md).
213
+
214
+ ## License
215
+
216
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,104 @@
1
+ import { NostrAuthMiddleware } from '../middleware/nostr-auth.middleware';
2
+ import { jest } from '@jest/globals';
3
+ jest.mock('../services/nostr.service');
4
+ describe('NostrAuthMiddleware', () => {
5
+ let middleware;
6
+ let mockNostrService;
7
+ let mockReq;
8
+ let mockRes;
9
+ let mockNext;
10
+ let mockConfig;
11
+ beforeEach(() => {
12
+ mockNostrService = {
13
+ createChallenge: jest.fn(),
14
+ verifyChallenge: jest.fn(),
15
+ createEnrollment: jest.fn(),
16
+ getProfile: jest.fn(),
17
+ generateToken: jest.fn(),
18
+ };
19
+ mockConfig = {
20
+ port: 3000,
21
+ nodeEnv: 'test',
22
+ corsOrigins: '*',
23
+ keyManagementMode: 'development',
24
+ testMode: true,
25
+ supabaseUrl: 'http://localhost:54321',
26
+ supabaseKey: 'test-key'
27
+ };
28
+ middleware = new NostrAuthMiddleware(mockConfig, mockNostrService);
29
+ mockReq = {
30
+ body: {},
31
+ headers: {},
32
+ params: {}
33
+ };
34
+ mockRes = {
35
+ status: jest.fn().mockReturnThis(),
36
+ json: jest.fn(),
37
+ };
38
+ mockNext = jest.fn();
39
+ });
40
+ describe('handleChallenge', () => {
41
+ const mockPubkey = '123abc';
42
+ const mockChallenge = {
43
+ id: '123',
44
+ pubkey: mockPubkey,
45
+ challenge: 'test-challenge',
46
+ event: {},
47
+ created_at: Date.now(),
48
+ expires_at: Date.now() + 300000
49
+ };
50
+ beforeEach(() => {
51
+ mockReq.params = { pubkey: mockPubkey };
52
+ mockNostrService.createChallenge.mockResolvedValue(mockChallenge);
53
+ });
54
+ it('should create and return a challenge', async () => {
55
+ await middleware.handleChallenge(mockReq, mockRes, mockNext);
56
+ expect(mockNostrService.createChallenge).toHaveBeenCalledWith(mockPubkey);
57
+ expect(mockRes.json).toHaveBeenCalledWith({ challenge: mockChallenge });
58
+ });
59
+ it('should handle errors', async () => {
60
+ const error = new Error('Test error');
61
+ mockNostrService.createChallenge.mockRejectedValue(error);
62
+ await middleware.handleChallenge(mockReq, mockRes, mockNext);
63
+ expect(mockNext).toHaveBeenCalledWith(error);
64
+ });
65
+ });
66
+ describe('handleVerification', () => {
67
+ const mockEvent = {
68
+ id: '1',
69
+ pubkey: '123abc',
70
+ created_at: Math.floor(Date.now() / 1000),
71
+ kind: 22242,
72
+ tags: [],
73
+ content: 'test-challenge',
74
+ sig: '123abc'
75
+ };
76
+ it('should verify challenge and return success', async () => {
77
+ const mockResult = {
78
+ success: true,
79
+ pubkey: mockEvent.pubkey
80
+ };
81
+ mockNostrService.verifyChallenge.mockResolvedValue(mockResult);
82
+ mockNostrService.generateToken.mockResolvedValue('test-token');
83
+ await middleware.handleVerification({ ...mockReq, body: { event: mockEvent } }, mockRes, mockNext);
84
+ expect(mockNostrService.verifyChallenge).toHaveBeenCalledWith(mockEvent);
85
+ expect(mockRes.json).toHaveBeenCalledWith({ ...mockResult, token: 'test-token' });
86
+ });
87
+ it('should handle verification failure', async () => {
88
+ const mockResult = {
89
+ success: false,
90
+ error: 'Invalid challenge'
91
+ };
92
+ mockNostrService.verifyChallenge.mockResolvedValue(mockResult);
93
+ await middleware.handleVerification({ ...mockReq, body: { event: mockEvent } }, mockRes, mockNext);
94
+ expect(mockRes.status).toHaveBeenCalledWith(401);
95
+ expect(mockRes.json).toHaveBeenCalledWith(mockResult);
96
+ });
97
+ it('should handle errors', async () => {
98
+ const error = new Error('Test error');
99
+ mockNostrService.verifyChallenge.mockRejectedValue(error);
100
+ await middleware.handleVerification({ ...mockReq, body: { event: mockEvent } }, mockRes, mockNext);
101
+ expect(mockNext).toHaveBeenCalledWith(error);
102
+ });
103
+ });
104
+ });
@@ -0,0 +1,7 @@
1
+ import { NostrConfig } from '../types/index.js';
2
+ export interface KeyConfig {
3
+ privateKey: string;
4
+ publicKey: string;
5
+ }
6
+ export declare const config: NostrConfig;
7
+ export declare function loadConfig(envPath?: string): Promise<NostrConfig>;
@@ -0,0 +1,148 @@
1
+ import { createLogger } from '../utils/logger.js';
2
+ import { generateKeyPair } from '../utils/crypto.utils.js';
3
+ import { createClient } from '@supabase/supabase-js';
4
+ import { writeFileSync, readFileSync } from 'fs';
5
+ import { resolve } from 'path';
6
+ import dotenv from 'dotenv';
7
+ const logger = createLogger('Config');
8
+ // Initialize config with default values
9
+ export const config = {
10
+ // Server config
11
+ port: parseInt(process.env.PORT || '3002'),
12
+ nodeEnv: process.env.NODE_ENV || 'development',
13
+ corsOrigins: process.env.CORS_ORIGINS?.split(',') || '*',
14
+ security: {
15
+ trustedProxies: process.env.TRUSTED_PROXIES?.split(',') || false,
16
+ allowedIPs: process.env.ALLOWED_IPS?.split(',') || [],
17
+ apiKeys: process.env.API_KEYS?.split(',') || [],
18
+ rateLimitWindowMs: parseInt(process.env.RATE_LIMIT_WINDOW_MS || '900000'),
19
+ rateLimitMaxRequests: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS || '100'),
20
+ },
21
+ // Supabase config
22
+ supabaseUrl: process.env.SUPABASE_URL,
23
+ supabaseKey: process.env.SUPABASE_KEY,
24
+ // Nostr config
25
+ nostrRelays: process.env.NOSTR_RELAYS?.split(',') || [
26
+ 'wss://relay.maiqr.app',
27
+ 'wss://relay.damus.io',
28
+ 'wss://relay.nostr.band'
29
+ ],
30
+ privateKey: process.env.SERVER_PRIVATE_KEY,
31
+ keyManagementMode: process.env.KEY_MANAGEMENT_MODE || 'development',
32
+ // Auth config
33
+ jwtSecret: process.env.JWT_SECRET || 'maiqr_nostr_auth_secret_key_2024',
34
+ jwtExpiresIn: '1h',
35
+ testMode: process.env.TEST_MODE === 'true',
36
+ // Optional configs
37
+ eventTimeoutMs: 5000,
38
+ challengePrefix: 'nostr:auth:'
39
+ };
40
+ export async function loadConfig(envPath) {
41
+ // Load environment variables
42
+ if (envPath) {
43
+ dotenv.config({ path: envPath });
44
+ }
45
+ else {
46
+ dotenv.config();
47
+ }
48
+ const loadedConfig = {
49
+ // Server config
50
+ port: parseInt(process.env.PORT || '3002'),
51
+ nodeEnv: process.env.NODE_ENV || 'development',
52
+ corsOrigins: process.env.CORS_ORIGINS?.split(',') || '*',
53
+ security: {
54
+ trustedProxies: process.env.TRUSTED_PROXIES?.split(',') || false,
55
+ allowedIPs: process.env.ALLOWED_IPS?.split(',') || [],
56
+ apiKeys: process.env.API_KEYS?.split(',') || [],
57
+ rateLimitWindowMs: parseInt(process.env.RATE_LIMIT_WINDOW_MS || '900000'),
58
+ rateLimitMaxRequests: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS || '100'),
59
+ },
60
+ // Supabase config
61
+ supabaseUrl: process.env.SUPABASE_URL,
62
+ supabaseKey: process.env.SUPABASE_KEY,
63
+ // Nostr config
64
+ nostrRelays: process.env.NOSTR_RELAYS?.split(',') || [
65
+ 'wss://relay.maiqr.app',
66
+ 'wss://relay.damus.io',
67
+ 'wss://relay.nostr.band'
68
+ ],
69
+ privateKey: process.env.SERVER_PRIVATE_KEY,
70
+ publicKey: process.env.SERVER_PUBLIC_KEY,
71
+ keyManagementMode: process.env.KEY_MANAGEMENT_MODE,
72
+ // Auth config
73
+ jwtSecret: process.env.JWT_SECRET,
74
+ jwtExpiresIn: process.env.JWT_EXPIRES_IN || '24h',
75
+ testMode: process.env.NODE_ENV !== 'production',
76
+ // Optional configs
77
+ eventTimeoutMs: parseInt(process.env.EVENT_TIMEOUT_MS || '5000'),
78
+ challengePrefix: process.env.CHALLENGE_PREFIX || 'nostr:auth:'
79
+ };
80
+ // Try to load keys from environment
81
+ if (process.env.SERVER_PRIVATE_KEY) {
82
+ const keyPair = await generateKeyPair();
83
+ loadedConfig.privateKey = process.env.SERVER_PRIVATE_KEY;
84
+ loadedConfig.publicKey = keyPair.publicKey;
85
+ logger.info('Loaded server keys from environment');
86
+ return loadedConfig;
87
+ }
88
+ // If in production, try to load from Supabase
89
+ if (!loadedConfig.testMode && loadedConfig.supabaseUrl && loadedConfig.supabaseKey) {
90
+ const supabase = createClient(loadedConfig.supabaseUrl, loadedConfig.supabaseKey);
91
+ try {
92
+ const { data, error } = await supabase
93
+ .from('server_keys')
94
+ .select('private_key, public_key')
95
+ .single();
96
+ if (error)
97
+ throw error;
98
+ if (data) {
99
+ loadedConfig.privateKey = data.private_key;
100
+ loadedConfig.publicKey = data.public_key;
101
+ logger.info('Loaded server keys from Supabase');
102
+ return loadedConfig;
103
+ }
104
+ }
105
+ catch (error) {
106
+ logger.warn('Failed to load keys from Supabase:', error);
107
+ }
108
+ }
109
+ // Generate new keys if none exist
110
+ logger.warn('No server keys found - generating new keypair');
111
+ const keyPair = await generateKeyPair();
112
+ loadedConfig.privateKey = Buffer.from(keyPair.privateKey).toString('hex');
113
+ loadedConfig.publicKey = keyPair.publicKey;
114
+ // Save to .env file in development
115
+ if (loadedConfig.testMode) {
116
+ try {
117
+ const envPath = resolve(process.cwd(), '.env');
118
+ const envContent = readFileSync(envPath, 'utf8');
119
+ const updatedContent = envContent
120
+ .replace(/^SERVER_PRIVATE_KEY=.*$/m, `SERVER_PRIVATE_KEY=${loadedConfig.privateKey}`)
121
+ .replace(/^SERVER_PUBLIC_KEY=.*$/m, `SERVER_PUBLIC_KEY=${loadedConfig.publicKey}`);
122
+ writeFileSync(envPath, updatedContent);
123
+ logger.info('Saved new server keys to .env file');
124
+ }
125
+ catch (error) {
126
+ logger.warn('Failed to save keys to .env file:', error);
127
+ }
128
+ }
129
+ // Save to Supabase in production
130
+ else if (loadedConfig.supabaseUrl && loadedConfig.supabaseKey) {
131
+ const supabase = createClient(loadedConfig.supabaseUrl, loadedConfig.supabaseKey);
132
+ try {
133
+ const { error } = await supabase
134
+ .from('server_keys')
135
+ .upsert({
136
+ private_key: loadedConfig.privateKey,
137
+ public_key: loadedConfig.publicKey
138
+ });
139
+ if (error)
140
+ throw error;
141
+ logger.info('Saved new server keys to Supabase');
142
+ }
143
+ catch (error) {
144
+ logger.warn('Failed to save keys to Supabase:', error);
145
+ }
146
+ }
147
+ return loadedConfig;
148
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { NostrAuthConfig } from './types';
2
+ export declare const config: NostrAuthConfig;
3
+ export declare function validateConfig(config: NostrAuthConfig): void;
package/dist/config.js ADDED
@@ -0,0 +1,68 @@
1
+ import { createLogger } from './utils/logger';
2
+ const logger = createLogger('Config');
3
+ function getEnvWithWarning(key) {
4
+ const value = process.env[key];
5
+ if (!value) {
6
+ logger.warn(`${key} not set in environment variables`);
7
+ }
8
+ return value;
9
+ }
10
+ function validatePrivateKey(privateKey) {
11
+ if (!privateKey) {
12
+ return undefined;
13
+ }
14
+ try {
15
+ // Validate hex format
16
+ if (!/^[0-9a-f]{64}$/.test(privateKey)) {
17
+ throw new Error('Invalid private key format');
18
+ }
19
+ return privateKey;
20
+ }
21
+ catch (error) {
22
+ logger.error('Invalid SERVER_PRIVATE_KEY:', error);
23
+ throw error;
24
+ }
25
+ }
26
+ export const config = {
27
+ keyManagementMode: process.env.KEY_MANAGEMENT_MODE === 'production' ? 'production' : 'development',
28
+ port: parseInt(process.env.PORT || '3002', 10),
29
+ nodeEnv: process.env.NODE_ENV || 'development',
30
+ corsOrigin: process.env.CORS_ORIGIN || '*',
31
+ corsCredentials: process.env.CORS_CREDENTIALS === 'true',
32
+ eventTimeoutMs: parseInt(process.env.EVENT_TIMEOUT_MS || '5000', 10),
33
+ challengePrefix: process.env.CHALLENGE_PREFIX || 'nostr:auth:',
34
+ testMode: process.env.TEST_MODE === 'true',
35
+ logLevel: process.env.LOG_LEVEL || 'info',
36
+ jwtSecret: getEnvWithWarning('JWT_SECRET'),
37
+ jwtExpiresIn: process.env.JWT_EXPIRES_IN || '24h',
38
+ supabaseUrl: getEnvWithWarning('SUPABASE_URL'),
39
+ supabaseKey: getEnvWithWarning('SUPABASE_KEY'),
40
+ privateKey: validatePrivateKey(process.env.SERVER_PRIVATE_KEY),
41
+ publicKey: process.env.SERVER_PUBLIC_KEY
42
+ };
43
+ export function validateConfig(config) {
44
+ if (!config) {
45
+ throw new Error('Config is required');
46
+ }
47
+ if (!config.keyManagementMode) {
48
+ throw new Error('keyManagementMode is required in config');
49
+ }
50
+ if (config.keyManagementMode === 'production') {
51
+ if (!config.privateKey) {
52
+ throw new Error('privateKey is required in production mode');
53
+ }
54
+ // Validate private key format
55
+ if (!/^[0-9a-f]{64}$/.test(config.privateKey)) {
56
+ throw new Error('Invalid private key format');
57
+ }
58
+ }
59
+ // Log config (excluding sensitive values)
60
+ const sanitizedConfig = {
61
+ ...config,
62
+ privateKey: config.privateKey ? '***' : undefined,
63
+ jwtSecret: config.jwtSecret ? '***' : undefined,
64
+ supabaseKey: config.supabaseKey ? '***' : undefined
65
+ };
66
+ logger.info('Config validated:', sanitizedConfig);
67
+ }
68
+ validateConfig(config);
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;AAEtC,SAAS,iBAAiB,CAAC,GAAW;IACpC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,CAAC,IAAI,CAAC,iCAAiC,GAAG,iCAAiC,CAAC,CAAC;IACrF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAuB;IACjD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,CAAC;QACH,sBAAsB;QACtB,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,CAAC;QACD,sBAAsB;QACtB,MAAM,eAAe,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,oCAAoC,EAAE,MAAM,CAAC,CAAC;QAC1D,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;QACnD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,gBAAgB;IAChB,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC;IAC9C,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa;IAE9C,OAAO;IACP,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG;IAExD,eAAe;IACf,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI;QACnD,sBAAsB;QACtB,wBAAwB;KACzB;IAED,yCAAyC;IACzC,WAAW,EAAE,iBAAiB,CAAC,cAAc,CAAC;IAC9C,WAAW,EAAE,iBAAiB,CAAC,cAAc,CAAC;IAE9C,oCAAoC;IACpC,SAAS,EAAE,iBAAiB,CAAC,YAAY,CAAC;IAC1C,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,KAAK;IAEjD,sBAAsB;IACtB,iBAAiB,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAiC;IAEpI,2CAA2C;IAC3C,UAAU,EAAE,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAC9D,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;IAExC,wDAAwD;IACxD,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,MAAM;IAE1C,UAAU;IACV,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM;CACjC,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Main exports for the Nostr Auth Middleware package
3
+ * @module @maiqr/nostr-auth-enroll
4
+ */
5
+ import { NostrAuthMiddleware } from './middleware/nostr-auth.middleware.js';
6
+ import type { NostrAuthConfig } from './types/index.js';
7
+ export { NostrAuthMiddleware };
8
+ export type { NostrAuthConfig, NostrChallenge, NostrProfile, NostrEnrollment, VerificationResult } from './types/index.js';
9
+ export type { NostrEvent } from './utils/types.js';
10
+ export { generateChallenge, generateEventHash, getPublicKey, verifySignature } from './utils/crypto.utils.js';
11
+ export { NostrService } from './services/nostr.service.js';
12
+ export { validateEvent, validateChallengeEvent, validateEnrollmentEvent } from './validators/event.validator.js';
13
+ export { config } from './config.js';
14
+ /**
15
+ * Create and configure a new Nostr Auth Middleware instance
16
+ * @param config Configuration options for the middleware
17
+ * @returns Configured NostrAuthMiddleware instance
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * import { createNostrAuth } from '@maiqr/nostr-auth-enroll';
22
+ *
23
+ * const nostrAuth = createNostrAuth({
24
+ * supabaseUrl: process.env.SUPABASE_URL,
25
+ * supabaseKey: process.env.SUPABASE_KEY,
26
+ * privateKey: process.env.SERVER_PRIVATE_KEY
27
+ * });
28
+ *
29
+ * app.use('/auth/nostr', nostrAuth.router);
30
+ * ```
31
+ */
32
+ export declare const createNostrAuth: (config: NostrAuthConfig) => NostrAuthMiddleware;
33
+ export default NostrAuthMiddleware;
package/dist/index.js ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Main exports for the Nostr Auth Middleware package
3
+ * @module @maiqr/nostr-auth-enroll
4
+ */
5
+ // Core middleware
6
+ import { NostrAuthMiddleware } from './middleware/nostr-auth.middleware.js';
7
+ // Re-export middleware
8
+ export { NostrAuthMiddleware };
9
+ // Crypto utilities
10
+ export { generateChallenge, generateEventHash, getPublicKey, verifySignature } from './utils/crypto.utils.js';
11
+ // Services
12
+ export { NostrService } from './services/nostr.service.js';
13
+ // Validators
14
+ export { validateEvent, validateChallengeEvent, validateEnrollmentEvent } from './validators/event.validator.js';
15
+ // Configuration
16
+ export { config } from './config.js';
17
+ /**
18
+ * Create and configure a new Nostr Auth Middleware instance
19
+ * @param config Configuration options for the middleware
20
+ * @returns Configured NostrAuthMiddleware instance
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * import { createNostrAuth } from '@maiqr/nostr-auth-enroll';
25
+ *
26
+ * const nostrAuth = createNostrAuth({
27
+ * supabaseUrl: process.env.SUPABASE_URL,
28
+ * supabaseKey: process.env.SUPABASE_KEY,
29
+ * privateKey: process.env.SERVER_PRIVATE_KEY
30
+ * });
31
+ *
32
+ * app.use('/auth/nostr', nostrAuth.router);
33
+ * ```
34
+ */
35
+ export const createNostrAuth = (config) => {
36
+ return new NostrAuthMiddleware(config);
37
+ };
38
+ // Default export for CommonJS compatibility
39
+ export default NostrAuthMiddleware;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,kBAAkB;AAClB,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAG5E,uBAAuB;AACvB,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAa/B,mBAAmB;AACnB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EAChB,MAAM,yBAAyB,CAAC;AAEjC,WAAW;AACX,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,aAAa;AACb,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAEtE,gBAAgB;AAChB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAuB,EAAuB,EAAE;IAC9E,OAAO,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;AACzC,CAAC,CAAC;AAEF,4CAA4C;AAC5C,eAAe,mBAAmB,CAAC"}