@ofeklabs/horizon-auth 0.3.0 โ†’ 0.4.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/README.md CHANGED
@@ -1,10 +1,17 @@
1
1
  # @ofeklabs/horizon-auth
2
2
 
3
- Production-ready NestJS authentication module with 2026 security standards. Deploy once, use everywhere.
3
+ Production-ready NestJS authentication module with 2026 security standards. One package, two modes: embedded auth or SSO - configured entirely through ENV variables.
4
4
 
5
- ## Use Cases
5
+ ## ๐ŸŽฏ Use Cases
6
6
 
7
- ### 1. Portfolio SSO (Recommended)
7
+ ### 1. Embedded Auth
8
+ Each application has its own isolated authentication. Perfect for standalone apps.
9
+
10
+ ```
11
+ myapp.com (App + Auth)
12
+ ```
13
+
14
+ ### 2. Portfolio SSO (Recommended)
8
15
  Deploy one auth service, use it across all your projects. Users sign in once and access everything.
9
16
 
10
17
  ```
@@ -15,8 +22,7 @@ auth.yourdomain.com (Auth Service)
15
22
  โ””โ”€โ”€ project3.yourdomain.com
16
23
  ```
17
24
 
18
- ### 2. Embedded Auth
19
- Each application has its own isolated authentication.
25
+ **Same package, different ENV variables!** No code changes needed.
20
26
 
21
27
  ## Features
22
28
 
@@ -29,99 +35,128 @@ Each application has its own isolated authentication.
29
35
  - ๐ŸŽฏ **Type-Safe**: Full TypeScript support
30
36
  - ๐Ÿ“ฆ **Zero Config**: Sensible defaults, fully customizable
31
37
 
32
- ## Quick Start
38
+ ### ๐Ÿ†• Enterprise Features (v0.3.0)
33
39
 
34
- ### Portfolio SSO Setup (Recommended)
40
+ - ๐Ÿ”’ **Two-Factor Authentication**: TOTP-based 2FA with QR codes and backup codes
41
+ - ๐Ÿ“ฑ **Device Management**: Track, list, and revoke user devices
42
+ - ๐Ÿ”” **Push Notifications**: Register and manage push tokens (FCM/APNS)
43
+ - ๐Ÿ‘ค **Account Management**: Deactivate, reactivate, and delete accounts
44
+ - ๐ŸŒ **Social Login**: Google and Facebook OAuth integration
35
45
 
36
- Deploy one auth service, use it across all your projects.
46
+ ## ๐Ÿš€ Quick Start
37
47
 
38
- #### 1. Deploy Auth Service (One Time)
48
+ ### Installation
39
49
 
40
50
  ```bash
41
- # Clone and deploy packages/horizon-auth to auth.yourdomain.com
42
- npm install
43
- npm run build
44
- npm run start:prod
51
+ npm install @ofeklabs/horizon-auth @prisma/client ioredis passport passport-jwt
52
+ npm install -D prisma
45
53
  ```
46
54
 
47
- **Environment Variables**:
48
- ```env
49
- DATABASE_URL=postgresql://...
50
- REDIS_HOST=your-redis-host
51
- JWT_PRIVATE_KEY=<your-private-key>
52
- JWT_PUBLIC_KEY=<your-public-key>
53
- COOKIE_DOMAIN=.yourdomain.com
54
- NODE_ENV=production
55
+ ### Generate RSA Keys
56
+
57
+ ```bash
58
+ openssl genrsa -out private.pem 2048
59
+ openssl rsa -in private.pem -pubout -out public.pem
55
60
  ```
56
61
 
57
- #### 2. Use in Your Projects
62
+ ---
58
63
 
59
- For each project:
64
+ ## Configuration Options
60
65
 
61
- ```bash
62
- npm install @ofeklabs/horizon-auth
66
+ ### Option 1: Environment Variables Only (Recommended โญ)
67
+
68
+ **Zero code configuration** - just set ENV variables and you're done!
69
+
70
+ #### Embedded Mode (Standalone App)
71
+
72
+ ```env
73
+ # .env
74
+ AUTH_MODE=full
75
+ DATABASE_URL=postgresql://user:password@localhost:5432/myapp
76
+ REDIS_HOST=localhost
77
+ REDIS_PORT=6379
78
+ JWT_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
79
+ JWT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"
80
+
81
+ # Optional: Enable features
82
+ ENABLE_2FA=true
83
+ ENABLE_DEVICE_MGMT=true
84
+ ENABLE_PUSH=true
85
+ ENABLE_ACCOUNT_MGMT=true
86
+ APP_NAME=MyApp
63
87
  ```
64
88
 
65
89
  ```typescript
66
90
  // app.module.ts
67
- HorizonAuthModule.forRoot({
68
- ssoMode: true,
69
- authServiceUrl: process.env.AUTH_SERVICE_URL,
70
- jwt: {
71
- publicKey: process.env.JWT_PUBLIC_KEY,
72
- },
73
- cookie: {
74
- domain: process.env.COOKIE_DOMAIN,
75
- secure: process.env.NODE_ENV === 'production',
76
- },
91
+ import { HorizonAuthModule } from '@ofeklabs/horizon-auth';
92
+
93
+ @Module({
94
+ imports: [
95
+ HorizonAuthModule.forRoot(), // ๐Ÿ‘ˆ No config needed! Uses ENV variables
96
+ ],
77
97
  })
98
+ export class AppModule {}
78
99
  ```
79
100
 
101
+ #### SSO Mode (Multiple Projects, One Auth)
102
+
103
+ **Auth Service (auth.yourdomain.com):**
80
104
  ```env
81
- # .env
105
+ AUTH_MODE=full
106
+ DATABASE_URL=postgresql://user:password@host:5432/auth_db
107
+ REDIS_HOST=redis.yourdomain.com
108
+ JWT_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
109
+ JWT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"
110
+ COOKIE_DOMAIN=.yourdomain.com
111
+ NODE_ENV=production
112
+ ENABLE_2FA=true
113
+ ENABLE_DEVICE_MGMT=true
114
+ APP_NAME=YourCompany
115
+ ```
116
+
117
+ **Your Projects (project1.yourdomain.com, project2.yourdomain.com):**
118
+ ```env
119
+ AUTH_MODE=sso
82
120
  AUTH_SERVICE_URL=https://auth.yourdomain.com
83
- JWT_PUBLIC_KEY=<paste-public-key>
121
+ JWT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"
84
122
  COOKIE_DOMAIN=.yourdomain.com
123
+ NODE_ENV=production
85
124
  ```
86
125
 
87
- Deploy to:
88
- - project1.yourdomain.com
89
- - project2.yourdomain.com
90
- - project3.yourdomain.com
126
+ ```typescript
127
+ // app.module.ts (same for all projects)
128
+ import { HorizonAuthModule } from '@ofeklabs/horizon-auth';
91
129
 
92
- Users sign in once, access all projects.
130
+ @Module({
131
+ imports: [
132
+ HorizonAuthModule.forRoot(), // ๐Ÿ‘ˆ Automatically uses SSO mode from ENV
133
+ ],
134
+ })
135
+ export class AppModule {}
136
+ ```
93
137
 
94
- ---
138
+ **That's it!** Deploy your auth service once, then use the same package in all your projects with different ENV variables. No code changes needed!
95
139
 
