Skip to content

Email rate limit is triggered even in scenarios where an email doesn't end up being sent #1236

Description

@makeusabrew

Bug report

  • I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

Describe the bug

Failed signups still count towards the email rate limit even though no user record is created and no email ends up being sent, leading to unwarranted AuthApiError: Email rate limit exceeded errors. Misuse of the registration process (by well-intentioned would-be users or deliberate bad actors) can very quickly lead to a denial of service whereby nobody can sign up for an account, even if no emails have been sent.

I've tried my best to report this in the right repository tracing through the calls I think the /signup flow makes starting with the Supabase Auth TypeScript helpers at the top of the stack. Apologies if this isn't the right place after all.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

Not the best reproduction steps here, sorry. In effect, using the built-in SMTP testing rate limits just by way of example, calling something like await supabase.auth.signUp({email: "a@b.com", password: "x"}) 5 times in an hour with default minimum password length restrictions in place will result in error responses as follows:

AuthApiError: Password should be at least 6 characters
AuthApiError: Password should be at least 6 characters
AuthApiError: Password should be at least 6 characters
AuthApiError: Password should be at least 6 characters
AuthApiError: Email rate limit exceeded

Of course, users are encouraged not to use the test SMTP endpoint - I'm only doing so as an example here. Even if users provide their own, they're encouraged to set sensible rate limits to mitigate abuse. The point is that no emails are actually being sent here.

Expected behavior

In the scenario above I would not expect to ever hit the "email rate limit exceeded" error, since no emails had been sent and no new users had been added to the database.

Screenshots

I don't think this helps much as you can't see the full implementation, but here's the tail of some logs of me deliberately entering a short password until hitting the rate limit (I'd previously been testing while writing this bug, hence why I only managed two "password should be..." errors before hitting the limit again).

image

System information

  • OS: macOS, but don't think it's relevant
  • Browser (if applies): N/A
  • Version of supabase-js:
    "@supabase/auth-helpers-nextjs": "^0.7.3"
    "@supabase/supabase-js": "^2.31.0"
  • Version of Node.js: 20.5.1

Additional context

I don't know Go at all, but a quick glance at internal/api/api.go around line 107/108 within this repo made me wonder if the rate limiter middleware is always invoked before the actual call, regardless of whether that call does the thing it's expected to or not.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions