kroxt 1.3.7 → 1.3.8
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 +230 -231
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,231 +1,230 @@
|
|
|
1
|
-
# Kroxt
|
|
2
|
-
|
|
3
|
-
**The Most Simplified auth library**
|
|
4
|
-
|
|
5
|
-
Kroxt is a premium, framework-agnostic, and security-hardened authentication library for modern TypeScript environments. Designed for 100% schema control and "Zero-Config" onboarding.
|
|
6
|
-
|
|
7
|
-
[](https://www.npmjs.com/package/kroxt)
|
|
8
|
-
[](https://opensource.org/licenses/MIT)
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## ⚡ 30-Second Onboarding
|
|
13
|
-
|
|
14
|
-
The recommended way to start is the **Kroxt CLI**. It detects your framework (Next.js, Express, Fastify) and scaffolds a professional auth structure automatically.
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
npx kroxt init
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## 🏗️ Core Architecture
|
|
23
|
-
|
|
24
|
-
Kroxt is "Headless." It provides the **Brain** (Logic, Hashing, JWTs, Security) while you provide the **Face** (UI/Routes).
|
|
25
|
-
|
|
26
|
-
### 1. The Configuration Matrix
|
|
27
|
-
Every feature in Kroxt is modular. Toggle security layers with a single boolean.
|
|
28
|
-
|
|
29
|
-
```typescript
|
|
30
|
-
import { createAuth } from "kroxt";
|
|
31
|
-
import { createMongoAdapter } from "kroxt/adapters/mongoose";
|
|
32
|
-
|
|
33
|
-
export const auth = createAuth({
|
|
34
|
-
adapter: createMongoAdapter(UserModel),
|
|
35
|
-
secret: process.env.JWT_SECRET,
|
|
36
|
-
|
|
37
|
-
// Security Layer 1: Sessions
|
|
38
|
-
session: {
|
|
39
|
-
expires: "15m", // Access Token duration
|
|
40
|
-
refreshExpires: "7d", // Refresh Token duration
|
|
41
|
-
enforceStrictRevocation: true, // DB-lookup on EVERY request (Admin-mode)
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
// Security Layer 2: Defense
|
|
45
|
-
rateLimit: {
|
|
46
|
-
max: 100, // Requests per window
|
|
47
|
-
windowMs: 60 * 1000 // 1 Minute window
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
// Security Layer 3: Brute Force
|
|
51
|
-
ipBlocking: {
|
|
52
|
-
maxStrikes: 5, // Ban after 5 failures
|
|
53
|
-
blockDurationMs: 15 * 60 * 1000 // 15 Min ban
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
// Security Layer 4: Crypto
|
|
57
|
-
passwordPolicy: {
|
|
58
|
-
minLength: 8,
|
|
59
|
-
requireUppercase: true,
|
|
60
|
-
requireSpecialCharacter: true,
|
|
61
|
-
usePepper: true // Requires JWT_PEPPER env variable
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
---
|
|
67
|
-
|
|
68
|
-
## 🔌 Universal Adapters
|
|
69
|
-
|
|
70
|
-
Bring your own schema. Kroxt adapts to you.
|
|
71
|
-
|
|
72
|
-
### Mongoose (MongoDB)
|
|
73
|
-
```typescript
|
|
74
|
-
import { createMongoAdapter } from "kroxt/adapters/mongoose";
|
|
75
|
-
const adapter = createMongoAdapter(User);
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### Prisma (SQL)
|
|
79
|
-
```typescript
|
|
80
|
-
import { createPrismaAdapter } from "kroxt/adapters/prisma";
|
|
81
|
-
const adapter = createPrismaAdapter(prisma.user);
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### Drizzle (SQL)
|
|
85
|
-
```typescript
|
|
86
|
-
import { createDrizzleAdapter } from "kroxt/adapters/drizzle";
|
|
87
|
-
import { eq } from "drizzle-orm";
|
|
88
|
-
const adapter = createDrizzleAdapter(db, users, eq);
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### Memory (Testing)
|
|
92
|
-
```typescript
|
|
93
|
-
import { createMemoryAdapter } from "kroxt";
|
|
94
|
-
const adapter = createMemoryAdapter();
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
---
|
|
98
|
-
|
|
99
|
-
## 🧠 API Reference
|
|
100
|
-
|
|
101
|
-
### `auth.signup(userData, password)`
|
|
102
|
-
Registers a new user. User data is strictly typed to your schema.
|
|
103
|
-
```typescript
|
|
104
|
-
const { user, accessToken, refreshToken } = await auth.signup({
|
|
105
|
-
email: "dev@kroxt.io",
|
|
106
|
-
role: "admin"
|
|
107
|
-
}, "secure_password");
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### `auth.loginWithPassword(email, password, clientIp?)`
|
|
111
|
-
Authenticates a user and generates tokens. Pass `clientIp` to enable IP-Blocking.
|
|
112
|
-
```typescript
|
|
113
|
-
const result = await auth.loginWithPassword(email, password, req.ip);
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### `auth.refreshSession(refreshToken, clientIp?)`
|
|
117
|
-
Rotates the session. If `enforceStrictRevocation` is on, it validates the token against the user's current password hash.
|
|
118
|
-
```typescript
|
|
119
|
-
const { user, accessToken, refreshToken: newRefresh } = await auth.refreshSession(token);
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
### `auth.logout(refreshToken)`
|
|
123
|
-
Invalidates a session.
|
|
124
|
-
```typescript
|
|
125
|
-
await auth.logout(refreshToken);
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### `auth.changePassword(userId, newPassword)`
|
|
129
|
-
Updates password and **instantly invalidates all other active sessions** globally via Hash-Linked revocation.
|
|
130
|
-
```typescript
|
|
131
|
-
await auth.changePassword(user.id, "new_secure_pass");
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
---
|
|
135
|
-
|
|
136
|
-
## 🧩 Middleware Implementation
|
|
137
|
-
|
|
138
|
-
### Express / Fastify
|
|
139
|
-
```typescript
|
|
140
|
-
const protect = async (req, res, next) => {
|
|
141
|
-
const token = req.headers.authorization?.split(" ")[1];
|
|
142
|
-
try {
|
|
143
|
-
const session = await auth.verifyAccessToken(token);
|
|
144
|
-
req.user = session.user;
|
|
145
|
-
next();
|
|
146
|
-
} catch (err) {
|
|
147
|
-
res.status(401).json({ error: "Unauthorized" });
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
---
|
|
153
|
-
|
|
154
|
-
## 🚀 Advanced Deployment
|
|
155
|
-
|
|
156
|
-
### Custom JWT Payloads
|
|
157
|
-
Inject metadata into your tokens safely.
|
|
158
|
-
```typescript
|
|
159
|
-
jwt: {
|
|
160
|
-
payload: (user, type) => {
|
|
161
|
-
return type === "access" ? { role: user.role } : {};
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### Password Peppering
|
|
167
|
-
Kroxt supports server-side peppering to protect against rainbow table attacks even if your database is leaked.
|
|
168
|
-
1. Set `usePepper: true` in config.
|
|
169
|
-
2. Add `JWT_PEPPER` to your `.env`.
|
|
170
|
-
|
|
171
|
-
---
|
|
172
|
-
|
|
173
|
-
## 🧠 API Reference (Exhaustive)
|
|
174
|
-
|
|
175
|
-
### `auth.signup()`
|
|
176
|
-
| Argument | Type | Description |
|
|
177
|
-
| --- | --- | --- |
|
|
178
|
-
| `userData` | `Omit<User, "id">` | Your user object without the ID (ID is auto-generated) |
|
|
179
|
-
| `password` | `string` (Optional) | Plain text password. Will be hashed using Argon2 |
|
|
180
|
-
|
|
181
|
-
### `auth.loginWithPassword()`
|
|
182
|
-
| Argument | Type | Description |
|
|
183
|
-
| --- | --- | --- |
|
|
184
|
-
| `email` | `string` | User email |
|
|
185
|
-
| `password` | `string` | User password |
|
|
186
|
-
| `clientIp` | `string` (Optional) | Required for IP-Blocking defense |
|
|
187
|
-
|
|
188
|
-
### `auth.changePassword()`
|
|
189
|
-
| Argument | Type | Description |
|
|
190
|
-
| --- | --- | --- |
|
|
191
|
-
| `userId` | `string` | The ID of the user to update |
|
|
192
|
-
| `newPassword` | `string` | The new plain text password |
|
|
193
|
-
|
|
194
|
-
> [!TIP]
|
|
195
|
-
> **Hash-Linked Revocation**: When you call `changePassword`, all existing refresh tokens for that user are immediately invalidated because they contain a fragment of the old password hash.
|
|
196
|
-
|
|
197
|
-
---
|
|
198
|
-
|
|
199
|
-
## 🚦 Error Handling
|
|
200
|
-
|
|
201
|
-
Kroxt throws descriptive errors that you can catch in your controller.
|
|
202
|
-
|
|
203
|
-
```typescript
|
|
204
|
-
try {
|
|
205
|
-
await auth.loginWithPassword(email, password, req.ip);
|
|
206
|
-
} catch (err) {
|
|
207
|
-
if (err.message === "IP is temporarily blocked.") {
|
|
208
|
-
return res.status(403).send("Banned.");
|
|
209
|
-
}
|
|
210
|
-
if (err.message === "Too many requests, please try again later.") {
|
|
211
|
-
return res.status(429).send("Slow down.");
|
|
212
|
-
}
|
|
213
|
-
return res.status(401).send("Invalid Credentials");
|
|
214
|
-
}
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
---
|
|
218
|
-
|
|
219
|
-
## 🔒 Security Best Practices
|
|
220
|
-
|
|
221
|
-
1. **Environmental Pepper**: Always use `JWT_PEPPER`. This adds a server-side secret to every password hash. If your database is stolen, your user passwords are still protected by this environment variable.
|
|
222
|
-
2. **Strict Revocation**: Set `enforceStrictRevocation: true` for high-security areas (like admin panels). This forces a database lookup on every single request to ensure the user hasn't been banned or changed their password in the last few seconds.
|
|
223
|
-
3. **Dual Tokens**: Always use the provided `accessToken` for short-term API access and the `refreshToken` (stored in an `HttpOnly` cookie) for session persistence.
|
|
224
|
-
|
|
225
|
-
---
|
|
226
|
-
|
|
227
|
-
## 🔗 Ecosystem
|
|
228
|
-
- [Kroxt Examples Repository](https://github.com/adepoju-oluwatobi/kroxt-examples)
|
|
229
|
-
|
|
230
|
-
## 📄 License
|
|
231
|
-
MIT © [Adepoju Oluwatobi](https://github.com/adepoju-oluwatobi)
|
|
1
|
+
# Kroxt
|
|
2
|
+
|
|
3
|
+
**The Most Simplified auth library**
|
|
4
|
+
|
|
5
|
+
Kroxt is a premium, framework-agnostic, and security-hardened authentication library for modern TypeScript environments. Designed for 100% schema control and "Zero-Config" onboarding.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/kroxt)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## ⚡ 30-Second Onboarding
|
|
13
|
+
|
|
14
|
+
The recommended way to start is the **Kroxt CLI**. It detects your framework (Next.js, Express, Fastify) and scaffolds a professional auth structure automatically.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npx kroxt init
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 🏗️ Core Architecture
|
|
23
|
+
|
|
24
|
+
Kroxt is "Headless." It provides the **Brain** (Logic, Hashing, JWTs, Security) while you provide the **Face** (UI/Routes).
|
|
25
|
+
|
|
26
|
+
### 1. The Configuration Matrix
|
|
27
|
+
Every feature in Kroxt is modular. Toggle security layers with a single boolean.
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { createAuth } from "kroxt";
|
|
31
|
+
import { createMongoAdapter } from "kroxt/adapters/mongoose";
|
|
32
|
+
|
|
33
|
+
export const auth = createAuth({
|
|
34
|
+
adapter: createMongoAdapter(UserModel),
|
|
35
|
+
secret: process.env.JWT_SECRET,
|
|
36
|
+
|
|
37
|
+
// Security Layer 1: Sessions
|
|
38
|
+
session: {
|
|
39
|
+
expires: "15m", // Access Token duration
|
|
40
|
+
refreshExpires: "7d", // Refresh Token duration
|
|
41
|
+
enforceStrictRevocation: true, // DB-lookup on EVERY request (Admin-mode)
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
// Security Layer 2: Defense
|
|
45
|
+
rateLimit: {
|
|
46
|
+
max: 100, // Requests per window
|
|
47
|
+
windowMs: 60 * 1000 // 1 Minute window
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
// Security Layer 3: Brute Force
|
|
51
|
+
ipBlocking: {
|
|
52
|
+
maxStrikes: 5, // Ban after 5 failures
|
|
53
|
+
blockDurationMs: 15 * 60 * 1000 // 15 Min ban
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
// Security Layer 4: Crypto
|
|
57
|
+
passwordPolicy: {
|
|
58
|
+
minLength: 8,
|
|
59
|
+
requireUppercase: true,
|
|
60
|
+
requireSpecialCharacter: true,
|
|
61
|
+
usePepper: true // Requires JWT_PEPPER env variable
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 🔌 Universal Adapters
|
|
69
|
+
|
|
70
|
+
Bring your own schema. Kroxt adapts to you.
|
|
71
|
+
|
|
72
|
+
### Mongoose (MongoDB)
|
|
73
|
+
```typescript
|
|
74
|
+
import { createMongoAdapter } from "kroxt/adapters/mongoose";
|
|
75
|
+
const adapter = createMongoAdapter(User);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Prisma (SQL)
|
|
79
|
+
```typescript
|
|
80
|
+
import { createPrismaAdapter } from "kroxt/adapters/prisma";
|
|
81
|
+
const adapter = createPrismaAdapter(prisma.user);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Drizzle (SQL)
|
|
85
|
+
```typescript
|
|
86
|
+
import { createDrizzleAdapter } from "kroxt/adapters/drizzle";
|
|
87
|
+
import { eq } from "drizzle-orm";
|
|
88
|
+
const adapter = createDrizzleAdapter(db, users, eq);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Memory (Testing)
|
|
92
|
+
```typescript
|
|
93
|
+
import { createMemoryAdapter } from "kroxt";
|
|
94
|
+
const adapter = createMemoryAdapter();
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 🧠 API Reference
|
|
100
|
+
|
|
101
|
+
### `auth.signup(userData, password)`
|
|
102
|
+
Registers a new user. User data is strictly typed to your schema.
|
|
103
|
+
```typescript
|
|
104
|
+
const { user, accessToken, refreshToken } = await auth.signup({
|
|
105
|
+
email: "dev@kroxt.io",
|
|
106
|
+
role: "admin"
|
|
107
|
+
}, "secure_password");
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### `auth.loginWithPassword(email, password, clientIp?)`
|
|
111
|
+
Authenticates a user and generates tokens. Pass `clientIp` to enable IP-Blocking.
|
|
112
|
+
```typescript
|
|
113
|
+
const result = await auth.loginWithPassword(email, password, req.ip);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### `auth.refreshSession(refreshToken, clientIp?)`
|
|
117
|
+
Rotates the session. If `enforceStrictRevocation` is on, it validates the token against the user's current password hash.
|
|
118
|
+
```typescript
|
|
119
|
+
const { user, accessToken, refreshToken: newRefresh } = await auth.refreshSession(token);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### `auth.logout(refreshToken)`
|
|
123
|
+
Invalidates a session.
|
|
124
|
+
```typescript
|
|
125
|
+
await auth.logout(refreshToken);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### `auth.changePassword(userId, newPassword)`
|
|
129
|
+
Updates password and **instantly invalidates all other active sessions** globally via Hash-Linked revocation.
|
|
130
|
+
```typescript
|
|
131
|
+
await auth.changePassword(user.id, "new_secure_pass");
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 🧩 Middleware Implementation
|
|
137
|
+
|
|
138
|
+
### Express / Fastify
|
|
139
|
+
```typescript
|
|
140
|
+
const protect = async (req, res, next) => {
|
|
141
|
+
const token = req.headers.authorization?.split(" ")[1];
|
|
142
|
+
try {
|
|
143
|
+
const session = await auth.verifyAccessToken(token);
|
|
144
|
+
req.user = session.user;
|
|
145
|
+
next();
|
|
146
|
+
} catch (err) {
|
|
147
|
+
res.status(401).json({ error: "Unauthorized" });
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 🚀 Advanced Deployment
|
|
155
|
+
|
|
156
|
+
### Custom JWT Payloads
|
|
157
|
+
Inject metadata into your tokens safely.
|
|
158
|
+
```typescript
|
|
159
|
+
jwt: {
|
|
160
|
+
payload: (user, type) => {
|
|
161
|
+
return type === "access" ? { role: user.role } : {};
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Password Peppering
|
|
167
|
+
Kroxt supports server-side peppering to protect against rainbow table attacks even if your database is leaked.
|
|
168
|
+
1. Set `usePepper: true` in config.
|
|
169
|
+
2. Add `JWT_PEPPER` to your `.env`.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## 🧠 API Reference (Exhaustive)
|
|
174
|
+
|
|
175
|
+
### `auth.signup()`
|
|
176
|
+
| Argument | Type | Description |
|
|
177
|
+
| --- | --- | --- |
|
|
178
|
+
| `userData` | `Omit<User, "id">` | Your user object without the ID (ID is auto-generated) |
|
|
179
|
+
| `password` | `string` (Optional) | Plain text password. Will be hashed using Argon2 |
|
|
180
|
+
|
|
181
|
+
### `auth.loginWithPassword()`
|
|
182
|
+
| Argument | Type | Description |
|
|
183
|
+
| --- | --- | --- |
|
|
184
|
+
| `email` | `string` | User email |
|
|
185
|
+
| `password` | `string` | User password |
|
|
186
|
+
| `clientIp` | `string` (Optional) | Required for IP-Blocking defense |
|
|
187
|
+
|
|
188
|
+
### `auth.changePassword()`
|
|
189
|
+
| Argument | Type | Description |
|
|
190
|
+
| --- | --- | --- |
|
|
191
|
+
| `userId` | `string` | The ID of the user to update |
|
|
192
|
+
| `newPassword` | `string` | The new plain text password |
|
|
193
|
+
|
|
194
|
+
> [!TIP]
|
|
195
|
+
> **Hash-Linked Revocation**: When you call `changePassword`, all existing refresh tokens for that user are immediately invalidated because they contain a fragment of the old password hash.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## 🚦 Error Handling
|
|
200
|
+
|
|
201
|
+
Kroxt throws descriptive errors that you can catch in your controller.
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
try {
|
|
205
|
+
await auth.loginWithPassword(email, password, req.ip);
|
|
206
|
+
} catch (err) {
|
|
207
|
+
if (err.message === "IP is temporarily blocked.") {
|
|
208
|
+
return res.status(403).send("Banned.");
|
|
209
|
+
}
|
|
210
|
+
if (err.message === "Too many requests, please try again later.") {
|
|
211
|
+
return res.status(429).send("Slow down.");
|
|
212
|
+
}
|
|
213
|
+
return res.status(401).send("Invalid Credentials");
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## 🔒 Security Best Practices
|
|
220
|
+
|
|
221
|
+
1. **Environmental Pepper**: Always use `JWT_PEPPER`. This adds a server-side secret to every password hash. If your database is stolen, your user passwords are still protected by this environment variable.
|
|
222
|
+
2. **Strict Revocation**: Set `enforceStrictRevocation: true` for high-security areas (like admin panels). This forces a database lookup on every single request to ensure the user hasn't been banned or changed their password in the last few seconds.
|
|
223
|
+
3. **Dual Tokens**: Always use the provided `accessToken` for short-term API access and the `refreshToken` (stored in an `HttpOnly` cookie) for session persistence.
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## 🔗 Ecosystem
|
|
228
|
+
- [Kroxt Examples Repository](https://github.com/adepoju-oluwatobi/kroxt-examples)
|
|
229
|
+
|
|
230
|
+
## 📄 License
|