@brika/auth 0.1.1

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 (62) hide show
  1. package/README.md +207 -0
  2. package/package.json +50 -0
  3. package/src/__tests__/AuthClient.test.ts +736 -0
  4. package/src/__tests__/AuthService.test.ts +140 -0
  5. package/src/__tests__/ScopeService.test.ts +156 -0
  6. package/src/__tests__/SessionService.test.ts +311 -0
  7. package/src/__tests__/UserService-avatar.test.ts +277 -0
  8. package/src/__tests__/UserService.test.ts +223 -0
  9. package/src/__tests__/canAccess.test.ts +166 -0
  10. package/src/__tests__/disabledScopes.test.ts +101 -0
  11. package/src/__tests__/middleware.test.ts +190 -0
  12. package/src/__tests__/plugin.test.ts +78 -0
  13. package/src/__tests__/requireSession.test.ts +78 -0
  14. package/src/__tests__/routes-auth.test.ts +248 -0
  15. package/src/__tests__/routes-profile.test.ts +403 -0
  16. package/src/__tests__/routes-scopes.test.ts +64 -0
  17. package/src/__tests__/routes-sessions.test.ts +235 -0
  18. package/src/__tests__/routes-users.test.ts +477 -0
  19. package/src/__tests__/serveImage.test.ts +277 -0
  20. package/src/__tests__/setup.test.ts +270 -0
  21. package/src/__tests__/verifyToken.test.ts +219 -0
  22. package/src/client/AuthClient.ts +312 -0
  23. package/src/client/http-client.ts +84 -0
  24. package/src/client/index.ts +19 -0
  25. package/src/config.ts +82 -0
  26. package/src/constants.ts +10 -0
  27. package/src/index.ts +16 -0
  28. package/src/lib/define-roles.ts +35 -0
  29. package/src/lib/define-scopes.ts +48 -0
  30. package/src/middleware/canAccess.ts +126 -0
  31. package/src/middleware/index.ts +13 -0
  32. package/src/middleware/requireAuth.ts +35 -0
  33. package/src/middleware/requireScope.ts +46 -0
  34. package/src/middleware/verifyToken.ts +52 -0
  35. package/src/plugin.ts +86 -0
  36. package/src/react/AuthProvider.tsx +105 -0
  37. package/src/react/hooks.ts +128 -0
  38. package/src/react/index.ts +51 -0
  39. package/src/react/withScopeGuard.tsx +73 -0
  40. package/src/roles.ts +40 -0
  41. package/src/schemas.ts +112 -0
  42. package/src/scopes.ts +60 -0
  43. package/src/server/index.ts +44 -0
  44. package/src/server/requireSession.ts +44 -0
  45. package/src/server/routes/auth.ts +102 -0
  46. package/src/server/routes/cookie.ts +7 -0
  47. package/src/server/routes/index.ts +32 -0
  48. package/src/server/routes/profile.ts +162 -0
  49. package/src/server/routes/scopes.ts +22 -0
  50. package/src/server/routes/sessions.ts +68 -0
  51. package/src/server/routes/setup.ts +50 -0
  52. package/src/server/routes/users.ts +175 -0
  53. package/src/server/serveImage.ts +91 -0
  54. package/src/services/AuthService.ts +80 -0
  55. package/src/services/ScopeService.ts +94 -0
  56. package/src/services/SessionService.ts +245 -0
  57. package/src/services/UserService.ts +245 -0
  58. package/src/setup.ts +99 -0
  59. package/src/tanstack/index.ts +15 -0
  60. package/src/tanstack/routeBuilder.ts +311 -0
  61. package/src/types.ts +118 -0
  62. package/tsconfig.json +8 -0
