create-chaaskit 0.1.0 → 0.1.2
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 +21 -0
- package/dist/commands/init.js +5 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/templates/app/root.tsx +26 -14
- package/dist/templates/app/routes/chat.admin.promo-codes.tsx +10 -0
- package/dist/templates/app/routes/chat.admin.waitlist.tsx +10 -0
- package/dist/templates/app/routes.ts +2 -0
- package/dist/templates/app/styles/app.css +9 -0
- package/dist/templates/config/app.config.ts +29 -80
- package/dist/templates/package.json +8 -5
- package/dist/templates/postcss.config.js +6 -0
- package/dist/templates/server.js +40 -10
- package/dist/templates/tailwind.config.ts +76 -0
- package/package.json +19 -10
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -25
- package/dist/cli.js.map +0 -1
- package/dist/templates/app/components/AcceptInviteClient.tsx +0 -10
- package/dist/templates/app/components/AdminDashboardClient.tsx +0 -10
- package/dist/templates/app/components/AdminTeamClient.tsx +0 -10
- package/dist/templates/app/components/AdminTeamsClient.tsx +0 -10
- package/dist/templates/app/components/AdminUsersClient.tsx +0 -10
- package/dist/templates/app/components/ApiKeysClient.tsx +0 -10
- package/dist/templates/app/components/AutomationsClient.tsx +0 -10
- package/dist/templates/app/components/ChatClient.tsx +0 -13
- package/dist/templates/app/components/DocumentsClient.tsx +0 -10
- package/dist/templates/app/components/OAuthConsentClient.tsx +0 -10
- package/dist/templates/app/components/PricingClient.tsx +0 -10
- package/dist/templates/app/components/TeamSettingsClient.tsx +0 -10
- package/dist/templates/app/components/VerifyEmailClient.tsx +0 -10
- package/dist/templates/app/routes/admin._index.tsx +0 -57
- package/dist/templates/app/routes/admin.teams.$teamId.tsx +0 -57
- package/dist/templates/app/routes/admin.teams._index.tsx +0 -57
- package/dist/templates/app/routes/admin.users.tsx +0 -57
- package/dist/templates/app/routes/api-keys.tsx +0 -57
- package/dist/templates/app/routes/automations.tsx +0 -57
- package/dist/templates/app/routes/documents.tsx +0 -57
- package/dist/templates/app/routes/team.$teamId.settings.tsx +0 -57
- package/dist/templates/app/routes/thread.$threadId.tsx +0 -102
- package/dist/templates/docs/admin.md +0 -257
- package/dist/templates/docs/api-keys.md +0 -403
- package/dist/templates/docs/authentication.md +0 -247
- package/dist/templates/docs/configuration.md +0 -1212
- package/dist/templates/docs/custom-pages.md +0 -466
- package/dist/templates/docs/deployment.md +0 -362
- package/dist/templates/docs/development.md +0 -411
- package/dist/templates/docs/documents.md +0 -293
- package/dist/templates/docs/extensions.md +0 -639
- package/dist/templates/docs/index.md +0 -139
- package/dist/templates/docs/installation.md +0 -286
- package/dist/templates/docs/mcp.md +0 -952
- package/dist/templates/docs/native-tools.md +0 -688
- package/dist/templates/docs/queue.md +0 -514
- package/dist/templates/docs/scheduled-prompts.md +0 -279
- package/dist/templates/docs/settings.md +0 -415
- package/dist/templates/docs/slack.md +0 -318
- package/dist/templates/docs/styling.md +0 -288
- package/dist/templates/index.html +0 -16
- package/dist/templates/prisma/schema.prisma +0 -271
- package/dist/templates/src/main.tsx +0 -8
|
@@ -1,403 +0,0 @@
|
|
|
1
|
-
# API Keys
|
|
2
|
-
|
|
3
|
-
API Keys allow users to access the API programmatically. This is useful for building integrations, CLI tools, or automated workflows.
|
|
4
|
-
|
|
5
|
-
## Configuration
|
|
6
|
-
|
|
7
|
-
Enable API keys in `config/app.config.ts`:
|
|
8
|
-
|
|
9
|
-
```typescript
|
|
10
|
-
api: {
|
|
11
|
-
enabled: true,
|
|
12
|
-
keyPrefix: 'myapp-', // Optional, default: "sk-"
|
|
13
|
-
allowedPlans: ['pro', 'enterprise'], // Optional: restrict to specific plans
|
|
14
|
-
allowedEndpoints: [ // Required: whitelist endpoints for API key access
|
|
15
|
-
'/api/chat',
|
|
16
|
-
'/api/threads',
|
|
17
|
-
'/api/threads/**',
|
|
18
|
-
],
|
|
19
|
-
}
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
### Configuration Options
|
|
23
|
-
|
|
24
|
-
| Option | Type | Default | Description |
|
|
25
|
-
|--------|------|---------|-------------|
|
|
26
|
-
| `enabled` | boolean | `false` | Enable API key creation and management |
|
|
27
|
-
| `keyPrefix` | string | `"sk-"` | Prefix for generated API keys |
|
|
28
|
-
| `allowedPlans` | string[] | `undefined` | If set, only these plans can create keys |
|
|
29
|
-
| `allowedEndpoints` | string[] | `[]` | Endpoints accessible via API keys (required) |
|
|
30
|
-
|
|
31
|
-
### Endpoint Patterns
|
|
32
|
-
|
|
33
|
-
The `allowedEndpoints` array supports pattern matching:
|
|
34
|
-
|
|
35
|
-
| Pattern | Matches | Does NOT Match |
|
|
36
|
-
|---------|---------|----------------|
|
|
37
|
-
| `/api/threads` | `/api/threads` (exact) | `/api/threads/123` |
|
|
38
|
-
| `/api/threads/*` | `/api/threads/123` | `/api/threads/123/messages` |
|
|
39
|
-
| `/api/threads/**` | `/api/threads/123`, `/api/threads/123/messages` | `/api/thread` |
|
|
40
|
-
|
|
41
|
-
**Pattern Types:**
|
|
42
|
-
- **Exact match**: `/api/chat` - matches only that exact path
|
|
43
|
-
- **Single segment wildcard (`*`)**: `/api/threads/*` - matches one path segment
|
|
44
|
-
- **Multi-segment wildcard (`**`)**: `/api/threads/**` - matches any depth
|
|
45
|
-
|
|
46
|
-
### Example Configurations
|
|
47
|
-
|
|
48
|
-
**Minimal (chat only):**
|
|
49
|
-
```typescript
|
|
50
|
-
api: {
|
|
51
|
-
enabled: true,
|
|
52
|
-
allowedEndpoints: ['/api/chat'],
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
**Full access:**
|
|
57
|
-
```typescript
|
|
58
|
-
api: {
|
|
59
|
-
enabled: true,
|
|
60
|
-
allowedEndpoints: [
|
|
61
|
-
'/api/chat',
|
|
62
|
-
'/api/threads',
|
|
63
|
-
'/api/threads/**',
|
|
64
|
-
'/api/search',
|
|
65
|
-
'/api/export/*',
|
|
66
|
-
],
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
**Restricted to pro users with custom prefix:**
|
|
71
|
-
```typescript
|
|
72
|
-
api: {
|
|
73
|
-
enabled: true,
|
|
74
|
-
keyPrefix: 'myapp-',
|
|
75
|
-
allowedPlans: ['pro', 'enterprise'],
|
|
76
|
-
allowedEndpoints: [
|
|
77
|
-
'/api/chat',
|
|
78
|
-
'/api/threads',
|
|
79
|
-
'/api/threads/*',
|
|
80
|
-
],
|
|
81
|
-
}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## User Interface
|
|
85
|
-
|
|
86
|
-
When API keys are enabled, users can manage their keys from the Settings modal.
|
|
87
|
-
|
|
88
|
-
### Settings Modal
|
|
89
|
-
|
|
90
|
-
A link to "Manage API Keys" appears in the Settings modal for users who have access to the feature (based on `allowedPlans`).
|
|
91
|
-
|
|
92
|
-
### API Keys Page
|
|
93
|
-
|
|
94
|
-
The dedicated `/api-keys` page allows users to:
|
|
95
|
-
|
|
96
|
-
1. **View existing keys** - Shows key name, prefix, scope, creation date, last used, and expiration
|
|
97
|
-
2. **Create new keys** - With options for:
|
|
98
|
-
- **Name**: A label for the key (e.g., "My CLI Tool")
|
|
99
|
-
- **Scope**: Personal or team (if teams are enabled)
|
|
100
|
-
- **Expiration**: Never, 30 days, 90 days, or 1 year
|
|
101
|
-
3. **Revoke keys** - Immediately invalidates a key
|
|
102
|
-
|
|
103
|
-
### Key Display
|
|
104
|
-
|
|
105
|
-
- Keys are shown with a masked prefix (e.g., `sk-a1b2c3...`)
|
|
106
|
-
- The full key is only displayed once at creation time
|
|
107
|
-
- Users must copy and securely store their key immediately
|
|
108
|
-
|
|
109
|
-
## API Key Format
|
|
110
|
-
|
|
111
|
-
Generated keys follow this format:
|
|
112
|
-
|
|
113
|
-
```
|
|
114
|
-
{prefix}{48 random hex characters}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
Examples:
|
|
118
|
-
- Default prefix: `sk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4`
|
|
119
|
-
- Custom prefix: `myapp-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4`
|
|
120
|
-
|
|
121
|
-
## Security
|
|
122
|
-
|
|
123
|
-
### Key Storage
|
|
124
|
-
|
|
125
|
-
- Keys are hashed with bcrypt before storage (like passwords)
|
|
126
|
-
- The full key cannot be retrieved after creation
|
|
127
|
-
- Only the prefix is stored in plain text for display purposes
|
|
128
|
-
|
|
129
|
-
### Key Validation
|
|
130
|
-
|
|
131
|
-
On each request:
|
|
132
|
-
1. The key prefix is used to find candidate keys
|
|
133
|
-
2. The full key is verified against the bcrypt hash
|
|
134
|
-
3. Expiration date is checked
|
|
135
|
-
4. For team-scoped keys, team membership is verified
|
|
136
|
-
|
|
137
|
-
### Endpoint Restrictions
|
|
138
|
-
|
|
139
|
-
- API keys can only access endpoints listed in `allowedEndpoints`
|
|
140
|
-
- If no endpoints are configured, API keys cannot access any endpoint
|
|
141
|
-
- Attempts to access non-whitelisted endpoints return 403 Forbidden
|
|
142
|
-
|
|
143
|
-
### Automatic Invalidation
|
|
144
|
-
|
|
145
|
-
Team-scoped keys are automatically invalidated if:
|
|
146
|
-
- The user is removed from the team
|
|
147
|
-
- The team is deleted
|
|
148
|
-
|
|
149
|
-
## Team-Scoped Keys
|
|
150
|
-
|
|
151
|
-
When teams are enabled, users can create keys scoped to a specific team.
|
|
152
|
-
|
|
153
|
-
### Behavior
|
|
154
|
-
|
|
155
|
-
| Key Scope | Behavior |
|
|
156
|
-
|-----------|----------|
|
|
157
|
-
| Personal | API requests operate as the user's personal account |
|
|
158
|
-
| Team | API requests use the team context (threads, projects, etc.) |
|
|
159
|
-
|
|
160
|
-
### Creating Team-Scoped Keys
|
|
161
|
-
|
|
162
|
-
1. In the "Create API Key" modal, select a team from the "Scope" dropdown
|
|
163
|
-
2. The user must be a member of the team to create a key for it
|
|
164
|
-
3. The key will have access to team resources only
|
|
165
|
-
|
|
166
|
-
### Team Context
|
|
167
|
-
|
|
168
|
-
When using a team-scoped key:
|
|
169
|
-
- Thread listing returns team threads
|
|
170
|
-
- New threads are created in the team context
|
|
171
|
-
- Team context is injected into AI prompts
|
|
172
|
-
- The `teamId` in request bodies is overridden by the key's team scope
|
|
173
|
-
|
|
174
|
-
## Using API Keys
|
|
175
|
-
|
|
176
|
-
### Authentication
|
|
177
|
-
|
|
178
|
-
Include the API key in the `Authorization` header:
|
|
179
|
-
|
|
180
|
-
```bash
|
|
181
|
-
curl -H "Authorization: Bearer sk-your-api-key-here" \
|
|
182
|
-
https://your-app.com/api/threads
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
### Available Endpoints
|
|
186
|
-
|
|
187
|
-
The following endpoints can be enabled for API key access:
|
|
188
|
-
|
|
189
|
-
| Endpoint | Methods | Description |
|
|
190
|
-
|----------|---------|-------------|
|
|
191
|
-
| `/api/threads` | GET, POST | List threads, create new thread |
|
|
192
|
-
| `/api/threads/*` | GET, PATCH, DELETE | Get, update, delete a specific thread |
|
|
193
|
-
| `/api/threads/**` | Various | Thread sub-routes (messages, etc.) |
|
|
194
|
-
| `/api/chat` | POST | Send messages, streaming responses |
|
|
195
|
-
| `/api/search` | GET | Search threads by query |
|
|
196
|
-
| `/api/export/*` | GET | Export a thread (JSON, Markdown) |
|
|
197
|
-
| `/api/templates` | GET, POST, PATCH, DELETE | Prompt templates |
|
|
198
|
-
| `/api/user/settings` | GET, PATCH | User settings |
|
|
199
|
-
| `/api/user/usage` | GET | Usage statistics |
|
|
200
|
-
| `/api/projects` | GET, POST | Project management |
|
|
201
|
-
| `/api/projects/*` | GET, PATCH, DELETE | Specific project operations |
|
|
202
|
-
|
|
203
|
-
### Example: Create a Thread
|
|
204
|
-
|
|
205
|
-
```bash
|
|
206
|
-
curl -X POST \
|
|
207
|
-
-H "Authorization: Bearer sk-your-api-key" \
|
|
208
|
-
-H "Content-Type: application/json" \
|
|
209
|
-
-d '{"title": "New Thread"}' \
|
|
210
|
-
https://your-app.com/api/threads
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
### Example: Send a Message
|
|
214
|
-
|
|
215
|
-
```bash
|
|
216
|
-
curl -X POST \
|
|
217
|
-
-H "Authorization: Bearer sk-your-api-key" \
|
|
218
|
-
-H "Content-Type: application/json" \
|
|
219
|
-
-d '{"threadId": "thread-id", "content": "Hello!"}' \
|
|
220
|
-
https://your-app.com/api/chat
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
### Example: Stream Response (SSE)
|
|
224
|
-
|
|
225
|
-
```bash
|
|
226
|
-
curl -N \
|
|
227
|
-
-H "Authorization: Bearer sk-your-api-key" \
|
|
228
|
-
-H "Content-Type: application/json" \
|
|
229
|
-
-d '{"threadId": "thread-id", "content": "Hello!"}' \
|
|
230
|
-
https://your-app.com/api/chat
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
The response is a Server-Sent Events stream with events:
|
|
234
|
-
- `thread` - Thread metadata
|
|
235
|
-
- `start` - Message ID
|
|
236
|
-
- `delta` - Content chunks
|
|
237
|
-
- `done` - Completion signal
|
|
238
|
-
|
|
239
|
-
## API Endpoints
|
|
240
|
-
|
|
241
|
-
### List API Keys
|
|
242
|
-
|
|
243
|
-
```http
|
|
244
|
-
GET /api/api-keys
|
|
245
|
-
Authorization: Bearer <jwt-token>
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
Returns the user's API keys (masked):
|
|
249
|
-
|
|
250
|
-
```json
|
|
251
|
-
{
|
|
252
|
-
"keys": [
|
|
253
|
-
{
|
|
254
|
-
"id": "key-id",
|
|
255
|
-
"name": "My CLI Tool",
|
|
256
|
-
"keyPrefix": "sk-a1b2c3",
|
|
257
|
-
"teamId": null,
|
|
258
|
-
"team": null,
|
|
259
|
-
"lastUsedAt": "2024-01-15T10:30:00Z",
|
|
260
|
-
"expiresAt": null,
|
|
261
|
-
"createdAt": "2024-01-01T00:00:00Z"
|
|
262
|
-
}
|
|
263
|
-
]
|
|
264
|
-
}
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
### Create API Key
|
|
268
|
-
|
|
269
|
-
```http
|
|
270
|
-
POST /api/api-keys
|
|
271
|
-
Authorization: Bearer <jwt-token>
|
|
272
|
-
Content-Type: application/json
|
|
273
|
-
|
|
274
|
-
{
|
|
275
|
-
"name": "My CLI Tool",
|
|
276
|
-
"teamId": "optional-team-id",
|
|
277
|
-
"expiresAt": "2024-12-31T23:59:59Z"
|
|
278
|
-
}
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
Returns the full key (only shown once):
|
|
282
|
-
|
|
283
|
-
```json
|
|
284
|
-
{
|
|
285
|
-
"key": {
|
|
286
|
-
"id": "key-id",
|
|
287
|
-
"name": "My CLI Tool",
|
|
288
|
-
"keyPrefix": "sk-a1b2c3",
|
|
289
|
-
"teamId": null,
|
|
290
|
-
"teamName": null,
|
|
291
|
-
"createdAt": "2024-01-01T00:00:00Z",
|
|
292
|
-
"expiresAt": null
|
|
293
|
-
},
|
|
294
|
-
"secret": "sk-a1b2c3d4e5f6..."
|
|
295
|
-
}
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
### Delete API Key
|
|
299
|
-
|
|
300
|
-
```http
|
|
301
|
-
DELETE /api/api-keys/:keyId
|
|
302
|
-
Authorization: Bearer <jwt-token>
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
### Check Access
|
|
306
|
-
|
|
307
|
-
```http
|
|
308
|
-
GET /api/api-keys/access
|
|
309
|
-
Authorization: Bearer <jwt-token>
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
Returns whether the user can create API keys:
|
|
313
|
-
|
|
314
|
-
```json
|
|
315
|
-
{
|
|
316
|
-
"canAccess": true
|
|
317
|
-
}
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
## Error Responses
|
|
321
|
-
|
|
322
|
-
### 401 Unauthorized
|
|
323
|
-
|
|
324
|
-
```json
|
|
325
|
-
{"error": "Invalid API key"}
|
|
326
|
-
{"error": "API key expired"}
|
|
327
|
-
{"error": "API key invalid - no longer a team member"}
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
### 403 Forbidden
|
|
331
|
-
|
|
332
|
-
```json
|
|
333
|
-
{"error": "API key access is not enabled for any endpoints"}
|
|
334
|
-
{"error": "API key access is not allowed for this endpoint"}
|
|
335
|
-
{"error": "API access not available for your plan"}
|
|
336
|
-
{"error": "You are not a member of this team"}
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
## Database Schema
|
|
340
|
-
|
|
341
|
-
```prisma
|
|
342
|
-
model ApiKey {
|
|
343
|
-
id String @id @default(cuid())
|
|
344
|
-
userId String
|
|
345
|
-
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
346
|
-
teamId String?
|
|
347
|
-
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
|
|
348
|
-
name String
|
|
349
|
-
keyPrefix String // First chars for display
|
|
350
|
-
keyHash String // bcrypt hash
|
|
351
|
-
lastUsedAt DateTime?
|
|
352
|
-
expiresAt DateTime?
|
|
353
|
-
createdAt DateTime @default(now())
|
|
354
|
-
|
|
355
|
-
@@index([userId])
|
|
356
|
-
@@index([teamId])
|
|
357
|
-
@@index([keyPrefix])
|
|
358
|
-
}
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
## Best Practices
|
|
362
|
-
|
|
363
|
-
1. **Restrict Endpoints**: Only whitelist endpoints that are actually needed
|
|
364
|
-
2. **Use Plan Restrictions**: Limit API access to paid plans if appropriate
|
|
365
|
-
3. **Set Expiration Dates**: Encourage or require expiration for security
|
|
366
|
-
4. **Use Team Scoping**: For team-related integrations, use team-scoped keys
|
|
367
|
-
5. **Rotate Keys Regularly**: Periodically revoke and recreate keys
|
|
368
|
-
6. **Monitor Usage**: Check `lastUsedAt` to identify unused keys
|
|
369
|
-
7. **Custom Prefix**: Use a custom prefix to identify your app's keys
|
|
370
|
-
|
|
371
|
-
## Troubleshooting
|
|
372
|
-
|
|
373
|
-
### "API key access is not enabled for any endpoints"
|
|
374
|
-
|
|
375
|
-
The `allowedEndpoints` array is empty. Add the endpoints you want to allow:
|
|
376
|
-
|
|
377
|
-
```typescript
|
|
378
|
-
api: {
|
|
379
|
-
enabled: true,
|
|
380
|
-
allowedEndpoints: ['/api/chat', '/api/threads/**'],
|
|
381
|
-
}
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
### "API key access is not allowed for this endpoint"
|
|
385
|
-
|
|
386
|
-
The endpoint you're trying to access is not in the `allowedEndpoints` list. Add it:
|
|
387
|
-
|
|
388
|
-
```typescript
|
|
389
|
-
allowedEndpoints: [
|
|
390
|
-
'/api/search', // Add missing endpoint
|
|
391
|
-
]
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
### "API access not available for your plan"
|
|
395
|
-
|
|
396
|
-
The user's plan is not in the `allowedPlans` list. Either:
|
|
397
|
-
- Upgrade the user's plan
|
|
398
|
-
- Add their plan to `allowedPlans`
|
|
399
|
-
- Remove `allowedPlans` to allow all plans
|
|
400
|
-
|
|
401
|
-
### Keys not working after team removal
|
|
402
|
-
|
|
403
|
-
Team-scoped keys are invalidated when the user is removed from the team. The user needs to create a new personal key or be re-added to the team.
|
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
# Authentication
|
|
2
|
-
|
|
3
|
-
The ChaasKit Template supports multiple authentication methods including email/password, OAuth providers, and magic links.
|
|
4
|
-
|
|
5
|
-
## Configuration
|
|
6
|
-
|
|
7
|
-
Configure authentication in `config/app.config.ts`:
|
|
8
|
-
|
|
9
|
-
```typescript
|
|
10
|
-
auth: {
|
|
11
|
-
methods: ['email-password', 'google', 'github', 'magic-link'],
|
|
12
|
-
allowUnauthenticated: false,
|
|
13
|
-
magicLink: {
|
|
14
|
-
enabled: true,
|
|
15
|
-
expiresInMinutes: 15,
|
|
16
|
-
},
|
|
17
|
-
}
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## Available Methods
|
|
21
|
-
|
|
22
|
-
### Email/Password
|
|
23
|
-
|
|
24
|
-
Built-in email and password authentication with bcrypt hashing.
|
|
25
|
-
|
|
26
|
-
**Configuration:**
|
|
27
|
-
```typescript
|
|
28
|
-
auth: {
|
|
29
|
-
methods: ['email-password'],
|
|
30
|
-
}
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
**Endpoints:**
|
|
34
|
-
- `POST /api/auth/register` - Create account
|
|
35
|
-
- `POST /api/auth/login` - Log in
|
|
36
|
-
- `POST /api/auth/logout` - Log out
|
|
37
|
-
|
|
38
|
-
### Google OAuth
|
|
39
|
-
|
|
40
|
-
**Setup:**
|
|
41
|
-
|
|
42
|
-
1. Create a project at [console.cloud.google.com](https://console.cloud.google.com)
|
|
43
|
-
2. Enable the Google+ API
|
|
44
|
-
3. Create OAuth 2.0 credentials
|
|
45
|
-
4. Add authorized redirect URI: `{API_URL}/api/auth/google/callback`
|
|
46
|
-
|
|
47
|
-
**Environment:**
|
|
48
|
-
```bash
|
|
49
|
-
GOOGLE_CLIENT_ID="your-client-id"
|
|
50
|
-
GOOGLE_CLIENT_SECRET="your-client-secret"
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
**Configuration:**
|
|
54
|
-
```typescript
|
|
55
|
-
auth: {
|
|
56
|
-
methods: ['google'],
|
|
57
|
-
}
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### GitHub OAuth
|
|
61
|
-
|
|
62
|
-
**Setup:**
|
|
63
|
-
|
|
64
|
-
1. Go to GitHub Settings > Developer settings > OAuth Apps
|
|
65
|
-
2. Create a new OAuth App
|
|
66
|
-
3. Set Authorization callback URL: `{API_URL}/api/auth/github/callback`
|
|
67
|
-
|
|
68
|
-
**Environment:**
|
|
69
|
-
```bash
|
|
70
|
-
GITHUB_CLIENT_ID="your-client-id"
|
|
71
|
-
GITHUB_CLIENT_SECRET="your-client-secret"
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
**Configuration:**
|
|
75
|
-
```typescript
|
|
76
|
-
auth: {
|
|
77
|
-
methods: ['github'],
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Magic Links
|
|
82
|
-
|
|
83
|
-
Passwordless authentication via email links.
|
|
84
|
-
|
|
85
|
-
**Configuration:**
|
|
86
|
-
```typescript
|
|
87
|
-
auth: {
|
|
88
|
-
methods: ['magic-link'],
|
|
89
|
-
magicLink: {
|
|
90
|
-
enabled: true,
|
|
91
|
-
expiresInMinutes: 15,
|
|
92
|
-
},
|
|
93
|
-
}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
**Note:** Requires email service configuration (not included by default).
|
|
97
|
-
|
|
98
|
-
## Anonymous Users
|
|
99
|
-
|
|
100
|
-
Allow users to chat without authentication:
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
auth: {
|
|
104
|
-
allowUnauthenticated: true,
|
|
105
|
-
}
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
Anonymous users:
|
|
109
|
-
- Can create threads and send messages
|
|
110
|
-
- Cannot access saved threads after session ends
|
|
111
|
-
- No access to premium features
|
|
112
|
-
|
|
113
|
-
## JWT Tokens
|
|
114
|
-
|
|
115
|
-
Authentication uses JWT tokens stored in HTTP-only cookies.
|
|
116
|
-
|
|
117
|
-
**Token Structure:**
|
|
118
|
-
```typescript
|
|
119
|
-
{
|
|
120
|
-
sub: userId,
|
|
121
|
-
email: userEmail,
|
|
122
|
-
iat: issuedAt,
|
|
123
|
-
exp: expiresAt,
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
**Cookie Settings:**
|
|
128
|
-
- `httpOnly: true` - Not accessible via JavaScript
|
|
129
|
-
- `secure: true` - HTTPS only in production
|
|
130
|
-
- `sameSite: 'lax'` - CSRF protection
|
|
131
|
-
|
|
132
|
-
## Protected Routes
|
|
133
|
-
|
|
134
|
-
### Backend
|
|
135
|
-
|
|
136
|
-
Use middleware to protect routes:
|
|
137
|
-
|
|
138
|
-
```typescript
|
|
139
|
-
import { requireAuth, optionalAuth } from '../middleware/auth.js';
|
|
140
|
-
|
|
141
|
-
// Requires authentication
|
|
142
|
-
router.get('/private', requireAuth, async (req, res) => {
|
|
143
|
-
// req.user is guaranteed to exist
|
|
144
|
-
res.json({ userId: req.user.id });
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
// Optional authentication
|
|
148
|
-
router.get('/public', optionalAuth, async (req, res) => {
|
|
149
|
-
// req.user may or may not exist
|
|
150
|
-
if (req.user) {
|
|
151
|
-
res.json({ message: 'Hello, ' + req.user.email });
|
|
152
|
-
} else {
|
|
153
|
-
res.json({ message: 'Hello, anonymous' });
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
### Frontend
|
|
159
|
-
|
|
160
|
-
Use the AuthContext:
|
|
161
|
-
|
|
162
|
-
```tsx
|
|
163
|
-
import { useAuth } from '../contexts/AuthContext';
|
|
164
|
-
|
|
165
|
-
function MyComponent() {
|
|
166
|
-
const { user, isAuthenticated, login, logout } = useAuth();
|
|
167
|
-
|
|
168
|
-
if (!isAuthenticated) {
|
|
169
|
-
return <Navigate to="/login" />;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return <div>Hello, {user.email}</div>;
|
|
173
|
-
}
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
## User Model
|
|
177
|
-
|
|
178
|
-
```prisma
|
|
179
|
-
model User {
|
|
180
|
-
id String @id @default(cuid())
|
|
181
|
-
email String @unique
|
|
182
|
-
passwordHash String?
|
|
183
|
-
name String?
|
|
184
|
-
avatarUrl String?
|
|
185
|
-
|
|
186
|
-
// OAuth
|
|
187
|
-
oauthProvider String?
|
|
188
|
-
oauthId String?
|
|
189
|
-
|
|
190
|
-
// Subscription
|
|
191
|
-
plan String @default("free")
|
|
192
|
-
|
|
193
|
-
// Settings
|
|
194
|
-
settings Json @default("{}")
|
|
195
|
-
|
|
196
|
-
createdAt DateTime @default(now())
|
|
197
|
-
updatedAt DateTime @updatedAt
|
|
198
|
-
}
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
## Security Considerations
|
|
202
|
-
|
|
203
|
-
1. **Password Hashing**: bcrypt with automatic salt
|
|
204
|
-
2. **JWT Secrets**: Use 32+ character random strings
|
|
205
|
-
3. **HTTPS**: Required in production
|
|
206
|
-
4. **CSRF Protection**: SameSite cookies
|
|
207
|
-
5. **Rate Limiting**: Built-in via express-rate-limit
|
|
208
|
-
|
|
209
|
-
## Customization
|
|
210
|
-
|
|
211
|
-
### Add a New OAuth Provider
|
|
212
|
-
|
|
213
|
-
1. Install Passport strategy:
|
|
214
|
-
```bash
|
|
215
|
-
pnpm add passport-twitter -F @chaaskit/server
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
2. Add route in `packages/server/src/api/auth.ts`
|
|
219
|
-
|
|
220
|
-
3. Configure strategy in passport setup
|
|
221
|
-
|
|
222
|
-
4. Add to config:
|
|
223
|
-
```typescript
|
|
224
|
-
auth: {
|
|
225
|
-
methods: ['twitter'],
|
|
226
|
-
}
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### Custom Auth Provider
|
|
230
|
-
|
|
231
|
-
Implement using the registry pattern:
|
|
232
|
-
|
|
233
|
-
```typescript
|
|
234
|
-
// extensions/auth-providers/my-provider.ts
|
|
235
|
-
import { BaseAuthProvider } from '@chaaskit/server';
|
|
236
|
-
|
|
237
|
-
export class MyAuthProvider extends BaseAuthProvider {
|
|
238
|
-
async authenticate(credentials) {
|
|
239
|
-
// Custom auth logic
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
Register:
|
|
245
|
-
```typescript
|
|
246
|
-
registry.register('auth-provider', 'my-provider', MyAuthProvider);
|
|
247
|
-
```
|