@dax-crafta/auth 2.1.1 → 2.1.3
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 +22 -0
- package/dev-testing.md +48 -0
- package/package.json +65 -62
- package/src/index.d.ts +104 -9
- package/src/index.js +442 -336
- package/src/middlewares/auth.middleware.js +19 -15
- package/src/models/audit-log.js +18 -1
- package/src/models/user.js +20 -2
- package/src/services/auth.service.js +92 -11
- package/src/testing/adaptive-runner.js +74 -0
- package/src/utils/api-error.js +8 -0
- package/src/utils/email.js +21 -4
- package/src/utils/logger.js +38 -0
package/README.md
CHANGED
|
@@ -53,12 +53,34 @@ const app = crafta();
|
|
|
53
53
|
auth({
|
|
54
54
|
strategy: 'jwt',
|
|
55
55
|
fields: ['email', 'password'],
|
|
56
|
+
// Works even without SMTP in local dev.
|
|
57
|
+
// Email flows auto-disable if SMTP is not configured.
|
|
56
58
|
emailVerification: true
|
|
57
59
|
})(app);
|
|
58
60
|
|
|
59
61
|
app.listen(3000);
|
|
60
62
|
```
|
|
61
63
|
|
|
64
|
+
## Feature Toggles (Simple JSON)
|
|
65
|
+
|
|
66
|
+
Disable any feature by setting it to `false`:
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
auth({
|
|
70
|
+
features: {
|
|
71
|
+
emailVerification: false,
|
|
72
|
+
loginAlerts: false,
|
|
73
|
+
securityAttempts: false,
|
|
74
|
+
rateLimit: true,
|
|
75
|
+
auditLogs: true,
|
|
76
|
+
twoFactor: true,
|
|
77
|
+
csrf: false
|
|
78
|
+
}
|
|
79
|
+
})(app);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Example: if `securityAttempts: false`, login-attempt lock handling and lock emails are disabled.
|
|
83
|
+
|
|
62
84
|
## Configuration
|
|
63
85
|
|
|
64
86
|
```javascript
|
package/dev-testing.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Adaptive Testing & Logging (Developer Guide)
|
|
2
|
+
|
|
3
|
+
This is a lightweight, developer-friendly testing + logging skeleton you can extend.
|
|
4
|
+
|
|
5
|
+
## Files (shipped with `src/` for publish)
|
|
6
|
+
- `dev-tools/logger.js` — colored terminal logging (`SUCCESS`, `WARN`, `FAIL`, `SKIP`, `INFO`).
|
|
7
|
+
- `dev-tools/feature-config.js` — sample feature toggles + auth config.
|
|
8
|
+
- `dev-tools/tests.js` — mock feature tests (JWT, Email OTP, OAuth, 2FA) tagged by feature key.
|
|
9
|
+
- `dev-tools/run-tests.js` — adaptive runner that executes only enabled-feature tests.
|
|
10
|
+
- `dev-tools/example-app.js` — minimal Express wiring showing startup logs and honoring feature flags.
|
|
11
|
+
|
|
12
|
+
## Library exports (for consumers)
|
|
13
|
+
- `runAdaptiveTests(config, featureFlags?, opts?)`
|
|
14
|
+
- `inferFeatureFlags(config)`
|
|
15
|
+
- `testCatalog` (for extension)
|
|
16
|
+
|
|
17
|
+
## Run adaptive tests
|
|
18
|
+
```bash
|
|
19
|
+
node dev-tools/run-tests.js
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Sample output
|
|
23
|
+
```
|
|
24
|
+
[INFO] Adaptive test runner starting…
|
|
25
|
+
[INFO] JWT secret present, token signing would proceed
|
|
26
|
+
[SUCCESS] JWT issues token
|
|
27
|
+
[INFO] SMTP host: smtp.example.com
|
|
28
|
+
[SUCCESS] Email OTP sends message
|
|
29
|
+
[SKIP] OAuth login flow - feature disabled
|
|
30
|
+
[INFO] 2FA code verification simulated
|
|
31
|
+
[SUCCESS] 2FA TOTP validation
|
|
32
|
+
[SUCCESS] Adaptive tests complete.
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## How it works
|
|
36
|
+
- Feature flags live in `feature-config.js` (`features.jwt`, `features.emailOtp`, `features.oauth`, `features.twofa`).
|
|
37
|
+
- The runner reads the flags and only executes tests whose `feature` matches an enabled flag.
|
|
38
|
+
- Config changes require no test edits; toggling a flag updates which tests run.
|
|
39
|
+
- Add new features by adding a flag in `feature-config.js` and a test entry in `tests.js`.
|
|
40
|
+
|
|
41
|
+
## Integrating with the auth library
|
|
42
|
+
- `dev-tools/example-app.js` shows how to load your library (`auth(cfg)(app)`) and print startup messages reflecting enabled features.
|
|
43
|
+
- Wire real tests by replacing the mock test bodies in `tests.js` with actual calls to your services/routes.
|
|
44
|
+
|
|
45
|
+
## Extending
|
|
46
|
+
- Add more log helpers in `logger.js` if you want structured output.
|
|
47
|
+
- Add more feature keys (e.g., `emailVerification`, `refreshTokens`) and corresponding tests.
|
|
48
|
+
- Point `feature-config.js` at your real project config or load from env for true parity.
|
package/package.json
CHANGED
|
@@ -1,62 +1,65 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@dax-crafta/auth",
|
|
3
|
-
"version": "2.1.
|
|
4
|
-
"description": "A powerful, flexible, and secure authentication plugin for the Crafta framework. Supports JWT, social login, 2FA, RBAC, audit logging, and enterprise-grade security features.",
|
|
5
|
-
"main": "src/index.js",
|
|
6
|
-
"types": "src/index.d.ts",
|
|
7
|
-
"private": false,
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"passport
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
},
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"url": "https://github.com/daxp472/crafta
|
|
58
|
-
},
|
|
59
|
-
"
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@dax-crafta/auth",
|
|
3
|
+
"version": "2.1.3",
|
|
4
|
+
"description": "A powerful, flexible, and secure authentication plugin for the Crafta framework. Supports JWT, social login, 2FA, RBAC, audit logging, and enterprise-grade security features.",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"types": "src/index.d.ts",
|
|
7
|
+
"private": false,
|
|
8
|
+
"scripts": {
|
|
9
|
+
"test": "node dev-tools/smoke-tests/run-smoke-tests.js"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"bcryptjs": "^2.4.3",
|
|
13
|
+
"cookie-parser": "^1.4.7",
|
|
14
|
+
"csurf": "^1.11.0",
|
|
15
|
+
"express-brute": "^1.0.1",
|
|
16
|
+
"express-rate-limit": "^7.1.4",
|
|
17
|
+
"express-validator": "^7.3.0",
|
|
18
|
+
"google-auth-library": "^9.2.0",
|
|
19
|
+
"helmet": "^8.1.0",
|
|
20
|
+
"jsonwebtoken": "^9.0.2",
|
|
21
|
+
"mongoose": "^7.6.3",
|
|
22
|
+
"nodemailer": "^6.9.7",
|
|
23
|
+
"otplib": "^12.0.1",
|
|
24
|
+
"passport": "^0.6.0",
|
|
25
|
+
"passport-facebook": "^3.0.0",
|
|
26
|
+
"passport-github2": "^0.1.12",
|
|
27
|
+
"passport-google-oauth20": "^2.0.0",
|
|
28
|
+
"qrcode": "^1.5.3",
|
|
29
|
+
"speakeasy": "^2.0.0",
|
|
30
|
+
"validator": "^13.11.0",
|
|
31
|
+
"winston": "^3.11.0",
|
|
32
|
+
"zxcvbn": "^4.4.2"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"crafta": "^1.1.4"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"authentication",
|
|
39
|
+
"auth",
|
|
40
|
+
"jwt",
|
|
41
|
+
"oauth",
|
|
42
|
+
"social-login",
|
|
43
|
+
"role-based-access-control",
|
|
44
|
+
"rbac",
|
|
45
|
+
"2fa",
|
|
46
|
+
"mfa",
|
|
47
|
+
"audit-logging",
|
|
48
|
+
"express",
|
|
49
|
+
"nodejs",
|
|
50
|
+
"crafta",
|
|
51
|
+
"secure-authentication",
|
|
52
|
+
"enterprise-security",
|
|
53
|
+
"user-management"
|
|
54
|
+
],
|
|
55
|
+
"repository": {
|
|
56
|
+
"type": "git",
|
|
57
|
+
"url": "git+https://github.com/daxp472/crafta.git"
|
|
58
|
+
},
|
|
59
|
+
"bugs": {
|
|
60
|
+
"url": "https://github.com/daxp472/crafta/issues"
|
|
61
|
+
},
|
|
62
|
+
"homepage": "https://github.com/daxp472/crafta#readme",
|
|
63
|
+
"license": "MIT",
|
|
64
|
+
"author": "Dax Patel"
|
|
65
|
+
}
|
package/src/index.d.ts
CHANGED
|
@@ -1,12 +1,107 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export interface CraftaAuthRoutes {
|
|
2
|
+
register?: string;
|
|
3
|
+
login?: string;
|
|
4
|
+
verify?: string;
|
|
5
|
+
forgotPassword?: string;
|
|
6
|
+
resetPassword?: string;
|
|
7
|
+
refreshToken?: string;
|
|
8
|
+
profile?: string;
|
|
9
|
+
twoFactor?: string;
|
|
10
|
+
roles?: string;
|
|
11
|
+
permissions?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface PasswordPolicyConfig {
|
|
15
|
+
minLength?: number;
|
|
16
|
+
requireUppercase?: boolean;
|
|
17
|
+
requireLowercase?: boolean;
|
|
18
|
+
requireNumbers?: boolean;
|
|
19
|
+
requireSpecialChars?: boolean;
|
|
20
|
+
expiryDays?: number;
|
|
21
|
+
minStrength?: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface SmtpConfig {
|
|
25
|
+
host: string;
|
|
26
|
+
port: number;
|
|
27
|
+
auth: {
|
|
28
|
+
user: string;
|
|
29
|
+
pass: string;
|
|
30
|
+
};
|
|
31
|
+
from: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface SocialGoogleConfig {
|
|
35
|
+
clientID: string;
|
|
36
|
+
clientSecret: string;
|
|
37
|
+
callbackURL: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface SocialConfig {
|
|
41
|
+
google?: SocialGoogleConfig | null;
|
|
42
|
+
facebook?: any;
|
|
43
|
+
github?: any;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface EnvConfig {
|
|
47
|
+
JWT_SECRET: string;
|
|
48
|
+
[key: string]: any;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface AuthConfig {
|
|
52
|
+
strategy?: 'jwt';
|
|
53
|
+
fields?: string[];
|
|
54
|
+
routes?: CraftaAuthRoutes;
|
|
55
|
+
mongoUrl?: string;
|
|
56
|
+
maxLoginAttempts?: number;
|
|
57
|
+
emailVerification?: boolean;
|
|
58
|
+
loginAlerts?: boolean;
|
|
59
|
+
passwordPolicy?: PasswordPolicyConfig;
|
|
60
|
+
smtp?: SmtpConfig | null;
|
|
61
|
+
social?: SocialConfig;
|
|
62
|
+
env?: EnvConfig;
|
|
63
|
+
accessTokenExpiry?: string;
|
|
64
|
+
refreshTokenDays?: number;
|
|
65
|
+
enableCSRF?: boolean;
|
|
66
|
+
limits?: {
|
|
67
|
+
loginMax?: number;
|
|
68
|
+
twoFAMax?: number;
|
|
69
|
+
forgotPasswordMax?: number;
|
|
70
|
+
refreshMax?: number;
|
|
71
|
+
};
|
|
72
|
+
baseUrl?: string;
|
|
73
|
+
emailTemplateDir?: string;
|
|
74
|
+
features?: AuthFeaturesConfig;
|
|
75
|
+
logging?: boolean;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface AuthFeaturesConfig {
|
|
79
|
+
emailVerification?: boolean;
|
|
80
|
+
loginAlerts?: boolean;
|
|
81
|
+
securityAttempts?: boolean;
|
|
82
|
+
rateLimit?: boolean;
|
|
83
|
+
auditLogs?: boolean;
|
|
84
|
+
twoFactor?: boolean;
|
|
85
|
+
csrf?: boolean;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export class ApiError extends Error {
|
|
89
|
+
status: number;
|
|
90
|
+
constructor(message: string, status?: number);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function auth(config?: AuthConfig): (app: any) => void;
|
|
4
94
|
|
|
5
|
-
export interface
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
95
|
+
export interface AdaptiveTestCase {
|
|
96
|
+
name: string;
|
|
97
|
+
feature: string;
|
|
98
|
+
run: (cfg: AuthConfig, log: any) => Promise<void>;
|
|
9
99
|
}
|
|
10
100
|
|
|
11
|
-
export function
|
|
12
|
-
export function
|
|
101
|
+
export function inferFeatureFlags(authConfig?: AuthConfig): Record<string, boolean>;
|
|
102
|
+
export function runAdaptiveTests(
|
|
103
|
+
authConfig?: AuthConfig,
|
|
104
|
+
featureFlags?: Record<string, boolean>,
|
|
105
|
+
opts?: { logging?: boolean }
|
|
106
|
+
): Promise<boolean>;
|
|
107
|
+
export const testCatalog: AdaptiveTestCase[];
|