@mostajs/auth-lite 0.1.0 → 0.1.1
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.js +16 -20
- package/package.json +1 -4
package/dist/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { createHash, randomBytes, timingSafeEqual } from 'crypto';
|
|
2
|
-
import { baseFromHeaders } from '@mostajs/url';
|
|
3
2
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
3
|
+
* Réponse 303 avec un `Location` **relatif** (ex. `/dashboard`). Le navigateur
|
|
4
|
+
* le résout contre l'URL PUBLIQUE de la requête courante → fonctionne en
|
|
5
|
+
* WebContainer (StackBlitz/Bolt — qui ne transmettent pas l'hôte public au
|
|
6
|
+
* serveur), derrière un reverse proxy, et en localhost, **sans que le serveur
|
|
7
|
+
* ait besoin de connaître son hôte**. Plus robuste qu'une URL absolue.
|
|
9
8
|
*/
|
|
10
|
-
function
|
|
11
|
-
|
|
9
|
+
async function see(location) {
|
|
10
|
+
const { NextResponse } = await import('next/server');
|
|
11
|
+
return new NextResponse(null, { status: 303, headers: { Location: location } });
|
|
12
12
|
}
|
|
13
13
|
// ---------------------------------------------------------------------------
|
|
14
14
|
// Password hashing — salted, iterated SHA-256 (no native addon, boots anywhere)
|
|
@@ -59,48 +59,44 @@ export function createAuthHandlers(config) {
|
|
|
59
59
|
const afterLogout = config.afterLogout ?? '/';
|
|
60
60
|
const loginError = config.loginErrorPath ?? '/login?error=invalid';
|
|
61
61
|
const signupError = config.signupErrorPath ?? ((k) => `/signup?error=${k}`);
|
|
62
|
-
async function startSession(
|
|
63
|
-
const { NextResponse } = await import('next/server');
|
|
62
|
+
async function startSession(sessions, userId) {
|
|
64
63
|
const token = randomBytes(32).toString('hex');
|
|
65
64
|
const expiresAt = new Date(Date.now() + ttlMs);
|
|
66
65
|
await sessions.create({ token, user: userId, expiresAt });
|
|
67
|
-
const res =
|
|
66
|
+
const res = await see(afterAuth);
|
|
68
67
|
res.cookies.set(cookie, token, { httpOnly: true, sameSite: 'lax', path: '/', expires: expiresAt });
|
|
69
68
|
return res;
|
|
70
69
|
}
|
|
71
70
|
/** POST handler — verify credentials, start a session. */
|
|
72
71
|
async function login(req) {
|
|
73
|
-
const { NextResponse } = await import('next/server');
|
|
74
72
|
const form = await req.formData();
|
|
75
73
|
const email = String(form.get('email') ?? '').toLowerCase().trim();
|
|
76
74
|
const password = String(form.get('password') ?? '');
|
|
77
75
|
const { users, sessions } = await config.getRepos();
|
|
78
76
|
const user = await users.findOne({ email });
|
|
79
77
|
if (!user || !verifyPassword(password, user.passwordHash)) {
|
|
80
|
-
return
|
|
78
|
+
return see(loginError);
|
|
81
79
|
}
|
|
82
|
-
return startSession(
|
|
80
|
+
return startSession(sessions, user.id);
|
|
83
81
|
}
|
|
84
82
|
/** POST handler — create the account, start a session. */
|
|
85
83
|
async function signup(req) {
|
|
86
|
-
const { NextResponse } = await import('next/server');
|
|
87
84
|
const form = await req.formData();
|
|
88
85
|
const email = String(form.get('email') ?? '').toLowerCase().trim();
|
|
89
86
|
const name = String(form.get('name') ?? '').trim();
|
|
90
87
|
const password = String(form.get('password') ?? '');
|
|
91
88
|
if (!email || !name || password.length < 6) {
|
|
92
|
-
return
|
|
89
|
+
return see(signupError('invalid'));
|
|
93
90
|
}
|
|
94
91
|
const { users, sessions } = await config.getRepos();
|
|
95
92
|
if (await users.findOne({ email })) {
|
|
96
|
-
return
|
|
93
|
+
return see(signupError('exists'));
|
|
97
94
|
}
|
|
98
95
|
const user = await users.create({ email, name, passwordHash: hashPassword(password) });
|
|
99
|
-
return startSession(
|
|
96
|
+
return startSession(sessions, user.id);
|
|
100
97
|
}
|
|
101
98
|
/** POST handler — destroy the session (DB + cookie). */
|
|
102
99
|
async function logout(req) {
|
|
103
|
-
const { NextResponse } = await import('next/server');
|
|
104
100
|
const token = req.cookies.get(cookie)?.value;
|
|
105
101
|
if (token) {
|
|
106
102
|
const { sessions } = await config.getRepos();
|
|
@@ -108,7 +104,7 @@ export function createAuthHandlers(config) {
|
|
|
108
104
|
if (session)
|
|
109
105
|
await sessions.delete(session.id);
|
|
110
106
|
}
|
|
111
|
-
const res =
|
|
107
|
+
const res = await see(afterLogout);
|
|
112
108
|
res.cookies.delete(cookie);
|
|
113
109
|
return res;
|
|
114
110
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mostajs/auth-lite",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Minimal email/password + session auth for Next.js on @mostajs/orm. No native addon — boots in Bolt.new / StackBlitz / edge.",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"author": "Dr Hamid MADANI <drmdh@msn.com>",
|
|
@@ -57,8 +57,5 @@
|
|
|
57
57
|
"funding": {
|
|
58
58
|
"type": "github",
|
|
59
59
|
"url": "https://github.com/sponsors/apolocine"
|
|
60
|
-
},
|
|
61
|
-
"dependencies": {
|
|
62
|
-
"@mostajs/url": "^0.5.0"
|
|
63
60
|
}
|
|
64
61
|
}
|