💎 Using Ruby's SecureRandom to Strengthen User Authentication
Published: 2024-05-12 13:47:42


## Introduction

Hi, I'm [Take](https://dev.to/take0420/self-introduction-im-new-to-devto-21kb), and I work as an engineer at an in-house development company in Tokyo. 

In this article, I'll share what I've learned about generating tokens necessary for secure user authentication using Ruby’s standard library, SecureRandom.


## Background

### What is SecureRandom?
SecureRandom is a tool used to generate random numbers and strings that are hard to predict. You can learn more about it in this helpful article [here](https://api.rubyonrails.org/classes/SecureRandom.html).


### What is a Token?
A token is a randomly generated string used temporarily to identify a user.


### What is a Digest?
During authentication, the data sent is transformed using the same hash function and verified against the stored digest, which is kept on the server side.

### Comparing Tokens and Digests

| Feature    | Token                                          | Digest                                         |
|------------|------------------------------------------------|------------------------------------------------|
| **Purpose** | Temporarily stored in the user's browser and used directly for authentication. | Stored in the database and used for token verification. |
| **Generation Method** | Generated using random data functions like `SecureRandom.urlsafe_base64`. | Generated from the token using hash functions like `SHA-256`. |
| **Security**   | Randomly generated, but can be misused if stolen. | Stored in a hashed form, making it difficult to identify the original token if stolen. |



![Golden Security](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tnbe4cvaqfb7qvxevuvu.png)


## Generating a Token

The `SecureRandom.urlsafe_base64` method generates a safe, random token. This method produces a 22-character string from a set of 64 possible characters (A-Z, a-z, 0-9, "-", "_").


```ruby
irb(main):001> SecureRandom.urlsafe_base64
=> "TGYseMGxXvuG4tmD08MiAQ"
irb(main):002> SecureRandom.urlsafe_base64
=> "a_xN8Hw0BMuRHrGszl-CLA"
irb(main):003> SecureRandom.urlsafe_base64
=> "AUMBKxwWbV0eMGGEP2LNJg"
```

## Generating a Digest

The token generated is hashed using the User.digest method, and this hashed version (digest) is stored in the database. This makes it difficult to identify the actual token if it were ever leaked.

```ruby
def remember
  self.remember_token = User.new_token
  update_attribute(:remember_digest, User.digest(remember_token))
end
```

This method generates a new token and saves it to the remember_token property of the user instance before updating the token’s digest in the remember_digest field.

## User Authentication Process

When a user revisits the site, the token saved in the cookies is retrieved, hashed, and verified against the digest stored in the database. This process authenticates the user.


```ruby
rails console --sandbox
user = User.first
user.remember
  TRANSACTION (0.1ms)  SAVEPOINT active_record_1
  User Update (0.3ms)  UPDATE "users" SET "updated_at" = ?, "remember_digest" = ? WHERE "users"."id" = ?  [["updated_at", "2024-05-12 05:18:18.739100"], ["remember_digest", "$2a$12$RQayRzS/lv5Je8NDcycI9ut2uMn8uNDMWUZ.H0t1ixBXyRHFn6mYS"], ["id", 1]]
  TRANSACTION (0.0ms)  RELEASE SAVEPOINT active_record_1
=> true
```

## Conclusion

Through this article, we've explored secure methods of user authentication using tokens and digests, with a focus on SecureRandom for generating safe tokens. Understanding this foundation is crucial for further strengthening security measures.


Thank you for reading! If you liked this article, please give it a "like" 🎉.