Account enumeration

An account enumeration attack occurs when a bad actor tries to identify valid users, emails, etc within an app's authentication flow. Account enumeration is primarily used to gain information about a system that can be used in further attacks, and does not directly result in compromised accounts.

Example

In order for account enumeration to occur, your app must expose some information about a user's state. For example, if you leverage our Email Magic Links Send endpoint, this endpoint requires that a user already exist before a magic link may be sent. That means if a bad actor enters an arbitrary email address, the Send endpoint will return a 200 success response if that email address exists as a user in your app and a 404 error response if that email address does not exist in your app. Using the Email Magic Links Login or Create endpoint will always send an email, and will always return a consistent response and will not reveal whether the email address already existed in the application or not.

This exposes to the bad actor that an email address belongs to a user of your app and the bad actor may leverage this information in a subsequent attack to phish, or compromise this user.

Recommendations

Generally account enumeration does not represent a major risk to your application, non-sensitive consumer applications carry very little risk from account enumeration. In fact, account enumeration via useful and actionable error messages is often helpful for consumer login flows. For example, telling a user that their login failed because they do not have an account is a better user experience than presenting a generic failure message.

However if your domain is particularly sensitive to security, e.g. government, fintech, healthcare etc, or your application is at a large enough scale, we do recommend you take a few steps to protect your against account enumeration.

  • Don't use error messages that give away key information about why a particular action failed. For example, if an actor initiates a password reset for an account that does not exist, don't show an error message. Instead, show a message to the effect of "If an account is associated with that email, a reset link has been sent."

  • Don't expose unmasked Personally Identifiable Information (PII), e.g. only display the last four digits of a phone number in your UI as opposed to the full value.

  • Limit how much user state you share with your frontend (user-facing client).

  • If you're using our frontend SDKs, the Send methods will error if the user hasn't been pre-created. If this is critical, we recommend disabling the Send methods and exclusively using the LoginOrCreate methods, or using our API directly from your backend.