From 54f6c06b975f2c1e32c6c48edaa5bc194b4d6f91 Mon Sep 17 00:00:00 2001 From: psibean Date: Fri, 18 Aug 2023 19:43:42 +0930 Subject: [PATCH] refactor!: swap generateToken request and response parameter order BREAKING CHANGE: generateToken(req, res, overwrite) --- README.md | 12 ++++++------ src/index.ts | 6 +++--- src/tests/testsuite.ts | 8 ++++---- src/tests/utils/mock.ts | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index e2cef1b..de2aef0 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ const { ```js const myRoute = (request, response) => { - const csrfToken = generateToken(response, request); + const csrfToken = generateToken(request, response); // You could also pass the token into the context of a HTML response. res.json({ csrfToken }); }; @@ -125,7 +125,7 @@ const myProtectedRoute = (req, res) =>

Instead of importing and using generateToken, you can also use req.csrfToken any time after the doubleCsrfProtection middleware has executed on your incoming request.

```js -request.csrfToken(); // same as generateToken(res, req); +request.csrfToken(); // same as generateToken(req, res); ```

@@ -324,20 +324,20 @@ number;

generateToken

```ts -(response: Response, request: Request, overwrite?: boolean) => string; +(request: Request, response: Response, overwrite?: boolean) => string; ```

By default if a csrf-csrf cookie already exists on an incoming request, generateToken will not overwrite it, it will simply return the existing token. If you wish to force a token generation, you can use the third parameter:

```ts -generateToken(res, req, true); // This will force a new token to be generated, and a new cookie to be set, even if one already exists +generateToken(req, res, true); // This will force a new token to be generated, and a new cookie to be set, even if one already exists ```

Instead of importing and using generateToken, you can also use req.csrfToken any time after the doubleCsrfProtection middleware has executed on your incoming request.

```ts -req.csrfToken(); // same as generateToken(res, req) and generateToken(res, req, false); -req.csrfToken(true); // same as generateToken(res, req, true); +req.csrfToken(); // same as generateToken(req, res) and generateToken(req, res, false); +req.csrfToken(true); // same as generateToken(req, res, true); ```

The generateToken function serves the purpose of establishing a CSRF (Cross-Site Request Forgery) protection mechanism by generating a token and an associated cookie. This function also provides the option to utilize a third parameter called overwrite. By default, this parameter is set to false.

diff --git a/src/index.ts b/src/index.ts index 8c4f02c..106cf90 100644 --- a/src/index.ts +++ b/src/index.ts @@ -54,8 +54,8 @@ export type CsrfCookieSetter = ( options: DoubleCsrfCookieOptions ) => void; export type CsrfTokenCreator = ( - res: Response, req: Request, + res: Response, ovewrite?: boolean ) => string; @@ -131,8 +131,8 @@ export function doubleCsrf({ // Do NOT send the csrfToken as a cookie, embed it in your HTML response, or as JSON. const generateToken: CsrfTokenCreator = ( - res: Response, req: Request, + res: Response, overwrite?: boolean ) => { const { csrfToken, csrfTokenHash } = generateTokenAndHash(req, overwrite); @@ -180,7 +180,7 @@ export function doubleCsrf({ }; const doubleCsrfProtection: doubleCsrfProtection = (req, res, next) => { - req.csrfToken = (overwrite?: boolean) => generateToken(res, req, overwrite); + req.csrfToken = (overwrite?: boolean) => generateToken(req, res, overwrite); if (ignoredMethodsSet.has(req.method as RequestMethod)) { next(); } else if (validateRequest(req)) { diff --git a/src/tests/testsuite.ts b/src/tests/testsuite.ts index 608e2ab..9580a02 100644 --- a/src/tests/testsuite.ts +++ b/src/tests/testsuite.ts @@ -87,7 +87,7 @@ export const createTestSuite: CreateTestsuite = (name, doubleCsrfOptions) => { mockResponse.setHeader("set-cookie", []); // overwrite is false by default - const generatedToken = generateToken(mockResponse, mockRequest); + const generatedToken = generateToken(mockRequest, mockResponse); const newCookieValue = getCookieFromResponse(mockResponse); assert.equal(generatedToken, csrfToken); @@ -105,7 +105,7 @@ export const createTestSuite: CreateTestsuite = (name, doubleCsrfOptions) => { // reset the mock response to have no cookies (in reality this would just be a new instance of Response) mockResponse.setHeader("set-cookie", []); - const generatedToken = generateToken(mockResponse, mockRequest, true); + const generatedToken = generateToken(mockRequest, mockResponse, true); const newCookieValue = getCookieFromResponse(mockResponse); assert.notEqual(newCookieValue, oldCookieValue); @@ -124,7 +124,7 @@ export const createTestSuite: CreateTestsuite = (name, doubleCsrfOptions) => { : (mockRequest.cookies[cookieName] = (decodedCookieValue as string).split("|")[0] + "|invalid-hash"); - expect(() => generateToken(mockResponse, mockRequest)).to.throw( + expect(() => generateToken(mockRequest, mockResponse)).to.throw( invalidCsrfTokenError.message ); @@ -136,7 +136,7 @@ export const createTestSuite: CreateTestsuite = (name, doubleCsrfOptions) => { )}`) : (mockRequest.cookies[cookieName] = "invalid-value"); - expect(() => generateToken(mockResponse, mockRequest)).to.throw( + expect(() => generateToken(mockRequest, mockResponse)).to.throw( invalidCsrfTokenError.message ); }); diff --git a/src/tests/utils/mock.ts b/src/tests/utils/mock.ts index 1d44775..be3cd70 100644 --- a/src/tests/utils/mock.ts +++ b/src/tests/utils/mock.ts @@ -81,7 +81,7 @@ export const generateMocksWithToken = ({ }: GenerateMocksWithTokenOptions) => { const { mockRequest, mockResponse, mockResponseHeaders } = generateMocks(); - const csrfToken = generateToken(mockResponse, mockRequest); + const csrfToken = generateToken(mockRequest, mockResponse); const { setCookie, cookieValue } = getCookieValueFromResponse(mockResponse); mockRequest.headers.cookie = `${cookieName}=${cookieValue};`; const decodedCookieValue = signed