@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 +65 -20
- package/dist/toker-express.js +11 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ $ npm i @dwtechs/toker-express
|
|
|
47
47
|
```javascript
|
|
48
48
|
|
|
49
49
|
// @ts-check
|
|
50
|
-
import
|
|
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
|
-
|
|
70
|
-
|
|
69
|
+
parseBearerToken,
|
|
70
|
+
decodeAccess,
|
|
71
|
+
decodeRefresh,
|
|
71
72
|
checkToken,
|
|
72
|
-
|
|
73
|
+
refresh,
|
|
73
74
|
cEntity.update,
|
|
74
75
|
];
|
|
75
76
|
|
|
76
77
|
const del = [
|
|
77
78
|
checkToken,
|
|
78
|
-
|
|
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
|
|
164
|
+
* Express middleware function to parse the bearer token from the Authorization header.
|
|
163
165
|
*
|
|
164
|
-
* This middleware extracts the JWT
|
|
165
|
-
*
|
|
166
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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,
|
|
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()`
|
|
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
|
|
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`,
|
|
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
|
-
|
|
288
|
+
##### parseBearerToken()
|
|
260
289
|
|
|
261
|
-
|
|
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
|
-
|
|
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.
|
package/dist/toker-express.js
CHANGED
|
@@ -64,18 +64,23 @@ function refresh(req, res, next) {
|
|
|
64
64
|
}
|
|
65
65
|
next();
|
|
66
66
|
}
|
|
67
|
-
function
|
|
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
|
-
|
|
70
|
+
log.debug(`${LOGS_PREFIX}parse bearer token`);
|
|
72
71
|
try {
|
|
73
|
-
|
|
72
|
+
res.locals.accessToken = parseBearer(req.headers.authorization);
|
|
74
73
|
}
|
|
75
74
|
catch (e) {
|
|
76
75
|
return next(e);
|
|
77
76
|
}
|
|
78
|
-
|
|
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 };
|