nova-auth 0.1.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/dist/index.d.mts +45 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +174 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +137 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +31 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ZodRawShape, ZodObject } from 'zod';
|
|
2
|
+
import { Redis } from '@upstash/redis';
|
|
3
|
+
|
|
4
|
+
type Cookies = {
|
|
5
|
+
set: (key: string, value: string, options: {
|
|
6
|
+
secure?: boolean;
|
|
7
|
+
httpOnly?: boolean;
|
|
8
|
+
sameSite?: "strict" | "lax";
|
|
9
|
+
expires?: number;
|
|
10
|
+
}) => void;
|
|
11
|
+
get: (key: string) => {
|
|
12
|
+
name: string;
|
|
13
|
+
value: string;
|
|
14
|
+
} | undefined;
|
|
15
|
+
delete: (key: string) => void;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type AuthInstance<T extends ZodRawShape = ZodRawShape> = {
|
|
19
|
+
_schema: ZodObject<T>;
|
|
20
|
+
_redis: Redis;
|
|
21
|
+
ttl: number;
|
|
22
|
+
getCurrentUser(cookies: Pick<Cookies, "get">): Promise<unknown | null>;
|
|
23
|
+
createUserSession(user: unknown, cookies: Pick<Cookies, "set">): Promise<void>;
|
|
24
|
+
updateUserSession(user: unknown, cookies: Pick<Cookies, "get">): Promise<void | null>;
|
|
25
|
+
removeUserFromSession(cookies: Pick<Cookies, "get" | "delete">): Promise<void | null>;
|
|
26
|
+
hashPassword(password: string, salt: string): Promise<string>;
|
|
27
|
+
generateSalt(): string;
|
|
28
|
+
comparePassword(params: {
|
|
29
|
+
password: string;
|
|
30
|
+
salt: string;
|
|
31
|
+
hashedPassword: string;
|
|
32
|
+
}): Promise<boolean>;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
type CreateAuthOptions<T extends ZodRawShape> = {
|
|
36
|
+
sessionSchema: ZodObject<T>;
|
|
37
|
+
ttl: number;
|
|
38
|
+
redis: {
|
|
39
|
+
url: string;
|
|
40
|
+
token: string;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
declare function createAuth<T extends ZodRawShape>(options: CreateAuthOptions<T>): AuthInstance<T>;
|
|
44
|
+
|
|
45
|
+
export { createAuth };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ZodRawShape, ZodObject } from 'zod';
|
|
2
|
+
import { Redis } from '@upstash/redis';
|
|
3
|
+
|
|
4
|
+
type Cookies = {
|
|
5
|
+
set: (key: string, value: string, options: {
|
|
6
|
+
secure?: boolean;
|
|
7
|
+
httpOnly?: boolean;
|
|
8
|
+
sameSite?: "strict" | "lax";
|
|
9
|
+
expires?: number;
|
|
10
|
+
}) => void;
|
|
11
|
+
get: (key: string) => {
|
|
12
|
+
name: string;
|
|
13
|
+
value: string;
|
|
14
|
+
} | undefined;
|
|
15
|
+
delete: (key: string) => void;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type AuthInstance<T extends ZodRawShape = ZodRawShape> = {
|
|
19
|
+
_schema: ZodObject<T>;
|
|
20
|
+
_redis: Redis;
|
|
21
|
+
ttl: number;
|
|
22
|
+
getCurrentUser(cookies: Pick<Cookies, "get">): Promise<unknown | null>;
|
|
23
|
+
createUserSession(user: unknown, cookies: Pick<Cookies, "set">): Promise<void>;
|
|
24
|
+
updateUserSession(user: unknown, cookies: Pick<Cookies, "get">): Promise<void | null>;
|
|
25
|
+
removeUserFromSession(cookies: Pick<Cookies, "get" | "delete">): Promise<void | null>;
|
|
26
|
+
hashPassword(password: string, salt: string): Promise<string>;
|
|
27
|
+
generateSalt(): string;
|
|
28
|
+
comparePassword(params: {
|
|
29
|
+
password: string;
|
|
30
|
+
salt: string;
|
|
31
|
+
hashedPassword: string;
|
|
32
|
+
}): Promise<boolean>;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
type CreateAuthOptions<T extends ZodRawShape> = {
|
|
36
|
+
sessionSchema: ZodObject<T>;
|
|
37
|
+
ttl: number;
|
|
38
|
+
redis: {
|
|
39
|
+
url: string;
|
|
40
|
+
token: string;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
declare function createAuth<T extends ZodRawShape>(options: CreateAuthOptions<T>): AuthInstance<T>;
|
|
44
|
+
|
|
45
|
+
export { createAuth };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
createAuth: () => createAuth
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(index_exports);
|
|
36
|
+
|
|
37
|
+
// src/create-auth.ts
|
|
38
|
+
var import_crypto = __toESM(require("crypto"));
|
|
39
|
+
|
|
40
|
+
// src/internal/redis-client.ts
|
|
41
|
+
var import_redis = require("@upstash/redis");
|
|
42
|
+
var createRedisClient = ({ url, token }) => {
|
|
43
|
+
if (!url || !token) {
|
|
44
|
+
throw new Error("Both REDIS URL and TOKEN are required to create Redis client");
|
|
45
|
+
}
|
|
46
|
+
const redisClient = new import_redis.Redis({
|
|
47
|
+
url,
|
|
48
|
+
token
|
|
49
|
+
});
|
|
50
|
+
return redisClient;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// src/internal/utils.ts
|
|
54
|
+
function stringifyBigInt(obj) {
|
|
55
|
+
return JSON.stringify(
|
|
56
|
+
obj,
|
|
57
|
+
(_, value) => typeof value === "bigint" ? value.toString() : value
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
function generateSessionId() {
|
|
61
|
+
const array = new Uint8Array(512);
|
|
62
|
+
crypto.getRandomValues(array);
|
|
63
|
+
return Array.from(array).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/internal/keys.ts
|
|
67
|
+
var COOKIE_SESSION_KEY = "session-id";
|
|
68
|
+
|
|
69
|
+
// src/internal/cookie.ts
|
|
70
|
+
function getSessionId(cookies) {
|
|
71
|
+
return cookies.get(COOKIE_SESSION_KEY)?.value ?? null;
|
|
72
|
+
}
|
|
73
|
+
function deleteSessionCookie(cookies) {
|
|
74
|
+
cookies.delete(COOKIE_SESSION_KEY);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/internal/session.ts
|
|
78
|
+
async function getUserFromSession(auth, cookies) {
|
|
79
|
+
const sessionId = cookies.get(COOKIE_SESSION_KEY)?.value;
|
|
80
|
+
if (!sessionId) return null;
|
|
81
|
+
const data = await auth._redis.get(`session:${sessionId}`);
|
|
82
|
+
if (!data) return null;
|
|
83
|
+
return auth._schema.parse(JSON.parse(data));
|
|
84
|
+
}
|
|
85
|
+
async function createUserSession(auth, user, cookies) {
|
|
86
|
+
const sessionId = generateSessionId();
|
|
87
|
+
const data = auth._schema.parse(user);
|
|
88
|
+
await auth._redis.set(
|
|
89
|
+
`session:${sessionId}`,
|
|
90
|
+
stringifyBigInt(data),
|
|
91
|
+
{ ex: auth.ttl }
|
|
92
|
+
);
|
|
93
|
+
cookies.set(COOKIE_SESSION_KEY, sessionId, {
|
|
94
|
+
httpOnly: true,
|
|
95
|
+
secure: true,
|
|
96
|
+
sameSite: "lax",
|
|
97
|
+
expires: Math.floor(Date.now() / 1e3) + auth.ttl
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
async function updateUserSession(auth, user, cookies) {
|
|
101
|
+
const sessionId = getSessionId(cookies);
|
|
102
|
+
if (!sessionId) return null;
|
|
103
|
+
const data = auth._schema.parse(user);
|
|
104
|
+
await auth._redis.set(
|
|
105
|
+
`session:${sessionId}`,
|
|
106
|
+
stringifyBigInt(data),
|
|
107
|
+
{ ex: auth.ttl }
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
async function removeUserFromSession(auth, cookies) {
|
|
111
|
+
const sessionId = getSessionId(cookies);
|
|
112
|
+
if (!sessionId) return null;
|
|
113
|
+
await auth._redis.del(`session:${sessionId}`);
|
|
114
|
+
deleteSessionCookie(cookies);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/create-auth.ts
|
|
118
|
+
function createAuth(options) {
|
|
119
|
+
if (!("id" in options.sessionSchema.shape)) {
|
|
120
|
+
throw new Error("sessionSchema must include an `id` field");
|
|
121
|
+
}
|
|
122
|
+
const redis = createRedisClient(options.redis);
|
|
123
|
+
const auth = {
|
|
124
|
+
_schema: options.sessionSchema,
|
|
125
|
+
_redis: redis,
|
|
126
|
+
ttl: options.ttl,
|
|
127
|
+
getCurrentUser(cookies) {
|
|
128
|
+
return getUserFromSession(auth, cookies);
|
|
129
|
+
},
|
|
130
|
+
createUserSession(user, cookies) {
|
|
131
|
+
return createUserSession(auth, user, cookies);
|
|
132
|
+
},
|
|
133
|
+
updateUserSession(user, cookies) {
|
|
134
|
+
return updateUserSession(auth, user, cookies);
|
|
135
|
+
},
|
|
136
|
+
removeUserFromSession(cookies) {
|
|
137
|
+
return removeUserFromSession(auth, cookies);
|
|
138
|
+
},
|
|
139
|
+
// 🔒 Add password helpers
|
|
140
|
+
hashPassword(password, salt) {
|
|
141
|
+
return new Promise((resolve, reject) => {
|
|
142
|
+
import_crypto.default.scrypt(
|
|
143
|
+
password.normalize(),
|
|
144
|
+
salt,
|
|
145
|
+
64,
|
|
146
|
+
(err, derivedKey) => {
|
|
147
|
+
if (err) return reject(err);
|
|
148
|
+
resolve(derivedKey.toString("hex").normalize());
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
});
|
|
152
|
+
},
|
|
153
|
+
generateSalt() {
|
|
154
|
+
return import_crypto.default.randomBytes(16).toString("hex").normalize();
|
|
155
|
+
},
|
|
156
|
+
async comparePassword({
|
|
157
|
+
password,
|
|
158
|
+
salt,
|
|
159
|
+
hashedPassword
|
|
160
|
+
}) {
|
|
161
|
+
const inputHashed = await auth.hashPassword(password, salt);
|
|
162
|
+
return import_crypto.default.timingSafeEqual(
|
|
163
|
+
Buffer.from(inputHashed, "hex"),
|
|
164
|
+
Buffer.from(hashedPassword, "hex")
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
return auth;
|
|
169
|
+
}
|
|
170
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
171
|
+
0 && (module.exports = {
|
|
172
|
+
createAuth
|
|
173
|
+
});
|
|
174
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/create-auth.ts","../src/internal/redis-client.ts","../src/internal/utils.ts","../src/internal/keys.ts","../src/internal/cookie.ts","../src/internal/session.ts"],"sourcesContent":["export { createAuth } from \"./create-auth\";","import crypto from \"crypto\";\r\nimport { ZodObject, ZodRawShape } from \"zod\";\r\nimport { createRedisClient } from \"./internal/redis-client\";\r\nimport {\r\n getUserFromSession,\r\n createUserSession,\r\n updateUserSession,\r\n removeUserFromSession,\r\n} from \"./internal/session\";\r\nimport { AuthInstance } from \"./internal/types\";\r\n\r\ntype CreateAuthOptions<T extends ZodRawShape> = {\r\n sessionSchema: ZodObject<T>;\r\n ttl: number;\r\n redis: {\r\n url: string;\r\n token: string;\r\n };\r\n};\r\n\r\nexport function createAuth<T extends ZodRawShape>(\r\n options: CreateAuthOptions<T>\r\n): AuthInstance<T> {\r\n if (!(\"id\" in options.sessionSchema.shape)) {\r\n throw new Error(\"sessionSchema must include an `id` field\");\r\n }\r\n\r\n const redis = createRedisClient(options.redis);\r\n\r\n const auth: AuthInstance<T> = {\r\n _schema: options.sessionSchema,\r\n _redis: redis,\r\n ttl: options.ttl,\r\n\r\n getCurrentUser(cookies) {\r\n return getUserFromSession(auth, cookies);\r\n },\r\n\r\n createUserSession(user, cookies) {\r\n return createUserSession(auth, user, cookies);\r\n },\r\n\r\n updateUserSession(user, cookies) {\r\n return updateUserSession(auth, user, cookies);\r\n },\r\n\r\n removeUserFromSession(cookies) {\r\n return removeUserFromSession(auth, cookies);\r\n },\r\n\r\n // 🔒 Add password helpers\r\n hashPassword(password: string, salt: string): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n crypto.scrypt(\r\n password.normalize(),\r\n salt,\r\n 64,\r\n (err: Error | null, derivedKey: Buffer) => {\r\n if (err) return reject(err);\r\n resolve(derivedKey.toString(\"hex\").normalize());\r\n }\r\n );\r\n });\r\n },\r\n\r\n generateSalt(): string {\r\n return crypto.randomBytes(16).toString(\"hex\").normalize();\r\n },\r\n\r\n async comparePassword({\r\n password,\r\n salt,\r\n hashedPassword,\r\n }: {\r\n password: string;\r\n salt: string;\r\n hashedPassword: string;\r\n }): Promise<boolean> {\r\n const inputHashed = await auth.hashPassword(password, salt);\r\n return crypto.timingSafeEqual(\r\n Buffer.from(inputHashed, \"hex\"),\r\n Buffer.from(hashedPassword, \"hex\")\r\n );\r\n },\r\n };\r\n\r\n return auth;\r\n}\r\n","import { Redis } from \"@upstash/redis\";\r\n\r\nexport type CreateRedisClientOptions = {\r\n url: string;\r\n token: string;\r\n};\r\n\r\nexport const createRedisClient = ({ url, token }: CreateRedisClientOptions) => {\r\n if (!url || !token) {\r\n throw new Error(\"Both REDIS URL and TOKEN are required to create Redis client\");\r\n }\r\n\r\n const redisClient = new Redis({\r\n url,\r\n token,\r\n });\r\n\r\n return redisClient;\r\n};\r\n","export function stringifyBigInt<T>(obj: T): string {\r\n return JSON.stringify(obj, (_, value) =>\r\n typeof value === \"bigint\" ? value.toString() : value\r\n );\r\n}\r\n\r\nexport function generateSessionId(): string {\r\n const array = new Uint8Array(512);\r\n crypto.getRandomValues(array);\r\n\r\n return Array.from(array)\r\n .map((b) => b.toString(16).padStart(2, \"0\"))\r\n .join(\"\");\r\n}","export const COOKIE_SESSION_KEY = \"session-id\"","import { COOKIE_SESSION_KEY } from \"./keys\";\r\nimport { AuthInstance } from \"./types\";\r\n\r\nexport type Cookies = {\r\n set: (\r\n key: string,\r\n value: string,\r\n options: {\r\n secure?: boolean;\r\n httpOnly?: boolean;\r\n sameSite?: \"strict\" | \"lax\";\r\n expires?: number;\r\n }\r\n ) => void;\r\n get: (key: string) => { name: string; value: string } | undefined;\r\n delete: (key: string) => void;\r\n};\r\n\r\nexport function setSessionCookie(\r\n auth: AuthInstance,\r\n sessionId: string,\r\n cookies: Pick<Cookies, \"set\">\r\n) {\r\n cookies.set(COOKIE_SESSION_KEY, sessionId, {\r\n secure: true,\r\n httpOnly: true,\r\n sameSite: \"lax\",\r\n expires: Date.now() + Number(auth.ttl) * 1000,\r\n });\r\n}\r\n\r\nexport function getSessionId(\r\n cookies: Pick<Cookies, \"get\">\r\n): string | null {\r\n return cookies.get(COOKIE_SESSION_KEY)?.value ?? null;\r\n}\r\n\r\nexport function deleteSessionCookie(\r\n cookies: Pick<Cookies, \"delete\">\r\n) {\r\n cookies.delete(COOKIE_SESSION_KEY);\r\n}\r\n","import { stringifyBigInt, generateSessionId } from \"./utils\";\r\nimport {\r\n getSessionId,\r\n deleteSessionCookie,\r\n Cookies,\r\n} from \"./cookie\";\r\nimport { AuthInstance } from \"./types\";\r\nimport { COOKIE_SESSION_KEY } from \"./keys\";\r\n\r\nexport async function getUserFromSession(\r\n auth: AuthInstance,\r\n cookies: Pick<Cookies, \"get\">\r\n) {\r\n const sessionId = cookies.get(COOKIE_SESSION_KEY)?.value;\r\n if (!sessionId) return null;\r\n\r\n const data = await auth._redis.get<string>(`session:${sessionId}`)\r\n if (!data) return null;\r\n\r\n return auth._schema.parse(JSON.parse(data));\r\n}\r\n\r\nexport async function createUserSession<T>(\r\n auth: AuthInstance,\r\n user: T,\r\n cookies: Pick<Cookies, \"set\">\r\n) {\r\n const sessionId = generateSessionId();\r\n const data = auth._schema.parse(user);\r\n\r\n await auth._redis.set(\r\n `session:${sessionId}`,\r\n stringifyBigInt(data),\r\n { ex: auth.ttl }\r\n );\r\n\r\n cookies.set(COOKIE_SESSION_KEY, sessionId, {\r\n httpOnly: true,\r\n secure: true,\r\n sameSite: \"lax\",\r\n expires: Math.floor(Date.now() / 1000) + auth.ttl,\r\n });\r\n}\r\n\r\nexport async function updateUserSession<T>(\r\n auth: AuthInstance,\r\n user: T,\r\n cookies: Pick<Cookies, \"get\">\r\n) {\r\n const sessionId = getSessionId(cookies);\r\n if (!sessionId) return null;\r\n\r\n const data = auth._schema.parse(user);\r\n\r\n await auth._redis.set(\r\n `session:${sessionId}`,\r\n stringifyBigInt(data),\r\n { ex: auth.ttl }\r\n );\r\n}\r\n\r\nexport async function removeUserFromSession(\r\n auth: AuthInstance,\r\n cookies: Pick<Cookies, \"get\" | \"delete\">\r\n) {\r\n const sessionId = getSessionId(cookies);\r\n if (!sessionId) return null;\r\n\r\n await auth._redis.del(`session:${sessionId}`);\r\n deleteSessionCookie(cookies);\r\n}\r\n"],"mappings":"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","names":["crypto"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// src/create-auth.ts
|
|
2
|
+
import crypto2 from "crypto";
|
|
3
|
+
|
|
4
|
+
// src/internal/redis-client.ts
|
|
5
|
+
import { Redis } from "@upstash/redis";
|
|
6
|
+
var createRedisClient = ({ url, token }) => {
|
|
7
|
+
if (!url || !token) {
|
|
8
|
+
throw new Error("Both REDIS URL and TOKEN are required to create Redis client");
|
|
9
|
+
}
|
|
10
|
+
const redisClient = new Redis({
|
|
11
|
+
url,
|
|
12
|
+
token
|
|
13
|
+
});
|
|
14
|
+
return redisClient;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// src/internal/utils.ts
|
|
18
|
+
function stringifyBigInt(obj) {
|
|
19
|
+
return JSON.stringify(
|
|
20
|
+
obj,
|
|
21
|
+
(_, value) => typeof value === "bigint" ? value.toString() : value
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
function generateSessionId() {
|
|
25
|
+
const array = new Uint8Array(512);
|
|
26
|
+
crypto.getRandomValues(array);
|
|
27
|
+
return Array.from(array).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/internal/keys.ts
|
|
31
|
+
var COOKIE_SESSION_KEY = "session-id";
|
|
32
|
+
|
|
33
|
+
// src/internal/cookie.ts
|
|
34
|
+
function getSessionId(cookies) {
|
|
35
|
+
return cookies.get(COOKIE_SESSION_KEY)?.value ?? null;
|
|
36
|
+
}
|
|
37
|
+
function deleteSessionCookie(cookies) {
|
|
38
|
+
cookies.delete(COOKIE_SESSION_KEY);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/internal/session.ts
|
|
42
|
+
async function getUserFromSession(auth, cookies) {
|
|
43
|
+
const sessionId = cookies.get(COOKIE_SESSION_KEY)?.value;
|
|
44
|
+
if (!sessionId) return null;
|
|
45
|
+
const data = await auth._redis.get(`session:${sessionId}`);
|
|
46
|
+
if (!data) return null;
|
|
47
|
+
return auth._schema.parse(JSON.parse(data));
|
|
48
|
+
}
|
|
49
|
+
async function createUserSession(auth, user, cookies) {
|
|
50
|
+
const sessionId = generateSessionId();
|
|
51
|
+
const data = auth._schema.parse(user);
|
|
52
|
+
await auth._redis.set(
|
|
53
|
+
`session:${sessionId}`,
|
|
54
|
+
stringifyBigInt(data),
|
|
55
|
+
{ ex: auth.ttl }
|
|
56
|
+
);
|
|
57
|
+
cookies.set(COOKIE_SESSION_KEY, sessionId, {
|
|
58
|
+
httpOnly: true,
|
|
59
|
+
secure: true,
|
|
60
|
+
sameSite: "lax",
|
|
61
|
+
expires: Math.floor(Date.now() / 1e3) + auth.ttl
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
async function updateUserSession(auth, user, cookies) {
|
|
65
|
+
const sessionId = getSessionId(cookies);
|
|
66
|
+
if (!sessionId) return null;
|
|
67
|
+
const data = auth._schema.parse(user);
|
|
68
|
+
await auth._redis.set(
|
|
69
|
+
`session:${sessionId}`,
|
|
70
|
+
stringifyBigInt(data),
|
|
71
|
+
{ ex: auth.ttl }
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
async function removeUserFromSession(auth, cookies) {
|
|
75
|
+
const sessionId = getSessionId(cookies);
|
|
76
|
+
if (!sessionId) return null;
|
|
77
|
+
await auth._redis.del(`session:${sessionId}`);
|
|
78
|
+
deleteSessionCookie(cookies);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// src/create-auth.ts
|
|
82
|
+
function createAuth(options) {
|
|
83
|
+
if (!("id" in options.sessionSchema.shape)) {
|
|
84
|
+
throw new Error("sessionSchema must include an `id` field");
|
|
85
|
+
}
|
|
86
|
+
const redis = createRedisClient(options.redis);
|
|
87
|
+
const auth = {
|
|
88
|
+
_schema: options.sessionSchema,
|
|
89
|
+
_redis: redis,
|
|
90
|
+
ttl: options.ttl,
|
|
91
|
+
getCurrentUser(cookies) {
|
|
92
|
+
return getUserFromSession(auth, cookies);
|
|
93
|
+
},
|
|
94
|
+
createUserSession(user, cookies) {
|
|
95
|
+
return createUserSession(auth, user, cookies);
|
|
96
|
+
},
|
|
97
|
+
updateUserSession(user, cookies) {
|
|
98
|
+
return updateUserSession(auth, user, cookies);
|
|
99
|
+
},
|
|
100
|
+
removeUserFromSession(cookies) {
|
|
101
|
+
return removeUserFromSession(auth, cookies);
|
|
102
|
+
},
|
|
103
|
+
// 🔒 Add password helpers
|
|
104
|
+
hashPassword(password, salt) {
|
|
105
|
+
return new Promise((resolve, reject) => {
|
|
106
|
+
crypto2.scrypt(
|
|
107
|
+
password.normalize(),
|
|
108
|
+
salt,
|
|
109
|
+
64,
|
|
110
|
+
(err, derivedKey) => {
|
|
111
|
+
if (err) return reject(err);
|
|
112
|
+
resolve(derivedKey.toString("hex").normalize());
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
},
|
|
117
|
+
generateSalt() {
|
|
118
|
+
return crypto2.randomBytes(16).toString("hex").normalize();
|
|
119
|
+
},
|
|
120
|
+
async comparePassword({
|
|
121
|
+
password,
|
|
122
|
+
salt,
|
|
123
|
+
hashedPassword
|
|
124
|
+
}) {
|
|
125
|
+
const inputHashed = await auth.hashPassword(password, salt);
|
|
126
|
+
return crypto2.timingSafeEqual(
|
|
127
|
+
Buffer.from(inputHashed, "hex"),
|
|
128
|
+
Buffer.from(hashedPassword, "hex")
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
return auth;
|
|
133
|
+
}
|
|
134
|
+
export {
|
|
135
|
+
createAuth
|
|
136
|
+
};
|
|
137
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/create-auth.ts","../src/internal/redis-client.ts","../src/internal/utils.ts","../src/internal/keys.ts","../src/internal/cookie.ts","../src/internal/session.ts"],"sourcesContent":["import crypto from \"crypto\";\r\nimport { ZodObject, ZodRawShape } from \"zod\";\r\nimport { createRedisClient } from \"./internal/redis-client\";\r\nimport {\r\n getUserFromSession,\r\n createUserSession,\r\n updateUserSession,\r\n removeUserFromSession,\r\n} from \"./internal/session\";\r\nimport { AuthInstance } from \"./internal/types\";\r\n\r\ntype CreateAuthOptions<T extends ZodRawShape> = {\r\n sessionSchema: ZodObject<T>;\r\n ttl: number;\r\n redis: {\r\n url: string;\r\n token: string;\r\n };\r\n};\r\n\r\nexport function createAuth<T extends ZodRawShape>(\r\n options: CreateAuthOptions<T>\r\n): AuthInstance<T> {\r\n if (!(\"id\" in options.sessionSchema.shape)) {\r\n throw new Error(\"sessionSchema must include an `id` field\");\r\n }\r\n\r\n const redis = createRedisClient(options.redis);\r\n\r\n const auth: AuthInstance<T> = {\r\n _schema: options.sessionSchema,\r\n _redis: redis,\r\n ttl: options.ttl,\r\n\r\n getCurrentUser(cookies) {\r\n return getUserFromSession(auth, cookies);\r\n },\r\n\r\n createUserSession(user, cookies) {\r\n return createUserSession(auth, user, cookies);\r\n },\r\n\r\n updateUserSession(user, cookies) {\r\n return updateUserSession(auth, user, cookies);\r\n },\r\n\r\n removeUserFromSession(cookies) {\r\n return removeUserFromSession(auth, cookies);\r\n },\r\n\r\n // 🔒 Add password helpers\r\n hashPassword(password: string, salt: string): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n crypto.scrypt(\r\n password.normalize(),\r\n salt,\r\n 64,\r\n (err: Error | null, derivedKey: Buffer) => {\r\n if (err) return reject(err);\r\n resolve(derivedKey.toString(\"hex\").normalize());\r\n }\r\n );\r\n });\r\n },\r\n\r\n generateSalt(): string {\r\n return crypto.randomBytes(16).toString(\"hex\").normalize();\r\n },\r\n\r\n async comparePassword({\r\n password,\r\n salt,\r\n hashedPassword,\r\n }: {\r\n password: string;\r\n salt: string;\r\n hashedPassword: string;\r\n }): Promise<boolean> {\r\n const inputHashed = await auth.hashPassword(password, salt);\r\n return crypto.timingSafeEqual(\r\n Buffer.from(inputHashed, \"hex\"),\r\n Buffer.from(hashedPassword, \"hex\")\r\n );\r\n },\r\n };\r\n\r\n return auth;\r\n}\r\n","import { Redis } from \"@upstash/redis\";\r\n\r\nexport type CreateRedisClientOptions = {\r\n url: string;\r\n token: string;\r\n};\r\n\r\nexport const createRedisClient = ({ url, token }: CreateRedisClientOptions) => {\r\n if (!url || !token) {\r\n throw new Error(\"Both REDIS URL and TOKEN are required to create Redis client\");\r\n }\r\n\r\n const redisClient = new Redis({\r\n url,\r\n token,\r\n });\r\n\r\n return redisClient;\r\n};\r\n","export function stringifyBigInt<T>(obj: T): string {\r\n return JSON.stringify(obj, (_, value) =>\r\n typeof value === \"bigint\" ? value.toString() : value\r\n );\r\n}\r\n\r\nexport function generateSessionId(): string {\r\n const array = new Uint8Array(512);\r\n crypto.getRandomValues(array);\r\n\r\n return Array.from(array)\r\n .map((b) => b.toString(16).padStart(2, \"0\"))\r\n .join(\"\");\r\n}","export const COOKIE_SESSION_KEY = \"session-id\"","import { COOKIE_SESSION_KEY } from \"./keys\";\r\nimport { AuthInstance } from \"./types\";\r\n\r\nexport type Cookies = {\r\n set: (\r\n key: string,\r\n value: string,\r\n options: {\r\n secure?: boolean;\r\n httpOnly?: boolean;\r\n sameSite?: \"strict\" | \"lax\";\r\n expires?: number;\r\n }\r\n ) => void;\r\n get: (key: string) => { name: string; value: string } | undefined;\r\n delete: (key: string) => void;\r\n};\r\n\r\nexport function setSessionCookie(\r\n auth: AuthInstance,\r\n sessionId: string,\r\n cookies: Pick<Cookies, \"set\">\r\n) {\r\n cookies.set(COOKIE_SESSION_KEY, sessionId, {\r\n secure: true,\r\n httpOnly: true,\r\n sameSite: \"lax\",\r\n expires: Date.now() + Number(auth.ttl) * 1000,\r\n });\r\n}\r\n\r\nexport function getSessionId(\r\n cookies: Pick<Cookies, \"get\">\r\n): string | null {\r\n return cookies.get(COOKIE_SESSION_KEY)?.value ?? null;\r\n}\r\n\r\nexport function deleteSessionCookie(\r\n cookies: Pick<Cookies, \"delete\">\r\n) {\r\n cookies.delete(COOKIE_SESSION_KEY);\r\n}\r\n","import { stringifyBigInt, generateSessionId } from \"./utils\";\r\nimport {\r\n getSessionId,\r\n deleteSessionCookie,\r\n Cookies,\r\n} from \"./cookie\";\r\nimport { AuthInstance } from \"./types\";\r\nimport { COOKIE_SESSION_KEY } from \"./keys\";\r\n\r\nexport async function getUserFromSession(\r\n auth: AuthInstance,\r\n cookies: Pick<Cookies, \"get\">\r\n) {\r\n const sessionId = cookies.get(COOKIE_SESSION_KEY)?.value;\r\n if (!sessionId) return null;\r\n\r\n const data = await auth._redis.get<string>(`session:${sessionId}`)\r\n if (!data) return null;\r\n\r\n return auth._schema.parse(JSON.parse(data));\r\n}\r\n\r\nexport async function createUserSession<T>(\r\n auth: AuthInstance,\r\n user: T,\r\n cookies: Pick<Cookies, \"set\">\r\n) {\r\n const sessionId = generateSessionId();\r\n const data = auth._schema.parse(user);\r\n\r\n await auth._redis.set(\r\n `session:${sessionId}`,\r\n stringifyBigInt(data),\r\n { ex: auth.ttl }\r\n );\r\n\r\n cookies.set(COOKIE_SESSION_KEY, sessionId, {\r\n httpOnly: true,\r\n secure: true,\r\n sameSite: \"lax\",\r\n expires: Math.floor(Date.now() / 1000) + auth.ttl,\r\n });\r\n}\r\n\r\nexport async function updateUserSession<T>(\r\n auth: AuthInstance,\r\n user: T,\r\n cookies: Pick<Cookies, \"get\">\r\n) {\r\n const sessionId = getSessionId(cookies);\r\n if (!sessionId) return null;\r\n\r\n const data = auth._schema.parse(user);\r\n\r\n await auth._redis.set(\r\n `session:${sessionId}`,\r\n stringifyBigInt(data),\r\n { ex: auth.ttl }\r\n );\r\n}\r\n\r\nexport async function removeUserFromSession(\r\n auth: AuthInstance,\r\n cookies: Pick<Cookies, \"get\" | \"delete\">\r\n) {\r\n const sessionId = getSessionId(cookies);\r\n if (!sessionId) return null;\r\n\r\n await auth._redis.del(`session:${sessionId}`);\r\n deleteSessionCookie(cookies);\r\n}\r\n"],"mappings":"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","names":["crypto","crypto"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nova-auth",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Custom authentication system for apps",
|
|
5
|
+
"main": "dist/index.cjs.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"author": "Taimoor Safdar",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@upstash/redis": "^1.34.0",
|
|
24
|
+
"zod": "^3.23.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^20.0.0",
|
|
28
|
+
"tsup": "^8.5.1",
|
|
29
|
+
"typescript": "^5.4.0"
|
|
30
|
+
}
|
|
31
|
+
}
|