@dwtechs/toker-express 0.4.0 → 0.5.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 CHANGED
@@ -47,7 +47,7 @@ $ npm i @dwtechs/toker-express
47
47
  ```javascript
48
48
 
49
49
  // @ts-check
50
- import * as tk from "@dwtechs/Toker-express";
50
+ import { refresh as refreshTokens, parseBearerToken, decodeAccess, decodeRefresh } from "@dwtechs/toker-express";
51
51
  import express from "express";
52
52
  const router = express.Router();
53
53
 
@@ -66,16 +66,18 @@ const add = [
66
66
 
67
67
  const refresh = [
68
68
  cEntity.validate,
69
- tk.decodeAccess,
70
- tk.decodeRefresh,
69
+ parseBearerToken,
70
+ decodeAccess,
71
+ decodeRefresh,
71
72
  checkToken,
72
- tk.refresh,
73
+ refresh,
73
74
  cEntity.update,
74
75
  ];
75
76
 
76
77
  const del = [
77
78
  checkToken,
78
- tk.decodeAccess,
79
+ parseBearerToken,
80
+ decodeAccess,
79
81
  cEntity.delete,
80
82
  ];
81
83
 
@@ -159,22 +161,42 @@ const refreshDuration = isNumber(REFRESH_TOKEN_DURATION, false) ? REFRESH_TOKEN_
159
161
  function refresh(req: Request, res: Response, next: NextFunction): void {}
160
162
 
161
163
  /**
162
- * Express middleware function to decode and verify an access token from the Authorization header.
164
+ * Express middleware function to parse the bearer token from the Authorization header.
163
165
  *
164
- * This middleware extracts the JWT access token from the Authorization header, validates its format,
165
- * verifies its signature, and attaches the decoded token to res.locals.decodedAccessToken for use by subsequent
166
- * middleware. It only processes requests that have `res.locals.isProtected` set to true.
166
+ * This middleware extracts the JWT token from the Authorization header (Bearer scheme)
167
+ * and stores it in res.locals.accessToken for use by subsequent middleware.
168
+ * It only processes requests that have `res.locals.isProtected` set to true.
167
169
  *
168
170
  * @param {Request} req - The Express request object containing the Authorization header
169
171
  * @param {Response} res - The Express response object. Should contain:
170
172
  * - `res.locals.isProtected`: Boolean flag to determine if route requires JWT protection
171
- * Decoded token will be added to `res.locals.decodedAccessToken`
173
+ * Parsed token will be added to `res.locals.accessToken`
172
174
  * @param {NextFunction} next - The next middleware function to be called
173
175
  *
174
- * @returns {void} Calls the next middleware function with an error object if the token is invalid or iss is missing.
176
+ * @returns {void} Calls the next middleware function with an error object if parsing fails.
175
177
  *
176
178
  * @throws {MissingAuthorizationError} If the Authorization header is missing (HTTP 401)
177
179
  * @throws {InvalidBearerFormatError} If the Authorization header format is invalid (HTTP 401)
180
+ *
181
+ */
182
+ function parseBearerToken(req: Request, res: Response, next: NextFunction): void {}
183
+
184
+ /**
185
+ * Express middleware function to decode and verify an access token.
186
+ *
187
+ * This middleware validates the JWT access token from res.locals.accessToken,
188
+ * verifies its signature, and attaches the decoded token to res.locals.decodedAccessToken
189
+ * for use by subsequent middleware. It only processes requests that have `res.locals.isProtected` set to true.
190
+ *
191
+ * @param {Request} req - The Express request object
192
+ * @param {Response} res - The Express response object. Should contain:
193
+ * - `res.locals.isProtected`: Boolean flag to determine if route requires JWT protection
194
+ * - `res.locals.accessToken`: The JWT token to decode
195
+ * Decoded token will be added to `res.locals.decodedAccessToken`
196
+ * @param {NextFunction} next - The next middleware function to be called
197
+ *
198
+ * @returns {void} Calls the next middleware function with an error object if the token is invalid or iss is missing.
199
+ *
178
200
  * @throws {InvalidTokenError} If the token is malformed or has invalid structure (HTTP 401)
179
201
  * @throws {ExpiredTokenError} If the token has expired (exp claim) (HTTP 401)
180
202
  * @throws {InactiveTokenError} If the token cannot be used yet (nbf claim) (HTTP 401)
@@ -186,7 +208,7 @@ function refresh(req: Request, res: Response, next: NextFunction): void {}
186
208
  * - statusCode: 400 - When decoded token is missing required 'iss' claim
187
209
  *
188
210
  */
189
- function decodeAccess(req: Request, _res: Response, next: NextFunction): void {}
211
+ function decodeAccess(req: Request, res: Response, next: NextFunction): void {}
190
212
 
191
213
  /**
192
214
  * Middleware function to decode and verify a refresh token from the request body.
@@ -239,9 +261,9 @@ if (isArray(rbr, ">=", 1) && isObject(rbr[0])) {
239
261
 
240
262
  #### Route Protection with isProtected
241
263
 
242
- The `decodeAccess()` middleware only processes requests when `res.locals.isProtected` is set to `true`. This allows you to selectively protect routes that require authentication.
264
+ The `parseBearerToken()` and `decodeAccess()` middlewares only process requests when `res.locals.isProtected` is set to `true`. This allows you to selectively protect routes that require authentication.
243
265
 
244
- You should set this flag in a middleware before calling `decodeAccess()`:
266
+ You should set this flag in a middleware before calling these functions:
245
267
 
246
268
  ```Javascript
