Rails Broken
Authentication Guide:
Examples and Prevention


StackHawk|March 16, 2022

In this article we are aiming to explore the subject of broken authentication in the context of Ruby on Rails. Let's begin.

Rails Broken Authentication Guide: Examples and Prevention image

In terms of cybersecurity, authentication and authorization are two of our platforms' most significant security aspects. But, as we know, protecting our applications and our users' data is a battle of many fronts. No doors should be left unprotected.

Nevertheless, you'll spend most of your time and effort securing your website's main avenue of access. That's why understanding a subject like broken authentication is critical to offering a robust level of protection.

This article aims to explore the subject of broken authentication in the context of Ruby on Rails.

We'll briefly examine the concepts of authentication and help you get a good grasp on providing suitable security.

To achieve this, we'll first learn what broken authentication is. Then, we'll use some simple examples to help us characterize what a broken authentication attack might look like in the wild and what vulnerabilities it targets.

Finally, we'll provide you with some mitigating strategies to help you address the vulnerabilities that you might find.

Alright, let's jump right in.

Defining Broken Authentication

First, let's define what the term broken authentication means.

In simple terms, broken authentication is an umbrella used for several vulnerabilities that attackers can exploit to hijack our systems and impersonate other users.

We know that the job of an authentication mechanism in our platform is to ensure that only a verified user can access the information and privileges on the web application. However, it's called "broken" when an attacker successfully bypasses the process and impersonates the user on the application. Essentially, this attacker can skip the login security and gain access to all the privileges the hacked user owns.

To be more specific, broken authentication refers to the vulnerabilities or weaknesses inherent in an online platform or application's authentication mechanisms. We can usually find these vulnerabilities in poor session management and credential management.

Both of these are classified as broken authentication because attackers can disguise themselves as users, either by hijacking a session ID or stealing the login credentials. In addition, this breach enables attackers to compromise passwords, keys or session tokens, user account information, and other details to assume user identities.

Broken Authentication in Action

So, we know that authentication attacks mainly target our credential or session management. But, how does this actually happen?

Well, there are many ways, really. But for the purpose of brevity, we'll be exploring the cases where you implement poor management mechanisms and policies.

Credential Management

Implementing poor credential management mechanisms and policies is a potential avenue for attackers to gain access to your systems.

Security policies that allow the use of weak passwords like "12345" or "password" are one way to weaken our credential management's security.

In such a case, an attacker only needs simple password-cracking techniques like brute force, rainbow tables, dictionaries, and enough time to breach your security and access your system.

Additionally, the use of weak cryptography to secure your users' credentials is a significant loophole in your entire security strategy.

The use of inadequate encryption mechanisms like base64 and hashing algorithms like SHA1 or MD5 provide little to no protection in a database breach, exposing credentials and sensitive data.

Session Management

As we know, whenever a user interacts with your website, the server application provides them with a session ID for session management and records their interactions.

As stated by the OWASP broken authentication recommendations, this session ID is equivalent to your original login credentials. So, if a bad actor were to gain access to this session ID, they can effectively impersonate you and bypass all security mechanisms.

This security breach is known as session hijacking and has devastating consequences for the victim.

Examples of Broken Authentication

Now that we understand how broken authentication happens on our system, let's explore some examples of attacks that target specific vulnerabilities.

Password Spraying

The password spraying attack exploits systems that allow simple and weak passwords, such as "12345" or "password," by its users.

Attackers can use rainbow tables or dictionaries to try as many known passwords on user accounts to fish for weak credentials and gain access to the system.

Credential Stuffing

Credential stuffing refers to the use of credentials obtained from other breaches to gain access to our platforms.

This attack works on the assumption that a significant number of users reuse credentials between platforms due to convenience and friction.

Session Hijacking

As explained above, session hijacking happens when a bad actor takes over a user's session. This can be as simple as a user forgetting to log off from his computer before leaving and someone else taking his place.

Additionally, suppose the same ID is issued independently of authentication status. In that case, it could potentially open the door to an attack called session fixation, where an unauthorized session uses the session ID.

Session ID URL

Attackers can use unsecured WiFi access points, man in the middle attacks, or simple eavesdropping at the address bar to get the user session ID if it's in plain sight.

Mitigating Broken Authentication Vulnerabilities

The best way to address the vulnerabilities and mitigate the risks of breaches is by following the best practices from the OWASP.

Luckily for you, if you use robust and battle-tested gems like devise, you can easily protect your platform from these vulnerabilities.

To install devise, all you have to do is add the gem on your Gemfile.

