Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@otterhttp/csrf-csrf

Package Overview
Dependencies
Maintainers
0
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@otterhttp/csrf-csrf - npm Package Compare versions

Comparing version 3.0.0 to 3.1.0

17

dist/index.d.ts

@@ -20,8 +20,8 @@ import { IncomingMessage, ServerResponse } from 'node:http';

type ResolvedCSRFCookieOptions = SerializeOptions & Required<ExtraCookieOptions>;
type TokenRetriever = (req: CSRFRequest) => string | null | undefined;
type CsrfSecretRetriever = (req?: CSRFRequest) => string | Array<string>;
type doubleCsrfProtection = (req: CSRFRequest, res: CSRFResponse, next: NextFunction) => void;
type TokenRetriever = (req: CSRFRequest) => string | null | undefined | Promise<string | null | undefined>;
type CsrfSecretRetriever = (req?: CSRFRequest) => string | Array<string> | Promise<string | Array<string>>;
type doubleCsrfProtection = (req: CSRFRequest, res: CSRFResponse, next: NextFunction) => Promise<void>;
type RequestMethod = "GET" | "HEAD" | "PATCH" | "PUT" | "POST" | "DELETE" | "CONNECT" | "OPTIONS" | "TRACE";
type CsrfIgnoredMethods = Array<RequestMethod>;
type CsrfRequestValidator = (req: CSRFRequest) => boolean;
type CsrfRequestValidator = (req: CSRFRequest) => Promise<boolean>;
type CsrfTokenAndHashPairValidator = (req: CSRFRequest, { incomingHash, incomingToken, possibleSecrets, }: {

@@ -31,5 +31,4 @@ incomingHash: unknown;

possibleSecrets: Array<string>;
}) => boolean;
type CsrfCookieSetter = (res: CSRFResponse, name: string, value: string, options: CSRFCookieOptions) => void;
type CsrfTokenCreator = (req: CSRFRequest, res: CSRFResponse, options?: GenerateCsrfTokenOptions) => string;
}) => Promise<boolean>;
type CsrfTokenCreator = (req: CSRFRequest, res: CSRFResponse, options?: GenerateCsrfTokenOptions) => Promise<string>;
type CsrfErrorConfig = {

@@ -49,3 +48,3 @@ statusCode: keyof typeof statusMessages;

getSecret: CsrfSecretRetriever;
getSessionIdentifier: (req: CSRFRequest) => string;
getSessionIdentifier: (req: CSRFRequest) => string | Promise<string>;
cookieOptions?: CSRFCookieOptions;

@@ -68,2 +67,2 @@ delimiter?: string;

export { type CSRFCookieOptions, type CSRFRequest, type CSRFResponse, type CsrfCookieSetter, type CsrfErrorConfig, type CsrfErrorConfigOptions, type CsrfIgnoredMethods, type CsrfRequestValidator, type CsrfSecretRetriever, type CsrfTokenAndHashPairValidator, type CsrfTokenCreator, type DoubleCsrfConfig, type DoubleCsrfUtilities, type GenerateCsrfTokenConfig, type GenerateCsrfTokenOptions, type RequestMethod, type ResolvedCSRFCookieOptions, type TokenRetriever, doubleCsrf, type doubleCsrfProtection };
export { type CSRFCookieOptions, type CSRFRequest, type CSRFResponse, type CsrfErrorConfig, type CsrfErrorConfigOptions, type CsrfIgnoredMethods, type CsrfRequestValidator, type CsrfSecretRetriever, type CsrfTokenAndHashPairValidator, type CsrfTokenCreator, type DoubleCsrfConfig, type DoubleCsrfUtilities, type GenerateCsrfTokenConfig, type GenerateCsrfTokenOptions, type RequestMethod, type ResolvedCSRFCookieOptions, type TokenRetriever, doubleCsrf, type doubleCsrfProtection };

@@ -38,4 +38,4 @@ // src/index.ts

});
const generateTokenAndHash = (req, { overwrite, validateOnReuse }) => {
const getSecretResult = getSecret(req);
const generateTokenAndHash = async (req, { overwrite, validateOnReuse }) => {
const getSecretResult = await getSecret(req);
const possibleSecrets = Array.isArray(getSecretResult) ? getSecretResult : [getSecretResult];

@@ -45,3 +45,3 @@ const csrfCookie = getCsrfCookieFromRequest(req);

const [csrfToken2, csrfTokenHash2] = csrfCookie.value.split(delimiter);
if (validateTokenAndHashPair(req, {
if (await validateTokenAndHashPair(req, {
incomingToken: csrfToken2,

@@ -59,7 +59,7 @@ incomingHash: csrfTokenHash2,

const secret = possibleSecrets[0];
const csrfTokenHash = createHmac(hmacAlgorithm, secret).update(`${getSessionIdentifier(req)}${csrfToken}`).digest("hex");
const csrfTokenHash = createHmac(hmacAlgorithm, secret).update(`${await getSessionIdentifier(req)}${csrfToken}`).digest("hex");
return { csrfToken, csrfTokenHash };
};
const generateToken = (req, res, { cookieOptions: cookieOptions2 = defaultCookieOptions, overwrite = false, validateOnReuse = true } = {}) => {
const { csrfToken, csrfTokenHash } = generateTokenAndHash(req, {
const generateToken = async (req, res, { cookieOptions: cookieOptions2 = defaultCookieOptions, overwrite = false, validateOnReuse = true } = {}) => {
const { csrfToken, csrfTokenHash } = await generateTokenAndHash(req, {
overwrite,

@@ -76,6 +76,6 @@ validateOnReuse

};
const validateTokenAndHashPair = (req, { incomingHash, incomingToken, possibleSecrets }) => {
const validateTokenAndHashPair = async (req, { incomingHash, incomingToken, possibleSecrets }) => {
if (typeof incomingToken !== "string" || typeof incomingHash !== "string") return false;
for (const secret of possibleSecrets) {
const expectedHash = createHmac(hmacAlgorithm, secret).update(`${getSessionIdentifier(req)}${incomingToken}`).digest("hex");
const expectedHash = createHmac(hmacAlgorithm, secret).update(`${await getSessionIdentifier(req)}${incomingToken}`).digest("hex");
if (incomingHash === expectedHash) return true;

@@ -85,10 +85,10 @@ }

};
const validateRequest = (req) => {
const validateRequest = async (req) => {
const csrfCookie = getCsrfCookieFromRequest(req);
if (typeof csrfCookie !== "object") return false;
const [csrfTokenFromCookie, csrfTokenHash] = csrfCookie.value.split(delimiter);
const csrfTokenFromRequest = getTokenFromRequest(req);
const getSecretResult = getSecret(req);
const csrfTokenFromRequest = await getTokenFromRequest(req);
const getSecretResult = await getSecret(req);
const possibleSecrets = Array.isArray(getSecretResult) ? getSecretResult : [getSecretResult];
return csrfTokenFromCookie === csrfTokenFromRequest && validateTokenAndHashPair(req, {
return csrfTokenFromCookie === csrfTokenFromRequest && await validateTokenAndHashPair(req, {
incomingToken: csrfTokenFromRequest,

@@ -99,10 +99,11 @@ incomingHash: csrfTokenHash,

};
const doubleCsrfProtection = (req, res, next) => {
const doubleCsrfProtection = async (req, res, next) => {
if (ignoredMethodsSet.has(req.method)) {
next();
} else if (validateRequest(req)) {
next();
} else {
return;
}
if (!await validateRequest(req)) {
throw invalidCsrfTokenError;
}
next();
};

@@ -109,0 +110,0 @@ return {

@@ -64,3 +64,3 @@ {

"packageManager": "pnpm@9.5.0",
"version": "3.0.0"
"version": "3.1.0"
}
# @otterjs/csrf-csrf
**Double-submit cookie pattern CSRF protection middleware for modern Node.js.**
**Double-submit cookie pattern CSRF protection middleware for Otterhttp.**

@@ -43,6 +43,3 @@ > :pushpin: This project is a fork of [Psifi-Solutions/csrf-csrf](https://github.com/Psifi-Solutions/csrf-csrf).

You will need to be using [tinyhttp/cookie-parser](https://github.com/tinyhttp/cookie-parser) whose middleware
should be registered before `csrf-csrf`.
In case you want to use signed CSRF cookies, you **will need to** provide `cookie-parser` with a unique secret
for cookie signing.
In case you want to use signed CSRF cookies, you **will need to** configure otterhttp for that.
This utility will (1) set a cookie containing both the csrf token and a hash of the csrf token, and

@@ -53,3 +50,3 @@ (2) provide the plain csrf token.

```
npm install @tinyhttp/cookie-parser @otterjs/csrf-csrf
npm install @otterhttp/csrf-csrf
```

@@ -93,6 +90,4 @@

```js
// Make sure your session middleware is registered before these
express.use(session);
express.get("/csrf-token", myRoute);
express.use(doubleCsrfProtection);
app.get("/csrf-token", myRoute);
app.use(doubleCsrfProtection);
// Any non GET routes registered after this will be considered "protected"

@@ -185,3 +180,2 @@ ```

secure?: boolean;
signed?: boolean;
}

@@ -201,3 +195,2 @@ ```

secure: true,
signed: false,
}

@@ -204,0 +197,0 @@ ```

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc