auth-events 1.0.0 → 1.2.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.
Files changed (2) hide show
  1. package/README.md +3 -308
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,7 +1,4 @@
1
- # auth-events
2
-
3
1
  ![npm](https://img.shields.io/npm/v/auth-events)
4
-
5
2
  # Auth Events
6
3
 
7
4
  **`auth-events`** is a lightweight, powerful, and extensible Node.js library to handle authentication and user-related events in your application. It provides an **event-driven architecture** for login, logout, registration, password changes, role updates, device tracking, risk signals, and more.
@@ -27,312 +24,10 @@ Designed for **security, audit, and automation**, it works with any auth provide
27
24
 
28
25
  ---
29
26
 
30
- ## Installation
31
-
32
- ```bash
33
- npm install auth-events
34
- # or
35
- yarn add auth-events
36
-
37
- auth-events
38
-
39
- A lightweight event layer for authentication flows.
40
-
41
- 🧠 Mental Model (Read this first)
42
-
43
- Think of authentication in two responsibilities:
44
-
45
- Auth Code → WHAT happened?
46
- Auth Events → WHAT should we do about it?
47
-
48
-
49
- Examples:
50
-
51
- Login happened → emit event
52
-
53
- Password changed → emit event
54
-
55
- New device detected → emit event
56
-
57
- auth-events only broadcasts facts.
58
- It does not decide business logic.
59
-
60
- This keeps authentication clean and predictable.
61
-
62
- ❓ Why auth-events?
63
-
64
- Authentication logic often becomes bloated over time.
65
-
66
- A simple login flow slowly accumulates responsibilities:
67
-
68
- audit logging
69
-
70
- security checks
71
-
72
- analytics
73
-
74
- notifications
75
-
76
- Soon, your auth code becomes:
77
-
78
- hard to read
79
-
80
- hard to test
81
-
82
- risky to change
83
-
84
- auth-events solves this by introducing a small event layer after authentication.
85
-
86
- Auth code emits events.
87
- Side-effects live elsewhere.
88
-
89
- 🧩 How it works
90
-
91
- Your app emits an auth event (e.g. "login").
92
-
93
- One or more listeners react to that event.
94
-
95
- Authentication logic stays clean and focused.
96
-
97
- There is no coupling between auth code and side-effects.
98
-
99
- 📁 Recommended File Structure
100
-
101
- This is where most projects go wrong — structure matters.
102
-
103
- src/
104
- ├─ auth/
105
- │ ├─ auth.controller.ts # login, signup, logout
106
- │ ├─ auth.service.ts # password verification, token logic
107
-
108
- ├─ auth-events/
109
- │ ├─ index.ts # single AuthEvents instance
110
- │ ├─ listeners/
111
- │ │ ├─ audit.listener.ts
112
- │ │ ├─ security.listener.ts
113
- │ │ ├─ analytics.listener.ts
114
- │ │ └─ notification.listener.ts
115
-
116
- ├─ app.ts
117
- └─ server.ts
118
-
119
- 🧩 Step 1: Create one global AuthEvents instance
120
-
121
- 📍 src/auth-events/index.ts
122
-
123
- import { AuthEvents } from "auth-events";
124
-
125
- export const authEvents = new AuthEvents();
126
-
127
-
128
- ⚠️ Important
129
-
130
- Your application should have only one AuthEvents instance.
131
- All listeners and emitters must use this same instance.
132
-
133
- 🧩 Step 2: Emit events inside existing auth code
134
-
135
- 📍 src/auth/auth.controller.ts
136
-
137
- import { authEvents } from "../auth-events";
138
-
139
- export const login = async (req, res) => {
140
- const user = await authService.login(req.body);
141
-
142
- // Emit fact, not logic
143
- await authEvents.emit("login", {
144
- userId: user.id,
145
- ip: req.ip,
146
- userAgent: req.headers["user-agent"],
147
- sessionId: req.sessionID
148
- )});
149
-
150
- res.json({ token: user.token });
151
- };
152
-
153
-
154
- ✅ Login responsibility = done
155
- ❌ No logging
156
- ❌ No analytics
157
- ❌ No security rules
158
-
159
- 🧩 Step 3: Attach operations using listeners
160
-
161
- This is where auth-events shines.
162
-
163
- 🔐 Security listener
164
-
165
- 📍 auth-events/listeners/security.listener.ts
166
-
167
- import { authEvents } from "../index";
168
-
169
- authEvents.on("login", async (event) => {
170
- if (isNewDevice(event)) {
171
- await authEvents.emit("new_device_detected", event);
172
- }
173
- });
174
-
175
- 📜 Audit logging
176
-
177
- 📍 auth-events/listeners/audit.listener.ts
178
-
179
- authEvents.on("login", async (event) => {
180
- await AuditLog.create({
181
- userId: event.userId,
182
- action: "LOGIN",
183
- ip: event.ip,
184
- userAgent: event.userAgent
185
- });
186
- });
187
-
188
- 📊 Analytics tracking
189
-
190
- 📍 auth-events/listeners/analytics.listener.ts
191
-
192
- authEvents.on("login", async (event) => {
193
- analytics.track("user_login", {
194
- userId: event.userId,
195
- device: event.userAgent
196
- )});
197
-
198
- 🔔 Notifications
199
-
200
- 📍 auth-events/listeners/notification.listener.ts
201
-
202
- authEvents.on("new_device_detected", async (event) => {
203
- await sendEmail({
204
- to: event.userId,
205
- subject: "New device login detected"
206
- });
207
- });
208
-
209
-
210
-
211
- // Emit a login event
212
- await authEvents.login({
213
- userId: "123",
214
- email: "user@example.com",
215
- ip: "192.168.1.1",
216
- deviceId: "device_abc123",
217
- deviceType: "desktop",
218
- browser: "Chrome",
219
- country: "IN",
220
- riskScore: 25,
221
- status: "success"
222
- });
223
- AuthEvent Interface
224
- Each event provides a rich set of fields for security, auditing, and automation:
225
-
226
- export interface AuthEvent {
227
- type: AuthEventType;
228
- userId: string;
229
- email?: string;
230
- roles?: string[];
231
-
232
- // Session & Token
233
- sessionId?: string;
234
- tokenId?: string;
235
- tokenType?: "jwt" | "session";
236
- tokenIssuedAt?: Date;
237
- tokenExpiresAt?: Date;
238
-
239
- // Network
240
- ip?: string;
241
- isp?: string;
242
- country?: string;
243
- region?: string;
244
- city?: string;
245
- timezone?: string;
246
-
247
- // Device
248
- deviceId?: string;
249
- deviceType?: "mobile" | "desktop" | "tablet";
250
- os?: string;
251
- browser?: string;
252
- userAgent?: string;
253
-
254
- // Auth context
255
- provider?: "google" | "firebase" | "auth0" | "custom";
256
- origin?: "web" | "mobile" | "api";
257
- referrer?: string;
258
- status?: "success" | "failed";
259
- failureReason?: string;
260
- attemptCount?: number;
261
- authMethod?: "password" | "oauth" | "magic_link" | "otp";
262
-
263
- // Risk signals
264
- riskScore?: number;
265
- deviceRiskScore?: number;
266
- geoVelocityRisk?: boolean;
267
- isNewDevice?: boolean;
268
- isNewIP?: boolean;
269
- isProxy?: boolean;
270
- isTor?: boolean;
271
- isBot?: boolean;
272
-
273
- // Update / Change tracking
274
- changedFields?: string[];
275
- previousValues?: Record<string, any>;
276
- newValues?: Record<string, any>;
277
- updatedBy?: string;
278
- updatedVia?: "user" | "admin" | "api" | "system";
279
- changeId?: string;
280
- previousVersion?: number;
281
- newVersion?: number;
282
-
283
- // Meta & audit
284
- metadata?: Record<string, any>;
285
- requestId?: string;
286
- correlationId?: string;
287
-
288
- timestamp: Date;
289
- }
290
-
291
-
292
- AuthEventType
293
- All supported events (enterprise-ready):
294
-
295
- export type AuthEventType =
296
- | "login" | "logout" | "register" | "login_failed"
297
- | "suspicious_login" | "brute_force_detected"
298
- | "account_locked" | "account_unlocked"
299
- | "ip_blocked" | "device_blocked" | "location_changed"
300
- | "otp_sent" | "otp_verified" | "otp_failed"
301
- | "mfa_enabled" | "mfa_disabled" | "email_verified" | "phone_verified"
302
- | "session_created" | "session_revoked" | "session_expired" | "session_refreshed"
303
- | "token_issued" | "token_refreshed" | "token_revoked" | "token_expired"
304
- | "new_device_detected" | "device_trusted" | "device_untrusted" | "device_removed"
305
- | "password_changed" | "role_changed"
306
- | "profile_updated" | "email_changed" | "phone_changed"
307
- | "rate_limit_exceeded" | "policy_violation" | "security_rule_triggered" | "risk_score_updated"
308
- | "provider_linked" | "provider_unlinked" | "provider_login" | "provider_error";
309
-
310
-
311
-
312
-
313
- Developer Tips
314
-
315
- Use changedFields, previousValues, and newValues for auditing profile updates.
316
-
317
- Use riskScore, isNewDevice, and geoVelocityRisk for security automation.
318
-
319
- Handlers can return actions: allow, block, or challenge (OTP, 2FA).
320
-
321
- Inject logger, db, cache in context for advanced workflows.
322
-
323
- Can be extended with plugins or middleware for notifications (email/SMS), dashboards, or analytics.
324
-
27
+ documentation
325
28
 
29
+ https://auth-events-web.vercel.app/
326
30
 
327
- Why use auth-events?
328
- Single source of truth for all auth-related actions
329
- Real-time risk analysis and automation
330
- Easy to integrate with any auth provider (custom, Firebase, Auth0, etc.)
331
- Enterprise-ready with audit trails, session management, MFA, and device trust
332
31
 
333
32
 
334
- Future Improvements
335
- Webhooks / external notifications
336
- Priority-based handler execution
337
- Event persistence for audit / replay
338
- Rule engine for automated security actions
33
+ Keep Coding Keep Exploring
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auth-events",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "A lightweight Node.js library to track and react to authentication events across any auth provider.",
5
5
  "type": "module",
6
6
  "license": "MIT",