@tozielinski/next-upstash-nonce 1.4.1 → 1.4.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.4.2](https://github.com/tozielinski/next-upstash-nonce/compare/v1.4.1...v1.4.2) (2025-12-27)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * add rateLimiter for server action, minor bugfixes ([967269d](https://github.com/tozielinski/next-upstash-nonce/commit/967269d87c12119765e05d150aa9458d730dc53c))
9
+
3
10
  ## [1.4.1](https://github.com/tozielinski/next-upstash-nonce/compare/v1.4.0...v1.4.1) (2025-12-17)
4
11
 
5
12
 
package/dist/index.d.ts CHANGED
@@ -22,14 +22,14 @@ export type RateLimitResult = {
22
22
  ip: string;
23
23
  requests: number;
24
24
  reason: `too-many-requests: ${number}`;
25
- response: Response;
25
+ response?: Response;
26
26
  };
27
27
  export declare class NonceManager {
28
28
  private redis;
29
- private ttlNonce;
30
- private prefix;
31
- private ttlRateLimit;
32
- private countRateLimit;
29
+ private readonly ttlNonce;
30
+ private readonly prefix;
31
+ private readonly ttlRateLimit;
32
+ private readonly countRateLimit;
33
33
  constructor(redis: Redis, opts?: NonceOptions);
34
34
  /**
35
35
  * makes option parameters available in the server in environment files
@@ -39,6 +39,10 @@ export declare class NonceManager {
39
39
  * extracts client IP from request headers
40
40
  */
41
41
  private getClientIp;
42
+ /**
43
+ * extracts client IP from headers for server actions
44
+ */
45
+ getClientIpFromHeaders(headers: Headers): Promise<string>;
42
46
  /**
43
47
  * generates a new, secure nonce,
44
48
  * inserts it into Redis with a TTL,
@@ -56,23 +60,24 @@ export declare class NonceManager {
56
60
  */
57
61
  verifyAndDelete(nonce: string): Promise<boolean>;
58
62
  /**
59
- * verifies a nonce from the Header of a request
63
+ * verifies nonce from the Header of a request
60
64
  * returns a NonceCheckResult if the nonce exists and has not expired.
61
65
  */
62
66
  verifyNonceFromRequest(req: Request): Promise<NonceCheckResult>;
63
67
  /**
64
- * verifies a nonce from the Header of a request and deletes it from Redis
68
+ * verifies nonce from the Header of a request and deletes it from Redis
65
69
  * returns a NonceCheckResult if the nonce exists and has not expired.
66
70
  */
67
71
  verifyAndDeleteNonceFromRequest(req: Request): Promise<NonceCheckResult>;
68
72
  /**
69
- * Optional: delete a nonce from Redis manually
73
+ * Optional: delete nonce from Redis manually
70
74
  */
71
75
  delete(nonce: string): Promise<void>;
72
76
  /**
73
77
  * rate limits requests from the same IP address
74
78
  */
75
79
  rateLimiter(req: Request): Promise<RateLimitResult>;
80
+ rateLimiterByIp(ip: string): Promise<RateLimitResult>;
76
81
  }
77
82
  export default NonceManager;
78
83
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGvC,MAAM,MAAM,YAAY,GAAG;IAEvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAK;IAC7B,KAAK,EAAE,IAAI,CAAC;IACZ,KAAK,EAAE,MAAM,CAAA;CAChB,GAAG;IACA,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,gBAAgB,GAAG,oBAAoB,CAAC;IAChD,QAAQ,EAAE,QAAQ,CAAA;CACrB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAK;IAC5B,KAAK,EAAE,IAAI,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CACpB,GAAG;IACA,KAAK,EAAE,KAAK,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,sBAAsB,MAAM,EAAE,CAAC;IACvC,QAAQ,EAAE,QAAQ,CAAC;CACtB,CAAC;AAEF,qBAAa,YAAY;IACrB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,cAAc,CAAS;gBAGnB,KAAK,EAAE,KAAK,EAAE,IAAI,GAAE,YAAiB;IAQjD;;OAEG;IACH,OAAO,CAAC,WAAW;IAWnB;;OAEG;IACH,OAAO,CAAC,WAAW;IAanB;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAU/B;;;OAGG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAa7C;;;OAGG;IACG,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAetD;;;OAGG;IACG,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoCrE;;;OAGG;IACG,+BAA+B,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoC9E;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM1C;;OAEG;IACG,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC;CAgB5D;AAED,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,KAAK,EAAC,MAAM,gBAAgB,CAAC;AAGrC,MAAM,MAAM,YAAY,GAAG;IAEvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAK;IAC7B,KAAK,EAAE,IAAI,CAAC;IACZ,KAAK,EAAE,MAAM,CAAA;CAChB,GAAG;IACA,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,gBAAgB,GAAG,oBAAoB,CAAC;IAChD,QAAQ,EAAE,QAAQ,CAAA;CACrB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAK;IAC5B,KAAK,EAAE,IAAI,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CACpB,GAAG;IACA,KAAK,EAAE,KAAK,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,sBAAsB,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACvB,CAAC;AAEF,qBAAa,YAAY;IACrB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAG5B,KAAK,EAAE,KAAK,EAAE,IAAI,GAAE,YAAiB;IAQjD;;OAEG;IACH,OAAO,CAAC,WAAW;IAWnB;;OAEG;IACH,OAAO,CAAC,WAAW;IAYnB;;OAEG;IACG,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAc/D;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAU/B;;;OAGG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAa7C;;;OAGG;IACG,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAetD;;;OAGG;IACG,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoCrE;;;OAGG;IACG,+BAA+B,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoC9E;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM1C;;OAEG;IACG,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC;IA0BnD,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CAsB9D;AAED,eAAe,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -41,6 +41,20 @@ class NonceManager {
41
41
  }
42
42
  return "unknown";
43
43
  }