247
269
  // Example middleware to mark route as protected
@@ -251,25 +273,48 @@ function protectRoute(req, res, next) {
251
273
  }
252
274
 
253
275
  // Usage
254
- router.get('/protected-route', protectRoute, tk.decodeAccess, yourHandler);
276
+ router.get('/protected-route', protectRoute, tk.parseBearerToken, tk.decodeAccess, yourHandler);
255
277
  ```
256
278
 
257
- If `res.locals.isProtected` is `false`, `undefined`, or `null`, the `decodeAccess()` middleware will simply call `next()` without processing the token, allowing the request to continue to the next middleware.
279
+ If `res.locals.isProtected` is `false`, `undefined`, or `null`, these middlewares will simply call `next()` without processing the token, allowing the request to continue to the next middleware.
280
+
281
+ #### Access Token Processing
282
+
283
+ The access token processing is now split into two separate middlewares for better flexibility:
284
+
285
+ 1. **parseBearerToken()** - Extracts the bearer token from the Authorization header
286
+ 2. **decodeAccess()** - Validates and decodes the JWT token
258
287
 
259
- #### Access Token Decoding
288
+ ##### parseBearerToken()
260
289
 
261
- decodeAccess() functions will look for a bearer in authorization headers.
290
+ This middleware extracts the JWT token from the Authorization header using the Bearer scheme.
262
291
 
263
292
  ```Javascript
264
- const bearer = req.headers.authorization;
293
+ const bearer = req.headers.authorization; // "Bearer <token>"
265
294
  ```
266
295
 
267
- It will then send the decoded token in the res object.
296
+ The parsed token is then stored in `res.locals.accessToken`:
297
+
298
+ ```Javascript
299
+ res.locals.accessToken = token;
300
+ ```
301
+
302
+ ##### decodeAccess()
303
+
304
+ This middleware takes the token from `res.locals.accessToken`, validates it, and decodes it.
305
+
306
+ ```Javascript
307
+ const token = res.locals.accessToken;
308
+ ```
309
+
310
+ The decoded token is then stored in `res.locals.decodedAccessToken`:
268
311
 
269
312
  ```Javascript
270
313
  res.locals.decodedAccessToken = decodedToken;
271
314
  ```
272
315
 
316
+ **Note:** You should use both middlewares in sequence for full access token processing, or you can use just `parseBearerToken()` if you only need to extract the token without decoding it.
317
+
273
318
  #### Refresh Token Decoding
274
319
 
275
320
  decodeRefresh() functions will look for a token in the client request body.
@@ -64,18 +64,23 @@ function refresh(req, res, next) {
64
64
  }
65
65
  next();
66
66
  }
67
- function decodeAccess(req, res, next) {
68
- log.debug(`${LOGS_PREFIX}decode access token`);
67
+ function parseBearerToken(req, res, next) {
69
68
  if (!res.locals.isProtected)
70
69
  return next();
71
- let t;
70
+ log.debug(`${LOGS_PREFIX}parse bearer token`);
72
71
  try {
73
- t = parseBearer(req.headers.authorization);
72
+ res.locals.accessToken = parseBearer(req.headers.authorization);
74
73
  }
75
74
  catch (e) {
76
75
  return next(e);
77
76
  }
78
- log.debug(`${LOGS_PREFIX}accessToken : ${t}`);
77
+ next();
78
+ }
79
+ function decodeAccess(_req, res, next) {
80
+ log.debug(`${LOGS_PREFIX}decode access token`);
81
+ if (!res.locals.isProtected)
82
+ return next();
83
+ const t = res.locals.accessToken;
79
84
  if (!isJWT(t))
80
85
  return next({ statusCode: 401, message: `${LOGS_PREFIX}Invalid access token` });
81
86
  let dt = null;
@@ -111,4 +116,4 @@ function decodeRefresh(req, res, next) {
111
116
  next();
112
117
  }
113
118
 
114
- export { decodeAccess, decodeRefresh, refresh };
119
+ export { decodeAccess, decodeRefresh, parseBearerToken, refresh };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dwtechs/toker-express",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Open source JWT management library for Express.js to refresh and decode tokens safely.",
5
5
  "keywords": [
6
6
  "JWT",