@powerhousedao/switchboard 4.1.0-dev.8 → 4.1.0-dev.80
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/.env +1 -1
- package/Auth.md +396 -0
- package/CHANGELOG.md +619 -0
- package/Dockerfile +6 -4
- package/README.md +15 -14
- package/dist/src/clients/redis.d.ts +1 -1
- package/dist/src/clients/redis.d.ts.map +1 -1
- package/dist/src/clients/redis.js.map +1 -1
- package/dist/src/config.d.ts +1 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +2 -1
- package/dist/src/config.js.map +1 -1
- package/dist/src/feature-flags.d.ts +4 -0
- package/dist/src/feature-flags.d.ts.map +1 -0
- package/dist/src/feature-flags.js +17 -0
- package/dist/src/feature-flags.js.map +1 -0
- package/dist/src/index.js +12 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/server.d.ts +1 -1
- package/dist/src/server.d.ts.map +1 -1
- package/dist/src/server.js +127 -54
- package/dist/src/server.js.map +1 -1
- package/dist/src/types.d.ts +12 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/gen-doc-model-type-defs.d.ts +1 -1
- package/dist/src/utils/gen-doc-model-type-defs.d.ts.map +1 -1
- package/dist/src/utils/gen-doc-model-type-defs.js +14 -13
- package/dist/src/utils/gen-doc-model-type-defs.js.map +1 -1
- package/dist/src/utils.d.ts +1 -1
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +1 -1
- package/dist/src/utils.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/entrypoint.sh +6 -0
- package/package.json +25 -21
- package/tsconfig.json +16 -2
package/.env
CHANGED
|
@@ -13,4 +13,4 @@ PH_SWITCHBOARD_REDIS_URL="redis://localhost:6380"
|
|
|
13
13
|
SWITCHBOARD_AUTH_ENABLED=true
|
|
14
14
|
SWITCHBOARD_AUTH_GUESTS=""
|
|
15
15
|
SWITCHBOARD_AUTH_USERS=""
|
|
16
|
-
SWITCHBOARD_AUTH_ADMINS="0x1AD3d72e54Fb0eB46e87F82f77B284FC8a66b16C"
|
|
16
|
+
SWITCHBOARD_AUTH_ADMINS="0x1AD3d72e54Fb0eB46e87F82f77B284FC8a66b16C"
|
package/Auth.md
ADDED
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
# Powerhouse Authentication System Tutorial
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The Powerhouse authentication system is a sophisticated, decentralized identity and authorization solution that combines blockchain-based authentication with role-based access control. It provides secure, verifiable, and privacy-preserving authentication for decentralized applications while maintaining the flexibility of traditional role-based systems.
|
|
6
|
+
|
|
7
|
+
## What It's Capable Of
|
|
8
|
+
|
|
9
|
+
### 🔐 **Decentralized Identity Management**
|
|
10
|
+
- **DID (Decentralized Identifier) Creation**: Generates unique, self-sovereign identifiers based on Ethereum addresses
|
|
11
|
+
- **Verifiable Credentials**: Uses W3C Verifiable Credentials standard for cryptographic proof of identity
|
|
12
|
+
- **Wallet Integration**: Seamless integration with Ethereum wallets and other Web3 providers
|
|
13
|
+
- **Privacy Preservation**: Users can maintain pseudonymous identities while building reputation
|
|
14
|
+
|
|
15
|
+
### 🎭 **Role-Based Access Control (RBAC)**
|
|
16
|
+
- **Three-Tier System**: Guests, Users, and Admins with different permission levels
|
|
17
|
+
- **Flexible Configuration**: Easy setup through environment variables or configuration files
|
|
18
|
+
- **Granular Permissions**: Fine-grained control over what each role can access
|
|
19
|
+
- **Dynamic Role Assignment**: Roles can be updated without restarting the system
|
|
20
|
+
|
|
21
|
+
### 🔒 **Advanced Security Features**
|
|
22
|
+
- **Challenge-Response Authentication**: Cryptographic proof of wallet ownership
|
|
23
|
+
- **JWT Token Management**: Secure session handling with automatic expiration
|
|
24
|
+
- **Credential Verification**: Real-time validation against the Renown API
|
|
25
|
+
- **Token Caching**: Performance optimization with secure token storage
|
|
26
|
+
- **Session Management**: Multiple active sessions with individual controls
|
|
27
|
+
|
|
28
|
+
### 🌐 **Cross-Platform Compatibility**
|
|
29
|
+
- **GraphQL Integration**: Native GraphQL support with authentication middleware
|
|
30
|
+
- **REST API Support**: Standard HTTP authentication headers
|
|
31
|
+
- **Multi-Origin Support**: Configurable CORS and origin restrictions
|
|
32
|
+
- **Mobile & Desktop**: Works across all platforms and devices
|
|
33
|
+
|
|
34
|
+
## How It Works Under the Hood
|
|
35
|
+
|
|
36
|
+
### 1. **Authentication Flow Architecture**
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
User Wallet → Challenge Request → Signature → Token Generation → Session Creation
|
|
40
|
+
↓ ↓ ↓ ↓ ↓
|
|
41
|
+
Ethereum Nonce + Message Signed JWT Token Active Session
|
|
42
|
+
Address (Cryptographic) Message (Verifiable) (Authorized)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 2. **Decentralized Identity Creation**
|
|
46
|
+
|
|
47
|
+
The system uses the **Renown** service to create and manage decentralized identities:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// DID Format: did:pkh:eip155:1:0x1234...
|
|
51
|
+
interface PKHDid {
|
|
52
|
+
networkId: string; // Network identifier (e.g., "mainnet")
|
|
53
|
+
chainId: number; // Blockchain chain ID (e.g., 1 for Ethereum mainnet)
|
|
54
|
+
address: `0x${string}`; // Ethereum wallet address
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Key Benefits:**
|
|
59
|
+
- **Self-Sovereign**: Users control their own identity without central authority
|
|
60
|
+
- **Portable**: Identity can be used across different applications
|
|
61
|
+
- **Verifiable**: Cryptographic proof of ownership and authenticity
|
|
62
|
+
- **Privacy-Preserving**: No personal information required
|
|
63
|
+
|
|
64
|
+
### 3. **Challenge-Response Authentication**
|
|
65
|
+
|
|
66
|
+
Instead of traditional username/password, the system uses cryptographic challenges:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
// Step 1: Create Challenge
|
|
70
|
+
const challenge = await createChallenge(userAddress);
|
|
71
|
+
// Returns: { nonce: "random-string", message: "Sign this message: ..." }
|
|
72
|
+
|
|
73
|
+
// Step 2: User Signs Message
|
|
74
|
+
const signature = await signMessage(challenge.message);
|
|
75
|
+
|
|
76
|
+
// Step 3: Verify Signature
|
|
77
|
+
const token = await solveChallenge(challenge.nonce, signature);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Security Features:**
|
|
81
|
+
- **Nonce-based**: Prevents replay attacks
|
|
82
|
+
- **Cryptographic Proof**: Verifies wallet ownership
|
|
83
|
+
- **Time-limited**: Challenges expire quickly
|
|
84
|
+
- **Unique per Session**: Each login uses a different challenge
|
|
85
|
+
|
|
86
|
+
### 4. **Verifiable Credentials System**
|
|
87
|
+
|
|
88
|
+
The system leverages W3C Verifiable Credentials for identity verification:
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
interface VerifiableCredential {
|
|
92
|
+
"@context": ["https://www.w3.org/2018/credentials/v1"];
|
|
93
|
+
type: ["VerifiableCredential"];
|
|
94
|
+
credentialSubject: {
|
|
95
|
+
chainId: number;
|
|
96
|
+
networkId: string;
|
|
97
|
+
address: string;
|
|
98
|
+
};
|
|
99
|
+
issuer: string; // DID of the credential issuer
|
|
100
|
+
issuanceDate: string; // When credential was created
|
|
101
|
+
proof: object; // Cryptographic proof of authenticity
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Verification Process:**
|
|
106
|
+
1. **Token Decoding**: Extract credential information from JWT
|
|
107
|
+
2. **Credential Validation**: Verify against W3C standards
|
|
108
|
+
3. **Issuer Verification**: Check credential issuer authenticity
|
|
109
|
+
4. **Renown API Check**: Validate credential still exists and is valid
|
|
110
|
+
5. **User Extraction**: Create user object from verified credentials
|
|
111
|
+
|
|
112
|
+
### 5. **Role-Based Authorization**
|
|
113
|
+
|
|
114
|
+
The system implements a three-tier role system with configurable permissions:
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
interface AuthConfig {
|
|
118
|
+
enabled: boolean;
|
|
119
|
+
guests: string[]; // Array of wallet addresses
|
|
120
|
+
users: string[]; // Array of wallet addresses
|
|
121
|
+
admins: string[]; // Array of wallet addresses
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Permission Levels:**
|
|
126
|
+
- **Guests**: Read-only access to public data
|
|
127
|
+
- **Users**: Standard access to most endpoints and operations
|
|
128
|
+
- **Admins**: Full access including administrative functions
|
|
129
|
+
|
|
130
|
+
### 6. **Session Management**
|
|
131
|
+
|
|
132
|
+
Advanced session handling with multiple active sessions:
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
interface Session {
|
|
136
|
+
id: string;
|
|
137
|
+
createdAt: Date;
|
|
138
|
+
createdBy: string;
|
|
139
|
+
referenceExpiryDate?: Date;
|
|
140
|
+
referenceTokenId?: string;
|
|
141
|
+
isUserCreated?: boolean;
|
|
142
|
+
name?: string;
|
|
143
|
+
revokedAt?: Date;
|
|
144
|
+
allowedOrigins?: string;
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Session Features:**
|
|
149
|
+
- **Multiple Sessions**: Users can have several active sessions
|
|
150
|
+
- **Custom Names**: Human-readable session identifiers
|
|
151
|
+
- **Expiration Control**: Configurable session lifetimes
|
|
152
|
+
- **Origin Restrictions**: Limit where sessions can be used
|
|
153
|
+
- **Revocation**: Immediate session termination capability
|
|
154
|
+
|
|
155
|
+
## How to Use the Authentication System
|
|
156
|
+
|
|
157
|
+
### 1. **Basic Configuration**
|
|
158
|
+
|
|
159
|
+
#### Environment Variables Method
|
|
160
|
+
```bash
|
|
161
|
+
# Enable authentication
|
|
162
|
+
export AUTH_ENABLED=true
|
|
163
|
+
|
|
164
|
+
# Configure roles (comma-separated wallet addresses)
|
|
165
|
+
export GUESTS="0x789,0xabc,0xdef"
|
|
166
|
+
export USERS="0x123,0x456,0x789"
|
|
167
|
+
export ADMINS="0x111,0x222,0x333"
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### Configuration File Method
|
|
171
|
+
```json
|
|
172
|
+
{
|
|
173
|
+
"auth": {
|
|
174
|
+
"enabled": true,
|
|
175
|
+
"guests": ["0x789", "0xabc", "0xdef"],
|
|
176
|
+
"users": ["0x123", "0x456", "0x789"],
|
|
177
|
+
"admins": ["0x111", "0x222", "0x333"]
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### 2. **Frontend Integration**
|
|
183
|
+
|
|
184
|
+
#### Using the useAuth Hook
|
|
185
|
+
```typescript
|
|
186
|
+
import useAuth from '../hooks/useAuth';
|
|
187
|
+
|
|
188
|
+
function LoginComponent() {
|
|
189
|
+
const { signIn, signOut, isAuthorized, address } = useAuth();
|
|
190
|
+
|
|
191
|
+
if (!isAuthorized) {
|
|
192
|
+
return (
|
|
193
|
+
<button
|
|
194
|
+
onClick={signIn}
|
|
195
|
+
className="bg-orange-500 hover:bg-orange-600 text-white px-4 py-2 rounded"
|
|
196
|
+
>
|
|
197
|
+
Sign in with Ethereum
|
|
198
|
+
</button>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return (
|
|
203
|
+
<div>
|
|
204
|
+
<p>Welcome, {address}</p>
|
|
205
|
+
<button onClick={signOut}>Sign Out</button>
|
|
206
|
+
</div>
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### Session Management
|
|
212
|
+
```typescript
|
|
213
|
+
const { createSession, revokeSession, sessions } = useAuth();
|
|
214
|
+
|
|
215
|
+
// Create a new session
|
|
216
|
+
const token = await createSession(
|
|
217
|
+
"My API Token", // Session name
|
|
218
|
+
3600, // Expiry in seconds (1 hour)
|
|
219
|
+
"https://myapp.com" // Allowed origin
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
// Revoke a session
|
|
223
|
+
await revokeSession(sessionId);
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### 3. **Backend Integration**
|
|
227
|
+
|
|
228
|
+
#### Express Middleware Setup
|
|
229
|
+
```typescript
|
|
230
|
+
import { AuthService } from '@powerhousedao/reactor-api';
|
|
231
|
+
|
|
232
|
+
const authService = new AuthService({
|
|
233
|
+
enabled: true,
|
|
234
|
+
guests: ['0x789', '0xabc'],
|
|
235
|
+
users: ['0x123', '0x456'],
|
|
236
|
+
admins: ['0x111', '0x222']
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// Apply to all routes
|
|
240
|
+
app.use(async (req, res, next) => {
|
|
241
|
+
await authService.authenticate(req, res, next);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// Access user info in route handlers
|
|
245
|
+
app.post('/api/data', (req, res) => {
|
|
246
|
+
const user = req.user; // Authenticated user object
|
|
247
|
+
const isAdmin = req.admins.includes(user.address);
|
|
248
|
+
|
|
249
|
+
if (isAdmin) {
|
|
250
|
+
// Admin-only operations
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### GraphQL Context Integration
|
|
256
|
+
```typescript
|
|
257
|
+
const graphqlManager = new GraphQLManager(/* config */);
|
|
258
|
+
|
|
259
|
+
// Add auth context fields
|
|
260
|
+
graphqlManager.setAdditionalContextFields(
|
|
261
|
+
authService.getAdditionalContextFields()
|
|
262
|
+
);
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### 4. **API Authentication**
|
|
266
|
+
|
|
267
|
+
#### HTTP Headers
|
|
268
|
+
```bash
|
|
269
|
+
# Include JWT token in Authorization header
|
|
270
|
+
curl -H "Authorization: Bearer <your-jwt-token>" \
|
|
271
|
+
https://api.example.com/data
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
#### GraphQL Queries
|
|
275
|
+
```typescript
|
|
276
|
+
// Apollo Client with auth link
|
|
277
|
+
const authLink = setContext((_, { headers }) => ({
|
|
278
|
+
headers: {
|
|
279
|
+
...headers,
|
|
280
|
+
authorization: token ? `Bearer ${token}` : "",
|
|
281
|
+
},
|
|
282
|
+
}));
|
|
283
|
+
|
|
284
|
+
const client = new ApolloClient({
|
|
285
|
+
link: authLink.concat(httpLink),
|
|
286
|
+
cache: new InMemoryCache(),
|
|
287
|
+
});
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### 5. **Advanced Features**
|
|
291
|
+
|
|
292
|
+
#### Custom Session Creation
|
|
293
|
+
```typescript
|
|
294
|
+
// Create a long-lived API token
|
|
295
|
+
const apiToken = await createSession(
|
|
296
|
+
"API Integration Token",
|
|
297
|
+
86400 * 30, // 30 days
|
|
298
|
+
"*" // Allow all origins
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
// Create a restricted session
|
|
302
|
+
const restrictedToken = await createSession(
|
|
303
|
+
"Mobile App Token",
|
|
304
|
+
86400 * 7, // 7 days
|
|
305
|
+
"https://mobile.myapp.com" // Restrict to mobile app
|
|
306
|
+
);
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
#### Role-Based Route Protection
|
|
310
|
+
```typescript
|
|
311
|
+
// Middleware for admin-only routes
|
|
312
|
+
const requireAdmin = (req, res, next) => {
|
|
313
|
+
if (!req.admins.includes(req.user.address)) {
|
|
314
|
+
return res.status(403).json({ error: "Admin access required" });
|
|
315
|
+
}
|
|
316
|
+
next();
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
app.post('/admin/users', requireAdmin, (req, res) => {
|
|
320
|
+
// Admin-only user management
|
|
321
|
+
});
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
## Security Considerations
|
|
325
|
+
|
|
326
|
+
### 🔒 **Best Practices**
|
|
327
|
+
|
|
328
|
+
1. **Token Storage**: Store tokens securely (localStorage for web, secure storage for mobile)
|
|
329
|
+
2. **Session Expiry**: Set reasonable expiration times for different use cases
|
|
330
|
+
3. **Origin Restrictions**: Limit session usage to specific domains when possible
|
|
331
|
+
4. **Regular Rotation**: Encourage users to rotate their sessions periodically
|
|
332
|
+
5. **Revocation**: Provide easy ways for users to revoke compromised sessions
|
|
333
|
+
|
|
334
|
+
### 🚨 **Security Features**
|
|
335
|
+
|
|
336
|
+
- **Automatic Expiration**: Sessions automatically expire based on configuration
|
|
337
|
+
- **Immediate Revocation**: Sessions can be revoked instantly if compromised
|
|
338
|
+
- **Credential Validation**: Real-time verification against the Renown API
|
|
339
|
+
- **Cryptographic Proof**: All authentication uses cryptographic signatures
|
|
340
|
+
- **No Password Storage**: No passwords to compromise or leak
|
|
341
|
+
|
|
342
|
+
## Troubleshooting
|
|
343
|
+
|
|
344
|
+
### Common Issues
|
|
345
|
+
|
|
346
|
+
1. **"Missing authorization token"**
|
|
347
|
+
- Ensure the Authorization header is included
|
|
348
|
+
- Check that the token format is `Bearer <token>`
|
|
349
|
+
|
|
350
|
+
2. **"Verification failed"**
|
|
351
|
+
- Token may be expired or malformed
|
|
352
|
+
- Check token validity and renewal
|
|
353
|
+
|
|
354
|
+
3. **"Credentials no longer valid"**
|
|
355
|
+
- User's Renown credentials may have been revoked
|
|
356
|
+
- Re-authenticate through the wallet connection
|
|
357
|
+
|
|
358
|
+
4. **"Forbidden"**
|
|
359
|
+
- User's wallet address not in allowed roles
|
|
360
|
+
- Check role configuration and user permissions
|
|
361
|
+
|
|
362
|
+
### Debug Mode
|
|
363
|
+
|
|
364
|
+
Enable detailed logging for troubleshooting:
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
// Enable verbose logging
|
|
368
|
+
const authService = new AuthService({
|
|
369
|
+
enabled: true,
|
|
370
|
+
debug: true, // Enable debug logging
|
|
371
|
+
// ... other config
|
|
372
|
+
});
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
## Performance Optimization
|
|
376
|
+
|
|
377
|
+
### Caching Strategies
|
|
378
|
+
|
|
379
|
+
- **Token Caching**: Frequently used tokens are cached in memory
|
|
380
|
+
- **Credential Validation**: Results are cached to reduce API calls
|
|
381
|
+
- **Session Lookup**: Fast session validation using indexed lookups
|
|
382
|
+
|
|
383
|
+
### Scalability Features
|
|
384
|
+
|
|
385
|
+
- **Stateless Design**: No server-side session storage required
|
|
386
|
+
- **Distributed Validation**: Credentials can be verified across multiple nodes
|
|
387
|
+
- **Efficient Lookups**: O(1) role checking using Set data structures
|
|
388
|
+
|
|
389
|
+
## Conclusion
|
|
390
|
+
|
|
391
|
+
The Powerhouse authentication system provides a robust, secure, and flexible foundation for decentralized applications. By combining blockchain-based identity with traditional role-based access control, it offers the best of both worlds: the security and privacy of Web3 with the familiarity and flexibility of enterprise authentication systems.
|
|
392
|
+
|
|
393
|
+
Whether you're building a simple web app or a complex enterprise system, the authentication system scales to meet your needs while maintaining the highest security standards. The decentralized nature ensures user privacy and control, while the role-based system provides the administrative oversight needed for production applications.
|
|
394
|
+
|
|
395
|
+
For more information and advanced usage examples, refer to the Powerhouse documentation and community resources.
|
|
396
|
+
|