44
+ /**
45
+ * extracts client IP from headers for server actions
46
+ */
47
+ async getClientIpFromHeaders(headers) {
48
+ const forwardedFor = headers.get("x-forwarded-for");
49
+ if (forwardedFor) {
50
+ return forwardedFor.split(",")[0].trim();
51
+ }
52
+ const realIp = headers.get("x-real-ip");
53
+ if (realIp) {
54
+ return realIp;
55
+ }
56
+ return "unknown";
57
+ }
44
58
  /**
45
59
  * generates a new, secure nonce,
46
60
  * inserts it into Redis with a TTL,
@@ -89,7 +103,7 @@ class NonceManager {
89
103
  }
90
104
  }
91
105
  /**
92
- * verifies a nonce from the Header of a request
106
+ * verifies nonce from the Header of a request
93
107
  * returns a NonceCheckResult if the nonce exists and has not expired.
94
108
  */
95
109
  async verifyNonceFromRequest(req) {
@@ -117,7 +131,7 @@ class NonceManager {
117
131
  };
118
132
  }
119
133
  /**
120
- * verifies a nonce from the Header of a request and deletes it from Redis
134
+ * verifies nonce from the Header of a request and deletes it from Redis
121
135
  * returns a NonceCheckResult if the nonce exists and has not expired.
122
136
  */
123
137
  async verifyAndDeleteNonceFromRequest(req) {
@@ -145,7 +159,7 @@ class NonceManager {
145
159
  };
146
160
  }
147
161
  /**
148
- * Optional: delete a nonce from Redis manually
162
+ * Optional: delete nonce from Redis manually
149
163
  */
150
164
  async delete(nonce) {
151
165
  const key = this.prefix + nonce;
@@ -163,7 +177,29 @@ class NonceManager {
163
177
  }
164
178
  if (requests > this.getEnvValue("RATE_LIMIT_COUNT", this.countRateLimit)) {
165
179
  const response = Response.json({ error: "Too many requests" }, { status: 429 });
166
- return { valid: false, ip, requests, reason: `too-many-requests: ${requests}`, response: response };
180
+ return {
181
+ valid: false,
182
+ ip,
183
+ requests,
184
+ reason: `too-many-requests: ${requests}`,
185
+ response: response
186
+ };
187
+ }
188
+ return { valid: true, ip, requests };
189
+ }
190
+ async rateLimiterByIp(ip) {
191
+ const key = `rate:${ip}`;
192
+ const requests = (await this.redis.incr(key)) ?? 0;
193
+ if (requests === 1) {
194
+ await this.redis.expire(key, this.getEnvValue("RATE_LIMIT_TTL_SECONDS", this.ttlRateLimit));
195
+ }
196
+ if (requests > this.getEnvValue("RATE_LIMIT_COUNT", this.countRateLimit)) {
197
+ return {
198
+ valid: false,
199
+ ip,
200
+ requests,
201
+ reason: `too-many-requests: ${requests}`,
202
+ };
167
203
  }
168
204
  return { valid: true, ip, requests };
169
205
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tozielinski/next-upstash-nonce",
3
- "version": "1.4.1",
3
+ "version": "1.4.2",
4
4
  "description": "Create, store, verify and delete nonces in Redis by Upstash for Next.js",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",