gem 'devise'

Once you've done this, you need to run the bundle install command to install the gem dependency in your project.

bundle install

Next, run the following command to generate the default resources the gem needs on your project.

$ rails generate devise:install

Now, add the following configuration in your config file to set up the emailing settings for user authentication and confirmation.

config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

After doing this, run the following command to generate or update the models representing the users in your project. In this case, you can replace MODEL for whatever model name you're using for your users.

$ rails generate devise MODEL

Finally, run the migration command to update the database to reflect the revised model structure.

rails db:migrate

All you need to do now is add the following line on the controllers you want to enforce authentication on, and that's pretty much it.

before_action :authenticate_user!

There are a few more steps that you might need to follow to have your application locked and loaded with devise. Please visit the devise official GitHub page here for more information.

Now, let's see how we can implement the mitigation strategies in our project.

Secure Password Storage

Best practices tell us to make sure that all passwords are not only encrypted but also hashed and salted. This policy safeguards the users' credentials in case of a breach by preventing or at least slowing down any attempts to access breached databases.

If you're using devise, you have encryption and salting active by default.

You can configure the encryption key by modifying the config.pepper value on the devise_initializer.rb file.

Don't Allow Weak Passwords

A secure application must require its users to fulfill specific requirements when creating passwords.

Some of the most common requirements are

  • requiring passwords to be of a particular length, and

  • requiring special characters as well as numbers.

These requirements must be first enforced and validated by policies created on the client side by JavaScript. However, you also have the option of validating the values provided on the server side with devise.

You can configure the password length on the devise_initializer.rb file with the config.password_length setting.

Additionally, to validate the password complexity, you can use the following method on your user model:

def password_complexity
  # Regexp extracted from https://stackoverflow.com/questions/19605150/regex-for-password-must-contain-at-least-eight-characters-at-least-one-number-a
  return if password.blank? || password =~ /(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-])/

  errors.add :password, 'Complexity requirement not met. Please use: 1 uppercase, 1 lowercase, 1 digit and 1 special character'

Keep in mind that some of these specifications are more competent than others in terms of protecting the user, but they might also cause the opposite effect when users might not want to comply with them.

Add a Strict Credential Recovery Process

The credential recovery process should require several validation checks that make it complicated and expensive for attackers to abuse it.

To achieve this in devise, you can make use of the following configuration settings in the devise_initializer.rb file:

  • config.unlock_strategy

  • config.lock_strategy

  • config.unlock_keys

  • config.maximum_attempts

  • config.reset_password_within

Implement Breached Password Protection

Implementing a breached password protection mechanism allows your system to lock the accounts of users whose passwords have been identified as compromised. This way, you ensure that users have a window to prevent breaches if bad actors steal their credentials.

To provide this security feature, we recommend Pwned, which provides an updated repository of breached passwords to cross-validate in real time.

Regulate Session Length

Web applications must end a user session after a certain period of inactivity has passed. To regulate the length of the session on your application, just modify the config.timeout_in setting in the devise_initializer.rb file.

Improve Session Management

It's imperative that our platform provides individual session IDs after every successful authentication attempt. In addition, our system must invalidate old session IDs to prevent hijacking as soon as a session ends.

Luckily, devise already takes care of this for us.

Disregard the Use of Session ID URL

Not much of an explainer is needed here. Web URLs must be secured with SSL and not include the session ID.

Add Automated Security Testing to Your Pipeline


That concludes our concise exploration of the subject of broken authentication and its complexities. But, keep in mind that it's by no means extensive or complete.

In this article, we took the time to lay out the subject of broken authentication and briefly examined many of the most common and insidious vulnerabilities on the web. Additionally, we provided some approachable and straightforward strategies to mitigate these vulnerabilities.

However, it's our job to enforce robust and extensive security measures to secure our users' data and our clients' assets.

That's why we recommend you consider using our dynamic application security testing at StackHawk.

DAST runs security tests against a running application in real time, finding vulnerabilities your team introduced as well as exploitable open-source vulnerabilities like broken authentication. You can find more about it here.

This post was written by Juan Reyes. Juan is an engineer by profession and a dreamer by heart who crossed the seas to reach Japan following the promise of opportunity and challenge. While trying to find himself and build a meaningful life in the east, Juan borrows wisdom from his experiences as an entrepreneur, artist, hustler, father figure, husband, and friend to start writing about passion, meaning, self-development, leadership, relationships, and mental health. His many years of struggle and self-discovery have inspired him and drive to embark on a journey for wisdom.

StackHawk  |  March 16, 2022