Baroshem / nuxt-security

🛡 Automatically configure your app to follow OWASP security patterns and principles by using HTTP Headers and Middleware
https://nuxt-security.vercel.app/
MIT License
743 stars 56 forks source link

Implementing a rate limiter the right way #357

Closed fayazara closed 5 months ago

fayazara commented 5 months ago

Hey @Baroshem,

I am using this module in of my app I made recently https://codeshare.app

Here's the repo - https://github.com/fayazara/codeshare.

Can you please help me implement rate limiting to the apis and my pages? I cant seem to understand how to implement this the right way.

More info - my app is in SSR mode and hosted on CF Pages

zukreindev commented 5 months ago

Hello, the documentation page is very badly coded so it took me a long time to understand it. But here's how I did it lVhU8s9 I gave ratelimit to all API in this way, you can give it to the route you want as you want.

fayazara commented 5 months ago

Hello, the documentation page is very badly coded so it took me a long time to understand it. But here's how I did it lVhU8s9 I gave ratelimit to all API in this way, you can give it to the route you want as you want.

I wonder if this works on CF pages, never worked with lrucache before, but thanks for sharing, implementing this

Baroshem commented 5 months ago

Hey @fayazara

Th example by @zukreindev is quite good but others in the documentation should help you as well.

Could you tell us more about your specific needs for this rate limiter? Then it would be easier to recommend anything because there is no single best approach here.

@zukreindev I am sad to see that you have not liked the documentation. Is there something we could do to make it better? Or maybe you could contribute to the documentation with better examples to help future users to understand better how it works?

fayazara commented 5 months ago

Hey @Baroshem I want to implement the rate limiter on CF pages for my project codeshare.app, so people wont abuse my API (already happened yesterday 😅), someone ran a script and wrote half a million rows on my db.

zukreindev commented 5 months ago

the examples and explanations in the documentation are not complete and this made it a bit difficult for me. if vsc intellisense was not there, maybe it would have taken me longer to solve. my suggestion is to strengthen it with examples.

Another issue is that I set image csp but all cdn's are blocked. I especially added the discord cdn link but still no result

Baroshem commented 5 months ago

@fayazara

So I would recommend protecting certain page or endpoint with a strict tokensPerInterval. By default, Nuxt Security sets the rate limiter globally to 150 requests.

I think this is generally secure but if you have an endpoint like /create-record that should be utilized for example maximally 10 times per hour, you could set this rule there.

Without knowing the details it is diffidult to recommend exact rules but you can also search the internet for common amount of requests per time for big applications like Twitter or Facebook

Baroshem commented 5 months ago

@zukreindev

So could you recommend specific things to replace or change in a separate issue?

I am more than happy to add them to the documentation but I would need more details because "Examples are not complete" does not tell me what is missing

zukreindev commented 5 months ago

I will open an issue and talk to you as soon as possible

fayazara commented 5 months ago

Thanks @Baroshem for the reply.

I tried implementing the rate limiter in my project. Below is my nuxt.config.ts, I have binded a KV namespace to my project in cloudflare and using the cloudflareKVBindingDriver driver, this isn't working for me, did I not set it up correctly?

// https://nuxt.com/docs/api/configuration/nuxt-config

import cloudflareKVBindingDriver from "unstorage/drivers/cloudflare-kv-binding";

export default defineNuxtConfig({
  devtools: { enabled: true },
  modules: [
    "@nuxt/ui",
    "nuxt-icon",
    "@nuxtjs/google-fonts",
    "@nuxtjs/fontaine",
    "@vueuse/nuxt",
    "nuxt-security",
  ],
  security: {
    headers: {
      crossOriginEmbedderPolicy:
        process.env.NODE_ENV === "development" ? "unsafe-none" : "require-corp",
    },
  },
  routeRules: {
    "/api/*": {
      security: {
        rateLimiter: {
          tokensPerInterval: 5,
          interval: 30000,
          driver: cloudflareKVBindingDriver({
            binding: process.env.KV,
          }),
          throwError: false,
        },
      },
    },
  },
});

Screenshot 24-01 at 11

Binding Screenshot 24-01 at 11

Baroshem commented 5 months ago

Hey @fayazara

Not sure what could be an issue but I would first check following things:

  1. Are you sure that you should be using the binding one instead of http? https://unstorage.unjs.io/drivers/cloudflare-kv-http
  2. Could you try to add some console logs to the code of Nuxt Security (specifically the rate limiter) to see if the driver is correctly mounted and if the set method correctly adds an item to the storage? Maybe there is an unhandled error there.
  3. Could you check if you are passing the driver correctly? Look at https://github.com/Baroshem/nuxt-security/blob/main/src/defaultConfig.ts line 52 where I am registering the lruCache driver. You should be doing something similar. And also here https://github.com/Baroshem/nuxt-security/blob/main/src/module.ts lune 256
fayazara commented 5 months ago

Hi @Baroshem,

Thank you for more info, it looks like I am supposed to use the the bind as an object instead of directly passing the binding method (h/t to @atinux).

I've now updated the my rate limiter options to this - https://github.com/fayazara/codeshare/blob/9ba1360b7bfa8212f5cbf083f43fcdec7ea2a6ce/nuxt.config.ts#L42-L47

Still doesn't seem to work, digging around the module more, will see if I find anything

Baroshem commented 5 months ago

@fayazara

Have you tried to debug in the security module in node_modules (in the source code) to add some console logs to see if the driver is actually mounted? Or if the set method actually does something? Maybe there is an unhandled rejection or issue that we are not handling properly.

node_modules/nuxt-security/dist/runtime/server/middleware/rateLimiter.mjs

fayazara commented 5 months ago

@Baroshem I've removed nuxt-security module in favour this module - https://github.com/timb-103/nuxt-rate-limit

I'll try to debug as per your notes above, thank you for the help, I will close this for now and reopen a new ticket with more details.