96
- ### Embedded Auth Setup (Alternative)
140
+ **๐Ÿ“š See [ENV-CONFIGURATION.md](https://github.com/OfekItzhaki/horizon-auth-platform/blob/main/ENV-CONFIGURATION.md) for complete ENV reference.**
97
141
 
98
- Each application has its own authentication.
142
+ **๐Ÿ“– See [DEPLOYMENT-EXAMPLES.md](https://github.com/OfekItzhaki/horizon-auth-platform/blob/main/DEPLOYMENT-EXAMPLES.md) for real-world deployment scenarios.**
99
143
 
100
- ### 1. Install
144
+ ---
101
145
 
102
- ```bash
103
- npm install @ofeklabs/horizon-auth @prisma/client ioredis passport passport-jwt
104
- npm install -D prisma
105
- ```
146
+ ### Option 2: Code Configuration (Advanced)
106
147
 
107
- ### 2. Generate RSA Keys
148
+ If you prefer code-based configuration or need dynamic config:
108
149
 
109
- ```bash
110
- # Generate private key
111
- openssl genrsa -out private.pem 2048
150
+ ### Option 2: Code Configuration (Advanced)
112
151
 
113
- # Generate public key
114
- openssl rsa -in private.pem -pubout -out public.pem
115
- ```
152
+ If you prefer code-based configuration or need dynamic config:
116
153
 
117
- ### 3. Configure Module
154
+ #### Embedded Mode
118
155
 
119
156
  ```typescript
120
157
  // app.module.ts
121
158
  import { Module } from '@nestjs/common';
122
159
  import { HorizonAuthModule } from '@ofeklabs/horizon-auth';
123
- import { readFileSync } from 'fs';
124
- import { join } from 'path';
125
160
 
126
161
  @Module({
127
162
  imports: [
@@ -132,12 +167,19 @@ import { join } from 'path';
132
167
  redis: {
133
168
  host: process.env.REDIS_HOST || 'localhost',
134
169
  port: parseInt(process.env.REDIS_PORT) || 6379,
135
- password: process.env.REDIS_PASSWORD,
136
170
  },
137
171
  jwt: {
138
- // For production: use environment variables
139
- privateKey: process.env.JWT_PRIVATE_KEY || readFileSync(join(__dirname, '../certs/private.pem'), 'utf8'),
140
- publicKey: process.env.JWT_PUBLIC_KEY || readFileSync(join(__dirname, '../certs/public.pem'), 'utf8'),
172
+ privateKey: process.env.JWT_PRIVATE_KEY,
173
+ publicKey: process.env.JWT_PUBLIC_KEY,
174
+ },
175
+ features: {
176
+ twoFactor: {
177
+ enabled: true,
178
+ issuer: 'YourApp',
179
+ },
180
+ deviceManagement: {
181
+ enabled: true,
182
+ },
141
183
  },
142
184
  }),
143
185
  ],
@@ -145,17 +187,48 @@ import { join } from 'path';
145
187
  export class AppModule {}
146
188
  ```
147
189
 
148
- ### 4. Set Up Database
190
+ #### SSO Mode
191
+
192
+ ```typescript
193
+ // app.module.ts
194
+ import { HorizonAuthModule } from '@ofeklabs/horizon-auth';
195
+
196
+ @Module({
197
+ imports: [
198
+ HorizonAuthModule.forRoot({
199
+ ssoMode: true,
200
+ authServiceUrl: process.env.AUTH_SERVICE_URL,
201
+ jwt: {
202
+ publicKey: process.env.JWT_PUBLIC_KEY,
203
+ },
204
+ cookie: {
205
+ domain: process.env.COOKIE_DOMAIN,
206
+ secure: process.env.NODE_ENV === 'production',
207
+ },
208
+ }),
209
+ ],
210
+ })
211
+ export class AppModule {}
212
+ ```
213
+
214
+ **Note:** ENV variables are still loaded automatically. Code config overrides ENV values.
215
+
216
+ ---
217
+
218
+ ## ๐Ÿ—„๏ธ Database Setup
149
219
 
150
220
  ```bash
151
- # Start PostgreSQL and Redis
152
- docker-compose up -d
221
+ # Start PostgreSQL and Redis (using Docker)
222
+ docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgres:15
223
+ docker run -d -p 6379:6379 redis:7-alpine
153
224
 
154
225
  # Run Prisma migrations
155
226
  npx prisma migrate dev
156
227
  ```
157
228
 
158
- ### 5. Use in Controllers
229
+ ---
230
+
231
+ ## ๐ŸŽจ Use in Your Application
159
232
 
160
233
  ```typescript
161
234
  import { Controller, Get, Post, Body, UseGuards } from '@nestjs/common';
@@ -164,8 +237,6 @@ import {
164
237
  CurrentUser,
165
238
  JwtAuthGuard,
166
239
  Roles,
167
- LoginDto,
168
- RegisterDto,
169
240
  } from '@ofeklabs/horizon-auth';
170
241
 
171
242
  @Controller()
@@ -194,69 +265,193 @@ export class AppController {
194
265
  }
195
266
  ```
196
267
 
197
- ## API Endpoints
268
+ ---
269
+
270
+ ## ๐Ÿ“ก API Endpoints
198
271
 
199
272
  The package automatically provides these endpoints:
200
273
 
201
- ### Authentication
274
+ ### Core Authentication
202
275
 
203
276
  - `POST /auth/register` - Register new user
204
277
  - `POST /auth/login` - Login with email/password
205
278
  - `POST /auth/refresh` - Refresh access token
206
279
  - `POST /auth/logout` - Logout and revoke tokens
207
280
  - `GET /auth/profile` - Get current user profile
208
-
209
- ### Password Management
210
-
211
281
  - `POST /auth/password-reset/request` - Request password reset
212
282
  - `POST /auth/password-reset/complete` - Complete password reset
213
283
  - `POST /auth/verify-email` - Verify email address
214
284
 
285
+ ### Enterprise Features (v0.3.0+)
286
+
287
+ **Two-Factor Authentication:**
288
+ - `POST /auth/2fa/enable` - Enable 2FA and get QR code
289
+ - `POST /auth/2fa/verify` - Verify 2FA setup
290
+ - `POST /auth/2fa/verify-login` - Complete login with 2FA
291
+ - `POST /auth/2fa/disable` - Disable 2FA
292
+ - `POST /auth/2fa/backup-codes/regenerate` - Regenerate backup codes
293
+
294
+ **Device Management:**
295
+ - `GET /auth/devices` - List user's active devices
296
+ - `POST /auth/devices/:deviceId/revoke` - Revoke specific device
297
+
298
+ **Push Notifications:**
299
+ - `POST /auth/push-tokens` - Register push notification token
300
+ - `DELETE /auth/push-tokens/:tokenId` - Revoke push token
301
+
302
+ **Account Management:**
303
+ - `POST /auth/account/deactivate` - Deactivate account
304
+ - `POST /auth/account/reactivate` - Reactivate account
305
+ - `DELETE /auth/account` - Permanently delete account
306
+
307
+ **Social Login:**
308
+ - `POST /auth/social/google` - Google OAuth callback
309
+ - `POST /auth/social/facebook` - Facebook OAuth callback
310
+
215
311
  ### Cross-Language Support
216
312
 
217
313
  - `GET /.well-known/jwks.json` - Public keys for JWT verification
218
314
 
219
- ## Configuration Options
315
+ ---
316
+
317
+ ## ๐ŸŽฏ How SSO Mode Works
318
+
319
+ When you deploy in SSO mode, here's what happens:
320
+
321
+ 1. **Auth Service (auth.yourdomain.com):**
322
+ - Runs in `AUTH_MODE=full`
323
+ - Has database and Redis
324
+ - Handles login, registration, 2FA, etc.
325
+ - Issues JWT tokens
326
+ - Sets cookies for `.yourdomain.com`
327
+
328
+ 2. **Your Projects (project1.yourdomain.com, project2.yourdomain.com):**
329
+ - Run in `AUTH_MODE=sso`
330
+ - No database or Redis needed
331
+ - Only verify JWT tokens using public key
332
+ - Read cookies from `.yourdomain.com`
333
+ - Users are automatically authenticated!
334
+
335
+ 3. **User Experience:**
336
+ - User visits `project1.yourdomain.com`
337
+ - Not logged in โ†’ Your frontend redirects to `auth.yourdomain.com/login`
338
+ - User logs in at auth service
339
+ - Cookie set for `.yourdomain.com`
340
+ - Redirect back to `project1.yourdomain.com`
341
+ - User is now logged in!
342
+ - User visits `project2.yourdomain.com` โ†’ Already logged in! (same cookie)
343
+
344
+ **Important:** This package is API-only. You need to build your own login/register UI that calls the auth endpoints.
345
+
346
+ ---
347
+
348
+ ## ๐Ÿ”ง Configuration Reference
349
+
350
+ ## ๐Ÿ”ง Configuration Reference
351
+
352
+ ### Complete Configuration Interface
220
353
 
221
354
  ```typescript
222
355
  interface HorizonAuthConfig {
223
- // Required
224
- database: {
356
+ // Mode Selection
357
+ ssoMode?: boolean; // false = full auth service, true = token verification only
358
+ authServiceUrl?: string; // Required when ssoMode=true
359
+
360
+ // Database (required when ssoMode=false)
361
+ database?: {
225
362
  url: string;
226
363
  };
227
- redis: {
364
+
365
+ // Redis (required when ssoMode=false)
366
+ redis?: {
228
367
  host: string;
229
368
  port: number;
230
369
  password?: string;
231
370
  db?: number;
232
371
  };
372
+
373
+ // JWT (always required)
233
374
  jwt: {
234
- privateKey: string; // RSA private key (PEM format)
235
- publicKey: string; // RSA public key (PEM format)
375
+ privateKey?: string; // Required when ssoMode=false
376
+ publicKey: string; // Always required
236
377
  accessTokenExpiry?: string; // Default: '15m'
237
378
  refreshTokenExpiry?: string; // Default: '7d'
238
379
  issuer?: string; // Default: 'horizon-auth'
239
380
  audience?: string; // Default: 'horizon-api'
381
+ kid?: string; // Default: 'horizon-auth-key-1'
240
382
  };
241
-
242
- // Optional
383
+
384
+ // Cookie Configuration
385
+ cookie?: {
386
+ domain?: string; // e.g., '.yourdomain.com' for SSO
387
+ secure?: boolean; // Default: true in production
388
+ sameSite?: 'strict' | 'lax' | 'none'; // Default: 'lax'
389
+ };
390
+
391
+ // Multi-Tenant Support
243
392
  multiTenant?: {
244
393
  enabled: boolean;
245
394
  tenantIdExtractor?: 'header' | 'subdomain' | 'custom';
246
395
  defaultTenantId?: string;
247
396
  };
397
+
398
+ // Rate Limiting
248
399
  rateLimit?: {
249
400
  login?: { limit: number; ttl: number };
250
401
  register?: { limit: number; ttl: number };
251
402
  passwordReset?: { limit: number; ttl: number };
252
403
  };
404
+
405
+ // Email Configuration
406
+ email?: {
407
+ provider: 'resend' | 'sendgrid' | 'custom';
408
+ apiKey?: string;
409
+ from?: string;
410
+ };
411
+
412
+ // Global Guards
253
413
  guards?: {
254
414
  applyJwtGuardGlobally?: boolean;
255
415
  };
416
+
417
+ // Enterprise Features
418
+ features?: {
419
+ twoFactor?: {
420
+ enabled: boolean;
421
+ issuer?: string; // Shows in authenticator apps
422
+ };
423
+ deviceManagement?: {
424
+ enabled: boolean;
425
+ maxDevicesPerUser?: number;
426
+ };
427
+ pushNotifications?: {
428
+ enabled: boolean;
429
+ };
430
+ accountManagement?: {
431
+ enabled: boolean;
432
+ allowReactivation?: boolean;
433
+ };
434
+ socialLogin?: {
435
+ google?: {
436
+ clientId: string;
437
+ clientSecret: string;
438
+ callbackUrl: string;
439
+ };
440
+ facebook?: {
441
+ appId: string;
442
+ appSecret: string;
443
+ callbackUrl: string;
444
+ };
445
+ };
446
+ };
256
447
  }
257
448
  ```
258
449
 
259
- ## Decorators
450
+ **๐Ÿ’ก Tip:** Use ENV variables instead of code config for maximum flexibility!
451
+
452
+ ---
453
+
454
+ ## ๐ŸŽญ Decorators
260
455
 
261
456
  ### @Public()
262
457
  Mark routes as publicly accessible (skip authentication)
@@ -300,105 +495,113 @@ getTenantData(@CurrentTenant() tenantId: string) {
300
495
  }
301
496
  ```
302
497
 
303
- ## Multi-Tenant Configuration
498
+ ## Enterprise Features Usage
499
+
500
+ ### Two-Factor Authentication
304
501
 
305
502
  ```typescript
306
- HorizonAuthModule.forRoot({
307
- // ... other config
308
- multiTenant: {
309
- enabled: true,
310
- tenantIdExtractor: 'header', // or 'subdomain' or 'custom'
311
- defaultTenantId: 'default',
312
- },
503
+ // Enable 2FA for a user
504
+ const setup = await fetch('/auth/2fa/enable', {
505
+ method: 'POST',
506
+ headers: { Authorization: `Bearer ${accessToken}` },
313
507
  });
314
- ```
315
-
316
- ## Dev SSO Mode
317
-
318
- For local development with multiple microservices:
508
+ const { secret, qrCode } = await setup.json();
319
509
 
320
- ```yaml
321
- # docker-compose.dev-sso.yml
322
- version: '3.8'
323
- services:
324
- auth-service:
325
- build: .
326
- ports:
327
- - '3000:3000'
328
- environment:
329
- COOKIE_DOMAIN: '.localhost'
330
- REDIS_HOST: redis
331
- depends_on:
332
- - postgres
333
- - redis
334
- ```
510
+ // Display QR code to user (qrCode is a data URL)
511
+ // User scans with Google Authenticator or Authy
335
512
 
336
- All `*.localhost:3000` apps will share the same authentication session.
513
+ // Verify setup with code from authenticator
514
+ await fetch('/auth/2fa/verify', {
515
+ method: 'POST',
516
+ headers: {
517
+ Authorization: `Bearer ${accessToken}`,
518
+ 'Content-Type': 'application/json',
519
+ },
520
+ body: JSON.stringify({ code: '123456' }),
521
+ });
337
522
 
338
- ## Cross-Language Token Verification
523
+ // Login with 2FA
524
+ const loginResponse = await fetch('/auth/login', {
525
+ method: 'POST',
526
+ body: JSON.stringify({ email, password }),
527
+ });
339
528
 
340
- ### C# Example
529
+ if (loginResponse.requiresTwoFactor) {
530
+ // Prompt user for 2FA code
531
+ await fetch('/auth/2fa/verify-login', {
532
+ method: 'POST',
533
+ body: JSON.stringify({
534
+ userId: loginResponse.userId,
535
+ code: '123456', // or backup code
536
+ }),
537
+ });
538
+ }
539
+ ```
341
540
 
342
- ```csharp
343
- using Microsoft.IdentityModel.Tokens;
344
- using System.IdentityModel.Tokens.Jwt;
541
+ ### Device Management
345
542
 
346
- var jwks = await httpClient.GetStringAsync("http://auth-service/.well-known/jwks.json");
347
- var keys = JsonConvert.DeserializeObject<JsonWebKeySet>(jwks);
543
+ ```typescript
544
+ // List user's devices (automatically tracked on login)
545
+ const devices = await fetch('/auth/devices', {
546
+ headers: { Authorization: `Bearer ${accessToken}` },
547
+ }).then(r => r.json());
548
+
549
+ // Revoke a specific device
550
+ await fetch(`/auth/devices/${deviceId}/revoke`, {
551
+ method: 'POST',
552
+ headers: { Authorization: `Bearer ${accessToken}` },
553
+ });
554
+ ```
348
555
 
349
- var tokenHandler = new JwtSecurityTokenHandler();
350
- var validationParameters = new TokenValidationParameters
351
- {
352
- ValidateIssuerSigningKey = true,
353
- IssuerSigningKeys = keys.Keys,
354
- ValidateIssuer = true,
355
- ValidIssuer = "horizon-auth",
356
- ValidateAudience = true,
357
- ValidAudience = "horizon-api"
358
- };
556
+ ### Push Notifications
359
557
 
360
- var principal = tokenHandler.ValidateToken(token, validationParameters, out var validatedToken);
558
+ ```typescript
559
+ // Register push token (requires device from login)
560
+ await fetch('/auth/push-tokens', {
561
+ method: 'POST',
562
+ headers: {
563
+ Authorization: `Bearer ${accessToken}`,
564
+ 'Content-Type': 'application/json',
565
+ },
566
+ body: JSON.stringify({
567
+ token: fcmToken, // From Firebase Cloud Messaging
568
+ tokenType: 'FCM', // or 'APNS' for iOS
569
+ deviceId: deviceId, // From device list
570
+ }),
571
+ });
361
572
  ```
362
573
 
363
- ### Python Example
574
+ ### Account Management
364
575
 
365
- ```python
366
- import jwt
367
- import requests
576
+ ```typescript
577
+ // Deactivate account
578
+ await fetch('/auth/account/deactivate', {
579
+ method: 'POST',
580
+ headers: {
581
+ Authorization: `Bearer ${accessToken}`,
582
+ 'Content-Type': 'application/json',
583
+ },
584
+ body: JSON.stringify({
585
+ reason: 'Taking a break',
586
+ }),
587
+ });
368
588
 
369
- # Fetch JWKS
370
- jwks_url = "http://auth-service/.well-known/jwks.json"
371
- jwks = requests.get(jwks_url).json()
589
+ // Reactivate account (no auth required)
590
+ await fetch('/auth/account/reactivate', {
591
+ method: 'POST',
592
+ body: JSON.stringify({ email, password }),
593
+ });
372
594
 
373
- # Verify token
374
- token = "your-jwt-token"
375
- decoded = jwt.decode(
376
- token,
377
- jwks,
378
- algorithms=["RS256"],
379
- issuer="horizon-auth",
380
- audience="horizon-api"
381
- )
595
+ // Permanently delete account
596
+ await fetch('/auth/account', {
597
+ method: 'DELETE',
598
+ headers: { Authorization: `Bearer ${accessToken}` },
599
+ });
382
600
  ```
383
601
 
384
- ## Security Best Practices
385
-
386
- 1. **Always use HTTPS in production**
387
- 2. **Store RSA keys securely** (environment variables, secrets manager)
388
- 3. **Enable rate limiting** to prevent brute force attacks
389
- 4. **Monitor security events** (failed logins, token reuse)
390
- 5. **Rotate JWT keys periodically**
391
- 6. **Use strong Redis passwords** in production
392
-
393
- ## Environment Variables
394
-
395
- ```env
396
- # Database
397
- DATABASE_URL=postgresql://user:password@localhost:5432/horizon_auth
602
+ ---
398
603
 
399
- # Redis
400
- REDIS_HOST=localhost
401
- REDIS_PORT=6379
604
+ ## ๐ŸŒ Cross-Language Token Verification
402
605
  REDIS_PASSWORD=your_redis_password
403
606
 
404
607
  # JWT Keys (for production - use multiline env vars)
@@ -548,22 +751,188 @@ docker run -p 3000:3000 \
548
751
  - All user tokens have been revoked for security
549
752
  - User needs to login again
550
753
 
551
- ## Migration from Existing Auth
754
+ ### "Device ID required for push tokens"
755
+ - Push tokens require a valid deviceId
756
+ - Devices are created automatically on login (not registration)
757
+ - Login first, then get device list, then register push token
758
+
759
+ ### "Feature disabled" error
760
+ - The feature you're trying to use is not enabled in configuration
761
+ - Enable it in `HorizonAuthModule.forRoot({ features: { ... } })`
762
+
763
+ ## Testing Status
764
+
765
+ **โœ… Fully Tested:**
766
+ - User registration and login
767
+ - JWT token generation and validation
768
+ - Refresh token rotation
769
+ - 2FA setup (QR code generation)
770
+ - Account deactivation/reactivation
771
+ - Login protection for deactivated accounts
772
+
773
+ **โš ๏ธ Requires Manual Testing:**
774
+ - 2FA login flow (requires actual authenticator app)
775
+ - Device tracking (automatic on login)
776
+ - Push token registration (requires valid device)
777
+ - Social login (requires OAuth credentials from Google/Facebook)
778
+ - Backup codes usage during login
779
+
780
+ ## ๐ŸŒ Cross-Language Token Verification
781
+
782
+ Your other services (in any language) can verify tokens using the JWKS endpoint:
783
+
784
+ ### C# Example
552
785
 
553
- See [MIGRATION.md](./MIGRATION.md) for guides on:
554
- - Migrating from bcrypt to Argon2id
555
- - Migrating from HS256 to RS256
556
- - Database schema migration
786
+ ```csharp
787
+ using Microsoft.IdentityModel.Tokens;
788
+ using System.IdentityModel.Tokens.Jwt;
557
789
 
558
- ## License
790
+ var jwks = await httpClient.GetStringAsync("https://auth.yourdomain.com/.well-known/jwks.json");
791
+ var keys = JsonConvert.DeserializeObject<JsonWebKeySet>(jwks);
792
+
793
+ var tokenHandler = new JwtSecurityTokenHandler();
794
+ var validationParameters = new TokenValidationParameters
795
+ {
796
+ ValidateIssuerSigningKey = true,
797
+ IssuerSigningKeys = keys.Keys,
798
+ ValidateIssuer = true,
799
+ ValidIssuer = "horizon-auth",
800
+ ValidateAudience = true,
801
+ ValidAudience = "horizon-api"
802
+ };
803
+
804
+ var principal = tokenHandler.ValidateToken(token, validationParameters, out var validatedToken);
805
+ ```
806
+
807
+ ### Python Example
808
+
809
+ ```python
810
+ import jwt
811
+ import requests
812
+
813
+ # Fetch JWKS
814
+ jwks_url = "https://auth.yourdomain.com/.well-known/jwks.json"
815
+ jwks = requests.get(jwks_url).json()
816
+
817
+ # Verify token
818
+ token = "your-jwt-token"
819
+ decoded = jwt.decode(
820
+ token,
821
+ jwks,
822
+ algorithms=["RS256"],
823
+ issuer="horizon-auth",
824
+ audience="horizon-api"
825
+ )
826
+ ```
827
+
828
+ ---
829
+
830
+ ## ๐Ÿ› Troubleshooting
831
+
832
+ ### "AUTH_SERVICE_URL is required when AUTH_MODE=sso"
833
+ Set `AUTH_SERVICE_URL` in your ENV file when using SSO mode.
834
+
835
+ ### "JWT_PRIVATE_KEY is required when AUTH_MODE=full"
836
+ Make sure you've set `JWT_PRIVATE_KEY` when running in full mode (auth service).
837
+
838
+ ### "Invalid or expired access token"
839
+ - Check that your JWT keys are correctly configured
840
+ - Verify token hasn't expired (default 15 minutes)
841
+ - Ensure token isn't blacklisted in Redis
842
+
843
+ ### "Redis connection error"
844
+ - Verify Redis is running: `docker ps` or check your cloud Redis service
845
+ - Check Redis connection settings in ENV
846
+ - Test connection: `redis-cli ping`
847
+
848
+ ### "Token reuse detected"
849
+ - This is a security feature - someone tried to reuse a revoked refresh token
850
+ - All user tokens have been revoked for security
851
+ - User needs to login again
852
+
853
+ ### "Device ID required for push tokens"
854
+ - Push tokens require a valid deviceId
855
+ - Devices are created automatically on login (not registration)
856
+ - Login first, then get device list, then register push token
857
+
858
+ ### "Feature disabled" error
859
+ - The feature you're trying to use is not enabled
860
+ - Enable it via ENV: `ENABLE_2FA=true`, `ENABLE_DEVICE_MGMT=true`, etc.
861
+
862
+ ### Cookies not working across subdomains
863
+ - Make sure `COOKIE_DOMAIN` starts with a dot: `.yourdomain.com`
864
+ - Verify `COOKIE_SECURE=true` in production (requires HTTPS)
865
+ - Check that all apps use the same cookie domain
866
+
867
+ ---
868
+
869
+ ## ๐Ÿ“š Documentation
870
+
871
+ - **[ENV-CONFIGURATION.md](https://github.com/OfekItzhaki/horizon-auth-platform/blob/main/ENV-CONFIGURATION.md)** - Complete environment variable reference
872
+ - **[DEPLOYMENT-EXAMPLES.md](https://github.com/OfekItzhaki/horizon-auth-platform/blob/main/DEPLOYMENT-EXAMPLES.md)** - Real-world deployment scenarios
873
+ - **[GitHub Repository](https://github.com/OfekItzhaki/horizon-auth-platform)** - Source code and issues
874
+
875
+ ---
876
+
877
+ ## ๐Ÿงช Testing Status
878
+
879
+ **โœ… Fully Tested:**
880
+ - User registration and login
881
+ - JWT token generation and validation
882
+ - Refresh token rotation
883
+ - 2FA setup (QR code generation)
884
+ - Account deactivation/reactivation
885
+ - Login protection for deactivated accounts
886
+ - SSO mode token verification
887
+
888
+ **โš ๏ธ Requires Manual Testing:**
889
+ - 2FA login flow (requires actual authenticator app)
890
+ - Device tracking (automatic on login)
891
+ - Push token registration (requires valid device)
892
+ - Social login (requires OAuth credentials from Google/Facebook)
893
+ - Backup codes usage during login
894
+
895
+ ---
896
+
897
+ ## ๐Ÿ“ฆ What's New
898
+
899
+ ### v0.4.0 (Latest)
900
+ - โœจ **ENV-based configuration** - Zero code changes needed!
901
+ - โœจ **Flexible deployment** - Same package for embedded and SSO modes
902
+ - ๐Ÿ“ Complete ENV variable documentation
903
+ - ๐Ÿ“ Real-world deployment examples
904
+ - ๐Ÿ”ง Improved configuration merging
905
+
906
+ ### v0.3.0
907
+ - โœจ Two-Factor Authentication (TOTP)
908
+ - โœจ Device Management
909
+ - โœจ Push Notifications
910
+ - โœจ Account Management
911
+ - โœจ Social Login (Google, Facebook)
912
+
913
+ ### v0.2.1
914
+ - ๐Ÿ› Fixed SSO mode JWT strategy
915
+ - ๐Ÿ”ง Dynamic module configuration
916
+
917
+ ---
918
+
919
+ ## ๐Ÿ“„ License
559
920
 
560
921
  MIT
561
922
 
562
- ## Support
923
+ ---
924
+
925
+ ## ๐Ÿค Support
926
+
927
+ - **Issues:** [GitHub Issues](https://github.com/OfekItzhaki/horizon-auth-platform/issues)
928
+ - **Discussions:** [GitHub Discussions](https://github.com/OfekItzhaki/horizon-auth-platform/discussions)
563
929
 
564
- - GitHub Issues: https://github.com/OfekItzhaki/horizon-auth-platform/issues
565
- - Documentation: https://github.com/OfekItzhaki/horizon-auth-platform
930
+ ---
931
+
932
+ ## ๐Ÿ‘จโ€๐Ÿ’ป Author
566
933
 
567
- ## Credits
934
+ Created by **Ofek Itzhaki**
935
+
936
+ ---
568
937
 
569
- Created by Ofek Itzhaki
938
+ **โญ If this package helps you, consider giving it a star on GitHub!**