sentri 1.0.4 → 1.0.6

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.
Files changed (53) hide show
  1. package/README.md +314 -860
  2. package/dist/cli.js +79 -26
  3. package/dist/cli.js.map +1 -1
  4. package/dist/client.d.ts +34 -69
  5. package/dist/client.d.ts.map +1 -1
  6. package/dist/client.js +0 -6
  7. package/dist/client.js.map +1 -1
  8. package/dist/index.d.ts +1 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/libs/config.d.ts +45 -1
  12. package/dist/libs/config.d.ts.map +1 -1
  13. package/dist/libs/config.js +40 -2
  14. package/dist/libs/config.js.map +1 -1
  15. package/dist/libs/hash.d.ts +14 -0
  16. package/dist/libs/hash.d.ts.map +1 -1
  17. package/dist/libs/hash.js +14 -0
  18. package/dist/libs/hash.js.map +1 -1
  19. package/dist/libs/token.d.ts +37 -0
  20. package/dist/libs/token.d.ts.map +1 -1
  21. package/dist/libs/token.js +63 -0
  22. package/dist/libs/token.js.map +1 -1
  23. package/dist/middleware/authorize.d.ts +15 -0
  24. package/dist/middleware/authorize.d.ts.map +1 -1
  25. package/dist/middleware/authorize.js +18 -3
  26. package/dist/middleware/authorize.js.map +1 -1
  27. package/dist/middleware/permit.d.ts +8 -8
  28. package/dist/middleware/permit.d.ts.map +1 -1
  29. package/dist/middleware/permit.js +10 -10
  30. package/dist/middleware/permit.js.map +1 -1
  31. package/dist/middleware/protect.d.ts +17 -0
  32. package/dist/middleware/protect.d.ts.map +1 -1
  33. package/dist/middleware/protect.js +22 -5
  34. package/dist/middleware/protect.js.map +1 -1
  35. package/dist/middleware/router.d.ts +10 -6
  36. package/dist/middleware/router.d.ts.map +1 -1
  37. package/dist/middleware/router.js +122 -124
  38. package/dist/middleware/router.js.map +1 -1
  39. package/dist/services/auth.d.ts +78 -2
  40. package/dist/services/auth.d.ts.map +1 -1
  41. package/dist/services/auth.js +90 -5
  42. package/dist/services/auth.js.map +1 -1
  43. package/dist/types/auth.d.ts +176 -2
  44. package/dist/types/auth.d.ts.map +1 -1
  45. package/dist/types/auth.js +20 -1
  46. package/dist/types/auth.js.map +1 -1
  47. package/package.json +11 -3
  48. package/templates/drizzle/adapter.ts +154 -0
  49. package/templates/drizzle/auth.ts +47 -0
  50. package/templates/drizzle/schema.ts +47 -0
  51. package/templates/prisma/adapter.ts +122 -0
  52. package/templates/prisma/auth.ts +50 -0
  53. /package/templates/{schema.prisma → prisma/schema.prisma} +0 -0
@@ -1,8 +1,10 @@
1
1
  import { Router } from 'express';
2
2
  import { AuthError } from '../errors/AuthError.js';
3
- import { signup, login, refresh, logout, logoutAll } from '../services/auth.js';
3
+ import { authErrorStatus } from '../types/auth.js';
4
+ import { signup, login, refresh, logout, logoutAll, assignRoles } from '../services/auth.js';
4
5
  import { resolveConfig, parseExpiry } from '../libs/config.js';
5
6
  import { protect } from './protect.js';
7
+ import { authorize } from './authorize.js';
6
8
  const MIN_PASSWORD_LENGTH = 8;
7
9
  // bcrypt silently truncates input beyond 72 bytes. Enforcing a cap makes the
8
10
  // truncation boundary explicit so two passwords that share the same first 72
@@ -12,6 +14,13 @@ const MAX_IDENTIFIER_LENGTH = 255;
12
14
  function badRequest(message) {
13
15
  return new AuthError('VALIDATION_ERROR', message);
14
16
  }
17
+ function ok(response, statusCode, message, data) {
18
+ response.status(statusCode).json({ error: false, statusCode, message, data });
19
+ }
20
+ function fail(response, error) {
21
+ const statusCode = authErrorStatus(error.code);
22
+ response.status(statusCode).json({ error: true, statusCode, message: error.message, data: null });
23
+ }
15
24
  function parseBody(body) {
16
25
  if (body === null || body === undefined || typeof body !== 'object' || Array.isArray(body)) {
17
26
  throw new AuthError('VALIDATION_ERROR', 'Request body is missing or not a JSON object. Did you apply express.json()?');
@@ -24,25 +33,28 @@ function readCookie(cookieHeader, name) {
24
33
  return undefined;
25
34
  const pair = cookieHeader
26
35
  .split(';')
27
- .map((s) => s.trim())
28
- .find((s) => s.startsWith(`${name}=`));
36
+ .map((segment) => segment.trim())
37
+ .find((segment) => segment.startsWith(`${name}=`));
29
38
  return pair !== undefined ? pair.slice(name.length + 1) : undefined;
30
39
  }
31
- function setCookie(res, token, config) {
32
- const cfg = config.cookie;
40
+ function getCookieName(config) {
41
+ return config.cookie?.name ?? 'refresh_token';
42
+ }
43
+ function setCookie(response, token, config) {
44
+ const cookieConfig = config.cookie ?? {};
33
45
  const resolved = resolveConfig(config);
34
46
  const maxAge = parseExpiry(resolved.refreshExpiresIn);
35
- res.cookie(cfg.name ?? 'refresh_token', token, {
36
- httpOnly: cfg.httpOnly ?? true,
37
- secure: cfg.secure ?? false,
38
- sameSite: cfg.sameSite ?? 'strict',
39
- path: cfg.path ?? '/',
47
+ response.cookie(getCookieName(config), token, {
48
+ httpOnly: cookieConfig.httpOnly ?? true,
49
+ secure: cookieConfig.secure ?? false,
50
+ sameSite: cookieConfig.sameSite ?? 'strict',
51
+ path: cookieConfig.path ?? '/',
40
52
  maxAge,
41
53
  });
42
54
  }
43
- function clearCookie(res, config) {
44
- const cfg = config.cookie;
45
- res.clearCookie(cfg.name ?? 'refresh_token', { path: cfg.path ?? '/' });
55
+ function clearCookie(response, config) {
56
+ const cookieConfig = config.cookie ?? {};
57
+ response.clearCookie(getCookieName(config), { path: cookieConfig.path ?? '/' });
46
58
  }
47
59
  /**
48
60
  * Creates a pre-built Express Router with all standard auth endpoints.
@@ -50,12 +62,13 @@ function clearCookie(res, config) {
50
62
  * Mount it once and all routes are ready:
51
63
  *
52
64
  * ```
53
- * POST /signup — register a new user
54
- * POST /login — authenticate and get tokens
55
- * POST /refresh — rotate refresh token
56
- * POST /logout — invalidate current session
57
- * POST /logout-all — invalidate all sessions for the authenticated user
58
- * GET /me — return the currently authenticated user
65
+ * POST /signup — register a new user
66
+ * POST /login — authenticate and get tokens
67
+ * POST /refresh — rotate refresh token
68
+ * POST /logout — invalidate current session
69
+ * POST /logout-all — invalidate all sessions for the authenticated user
70
+ * GET /me — return the currently authenticated user
71
+ * POST /users/:userId/roles — assign roles (admin only)
59
72
  * ```
60
73
  *
61
74
  * Requires `express.json()` to be applied before the router.
@@ -63,16 +76,26 @@ function clearCookie(res, config) {
63
76
  * When `cookie` is set in config, the refresh token is stored in an httpOnly
64
77
  * cookie automatically — no `cookie-parser` needed.
65
78
  *
79
+ * When `router` is set in config, individual service functions can be replaced
80
+ * while the router still handles validation and response formatting.
81
+ *
66
82
  * @example
67
83
  * app.use(express.json());
68
84
  * app.use('/auth', auth.router());
69
85
  */
70
86
  export function createAuthRouter(config) {
71
87
  const router = Router();
72
- const cookieMode = config.cookie !== undefined;
73
- router.post('/signup', async (req, res, next) => {
88
+ // Resolve service functions — use custom override from config.router when provided, else fall back to the built-in service.
89
+ const baseConfig = config;
90
+ const signupFn = config.router?.signup ?? ((input) => signup(input, baseConfig));
91
+ const loginFn = config.router?.login ?? ((input) => login(input, baseConfig));
92
+ const refreshFn = config.router?.refresh ?? ((token) => refresh(token, baseConfig));
93
+ const logoutFn = config.router?.logout ?? ((token) => token !== undefined ? logout(token, baseConfig) : Promise.resolve());
94
+ const logoutAllFn = config.router?.logoutAll ?? ((userId) => logoutAll(userId, baseConfig));
95
+ const assignRolesFn = config.router?.assignRoles ?? ((userId, roles) => assignRoles(userId, roles, baseConfig));
96
+ router.post('/signup', async (request, response, next) => {
74
97
  try {
75
- const body = parseBody(req.body);
98
+ const body = parseBody(request.body);
76
99
  const { identifier, password, roles } = body;
77
100
  if (typeof identifier !== 'string' || identifier.trim().length === 0) {
78
101
  throw badRequest('identifier is required and must be a non-empty string');
@@ -89,38 +112,27 @@ export function createAuthRouter(config) {
89
112
  if (roles !== undefined && !Array.isArray(roles)) {
90
113
  throw badRequest('roles must be an array of strings when provided');
91
114
  }
92
- if (Array.isArray(roles) && !roles.every((r) => typeof r === 'string')) {
115
+ if (Array.isArray(roles) && !roles.every((role) => typeof role === 'string')) {
93
116
  throw badRequest('each role must be a string');
94
117
  }
95
118
  const rolesInput = Array.isArray(roles) ? roles : undefined;
96
119
  const input = rolesInput !== undefined
97
120
  ? { identifier: identifier.trim(), password, roles: rolesInput }
98
121
  : { identifier: identifier.trim(), password };
99
- const result = await signup(input, config);
122
+ const result = await signupFn(input);
100
123
  if (!result.success) {
101
- const status = result.error.code === 'USER_ALREADY_EXISTS' ? 409 : 400;
102
- res.status(status).json({ code: result.error.code, message: result.error.message });
124
+ fail(response, result.error);
103
125
  return;
104
126
  }
105
- if (cookieMode) {
106
- setCookie(res, result.refreshToken, config);
107
- res.status(201).json({ accessToken: result.accessToken, user: result.user });
108
- }
109
- else {
110
- res.status(201).json({
111
- accessToken: result.accessToken,
112
- refreshToken: result.refreshToken,
113
- user: result.user,
114
- });
115
- }
127
+ ok(response, 201, 'User registered successfully', { user: result.user });
116
128
  }
117
- catch (err) {
118
- next(err);
129
+ catch (error) {
130
+ next(error);
119
131
  }
120
132
  });
121
- router.post('/login', async (req, res, next) => {
133
+ router.post('/login', async (request, response, next) => {
122
134
  try {
123
- const body = parseBody(req.body);
135
+ const body = parseBody(request.body);
124
136
  const { identifier, password } = body;
125
137
  if (typeof identifier !== 'string' || identifier.trim().length === 0) {
126
138
  throw badRequest('identifier is required and must be a non-empty string');
@@ -134,110 +146,96 @@ export function createAuthRouter(config) {
134
146
  if (password.length > MAX_PASSWORD_LENGTH) {
135
147
  throw badRequest(`password must not exceed ${MAX_PASSWORD_LENGTH} characters`);
136
148
  }
137
- const result = await login({ identifier: identifier.trim(), password }, config);
149
+ const result = await loginFn({ identifier: identifier.trim(), password });
138
150
  if (!result.success) {
139
- res.status(401).json({ code: result.error.code, message: result.error.message });
151
+ fail(response, result.error);
140
152
  return;
141
153
  }
142
- if (cookieMode) {
143
- setCookie(res, result.refreshToken, config);
144
- res.json({ accessToken: result.accessToken, user: result.user });
145
- }
146
- else {
147
- res.json({
148
- accessToken: result.accessToken,
149
- refreshToken: result.refreshToken,
150
- user: result.user,
151
- });
152
- }
154
+ setCookie(response, result.refreshToken, config);
155
+ ok(response, 200, 'Login successful', { accessToken: result.accessToken, user: result.user });
153
156
  }
154
- catch (err) {
155
- next(err);
157
+ catch (error) {
158
+ next(error);
156
159
  }
157
160
  });
158
- router.post('/refresh', async (req, res, next) => {
161
+ router.post('/refresh', async (request, response, next) => {
159
162
  try {
160
- let refreshToken;
161
- if (cookieMode) {
162
- const fromCookie = readCookie(req.headers['cookie'], config.cookie?.name ?? 'refresh_token');
163
- if (!fromCookie) {
164
- throw new AuthError('UNAUTHORIZED', 'Refresh token cookie is missing');
165
- }
166
- refreshToken = fromCookie;
167
- }
168
- else {
169
- const body = parseBody(req.body);
170
- const { refreshToken: fromBody } = body;
171
- if (typeof fromBody !== 'string' || fromBody.trim().length === 0) {
172
- throw badRequest('refreshToken is required');
173
- }
174
- refreshToken = fromBody;
175
- }
176
- const result = await refresh(refreshToken, config);
163
+ const fromCookie = readCookie(request.headers['cookie'], getCookieName(config));
164
+ if (!fromCookie) {
165
+ throw new AuthError('UNAUTHORIZED', 'Refresh token cookie is missing');
166
+ }
167
+ const result = await refreshFn(fromCookie);
177
168
  if (!result.success) {
178
- if (cookieMode)
179
- clearCookie(res, config);
180
- res.status(401).json({ code: result.error.code, message: result.error.message });
169
+ clearCookie(response, config);
170
+ fail(response, result.error);
181
171
  return;
182
172
  }
183
- if (cookieMode) {
184
- setCookie(res, result.refreshToken, config);
185
- res.json({ accessToken: result.accessToken });
186
- }
187
- else {
188
- res.json({
189
- accessToken: result.accessToken,
190
- refreshToken: result.refreshToken,
191
- });
192
- }
173
+ setCookie(response, result.refreshToken, config);
174
+ ok(response, 200, 'Token refreshed', { accessToken: result.accessToken });
193
175
  }
194
- catch (err) {
195
- next(err);
176
+ catch (error) {
177
+ next(error);
196
178
  }
197
179
  });
198
- router.post('/logout', async (req, res, next) => {
180
+ router.post('/logout', async (request, response, next) => {
199
181
  try {
200
- let refreshToken;
201
- if (cookieMode) {
202
- const fromCookie = readCookie(req.headers['cookie'], config.cookie?.name ?? 'refresh_token');
203
- if (!fromCookie) {
204
- // Nothing to revoke, just clear the cookie and return success
205
- clearCookie(res, config);
206
- res.json({ message: 'logged out' });
207
- return;
208
- }
209
- refreshToken = fromCookie;
210
- }
211
- else {
212
- const body = parseBody(req.body);
213
- const { refreshToken: fromBody } = body;
214
- if (typeof fromBody !== 'string' || fromBody.trim().length === 0) {
215
- throw badRequest('refreshToken is required');
216
- }
217
- refreshToken = fromBody;
218
- }
219
- await logout(refreshToken, config);
220
- if (cookieMode)
221
- clearCookie(res, config);
222
- res.json({ message: 'logged out' });
182
+ const fromCookie = readCookie(request.headers['cookie'], getCookieName(config));
183
+ await logoutFn(fromCookie);
184
+ clearCookie(response, config);
185
+ ok(response, 200, 'Logged out', null);
223
186
  }
224
- catch (err) {
225
- next(err);
187
+ catch (error) {
188
+ next(error);
226
189
  }
227
190
  });
228
- router.post('/logout-all', protect(config), async (req, res, next) => {
191
+ router.post('/logout-all', protect(config), async (request, response, next) => {
229
192
  try {
230
- await logoutAll(req.user.id, config);
231
- if (cookieMode)
232
- clearCookie(res, config);
233
- res.json({ message: 'all sessions revoked' });
193
+ await logoutAllFn(request.user.id);
194
+ clearCookie(response, config);
195
+ ok(response, 200, 'All sessions revoked', null);
234
196
  }
235
- catch (err) {
236
- next(err);
197
+ catch (error) {
198
+ next(error);
237
199
  }
238
200
  });
239
- router.get('/me', protect(config), (req, res) => {
240
- res.json(req.user);
201
+ router.get('/me', protect(config), (request, response) => {
202
+ ok(response, 200, 'OK', request.user);
203
+ });
204
+ router.post('/users/:userId/roles', protect(config), authorize('admin'), async (request, response, next) => {
205
+ try {
206
+ const body = parseBody(request.body);
207
+ const { roles } = body;
208
+ const rawUserId = request.params['userId'];
209
+ const userId = typeof rawUserId === 'string' ? rawUserId : undefined;
210
+ if (!userId) {
211
+ throw badRequest('userId is required');
212
+ }
213
+ if (!Array.isArray(roles) || roles.length === 0) {
214
+ throw badRequest('roles must be a non-empty array of strings');
215
+ }
216
+ if (!roles.every((role) => typeof role === 'string')) {
217
+ throw badRequest('each role must be a string');
218
+ }
219
+ const result = await assignRolesFn(userId, roles);
220
+ if (!result.success) {
221
+ fail(response, result.error);
222
+ return;
223
+ }
224
+ ok(response, 200, 'Roles assigned successfully', { user: result.user });
225
+ }
226
+ catch (error) {
227
+ next(error);
228
+ }
229
+ });
230
+ // Centralized error handler — converts AuthError (and unexpected errors) to the
231
+ // standard envelope so every endpoint produces a consistent shape on failure.
232
+ router.use((error, _request, response, _next) => {
233
+ if (error instanceof AuthError) {
234
+ fail(response, error);
235
+ }
236
+ else {
237
+ response.status(500).json({ error: true, statusCode: 500, message: 'Internal server error', data: null });
238
+ }
241
239
  });
242
240
  return router;
243
241
  }
@@ -1 +1 @@
1
- {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/middleware/router.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/middleware/router.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,83 @@
1
- import type { AuthConfig, AuthResult, LoginInput, RefreshResult, SignupInput } from '../types/auth.js';
2
- export declare function signup(input: SignupInput, config: AuthConfig): Promise<AuthResult>;
1
+ import type { AssignRolesResult, AuthConfig, AuthResult, LoginInput, RefreshResult, SignupInput, SignupResult } from '../types/auth.js';
2
+ /**
3
+ * Register a new user.
4
+ *
5
+ * Validates that every requested role is in `validRoles`, rejects duplicate
6
+ * identifiers, hashes the password with bcrypt, creates the user record via
7
+ * the adapter, and returns the created user.
8
+ *
9
+ * No tokens are issued — the caller should invoke `login` after signup if
10
+ * immediate authentication is desired.
11
+ *
12
+ * @param input - Signup data: identifier, plain-text password, and optional roles.
13
+ * @param config - Auth configuration containing the adapter and role definitions.
14
+ * @returns `{ success: true, user }` on success, or `{ success: false, error }` with
15
+ * code `INVALID_ROLE` or `USER_ALREADY_EXISTS` on failure.
16
+ */
17
+ export declare function signup(input: SignupInput, config: AuthConfig): Promise<SignupResult>;
18
+ /**
19
+ * Authenticate an existing user by identifier and plain-text password.
20
+ *
21
+ * Looks up the user, verifies the password with bcrypt, creates a new session,
22
+ * and issues a JWT access token + refresh token pair.
23
+ *
24
+ * The failure response always uses code `INVALID_CREDENTIALS` regardless of
25
+ * whether the identifier or the password was wrong, preventing user enumeration.
26
+ *
27
+ * @param input - Login data: identifier and plain-text password.
28
+ * @param config - Auth configuration containing the adapter and JWT settings.
29
+ * @returns `{ success: true, accessToken, refreshToken, user }` on success, or
30
+ * `{ success: false, error }` with code `INVALID_CREDENTIALS` on failure.
31
+ */
3
32
  export declare function login(input: LoginInput, config: AuthConfig): Promise<AuthResult>;
33
+ /**
34
+ * Exchange a valid refresh token for a new access + refresh token pair.
35
+ *
36
+ * Implements **session rotation**: the old session is deleted and a fresh
37
+ * session is created, so each refresh token is single-use. An attacker
38
+ * replaying a stolen refresh token after it has already been rotated will
39
+ * find the session gone.
40
+ *
41
+ * @param refreshToken - The JWT refresh token (typically from an httpOnly cookie).
42
+ * @param config - Auth configuration containing the adapter and JWT settings.
43
+ * @returns `{ success: true, accessToken, refreshToken, user }` on success, or
44
+ * `{ success: false, error }` with code `UNAUTHORIZED`, `TOKEN_EXPIRED`, or
45
+ * `TOKEN_INVALID` on failure.
46
+ */
4
47
  export declare function refresh(refreshToken: string, config: AuthConfig): Promise<RefreshResult>;
48
+ /**
49
+ * Invalidate a single session identified by a refresh token.
50
+ *
51
+ * Safe to call even when the token is already expired or invalid — the JWT
52
+ * parse failure is silently swallowed and the function resolves normally.
53
+ * This makes logout idempotent from the client's perspective.
54
+ *
55
+ * @param refreshToken - The JWT refresh token bound to the session to revoke.
56
+ * @param config - Auth configuration containing the adapter and JWT settings.
57
+ */
5
58
  export declare function logout(refreshToken: string, config: AuthConfig): Promise<void>;
59
+ /**
60
+ * Delete all sessions for a user, effectively logging them out of every device.
61
+ *
62
+ * Delegates to `adapter.session.deleteAllForUser`. No token is required — the
63
+ * router route that calls this function is already guarded by `protect()`.
64
+ *
65
+ * @param userId - The user's primary key as stored in the database.
66
+ * @param config - Auth configuration containing the adapter.
67
+ */
6
68
  export declare function logoutAll(userId: string, config: AuthConfig): Promise<void>;
69
+ /**
70
+ * Add roles to a user account, merging them with any existing roles.
71
+ *
72
+ * Validates that every role in `rolesToAdd` is listed in `config.validRoles`.
73
+ * The resulting role set is deduplicated before being persisted via
74
+ * `adapter.user.updateRoles`.
75
+ *
76
+ * @param userId - The primary key of the user to update.
77
+ * @param rolesToAdd - Role names to assign. Must all be present in `validRoles`.
78
+ * @param config - Auth configuration containing the adapter and role definitions.
79
+ * @returns `{ success: true, user }` on success, or `{ success: false, error }` with
80
+ * code `INVALID_ROLE` or `USER_NOT_FOUND` on failure.
81
+ */
82
+ export declare function assignRoles(userId: string, rolesToAdd: string[], config: AuthConfig): Promise<AssignRolesResult>;
7
83
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/services/auth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEvG,wBAAsB,MAAM,CAC1B,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,UAAU,CAAC,CAyBrB;AAED,wBAAsB,KAAK,CACzB,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,UAAU,CAAC,CAoBrB;AAED,wBAAsB,OAAO,CAC3B,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,aAAa,CAAC,CA8BxB;AAED,wBAAsB,MAAM,CAC1B,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,IAAI,CAAC,CAQf;AAED,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,IAAI,CAAC,CAEf"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/services/auth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAExI;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,MAAM,CAC1B,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,YAAY,CAAC,CAoBvB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,KAAK,CACzB,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,UAAU,CAAC,CAoBrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,OAAO,CAC3B,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,aAAa,CAAC,CA8BxB;AAED;;;;;;;;;GASG;AACH,wBAAsB,MAAM,CAC1B,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAAE,EACpB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,iBAAiB,CAAC,CAiB5B"}
@@ -2,6 +2,21 @@ import { AuthError } from '../errors/AuthError.js';
2
2
  import { hashPassword, verifyPassword } from '../libs/hash.js';
3
3
  import { signAccessToken, signRefreshToken, verifyRefreshToken } from '../libs/token.js';
4
4
  import { resolveConfig, parseExpiry } from '../libs/config.js';
5
+ /**
6
+ * Register a new user.
7
+ *
8
+ * Validates that every requested role is in `validRoles`, rejects duplicate
9
+ * identifiers, hashes the password with bcrypt, creates the user record via
10
+ * the adapter, and returns the created user.
11
+ *
12
+ * No tokens are issued — the caller should invoke `login` after signup if
13
+ * immediate authentication is desired.
14
+ *
15
+ * @param input - Signup data: identifier, plain-text password, and optional roles.
16
+ * @param config - Auth configuration containing the adapter and role definitions.
17
+ * @returns `{ success: true, user }` on success, or `{ success: false, error }` with
18
+ * code `INVALID_ROLE` or `USER_ALREADY_EXISTS` on failure.
19
+ */
5
20
  export async function signup(input, config) {
6
21
  const resolved = resolveConfig(config);
7
22
  const requestedRoles = input.roles ?? [];
@@ -16,13 +31,23 @@ export async function signup(input, config) {
16
31
  }
17
32
  const passwordHash = await hashPassword(input.password, resolved.saltRounds);
18
33
  const created = await resolved.adapter.user.create({ identifier, passwordHash, roles: requestedRoles });
19
- const expiresAt = new Date(Date.now() + parseExpiry(resolved.refreshExpiresIn));
20
- const session = await resolved.adapter.session.create({ userId: created.id, expiresAt });
21
34
  const user = { id: created.id, identifier, roles: requestedRoles };
22
- const accessToken = signAccessToken(user, config);
23
- const refreshToken = signRefreshToken(session.id, config);
24
- return { success: true, accessToken, refreshToken, user };
35
+ return { success: true, user };
25
36
  }
37
+ /**
38
+ * Authenticate an existing user by identifier and plain-text password.
39
+ *
40
+ * Looks up the user, verifies the password with bcrypt, creates a new session,
41
+ * and issues a JWT access token + refresh token pair.
42
+ *
43
+ * The failure response always uses code `INVALID_CREDENTIALS` regardless of
44
+ * whether the identifier or the password was wrong, preventing user enumeration.
45
+ *
46
+ * @param input - Login data: identifier and plain-text password.
47
+ * @param config - Auth configuration containing the adapter and JWT settings.
48
+ * @returns `{ success: true, accessToken, refreshToken, user }` on success, or
49
+ * `{ success: false, error }` with code `INVALID_CREDENTIALS` on failure.
50
+ */
26
51
  export async function login(input, config) {
27
52
  const resolved = resolveConfig(config);
28
53
  const found = await resolved.adapter.user.findByIdentifier(input.identifier.trim());
@@ -40,6 +65,20 @@ export async function login(input, config) {
40
65
  const refreshToken = signRefreshToken(session.id, config);
41
66
  return { success: true, accessToken, refreshToken, user };
42
67
  }
68
+ /**
69
+ * Exchange a valid refresh token for a new access + refresh token pair.
70
+ *
71
+ * Implements **session rotation**: the old session is deleted and a fresh
72
+ * session is created, so each refresh token is single-use. An attacker
73
+ * replaying a stolen refresh token after it has already been rotated will
74
+ * find the session gone.
75
+ *
76
+ * @param refreshToken - The JWT refresh token (typically from an httpOnly cookie).
77
+ * @param config - Auth configuration containing the adapter and JWT settings.
78
+ * @returns `{ success: true, accessToken, refreshToken, user }` on success, or
79
+ * `{ success: false, error }` with code `UNAUTHORIZED`, `TOKEN_EXPIRED`, or
80
+ * `TOKEN_INVALID` on failure.
81
+ */
43
82
  export async function refresh(refreshToken, config) {
44
83
  const resolved = resolveConfig(config);
45
84
  let sessionId;
@@ -68,6 +107,16 @@ export async function refresh(refreshToken, config) {
68
107
  const newRefreshToken = signRefreshToken(newSession.id, config);
69
108
  return { success: true, accessToken: newAccessToken, refreshToken: newRefreshToken, user };
70
109
  }
110
+ /**
111
+ * Invalidate a single session identified by a refresh token.
112
+ *
113
+ * Safe to call even when the token is already expired or invalid — the JWT
114
+ * parse failure is silently swallowed and the function resolves normally.
115
+ * This makes logout idempotent from the client's perspective.
116
+ *
117
+ * @param refreshToken - The JWT refresh token bound to the session to revoke.
118
+ * @param config - Auth configuration containing the adapter and JWT settings.
119
+ */
71
120
  export async function logout(refreshToken, config) {
72
121
  let sessionId;
73
122
  try {
@@ -78,7 +127,43 @@ export async function logout(refreshToken, config) {
78
127
  }
79
128
  await resolveConfig(config).adapter.session.delete(sessionId);
80
129
  }
130
+ /**
131
+ * Delete all sessions for a user, effectively logging them out of every device.
132
+ *
133
+ * Delegates to `adapter.session.deleteAllForUser`. No token is required — the
134
+ * router route that calls this function is already guarded by `protect()`.
135
+ *
136
+ * @param userId - The user's primary key as stored in the database.
137
+ * @param config - Auth configuration containing the adapter.
138
+ */
81
139
  export async function logoutAll(userId, config) {
82
140
  await resolveConfig(config).adapter.session.deleteAllForUser(userId);
83
141
  }
142
+ /**
143
+ * Add roles to a user account, merging them with any existing roles.
144
+ *
145
+ * Validates that every role in `rolesToAdd` is listed in `config.validRoles`.
146
+ * The resulting role set is deduplicated before being persisted via
147
+ * `adapter.user.updateRoles`.
148
+ *
149
+ * @param userId - The primary key of the user to update.
150
+ * @param rolesToAdd - Role names to assign. Must all be present in `validRoles`.
151
+ * @param config - Auth configuration containing the adapter and role definitions.
152
+ * @returns `{ success: true, user }` on success, or `{ success: false, error }` with
153
+ * code `INVALID_ROLE` or `USER_NOT_FOUND` on failure.
154
+ */
155
+ export async function assignRoles(userId, rolesToAdd, config) {
156
+ const resolved = resolveConfig(config);
157
+ const invalidRoles = rolesToAdd.filter((role) => !resolved.validRoles.includes(role));
158
+ if (invalidRoles.length > 0) {
159
+ return { success: false, error: new AuthError('INVALID_ROLE', `Invalid roles: ${invalidRoles.join(', ')}`) };
160
+ }
161
+ const found = await resolved.adapter.user.findById(userId);
162
+ if (!found) {
163
+ return { success: false, error: new AuthError('USER_NOT_FOUND', 'User not found') };
164
+ }
165
+ const mergedRoles = Array.from(new Set([...found.roles, ...rolesToAdd]));
166
+ await resolved.adapter.user.updateRoles(userId, mergedRoles);
167
+ return { success: true, user: { id: found.id, identifier: found.identifier, roles: mergedRoles } };
168
+ }
84
169
  //# sourceMappingURL=auth.js.map