kroxt 1.2.1 → 1.3.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 +29 -96
- package/dist/adapters/drizzle.d.ts +2 -1
- package/dist/adapters/drizzle.d.ts.map +1 -1
- package/dist/adapters/index.d.ts +9 -0
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/memory.d.ts.map +1 -1
- package/dist/adapters/mongoose.d.ts +7 -1
- package/dist/adapters/mongoose.d.ts.map +1 -1
- package/dist/adapters/prisma.d.ts +2 -1
- package/dist/adapters/prisma.d.ts.map +1 -1
- package/dist/{adapters → auth/adapters}/drizzle.cjs +33 -2
- package/dist/auth/adapters/drizzle.cjs.map +7 -0
- package/dist/auth/adapters/drizzle.js +58 -0
- package/dist/auth/adapters/drizzle.js.map +7 -0
- package/dist/auth/adapters/index.cjs.map +7 -0
- package/dist/{adapters → auth/adapters}/memory.cjs +28 -0
- package/dist/auth/adapters/memory.cjs.map +7 -0
- package/dist/auth/adapters/memory.js +59 -0
- package/dist/auth/adapters/memory.js.map +7 -0
- package/dist/auth/adapters/mongoose.cjs +99 -0
- package/dist/auth/adapters/mongoose.cjs.map +7 -0
- package/dist/auth/adapters/mongoose.js +74 -0
- package/dist/auth/adapters/mongoose.js.map +7 -0
- package/dist/{adapters → auth/adapters}/prisma.cjs +36 -2
- package/dist/auth/adapters/prisma.cjs.map +7 -0
- package/dist/auth/adapters/prisma.js +68 -0
- package/dist/auth/adapters/prisma.js.map +7 -0
- package/dist/{core → auth/core}/index.cjs +67 -2
- package/dist/auth/core/index.cjs.map +7 -0
- package/dist/auth/core/index.js +143 -0
- package/dist/auth/core/index.js.map +7 -0
- package/dist/{index.cjs → auth/index.cjs} +12 -4
- package/dist/auth/index.cjs.map +7 -0
- package/dist/{index.js → auth/index.js} +6 -1
- package/dist/auth/index.js.map +7 -0
- package/dist/auth/providers/index.cjs.map +7 -0
- package/dist/auth/providers/index.js.map +7 -0
- package/dist/{security → auth/security}/index.cjs +10 -9
- package/dist/auth/security/index.cjs.map +7 -0
- package/dist/auth/security/index.js +19 -0
- package/dist/auth/security/index.js.map +7 -0
- package/dist/auth/security/rate-limit.cjs +82 -0
- package/dist/auth/security/rate-limit.cjs.map +7 -0
- package/dist/auth/security/rate-limit.js +57 -0
- package/dist/auth/security/rate-limit.js.map +7 -0
- package/dist/cli/index.cjs +134 -0
- package/dist/cli/index.cjs.map +7 -0
- package/dist/cli/index.js +111 -0
- package/dist/cli/index.js.map +7 -0
- package/dist/cli/templates.cjs +147 -0
- package/dist/cli/templates.cjs.map +7 -0
- package/dist/cli/templates.js +111 -0
- package/dist/cli/templates.js.map +7 -0
- package/dist/core/index.d.ts +16 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/security/index.d.ts +1 -0
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/rate-limit.d.ts +39 -0
- package/dist/security/rate-limit.d.ts.map +1 -0
- package/package.json +8 -2
- package/dist/adapters/drizzle.cjs.map +0 -7
- package/dist/adapters/drizzle.js +0 -27
- package/dist/adapters/drizzle.js.map +0 -7
- package/dist/adapters/index.cjs.map +0 -7
- package/dist/adapters/memory.cjs.map +0 -7
- package/dist/adapters/memory.js +0 -31
- package/dist/adapters/memory.js.map +0 -7
- package/dist/adapters/mongoose.cjs +0 -55
- package/dist/adapters/mongoose.cjs.map +0 -7
- package/dist/adapters/mongoose.js +0 -31
- package/dist/adapters/mongoose.js.map +0 -7
- package/dist/adapters/prisma.cjs.map +0 -7
- package/dist/adapters/prisma.js +0 -34
- package/dist/adapters/prisma.js.map +0 -7
- package/dist/core/index.cjs.map +0 -7
- package/dist/core/index.js +0 -78
- package/dist/core/index.js.map +0 -7
- package/dist/index.cjs.map +0 -7
- package/dist/index.js.map +0 -7
- package/dist/providers/index.cjs.map +0 -7
- package/dist/providers/index.js.map +0 -7
- package/dist/security/index.cjs.map +0 -7
- package/dist/security/index.js +0 -20
- package/dist/security/index.js.map +0 -7
- /package/dist/{adapters → auth/adapters}/index.cjs +0 -0
- /package/dist/{adapters → auth/adapters}/index.js +0 -0
- /package/dist/{adapters → auth/adapters}/index.js.map +0 -0
- /package/dist/{providers → auth/providers}/index.cjs +0 -0
- /package/dist/{providers → auth/providers}/index.js +0 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var mongoose_exports = {};
|
|
20
|
+
__export(mongoose_exports, {
|
|
21
|
+
createMongoAdapter: () => createMongoAdapter,
|
|
22
|
+
createRateLimitModel: () => createRateLimitModel
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(mongoose_exports);
|
|
25
|
+
function createRateLimitModel(mongoose) {
|
|
26
|
+
const schema = new mongoose.Schema({
|
|
27
|
+
key: { type: String, required: true, unique: true },
|
|
28
|
+
count: { type: Number, required: true, default: 1 },
|
|
29
|
+
resetTime: { type: Number, required: true },
|
|
30
|
+
expiresAt: { type: Date, required: true, expires: 0 }
|
|
31
|
+
});
|
|
32
|
+
return mongoose.models.KroxtRateLimit || mongoose.model("KroxtRateLimit", schema);
|
|
33
|
+
}
|
|
34
|
+
function createMongoAdapter(model, rateLimitModel) {
|
|
35
|
+
const adapter = {
|
|
36
|
+
async createUser(data) {
|
|
37
|
+
const user = await model.create(data);
|
|
38
|
+
const obj = user.toObject();
|
|
39
|
+
return { ...obj, id: obj._id.toString() };
|
|
40
|
+
},
|
|
41
|
+
async findUserByEmail(email) {
|
|
42
|
+
const user = await model.findOne({ email });
|
|
43
|
+
if (!user) return null;
|
|
44
|
+
const obj = user.toObject();
|
|
45
|
+
return { ...obj, id: obj._id.toString() };
|
|
46
|
+
},
|
|
47
|
+
async findUserById(id) {
|
|
48
|
+
const user = await model.findById(id);
|
|
49
|
+
if (!user) return null;
|
|
50
|
+
const obj = user.toObject();
|
|
51
|
+
return { ...obj, id: obj._id.toString() };
|
|
52
|
+
},
|
|
53
|
+
async updateUser(id, data) {
|
|
54
|
+
const user = await model.findByIdAndUpdate(id, data, { new: true });
|
|
55
|
+
if (!user) return null;
|
|
56
|
+
const obj = user.toObject();
|
|
57
|
+
return { ...obj, id: obj._id.toString() };
|
|
58
|
+
},
|
|
59
|
+
async linkOAuthAccount(userId, provider, providerId) {
|
|
60
|
+
await model.findByIdAndUpdate(userId, {
|
|
61
|
+
oauthProvider: provider,
|
|
62
|
+
oauthId: providerId
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
if (rateLimitModel) {
|
|
67
|
+
adapter.incrementRateLimit = async (key, windowMs) => {
|
|
68
|
+
const now = Date.now();
|
|
69
|
+
let record = await rateLimitModel.findOne({ key });
|
|
70
|
+
if (!record || now > record.resetTime) {
|
|
71
|
+
record = await rateLimitModel.findOneAndUpdate(
|
|
72
|
+
{ key },
|
|
73
|
+
{ count: 1, resetTime: now + windowMs, expiresAt: new Date(now + windowMs) },
|
|
74
|
+
{ upsert: true, new: true, setDefaultsOnInsert: true }
|
|
75
|
+
);
|
|
76
|
+
} else {
|
|
77
|
+
record = await rateLimitModel.findOneAndUpdate(
|
|
78
|
+
{ key },
|
|
79
|
+
{ $inc: { count: 1 } },
|
|
80
|
+
{ new: true }
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return { count: record.count, resetTime: record.resetTime };
|
|
84
|
+
};
|
|
85
|
+
adapter.getRateLimit = async (key) => {
|
|
86
|
+
const now = Date.now();
|
|
87
|
+
const record = await rateLimitModel.findOne({ key });
|
|
88
|
+
if (!record || now > record.resetTime) return null;
|
|
89
|
+
return { count: record.count, resetTime: record.resetTime };
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return adapter;
|
|
93
|
+
}
|
|
94
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
95
|
+
0 && (module.exports = {
|
|
96
|
+
createMongoAdapter,
|
|
97
|
+
createRateLimitModel
|
|
98
|
+
});
|
|
99
|
+
//# sourceMappingURL=mongoose.cjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/auth/adapters/mongoose.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AuthAdapter, User } from \"./index.js\";\r\n\r\n/**\r\n * Creates a pre-configured Mongoose model for rate limiting.\r\n * @param mongoose The mongoose instance to use for schema creation.\r\n */\r\nexport function createRateLimitModel(mongoose: any) {\r\n const schema = new mongoose.Schema({\r\n key: { type: String, required: true, unique: true },\r\n count: { type: Number, required: true, default: 1 },\r\n resetTime: { type: Number, required: true },\r\n expiresAt: { type: Date, required: true, expires: 0 }\r\n });\r\n return mongoose.models.KroxtRateLimit || mongoose.model('KroxtRateLimit', schema);\r\n}\r\n\r\n/**\r\n * Creates a MongoDB adapter using a Mongoose model.\r\n * \r\n * @param model - A Mongoose model instance (e.g., User model).\r\n * @param rateLimitModel - An optional Mongoose model for rate limiting tracking.\r\n * @returns An AuthAdapter compliant object.\r\n */\r\nexport function createMongoAdapter<TUser extends User = User>(model: any, rateLimitModel?: any): AuthAdapter<TUser> {\r\n const adapter: AuthAdapter<TUser> = {\r\n async createUser(data: any) {\r\n const user = await model.create(data);\r\n const obj = user.toObject();\r\n return { ...obj, id: obj._id.toString() } as TUser;\r\n },\r\n\r\n async findUserByEmail(email: string) {\r\n const user = await model.findOne({ email });\r\n if (!user) return null;\r\n const obj = user.toObject();\r\n return { ...obj, id: obj._id.toString() } as TUser;\r\n },\r\n\r\n async findUserById(id: string) {\r\n const user = await model.findById(id);\r\n if (!user) return null;\r\n const obj = user.toObject();\r\n return { ...obj, id: obj._id.toString() } as TUser;\r\n },\r\n\r\n async updateUser(id: string, data: Partial<TUser>) {\r\n const user = await model.findByIdAndUpdate(id, data, { new: true });\r\n if (!user) return null;\r\n const obj = user.toObject();\r\n return { ...obj, id: obj._id.toString() } as TUser;\r\n },\r\n\r\n async linkOAuthAccount(userId: string, provider: string, providerId: string) {\r\n await model.findByIdAndUpdate(userId, {\r\n oauthProvider: provider,\r\n oauthId: providerId,\r\n });\r\n },\r\n };\r\n\r\n if (rateLimitModel) {\r\n adapter.incrementRateLimit = async (key: string, windowMs: number) => {\r\n const now = Date.now();\r\n let record = await rateLimitModel.findOne({ key });\r\n \r\n if (!record || now > record.resetTime) {\r\n record = await rateLimitModel.findOneAndUpdate(\r\n { key },\r\n { count: 1, resetTime: now + windowMs, expiresAt: new Date(now + windowMs) },\r\n { upsert: true, new: true, setDefaultsOnInsert: true }\r\n );\r\n } else {\r\n record = await rateLimitModel.findOneAndUpdate(\r\n { key },\r\n { $inc: { count: 1 } },\r\n { new: true }\r\n );\r\n }\r\n\r\n return { count: record.count, resetTime: record.resetTime };\r\n };\r\n\r\n adapter.getRateLimit = async (key: string) => {\r\n const now = Date.now();\r\n const record = await rateLimitModel.findOne({ key });\r\n if (!record || now > record.resetTime) return null;\r\n return { count: record.count, resetTime: record.resetTime };\r\n };\r\n }\r\n\r\n return adapter;\r\n}\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
function createRateLimitModel(mongoose) {
|
|
2
|
+
const schema = new mongoose.Schema({
|
|
3
|
+
key: { type: String, required: true, unique: true },
|
|
4
|
+
count: { type: Number, required: true, default: 1 },
|
|
5
|
+
resetTime: { type: Number, required: true },
|
|
6
|
+
expiresAt: { type: Date, required: true, expires: 0 }
|
|
7
|
+
});
|
|
8
|
+
return mongoose.models.KroxtRateLimit || mongoose.model("KroxtRateLimit", schema);
|
|
9
|
+
}
|
|
10
|
+
function createMongoAdapter(model, rateLimitModel) {
|
|
11
|
+
const adapter = {
|
|
12
|
+
async createUser(data) {
|
|
13
|
+
const user = await model.create(data);
|
|
14
|
+
const obj = user.toObject();
|
|
15
|
+
return { ...obj, id: obj._id.toString() };
|
|
16
|
+
},
|
|
17
|
+
async findUserByEmail(email) {
|
|
18
|
+
const user = await model.findOne({ email });
|
|
19
|
+
if (!user) return null;
|
|
20
|
+
const obj = user.toObject();
|
|
21
|
+
return { ...obj, id: obj._id.toString() };
|
|
22
|
+
},
|
|
23
|
+
async findUserById(id) {
|
|
24
|
+
const user = await model.findById(id);
|
|
25
|
+
if (!user) return null;
|
|
26
|
+
const obj = user.toObject();
|
|
27
|
+
return { ...obj, id: obj._id.toString() };
|
|
28
|
+
},
|
|
29
|
+
async updateUser(id, data) {
|
|
30
|
+
const user = await model.findByIdAndUpdate(id, data, { new: true });
|
|
31
|
+
if (!user) return null;
|
|
32
|
+
const obj = user.toObject();
|
|
33
|
+
return { ...obj, id: obj._id.toString() };
|
|
34
|
+
},
|
|
35
|
+
async linkOAuthAccount(userId, provider, providerId) {
|
|
36
|
+
await model.findByIdAndUpdate(userId, {
|
|
37
|
+
oauthProvider: provider,
|
|
38
|
+
oauthId: providerId
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
if (rateLimitModel) {
|
|
43
|
+
adapter.incrementRateLimit = async (key, windowMs) => {
|
|
44
|
+
const now = Date.now();
|
|
45
|
+
let record = await rateLimitModel.findOne({ key });
|
|
46
|
+
if (!record || now > record.resetTime) {
|
|
47
|
+
record = await rateLimitModel.findOneAndUpdate(
|
|
48
|
+
{ key },
|
|
49
|
+
{ count: 1, resetTime: now + windowMs, expiresAt: new Date(now + windowMs) },
|
|
50
|
+
{ upsert: true, new: true, setDefaultsOnInsert: true }
|
|
51
|
+
);
|
|
52
|
+
} else {
|
|
53
|
+
record = await rateLimitModel.findOneAndUpdate(
|
|
54
|
+
{ key },
|
|
55
|
+
{ $inc: { count: 1 } },
|
|
56
|
+
{ new: true }
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return { count: record.count, resetTime: record.resetTime };
|
|
60
|
+
};
|
|
61
|
+
adapter.getRateLimit = async (key) => {
|
|
62
|
+
const now = Date.now();
|
|
63
|
+
const record = await rateLimitModel.findOne({ key });
|
|
64
|
+
if (!record || now > record.resetTime) return null;
|
|
65
|
+
return { count: record.count, resetTime: record.resetTime };
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return adapter;
|
|
69
|
+
}
|
|
70
|
+
export {
|
|
71
|
+
createMongoAdapter,
|
|
72
|
+
createRateLimitModel
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=mongoose.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/auth/adapters/mongoose.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AuthAdapter, User } from \"./index.js\";\r\n\r\n/**\r\n * Creates a pre-configured Mongoose model for rate limiting.\r\n * @param mongoose The mongoose instance to use for schema creation.\r\n */\r\nexport function createRateLimitModel(mongoose: any) {\r\n const schema = new mongoose.Schema({\r\n key: { type: String, required: true, unique: true },\r\n count: { type: Number, required: true, default: 1 },\r\n resetTime: { type: Number, required: true },\r\n expiresAt: { type: Date, required: true, expires: 0 }\r\n });\r\n return mongoose.models.KroxtRateLimit || mongoose.model('KroxtRateLimit', schema);\r\n}\r\n\r\n/**\r\n * Creates a MongoDB adapter using a Mongoose model.\r\n * \r\n * @param model - A Mongoose model instance (e.g., User model).\r\n * @param rateLimitModel - An optional Mongoose model for rate limiting tracking.\r\n * @returns An AuthAdapter compliant object.\r\n */\r\nexport function createMongoAdapter<TUser extends User = User>(model: any, rateLimitModel?: any): AuthAdapter<TUser> {\r\n const adapter: AuthAdapter<TUser> = {\r\n async createUser(data: any) {\r\n const user = await model.create(data);\r\n const obj = user.toObject();\r\n return { ...obj, id: obj._id.toString() } as TUser;\r\n },\r\n\r\n async findUserByEmail(email: string) {\r\n const user = await model.findOne({ email });\r\n if (!user) return null;\r\n const obj = user.toObject();\r\n return { ...obj, id: obj._id.toString() } as TUser;\r\n },\r\n\r\n async findUserById(id: string) {\r\n const user = await model.findById(id);\r\n if (!user) return null;\r\n const obj = user.toObject();\r\n return { ...obj, id: obj._id.toString() } as TUser;\r\n },\r\n\r\n async updateUser(id: string, data: Partial<TUser>) {\r\n const user = await model.findByIdAndUpdate(id, data, { new: true });\r\n if (!user) return null;\r\n const obj = user.toObject();\r\n return { ...obj, id: obj._id.toString() } as TUser;\r\n },\r\n\r\n async linkOAuthAccount(userId: string, provider: string, providerId: string) {\r\n await model.findByIdAndUpdate(userId, {\r\n oauthProvider: provider,\r\n oauthId: providerId,\r\n });\r\n },\r\n };\r\n\r\n if (rateLimitModel) {\r\n adapter.incrementRateLimit = async (key: string, windowMs: number) => {\r\n const now = Date.now();\r\n let record = await rateLimitModel.findOne({ key });\r\n \r\n if (!record || now > record.resetTime) {\r\n record = await rateLimitModel.findOneAndUpdate(\r\n { key },\r\n { count: 1, resetTime: now + windowMs, expiresAt: new Date(now + windowMs) },\r\n { upsert: true, new: true, setDefaultsOnInsert: true }\r\n );\r\n } else {\r\n record = await rateLimitModel.findOneAndUpdate(\r\n { key },\r\n { $inc: { count: 1 } },\r\n { new: true }\r\n );\r\n }\r\n\r\n return { count: record.count, resetTime: record.resetTime };\r\n };\r\n\r\n adapter.getRateLimit = async (key: string) => {\r\n const now = Date.now();\r\n const record = await rateLimitModel.findOne({ key });\r\n if (!record || now > record.resetTime) return null;\r\n return { count: record.count, resetTime: record.resetTime };\r\n };\r\n }\r\n\r\n return adapter;\r\n}\r\n"],
|
|
5
|
+
"mappings": "AAMO,SAAS,qBAAqB,UAAe;AAClD,QAAM,SAAS,IAAI,SAAS,OAAO;AAAA,IACjC,KAAK,EAAE,MAAM,QAAQ,UAAU,MAAM,QAAQ,KAAK;AAAA,IAClD,OAAO,EAAE,MAAM,QAAQ,UAAU,MAAM,SAAS,EAAE;AAAA,IAClD,WAAW,EAAE,MAAM,QAAQ,UAAU,KAAK;AAAA,IAC1C,WAAW,EAAE,MAAM,MAAM,UAAU,MAAM,SAAS,EAAE;AAAA,EACtD,CAAC;AACD,SAAO,SAAS,OAAO,kBAAkB,SAAS,MAAM,kBAAkB,MAAM;AAClF;AASO,SAAS,mBAA8C,OAAY,gBAA0C;AAClH,QAAM,UAA8B;AAAA,IAClC,MAAM,WAAW,MAAW;AAC1B,YAAM,OAAO,MAAM,MAAM,OAAO,IAAI;AACpC,YAAM,MAAM,KAAK,SAAS;AAC1B,aAAO,EAAE,GAAG,KAAK,IAAI,IAAI,IAAI,SAAS,EAAE;AAAA,IAC1C;AAAA,IAEA,MAAM,gBAAgB,OAAe;AACnC,YAAM,OAAO,MAAM,MAAM,QAAQ,EAAE,MAAM,CAAC;AAC1C,UAAI,CAAC,KAAM,QAAO;AAClB,YAAM,MAAM,KAAK,SAAS;AAC1B,aAAO,EAAE,GAAG,KAAK,IAAI,IAAI,IAAI,SAAS,EAAE;AAAA,IAC1C;AAAA,IAEA,MAAM,aAAa,IAAY;AAC7B,YAAM,OAAO,MAAM,MAAM,SAAS,EAAE;AACpC,UAAI,CAAC,KAAM,QAAO;AAClB,YAAM,MAAM,KAAK,SAAS;AAC1B,aAAO,EAAE,GAAG,KAAK,IAAI,IAAI,IAAI,SAAS,EAAE;AAAA,IAC1C;AAAA,IAEA,MAAM,WAAW,IAAY,MAAsB;AACjD,YAAM,OAAO,MAAM,MAAM,kBAAkB,IAAI,MAAM,EAAE,KAAK,KAAK,CAAC;AAClE,UAAI,CAAC,KAAM,QAAO;AAClB,YAAM,MAAM,KAAK,SAAS;AAC1B,aAAO,EAAE,GAAG,KAAK,IAAI,IAAI,IAAI,SAAS,EAAE;AAAA,IAC1C;AAAA,IAEA,MAAM,iBAAiB,QAAgB,UAAkB,YAAoB;AAC3E,YAAM,MAAM,kBAAkB,QAAQ;AAAA,QACpC,eAAe;AAAA,QACf,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,gBAAgB;AAClB,YAAQ,qBAAqB,OAAO,KAAa,aAAqB;AACpE,YAAM,MAAM,KAAK,IAAI;AACrB,UAAI,SAAS,MAAM,eAAe,QAAQ,EAAE,IAAI,CAAC;AAEjD,UAAI,CAAC,UAAU,MAAM,OAAO,WAAW;AACrC,iBAAS,MAAM,eAAe;AAAA,UAC5B,EAAE,IAAI;AAAA,UACN,EAAE,OAAO,GAAG,WAAW,MAAM,UAAU,WAAW,IAAI,KAAK,MAAM,QAAQ,EAAE;AAAA,UAC3E,EAAE,QAAQ,MAAM,KAAK,MAAM,qBAAqB,KAAK;AAAA,QACvD;AAAA,MACF,OAAO;AACL,iBAAS,MAAM,eAAe;AAAA,UAC5B,EAAE,IAAI;AAAA,UACN,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE;AAAA,UACrB,EAAE,KAAK,KAAK;AAAA,QACd;AAAA,MACF;AAEA,aAAO,EAAE,OAAO,OAAO,OAAO,WAAW,OAAO,UAAU;AAAA,IAC5D;AAEA,YAAQ,eAAe,OAAO,QAAgB;AAC5C,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,SAAS,MAAM,eAAe,QAAQ,EAAE,IAAI,CAAC;AACnD,UAAI,CAAC,UAAU,MAAM,OAAO,UAAW,QAAO;AAC9C,aAAO,EAAE,OAAO,OAAO,OAAO,WAAW,OAAO,UAAU;AAAA,IAC5D;AAAA,EACF;AAEA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -21,8 +21,8 @@ __export(prisma_exports, {
|
|
|
21
21
|
createPrismaAdapter: () => createPrismaAdapter
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(prisma_exports);
|
|
24
|
-
function createPrismaAdapter(model) {
|
|
25
|
-
|
|
24
|
+
function createPrismaAdapter(model, rateLimitModel) {
|
|
25
|
+
const adapter = {
|
|
26
26
|
async createUser(data) {
|
|
27
27
|
const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };
|
|
28
28
|
const user = await model.create({ data: dataToSave });
|
|
@@ -40,6 +40,13 @@ function createPrismaAdapter(model) {
|
|
|
40
40
|
});
|
|
41
41
|
return user;
|
|
42
42
|
},
|
|
43
|
+
async updateUser(id, data) {
|
|
44
|
+
const user = await model.update({
|
|
45
|
+
where: { id },
|
|
46
|
+
data
|
|
47
|
+
});
|
|
48
|
+
return user;
|
|
49
|
+
},
|
|
43
50
|
async linkOAuthAccount(userId, provider, providerId) {
|
|
44
51
|
await model.update({
|
|
45
52
|
where: { id: userId },
|
|
@@ -50,6 +57,33 @@ function createPrismaAdapter(model) {
|
|
|
50
57
|
});
|
|
51
58
|
}
|
|
52
59
|
};
|
|
60
|
+
if (rateLimitModel) {
|
|
61
|
+
adapter.incrementRateLimit = async (key, windowMs) => {
|
|
62
|
+
const now = Date.now();
|
|
63
|
+
const record = await rateLimitModel.findUnique({ where: { key } });
|
|
64
|
+
if (!record || now > record.resetTime) {
|
|
65
|
+
const newRecord = await rateLimitModel.upsert({
|
|
66
|
+
where: { key },
|
|
67
|
+
update: { count: 1, resetTime: now + windowMs },
|
|
68
|
+
create: { key, count: 1, resetTime: now + windowMs }
|
|
69
|
+
});
|
|
70
|
+
return { count: newRecord.count, resetTime: newRecord.resetTime };
|
|
71
|
+
} else {
|
|
72
|
+
const updated = await rateLimitModel.update({
|
|
73
|
+
where: { key },
|
|
74
|
+
data: { count: { increment: 1 } }
|
|
75
|
+
});
|
|
76
|
+
return { count: updated.count, resetTime: updated.resetTime };
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
adapter.getRateLimit = async (key) => {
|
|
80
|
+
const now = Date.now();
|
|
81
|
+
const record = await rateLimitModel.findUnique({ where: { key } });
|
|
82
|
+
if (!record || now > record.resetTime) return null;
|
|
83
|
+
return { count: record.count, resetTime: record.resetTime };
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return adapter;
|
|
53
87
|
}
|
|
54
88
|
// Annotate the CommonJS export names for ESM import in node:
|
|
55
89
|
0 && (module.exports = {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/auth/adapters/prisma.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AuthAdapter, User } from \"./index.js\";\r\n\r\n/**\r\n * Creates a Prisma adapter using a Prisma delegate (e.g., prisma.user).\r\n * \r\n * Works with any Prisma-supported database by using the standard\r\n * Prisma delegate operations (findUnique, create, update).\r\n * \r\n * @param model - A Prisma delegate instance (e.g., prisma.user).\r\n * @param rateLimitModel - An optional Prisma delegate for rate limit tracking.\r\n * @returns An AuthAdapter compliant object.\r\n */\r\nexport function createPrismaAdapter<TUser extends User = User>(model: any, rateLimitModel?: any): AuthAdapter<TUser> {\r\n const adapter: AuthAdapter<TUser> = {\r\n async createUser(data: any) {\r\n const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };\r\n const user = await model.create({ data: dataToSave });\r\n return user as TUser;\r\n },\r\n\r\n async findUserByEmail(email: string) {\r\n const user = await model.findUnique({\r\n where: { email },\r\n });\r\n return user as TUser | null;\r\n },\r\n\r\n async findUserById(id: string) {\r\n const user = await model.findUnique({\r\n where: { id },\r\n });\r\n return user as TUser | null;\r\n },\r\n\r\n async updateUser(id: string, data: Partial<TUser>) {\r\n const user = await model.update({\r\n where: { id },\r\n data,\r\n });\r\n return user as TUser | null;\r\n },\r\n\r\n async linkOAuthAccount(userId: string, provider: string, providerId: string) {\r\n await model.update({\r\n where: { id: userId },\r\n data: {\r\n oauthProvider: provider,\r\n oauthId: providerId,\r\n },\r\n });\r\n },\r\n };\r\n\r\n if (rateLimitModel) {\r\n adapter.incrementRateLimit = async (key: string, windowMs: number) => {\r\n const now = Date.now();\r\n const record = await rateLimitModel.findUnique({ where: { key } });\r\n \r\n if (!record || now > record.resetTime) {\r\n const newRecord = await rateLimitModel.upsert({\r\n where: { key },\r\n update: { count: 1, resetTime: now + windowMs },\r\n create: { key, count: 1, resetTime: now + windowMs }\r\n });\r\n return { count: newRecord.count, resetTime: newRecord.resetTime };\r\n } else {\r\n const updated = await rateLimitModel.update({\r\n where: { key },\r\n data: { count: { increment: 1 } }\r\n });\r\n return { count: updated.count, resetTime: updated.resetTime };\r\n }\r\n };\r\n\r\n adapter.getRateLimit = async (key: string) => {\r\n const now = Date.now();\r\n const record = await rateLimitModel.findUnique({ where: { key } });\r\n if (!record || now > record.resetTime) return null;\r\n return { count: record.count, resetTime: record.resetTime };\r\n };\r\n }\r\n\r\n return adapter;\r\n}\r\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAYO,SAAS,oBAA+C,OAAY,gBAA0C;AACnH,QAAM,UAA8B;AAAA,IAClC,MAAM,WAAW,MAAW;AAC1B,YAAM,aAAa,EAAE,IAAI,KAAK,MAAM,WAAW,OAAO,WAAW,GAAG,GAAG,KAAK;AAC5E,YAAM,OAAO,MAAM,MAAM,OAAO,EAAE,MAAM,WAAW,CAAC;AACpD,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,gBAAgB,OAAe;AACnC,YAAM,OAAO,MAAM,MAAM,WAAW;AAAA,QAClC,OAAO,EAAE,MAAM;AAAA,MACjB,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,aAAa,IAAY;AAC7B,YAAM,OAAO,MAAM,MAAM,WAAW;AAAA,QAClC,OAAO,EAAE,GAAG;AAAA,MACd,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,WAAW,IAAY,MAAsB;AACjD,YAAM,OAAO,MAAM,MAAM,OAAO;AAAA,QAC9B,OAAO,EAAE,GAAG;AAAA,QACZ;AAAA,MACF,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,iBAAiB,QAAgB,UAAkB,YAAoB;AAC3E,YAAM,MAAM,OAAO;AAAA,QACjB,OAAO,EAAE,IAAI,OAAO;AAAA,QACpB,MAAM;AAAA,UACJ,eAAe;AAAA,UACf,SAAS;AAAA,QACX;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,gBAAgB;AAClB,YAAQ,qBAAqB,OAAO,KAAa,aAAqB;AACpE,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,SAAS,MAAM,eAAe,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAEjE,UAAI,CAAC,UAAU,MAAM,OAAO,WAAW;AACnC,cAAM,YAAY,MAAM,eAAe,OAAO;AAAA,UAC1C,OAAO,EAAE,IAAI;AAAA,UACb,QAAQ,EAAE,OAAO,GAAG,WAAW,MAAM,SAAS;AAAA,UAC9C,QAAQ,EAAE,KAAK,OAAO,GAAG,WAAW,MAAM,SAAS;AAAA,QACvD,CAAC;AACD,eAAO,EAAE,OAAO,UAAU,OAAO,WAAW,UAAU,UAAU;AAAA,MACpE,OAAO;AACH,cAAM,UAAU,MAAM,eAAe,OAAO;AAAA,UACxC,OAAO,EAAE,IAAI;AAAA,UACb,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE;AAAA,QACpC,CAAC;AACD,eAAO,EAAE,OAAO,QAAQ,OAAO,WAAW,QAAQ,UAAU;AAAA,MAChE;AAAA,IACF;AAEA,YAAQ,eAAe,OAAO,QAAgB;AAC5C,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,SAAS,MAAM,eAAe,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACjE,UAAI,CAAC,UAAU,MAAM,OAAO,UAAW,QAAO;AAC9C,aAAO,EAAE,OAAO,OAAO,OAAO,WAAW,OAAO,UAAU;AAAA,IAC5D;AAAA,EACF;AAEA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
function createPrismaAdapter(model, rateLimitModel) {
|
|
2
|
+
const adapter = {
|
|
3
|
+
async createUser(data) {
|
|
4
|
+
const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };
|
|
5
|
+
const user = await model.create({ data: dataToSave });
|
|
6
|
+
return user;
|
|
7
|
+
},
|
|
8
|
+
async findUserByEmail(email) {
|
|
9
|
+
const user = await model.findUnique({
|
|
10
|
+
where: { email }
|
|
11
|
+
});
|
|
12
|
+
return user;
|
|
13
|
+
},
|
|
14
|
+
async findUserById(id) {
|
|
15
|
+
const user = await model.findUnique({
|
|
16
|
+
where: { id }
|
|
17
|
+
});
|
|
18
|
+
return user;
|
|
19
|
+
},
|
|
20
|
+
async updateUser(id, data) {
|
|
21
|
+
const user = await model.update({
|
|
22
|
+
where: { id },
|
|
23
|
+
data
|
|
24
|
+
});
|
|
25
|
+
return user;
|
|
26
|
+
},
|
|
27
|
+
async linkOAuthAccount(userId, provider, providerId) {
|
|
28
|
+
await model.update({
|
|
29
|
+
where: { id: userId },
|
|
30
|
+
data: {
|
|
31
|
+
oauthProvider: provider,
|
|
32
|
+
oauthId: providerId
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
if (rateLimitModel) {
|
|
38
|
+
adapter.incrementRateLimit = async (key, windowMs) => {
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
const record = await rateLimitModel.findUnique({ where: { key } });
|
|
41
|
+
if (!record || now > record.resetTime) {
|
|
42
|
+
const newRecord = await rateLimitModel.upsert({
|
|
43
|
+
where: { key },
|
|
44
|
+
update: { count: 1, resetTime: now + windowMs },
|
|
45
|
+
create: { key, count: 1, resetTime: now + windowMs }
|
|
46
|
+
});
|
|
47
|
+
return { count: newRecord.count, resetTime: newRecord.resetTime };
|
|
48
|
+
} else {
|
|
49
|
+
const updated = await rateLimitModel.update({
|
|
50
|
+
where: { key },
|
|
51
|
+
data: { count: { increment: 1 } }
|
|
52
|
+
});
|
|
53
|
+
return { count: updated.count, resetTime: updated.resetTime };
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
adapter.getRateLimit = async (key) => {
|
|
57
|
+
const now = Date.now();
|
|
58
|
+
const record = await rateLimitModel.findUnique({ where: { key } });
|
|
59
|
+
if (!record || now > record.resetTime) return null;
|
|
60
|
+
return { count: record.count, resetTime: record.resetTime };
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return adapter;
|
|
64
|
+
}
|
|
65
|
+
export {
|
|
66
|
+
createPrismaAdapter
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=prisma.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/auth/adapters/prisma.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AuthAdapter, User } from \"./index.js\";\r\n\r\n/**\r\n * Creates a Prisma adapter using a Prisma delegate (e.g., prisma.user).\r\n * \r\n * Works with any Prisma-supported database by using the standard\r\n * Prisma delegate operations (findUnique, create, update).\r\n * \r\n * @param model - A Prisma delegate instance (e.g., prisma.user).\r\n * @param rateLimitModel - An optional Prisma delegate for rate limit tracking.\r\n * @returns An AuthAdapter compliant object.\r\n */\r\nexport function createPrismaAdapter<TUser extends User = User>(model: any, rateLimitModel?: any): AuthAdapter<TUser> {\r\n const adapter: AuthAdapter<TUser> = {\r\n async createUser(data: any) {\r\n const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };\r\n const user = await model.create({ data: dataToSave });\r\n return user as TUser;\r\n },\r\n\r\n async findUserByEmail(email: string) {\r\n const user = await model.findUnique({\r\n where: { email },\r\n });\r\n return user as TUser | null;\r\n },\r\n\r\n async findUserById(id: string) {\r\n const user = await model.findUnique({\r\n where: { id },\r\n });\r\n return user as TUser | null;\r\n },\r\n\r\n async updateUser(id: string, data: Partial<TUser>) {\r\n const user = await model.update({\r\n where: { id },\r\n data,\r\n });\r\n return user as TUser | null;\r\n },\r\n\r\n async linkOAuthAccount(userId: string, provider: string, providerId: string) {\r\n await model.update({\r\n where: { id: userId },\r\n data: {\r\n oauthProvider: provider,\r\n oauthId: providerId,\r\n },\r\n });\r\n },\r\n };\r\n\r\n if (rateLimitModel) {\r\n adapter.incrementRateLimit = async (key: string, windowMs: number) => {\r\n const now = Date.now();\r\n const record = await rateLimitModel.findUnique({ where: { key } });\r\n \r\n if (!record || now > record.resetTime) {\r\n const newRecord = await rateLimitModel.upsert({\r\n where: { key },\r\n update: { count: 1, resetTime: now + windowMs },\r\n create: { key, count: 1, resetTime: now + windowMs }\r\n });\r\n return { count: newRecord.count, resetTime: newRecord.resetTime };\r\n } else {\r\n const updated = await rateLimitModel.update({\r\n where: { key },\r\n data: { count: { increment: 1 } }\r\n });\r\n return { count: updated.count, resetTime: updated.resetTime };\r\n }\r\n };\r\n\r\n adapter.getRateLimit = async (key: string) => {\r\n const now = Date.now();\r\n const record = await rateLimitModel.findUnique({ where: { key } });\r\n if (!record || now > record.resetTime) return null;\r\n return { count: record.count, resetTime: record.resetTime };\r\n };\r\n }\r\n\r\n return adapter;\r\n}\r\n"],
|
|
5
|
+
"mappings": "AAYO,SAAS,oBAA+C,OAAY,gBAA0C;AACnH,QAAM,UAA8B;AAAA,IAClC,MAAM,WAAW,MAAW;AAC1B,YAAM,aAAa,EAAE,IAAI,KAAK,MAAM,WAAW,OAAO,WAAW,GAAG,GAAG,KAAK;AAC5E,YAAM,OAAO,MAAM,MAAM,OAAO,EAAE,MAAM,WAAW,CAAC;AACpD,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,gBAAgB,OAAe;AACnC,YAAM,OAAO,MAAM,MAAM,WAAW;AAAA,QAClC,OAAO,EAAE,MAAM;AAAA,MACjB,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,aAAa,IAAY;AAC7B,YAAM,OAAO,MAAM,MAAM,WAAW;AAAA,QAClC,OAAO,EAAE,GAAG;AAAA,MACd,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,WAAW,IAAY,MAAsB;AACjD,YAAM,OAAO,MAAM,MAAM,OAAO;AAAA,QAC9B,OAAO,EAAE,GAAG;AAAA,QACZ;AAAA,MACF,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,iBAAiB,QAAgB,UAAkB,YAAoB;AAC3E,YAAM,MAAM,OAAO;AAAA,QACjB,OAAO,EAAE,IAAI,OAAO;AAAA,QACpB,MAAM;AAAA,UACJ,eAAe;AAAA,UACf,SAAS;AAAA,QACX;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,gBAAgB;AAClB,YAAQ,qBAAqB,OAAO,KAAa,aAAqB;AACpE,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,SAAS,MAAM,eAAe,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAEjE,UAAI,CAAC,UAAU,MAAM,OAAO,WAAW;AACnC,cAAM,YAAY,MAAM,eAAe,OAAO;AAAA,UAC1C,OAAO,EAAE,IAAI;AAAA,UACb,QAAQ,EAAE,OAAO,GAAG,WAAW,MAAM,SAAS;AAAA,UAC9C,QAAQ,EAAE,KAAK,OAAO,GAAG,WAAW,MAAM,SAAS;AAAA,QACvD,CAAC;AACD,eAAO,EAAE,OAAO,UAAU,OAAO,WAAW,UAAU,UAAU;AAAA,MACpE,OAAO;AACH,cAAM,UAAU,MAAM,eAAe,OAAO;AAAA,UACxC,OAAO,EAAE,IAAI;AAAA,UACb,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE;AAAA,QACpC,CAAC;AACD,eAAO,EAAE,OAAO,QAAQ,OAAO,WAAW,QAAQ,UAAU;AAAA,MAChE;AAAA,IACF;AAEA,YAAQ,eAAe,OAAO,QAAgB;AAC5C,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,SAAS,MAAM,eAAe,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACjE,UAAI,CAAC,UAAU,MAAM,OAAO,UAAW,QAAO;AAC9C,aAAO,EAAE,OAAO,OAAO,OAAO,WAAW,OAAO,UAAU;AAAA,IAC5D;AAAA,EACF;AAEA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -35,13 +35,18 @@ module.exports = __toCommonJS(core_exports);
|
|
|
35
35
|
var argon2 = __toESM(require("argon2"), 1);
|
|
36
36
|
var import_jose = require("jose");
|
|
37
37
|
var import_crypto = __toESM(require("crypto"), 1);
|
|
38
|
+
var import_rate_limit = require("../security/rate-limit.js");
|
|
38
39
|
function createAuth(options) {
|
|
39
|
-
const { adapter, secret, pepper, session, providers } = options;
|
|
40
|
+
const { adapter, secret, pepper, session, providers, rateLimit, ipBlocking } = options;
|
|
40
41
|
const encodedSecret = typeof secret === "string" ? new TextEncoder().encode(secret) : secret;
|
|
41
42
|
const expiration = session?.expires || "1h";
|
|
42
43
|
const refreshExpiration = session?.refreshExpires || "7d";
|
|
44
|
+
const configuredRateLimiter = (0, import_rate_limit.createRateLimiter)(adapter, rateLimit);
|
|
43
45
|
async function generateToken(user, type = "access") {
|
|
44
46
|
let payload = { sub: user.id, role: user.role, type };
|
|
47
|
+
if (user.passwordHash && (type === "refresh" || session?.enforceStrictRevocation)) {
|
|
48
|
+
payload.pw_frag = user.passwordHash.slice(-10);
|
|
49
|
+
}
|
|
45
50
|
if (options.jwt?.payload) {
|
|
46
51
|
const customPayload = options.jwt.payload(user, type);
|
|
47
52
|
payload = { ...payload, ...customPayload };
|
|
@@ -52,6 +57,12 @@ function createAuth(options) {
|
|
|
52
57
|
try {
|
|
53
58
|
const { payload } = await (0, import_jose.jwtVerify)(token, encodedSecret);
|
|
54
59
|
if (payload.type !== expectedType) return null;
|
|
60
|
+
if (expectedType === "access" && session?.enforceStrictRevocation && payload.pw_frag) {
|
|
61
|
+
const user = await adapter.findUserById(payload.sub);
|
|
62
|
+
if (!user || payload.pw_frag !== user.passwordHash?.slice(-10)) {
|
|
63
|
+
throw new Error("Strict Revocation: Access Token revoked due to password change");
|
|
64
|
+
}
|
|
65
|
+
}
|
|
55
66
|
return payload;
|
|
56
67
|
} catch (e) {
|
|
57
68
|
return null;
|
|
@@ -66,12 +77,37 @@ function createAuth(options) {
|
|
|
66
77
|
if (!user) {
|
|
67
78
|
throw new Error("User not found");
|
|
68
79
|
}
|
|
80
|
+
if (payload.pw_frag && user.passwordHash) {
|
|
81
|
+
if (payload.pw_frag !== user.passwordHash.slice(-10)) {
|
|
82
|
+
throw new Error("Session revoked (Password changed)");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
69
85
|
const accessToken = await generateToken(user, "access");
|
|
70
86
|
return { accessToken };
|
|
71
87
|
}
|
|
88
|
+
function validatePassword(password) {
|
|
89
|
+
if (!password || !options.passwordPolicy) return;
|
|
90
|
+
const p = options.passwordPolicy;
|
|
91
|
+
if (p.minLength && password.length < p.minLength) {
|
|
92
|
+
throw new Error(`Password must be at least ${p.minLength} characters`);
|
|
93
|
+
}
|
|
94
|
+
if (p.requireUppercase && !/[A-Z]/.test(password)) {
|
|
95
|
+
throw new Error("Password must contain at least one uppercase letter");
|
|
96
|
+
}
|
|
97
|
+
if (p.requireLowercase && !/[a-z]/.test(password)) {
|
|
98
|
+
throw new Error("Password must contain at least one lowercase letter");
|
|
99
|
+
}
|
|
100
|
+
if (p.requireNumber && !/[0-9]/.test(password)) {
|
|
101
|
+
throw new Error("Password must contain at least one number");
|
|
102
|
+
}
|
|
103
|
+
if (p.requireSpecialCharacter && !/[^A-Za-z0-9]/.test(password)) {
|
|
104
|
+
throw new Error("Password must contain at least one special character");
|
|
105
|
+
}
|
|
106
|
+
}
|
|
72
107
|
async function signup(userData, password) {
|
|
73
108
|
let dataToSave = { ...userData };
|
|
74
109
|
if (password) {
|
|
110
|
+
validatePassword(password);
|
|
75
111
|
const passwordWithPepper = pepper ? `${password}${pepper}` : password;
|
|
76
112
|
dataToSave.passwordHash = await argon2.hash(passwordWithPepper);
|
|
77
113
|
}
|
|
@@ -80,7 +116,22 @@ function createAuth(options) {
|
|
|
80
116
|
const refreshToken = await generateToken(newUser, "refresh");
|
|
81
117
|
return { user: newUser, accessToken, refreshToken };
|
|
82
118
|
}
|
|
83
|
-
async function loginWithPassword(email, password) {
|
|
119
|
+
async function loginWithPassword(email, password, clientIp) {
|
|
120
|
+
if (ipBlocking && clientIp && configuredRateLimiter) {
|
|
121
|
+
const strikeCheck = await configuredRateLimiter.check(`strike_${clientIp}`);
|
|
122
|
+
if (strikeCheck && strikeCheck.count >= ipBlocking.maxStrikes) {
|
|
123
|
+
throw new Error("IP is temporarily blocked.");
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (configuredRateLimiter) {
|
|
127
|
+
const limitStatus = await configuredRateLimiter.increment(`login_${email}`);
|
|
128
|
+
if (!limitStatus.success) {
|
|
129
|
+
if (ipBlocking && clientIp) {
|
|
130
|
+
await configuredRateLimiter.increment(`strike_${clientIp}`, ipBlocking.blockDurationMs);
|
|
131
|
+
}
|
|
132
|
+
throw new Error("Too many requests, please try again later.");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
84
135
|
const user = await adapter.findUserByEmail(email);
|
|
85
136
|
const dummyHash = "$argon2id$v=19$m=65536,t=3,p=4$c29tZXNhbHQ$RytpInY7i6C9M5l0D4n8Q+7j/J+i";
|
|
86
137
|
const targetHash = user?.passwordHash || dummyHash;
|
|
@@ -93,9 +144,23 @@ function createAuth(options) {
|
|
|
93
144
|
const refreshToken = await generateToken(user, "refresh");
|
|
94
145
|
return { user, accessToken, refreshToken };
|
|
95
146
|
}
|
|
147
|
+
async function changePassword(userId, newPassword) {
|
|
148
|
+
if (!adapter.updateUser) {
|
|
149
|
+
throw new Error("The AuthAdapter does not support updating user records natively.");
|
|
150
|
+
}
|
|
151
|
+
validatePassword(newPassword);
|
|
152
|
+
const passwordWithPepper = pepper ? `${newPassword}${pepper}` : newPassword;
|
|
153
|
+
const newHash = await argon2.hash(passwordWithPepper);
|
|
154
|
+
const updatedUser = await adapter.updateUser(userId, { passwordHash: newHash });
|
|
155
|
+
if (!updatedUser) {
|
|
156
|
+
throw new Error("User not found");
|
|
157
|
+
}
|
|
158
|
+
return updatedUser;
|
|
159
|
+
}
|
|
96
160
|
return {
|
|
97
161
|
signup,
|
|
98
162
|
loginWithPassword,
|
|
163
|
+
changePassword,
|
|
99
164
|
refresh,
|
|
100
165
|
verifyToken,
|
|
101
166
|
generateToken,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/auth/core/index.ts"],
|
|
4
|
+
"sourcesContent": ["import * as argon2 from \"argon2\";\r\nimport { SignJWT, jwtVerify } from \"jose\";\r\nimport crypto from \"crypto\";\r\nimport type { AuthAdapter, User } from \"../adapters/index.js\";\r\nimport type { Provider } from \"../providers/index.js\";\r\nimport { createRateLimiter, type RateLimitOptions } from \"../security/rate-limit.js\";\r\n\r\nexport interface CreateAuthOptions {\r\n adapter: AuthAdapter<any>;\r\n secret: string | Uint8Array;\r\n pepper?: string;\r\n session?: {\r\n expires?: string | number; // For access tokens\r\n refreshExpires?: string | number; // For refresh tokens\r\n enforceStrictRevocation?: boolean; // If true, DB check on access tokens\r\n };\r\n providers?: Provider[];\r\n jwt?: {\r\n /**\r\n * A callback to add custom fields to the JWT payload.\r\n * It receives the user object and the token type ('access' or 'refresh').\r\n * Return an object containing the fields to be merged into the payload.\r\n * You can also override default fields like 'sub'.\r\n */\r\n payload?: (user: User<any>, type: \"access\" | \"refresh\") => Record<string, any>;\r\n };\r\n rateLimit?: RateLimitOptions;\r\n ipBlocking?: { maxStrikes: number; blockDurationMs: number };\r\n passwordPolicy?: {\r\n minLength?: number;\r\n requireUppercase?: boolean;\r\n requireLowercase?: boolean;\r\n requireNumber?: boolean;\r\n requireSpecialCharacter?: boolean;\r\n };\r\n}\r\n\r\nexport function createAuth(options: CreateAuthOptions) {\r\n const { adapter, secret, pepper, session, providers, rateLimit, ipBlocking } = options;\r\n const encodedSecret = typeof secret === \"string\" ? new TextEncoder().encode(secret) : secret;\r\n const expiration = session?.expires || \"1h\"; // Default access token to 1h\r\n const refreshExpiration = session?.refreshExpires || \"7d\";\r\n\r\n const configuredRateLimiter = createRateLimiter(adapter, rateLimit);\r\n\r\n /**\r\n * Generates a stateless JWT for a user session\r\n */\r\n async function generateToken(user: User<any>, type: \"access\" | \"refresh\" = \"access\") {\r\n let payload: Record<string, any> = { sub: user.id, role: user.role, type };\r\n\r\n // Lightweight Session Revocation: Link token to current password hash state\r\n if (user.passwordHash && (type === \"refresh\" || session?.enforceStrictRevocation)) {\r\n payload.pw_frag = user.passwordHash.slice(-10);\r\n }\r\n\r\n if (options.jwt?.payload) {\r\n const customPayload = options.jwt.payload(user, type);\r\n payload = { ...payload, ...customPayload };\r\n }\r\n\r\n return new SignJWT(payload)\r\n .setProtectedHeader({ alg: \"HS256\" })\r\n .setIssuedAt()\r\n .setExpirationTime(type === \"access\" ? expiration : refreshExpiration)\r\n .sign(encodedSecret);\r\n }\r\n\r\n /**\r\n * Verifies a JWT and returns the payload.\r\n * Optionally checks for a specific token type (access/refresh).\r\n */\r\n async function verifyToken(token: string, expectedType: \"access\" | \"refresh\" = \"access\") {\r\n try {\r\n const { payload } = await jwtVerify(token, encodedSecret);\r\n if (payload.type !== expectedType) return null;\r\n\r\n if (expectedType === \"access\" && session?.enforceStrictRevocation && payload.pw_frag) {\r\n const user = await adapter.findUserById(payload.sub as string);\r\n if (!user || payload.pw_frag !== user.passwordHash?.slice(-10)) {\r\n throw new Error(\"Strict Revocation: Access Token revoked due to password change\");\r\n }\r\n }\r\n\r\n return payload;\r\n } catch (e) {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Refreshes an access token using a valid refresh token.\r\n */\r\n async function refresh(refreshToken: string) {\r\n const payload = await verifyToken(refreshToken, \"refresh\");\r\n if (!payload || !payload.sub) {\r\n throw new Error(\"Invalid or expired refresh token\");\r\n }\r\n\r\n const user = await adapter.findUserById(payload.sub as string);\r\n if (!user) {\r\n throw new Error(\"User not found\");\r\n }\r\n\r\n // Lightweight Session Revocation: Validate password hasn't changed since token issuance\r\n if (payload.pw_frag && user.passwordHash) {\r\n if (payload.pw_frag !== user.passwordHash.slice(-10)) {\r\n throw new Error(\"Session revoked (Password changed)\");\r\n }\r\n }\r\n\r\n const accessToken = await generateToken(user, \"access\");\r\n return { accessToken };\r\n }\r\n\r\n function validatePassword(password?: string) {\r\n if (!password || !options.passwordPolicy) return;\r\n \r\n const p = options.passwordPolicy;\r\n if (p.minLength && password.length < p.minLength) {\r\n throw new Error(`Password must be at least ${p.minLength} characters`);\r\n }\r\n if (p.requireUppercase && !/[A-Z]/.test(password)) {\r\n throw new Error(\"Password must contain at least one uppercase letter\");\r\n }\r\n if (p.requireLowercase && !/[a-z]/.test(password)) {\r\n throw new Error(\"Password must contain at least one lowercase letter\");\r\n }\r\n if (p.requireNumber && !/[0-9]/.test(password)) {\r\n throw new Error(\"Password must contain at least one number\");\r\n }\r\n if (p.requireSpecialCharacter && !/[^A-Za-z0-9]/.test(password)) {\r\n throw new Error(\"Password must contain at least one special character\");\r\n }\r\n }\r\n\r\n /**\r\n * Signup with a new user payload.\r\n * Incorporates server-side pepper for password hashing if provided.\r\n */\r\n async function signup(userData: Omit<User<any>, \"id\">, password?: string) {\r\n let dataToSave = { ...userData };\r\n\r\n if (password) {\r\n validatePassword(password);\r\n const passwordWithPepper = pepper ? `${password}${pepper}` : password;\r\n dataToSave.passwordHash = await argon2.hash(passwordWithPepper);\r\n }\r\n\r\n const newUser = await adapter.createUser(dataToSave);\r\n const accessToken = await generateToken(newUser, \"access\");\r\n const refreshToken = await generateToken(newUser, \"refresh\");\r\n\r\n return { user: newUser, accessToken, refreshToken };\r\n }\r\n\r\n /**\r\n * Standard Email/Password Login.\r\n * Includes timing attack protection and password peppering.\r\n */\r\n async function loginWithPassword(email: string, password: string, clientIp?: string) {\r\n if (ipBlocking && clientIp && configuredRateLimiter) {\r\n const strikeCheck = await configuredRateLimiter.check(`strike_${clientIp}`);\r\n if (strikeCheck && strikeCheck.count >= ipBlocking.maxStrikes) {\r\n throw new Error(\"IP is temporarily blocked.\");\r\n }\r\n }\r\n\r\n if (configuredRateLimiter) {\r\n const limitStatus = await configuredRateLimiter.increment(`login_${email}`);\r\n if (!limitStatus.success) {\r\n if (ipBlocking && clientIp) {\r\n await configuredRateLimiter.increment(`strike_${clientIp}`, ipBlocking.blockDurationMs);\r\n }\r\n throw new Error(\"Too many requests, please try again later.\");\r\n }\r\n }\r\n\r\n const user = await adapter.findUserByEmail(email);\r\n\r\n // Timing attack protection: Always verify a hash, even if user doesn't exist.\r\n // We use a dummy hash to keep execution time consistent.\r\n const dummyHash = \"$argon2id$v=19$m=65536,t=3,p=4$c29tZXNhbHQ$RytpInY7i6C9M5l0D4n8Q+7j/J+i\";\r\n const targetHash = user?.passwordHash || dummyHash;\r\n const passwordWithPepper = pepper ? `${password}${pepper}` : password;\r\n\r\n const isValid = await argon2.verify(targetHash, passwordWithPepper);\r\n\r\n if (!user || !user.passwordHash || !isValid) {\r\n throw new Error(\"Invalid credentials\");\r\n }\r\n\r\n const accessToken = await generateToken(user, \"access\");\r\n const refreshToken = await generateToken(user, \"refresh\");\r\n\r\n return { user, accessToken, refreshToken };\r\n }\r\n\r\n /**\r\n * Changes a user's password securely using the configured pepper and hashing algorithm.\r\n * Instantly revokes all active refresh tokens for the user globally.\r\n */\r\n async function changePassword(userId: string, newPassword: string) {\r\n if (!adapter.updateUser) {\r\n throw new Error(\"The AuthAdapter does not support updating user records natively.\");\r\n }\r\n\r\n validatePassword(newPassword);\r\n const passwordWithPepper = pepper ? `${newPassword}${pepper}` : newPassword;\r\n const newHash = await argon2.hash(passwordWithPepper);\r\n\r\n const updatedUser = await adapter.updateUser(userId, { passwordHash: newHash } as any);\r\n if (!updatedUser) {\r\n throw new Error(\"User not found\");\r\n }\r\n \r\n return updatedUser;\r\n }\r\n\r\n return {\r\n signup,\r\n loginWithPassword,\r\n changePassword,\r\n refresh,\r\n verifyToken,\r\n generateToken,\r\n _providers: providers\r\n };\r\n}\r\n\r\n/**\r\n * Utility to generate a high-entropy cryptographically secure secret.\r\n * Useful for initializing the 'secret' option in createAuth.\r\n */\r\nexport function generateSecret(length: number = 32): Uint8Array {\r\n return crypto.getRandomValues(new Uint8Array(length));\r\n}\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["crypto"]
|
|
7
|
+
}
|