package/README.md ADDED
@@ -0,0 +1,207 @@
1
+ # @brika/auth
2
+
3
+ Complete authentication system for Brika with cookie-based sessions, scope-based RBAC, and type-safe route protection.
4
+
5
+ ## Features
6
+
7
+ - **Cookie-Based Sessions** — HttpOnly, Secure, SameSite=Lax cookies with server-side SQLite session store
8
+ - **User Management** — CRUD, bcrypt password hashing (cost 12), avatar upload with image validation
9
+ - **Scope-Based RBAC** — Fine-grained permissions with role defaults and per-user overrides
10
+ - **Type-Safe Route Protection** — Single-source-of-truth route declarations with TanStack Router integration
11
+ - **Security Hardened** — Rate limiting, session limits, deactivated user checks, sliding expiration
12
+
13
+ ## Quick Start
14
+
15
+ ### Backend: Hub Integration
16
+
17
+ ```typescript
18
+ import { auth } from '@brika/auth/server';
19
+
20
+ await bootstrap()
21
+ .use(auth({ dataDir, server: inject(ApiServer) }))
22
+ .start();
23
+ ```
24
+
25
+ ### Frontend: React Setup
26
+
27
+ ```typescript
28
+ import { AuthProvider, useAuth, useCanAccess } from '@brika/auth/react';
29
+ import { Scope } from '@brika/auth';
30
+
31
+ function App() {
32
+ return (
33
+ <AuthProvider>
34
+ <Dashboard />
35
+ </AuthProvider>
36
+ );
37
+ }
38
+
39
+ function Dashboard() {
40
+ const { user, logout } = useAuth();
41
+ const canEdit = useCanAccess(Scope.WORKFLOW_WRITE);
42
+
43
+ return (
44
+ <>
45
+ <h1>Hello, {user?.name}!</h1>
46
+ {canEdit && <EditButton />}
47
+ <button onClick={logout}>Logout</button>
48
+ </>
49
+ );
50
+ }
51
+ ```
52
+
53
+ ## HTTP API
54
+
55
+ ### POST /api/auth/login
56
+
57
+ Rate limited: 5 requests per 60 seconds per IP.
58
+
59
+ ```bash
60
+ POST /api/auth/login
61
+ Content-Type: application/json
62
+
63
+ { "email": "user@example.com", "password": "SecurePassword123!" }
64
+
65
+ # Response (200) — session cookie set automatically
66
+ { "user": { "id": "...", "email": "...", "name": "...", "role": "user" } }
67
+ ```
68
+
69
+ ### POST /api/auth/logout
70
+
71
+ ```bash
72
+ POST /api/auth/logout
73
+ # Session cookie cleared
74
+ { "ok": true }
75
+ ```
76
+
77
+ ### GET /api/auth/session
78
+
79
+ ```bash
80
+ GET /api/auth/session
81
+ # Returns current session info
82
+ { "user": { ... }, "scopes": ["workflow:read", "board:read"] }
83
+ ```
84
+
85
+ ### Profile Endpoints
86
+
87
+ | Method | Path | Auth | Description |
88
+ |--------|------|------|-------------|
89
+ | PUT | `/api/auth/profile` | Required | Update name |
90
+ | PUT | `/api/auth/profile/password` | Required + Rate limited | Change password |
91
+ | PUT | `/api/auth/profile/avatar` | Required | Upload avatar (PNG/JPEG/WebP, max 5MB) |
92
+ | DELETE | `/api/auth/profile/avatar` | Required | Remove avatar |
93
+ | GET | `/api/auth/avatar/:userId` | Public | Serve avatar image |
94
+
95
+ ### Admin Endpoints (requires `admin:*` scope)
96
+
97
+ | Method | Path | Description |
98
+ |--------|------|-------------|
99
+ | GET | `/api/users` | List all users |
100
+ | POST | `/api/users` | Create user |
101
+ | GET | `/api/users/:id` | Get user (admin or self) |
102
+ | PUT | `/api/users/:id` | Update user |
103
+ | PUT | `/api/users/:id/password` | Reset password (revokes all sessions) |
104
+ | DELETE | `/api/users/:id` | Delete user (revokes all sessions) |
105
+
106
+ ## Security
107
+
108
+ ### Authentication Flow
109
+
110
+ 1. Login sends credentials over HTTPS, receives `Set-Cookie` with session token
111
+ 2. Session token is `HttpOnly; Secure; SameSite=Lax; Path=/api`
112
+ 3. Server stores SHA-256 hash of token in SQLite (raw token never stored)
113
+ 4. Token entropy: 256-bit CSPRNG (`crypto.randomBytes(32)`)
114
+
115
+ ### Protections
116
+
117
+ | Threat | Protection |
118
+ |--------|-----------|
119
+ | Brute-force login | Rate limiting (5/min per IP via sliding window counter) |
120
+ | Brute-force password change | Rate limiting (10/15min per IP) |
121
+ | Session hijacking | HttpOnly + Secure + SameSite=Lax cookies |
122
+ | Deactivated user access | Checked at login AND on every session validation |
123
+ | Password cracking | bcrypt cost 12, max 72 chars (bcrypt limit) |
124
+ | Session accumulation | Per-user session limit (default: 10), automatic cleanup every 6 hours |
125
+ | Memory exhaustion | Rate limiter store capped at 10K keys with automatic eviction |
126
+ | IP spoofing | Server uses socket IP, strips client-supplied proxy headers |
127
+ | Scope enumeration | 403 responses don't reveal user's actual scopes |
128
+ | Avatar abuse | Magic byte validation (PNG/JPEG/WebP), 5MB size limit |
129
+ | DB file access | Restrictive file permissions (0o600) |
130
+
131
+ ### Session Lifecycle
132
+
133
+ - **Sliding expiration**: TTL resets on each authenticated request
134
+ - **Password change**: All sessions revoked (self-change and admin reset)
135
+ - **User deletion**: All sessions explicitly revoked before deletion
136
+ - **Deactivation**: Sessions immediately invalid (checked via JOIN in validation query)
137
+ - **Expired session cleanup**: Runs on startup + every 6 hours
138
+
139
+ ## Configuration
140
+
141
+ ```typescript
142
+ auth({
143
+ dataDir: '~/.brika',
144
+ server: inject(ApiServer),
145
+ config: {
146
+ session: {
147
+ ttl: 604800, // 7 days (default)
148
+ cookieName: 'brika_session',
149
+ maxPerUser: 10, // Max concurrent sessions per user
150
+ },
151
+ password: {
152
+ minLength: 8,
153
+ requireUppercase: true,
154
+ requireNumbers: true,
155
+ requireSpecial: true,
156
+ },
157
+ },
158
+ });
159
+ ```
160
+
161
+ ## Package Structure
162
+
163
+ ```
164
+ @brika/auth
165
+ ├── Types & Constants — User, Session, Role, Scope, ROLE_SCOPES
166
+ ├── @brika/auth/server
167
+ │ ├── AuthService — Login, logout
168
+ │ ├── UserService — User CRUD, passwords, avatars
169
+ │ ├── SessionService — Session create/validate/revoke, cleanup
170
+ │ ├── ScopeService — Permission checks
171
+ │ ├── Middleware — verifyToken, requireAuth, requireScope, canAccess
172
+ │ ├── Routes — HTTP API endpoints
173
+ │ └── Plugin — Bootstrap integration with session cleanup scheduler
174
+ ├── @brika/auth/client
175
+ │ └── AuthClient — HTTP client for browser
176
+ ├── @brika/auth/react
177
+ │ ├── AuthProvider — Context with clearSession/refreshSession
178
+ │ ├── Hooks — useAuth, useCanAccess, useCanAccessAll, etc.
179
+ │ └── HOCs — withScopeGuard, withOptionalScope
180
+ └── @brika/auth/tanstack
181
+ └── createProtectedRoutes — Type-safe route builder with scope guards
182
+ ```
183
+
184
+ ## Roles & Scopes
185
+
186
+ | Role | Default Scopes |
187
+ |------|---------------|
188
+ | `admin` | All scopes (`admin:*`) |
189
+ | `user` | workflow:*, board:*, plugin:read, settings:read |
190
+ | `guest` | workflow:read, board:read, plugin:read |
191
+
192
+ ## CLI Commands
193
+
194
+ All commands are interactive (prompts for input):
195
+
196
+ ```bash
197
+ brika auth user add # Add a new user (email, name, role, password)
198
+ brika auth user list # List all users
199
+ brika auth user edit # Edit a user (name, role, status, password)
200
+ brika auth user delete # Delete a user
201
+
202
+ brika auth token create # Create an API token (user, scopes, expiration)
203
+ ```
204
+
205
+ ## License
206
+
207
+ MIT
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@brika/auth",
3
+ "version": "0.1.1",
4
+ "description": "Authentication & authorization system for Brika",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/brikalabs/brika",
10
+ "directory": "packages/auth"
11
+ },
12
+ "exports": {
13
+ ".": "./src/index.ts",
14
+ "./server": "./src/server/index.ts",
15
+ "./client": "./src/client/index.ts",
16
+ "./react": "./src/react/index.ts",
17
+ "./tanstack": "./src/tanstack/index.ts"
18
+ },
19
+ "scripts": {
20
+ "typecheck": "tsgo --noEmit",
21
+ "test": "bun test",
22
+ "test:watch": "bun test --watch"
23
+ },
24
+ "dependencies": {
25
+ "@brika/di": "0.3.1",
26
+ "@brika/photon": "0.3.1",
27
+ "@brika/router": "0.3.1",
28
+ "bcryptjs": "^2.4.3",
29
+ "zod": "^4.3.4"
30
+ },
31
+ "devDependencies": {
32
+ "@types/bcryptjs": "^2.4.6",
33
+ "@types/bun": "latest",
34
+ "@types/react": "^19.2.0",
35
+ "react": "^19.2.0",
36
+ "@tanstack/react-router": "^1.163.2"
37
+ },
38
+ "peerDependencies": {
39
+ "react": "^18 || ^19",
40
+ "@tanstack/react-router": ">=1.29.0"
41
+ },
42
+ "peerDependenciesMeta": {
43
+ "react": {
44
+ "optional": true
45
+ },
46
+ "@tanstack/react-router": {
47
+ "optional": true
48
+ }
49
+ }
50
+ }