DEV Community

Thierry Chau
Thierry Chau

Posted on

How to Use Sqids in Rails to Obfuscate IDs

When developing web applications, it’s common to expose database IDs in URLs, such as example.com/posts/123. While this is convenient, it has potential drawbacks. Sequential IDs can reveal information about your database, like the number of records or the order in which they were created. To address this, developers often look for ways to obfuscate these IDs while keeping them reversible for internal use. This is where SQIDs come into play.

What is Sqids?

Sqids is a library designed to generate short, non-sequential, and URL-friendly IDs from integers. Unlike UUIDs, which are long and not user-friendly, Sqids provide a compact alternative that can be used in URLs to hide the real database IDs. They’re particularly useful in scenarios where you want to obfuscate your IDs without modifying your database schema or introducing significant overhead.

Why Not Use UUID?

UUIDs (Universally Unique Identifiers) are often used as an alternative to numeric IDs for their uniqueness across distributed systems. However, UUIDs have a few drawbacks:

  • Length: UUIDs are typically 36 characters long, which can make URLs cumbersome.
  • Not Sequential: While they are unique, UUIDs are not sequential, making indexing in databases less efficient.

On the other hand, Sqids offer a balance between security, URL friendliness, and reversibility, making them an ideal choice for many applications.

Implementing Sqids in Rails

Here’s how you can implement Sqids in a Rails application using a concern. This approach ensures that you don’t have to modify your database schema, and you can easily integrate it with your existing models.

Step 1: Install the Sqids Gem

First, add the Sqids Ruby gem to your Gemfile:

gem 'sqids'
Enter fullscreen mode Exit fullscreen mode

Run bundle install to install the gem.

Step 2: Create a Concern for Sqids

Next, create a concern to encapsulate the logic for encoding and decoding Sqids:

# app/models/concerns/sqids_encodable.rb

module SqidsEncodable
  extend ActiveSupport::Concern

  # arguments here are optional ; you can change the alphabet to change the encoding sequence
  SQIDS = Sqids.new(alphabet: 'k3G7QAe51FCsPW92uEOyq4Bg6Sp8YzVTmnU0liwDdHXLajZrfxNhobJIRcMvKt', min_length: 8)

  def to_param
    sqid
  end

  def sqid
    SQIDS.encode([id])
  end

  class_methods do
    def find_by_sqid(sqid)
      find(SQIDS.decode(sqid).first)
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

This concern does a few key things:

  • to_param method: Overrides the default to_param method to return the SQID instead of the numeric ID. This ensures that Rails uses the SQID in URLs.
  • sqid method: Encodes the model’s ID using Sqids.
  • find_by_sqid method: Allows you to find a record by its SQID, decoding it back to the original ID.

Step 3: Use the Concern in Your Models

To use this in a model, include the SqidsEncodable concern:

# app/models/post.rb

class Post < ApplicationRecord
  include SqidsEncodable

  # Your model logic here
end
Enter fullscreen mode Exit fullscreen mode

With this setup, whenever you generate a URL for a Post, Rails will automatically use the SQID instead of the numeric ID.

Step 4: Use Sqids in Your Controllers

When querying for a record, use find_by_sqid:

# app/controllers/posts_controller.rb

class PostsController < ApplicationController
  def set_post
    @post = Post.find_by_sqid(params[:id])
  end

  # Other controller actions
end
Enter fullscreen mode Exit fullscreen mode

This ensures that Rails can correctly retrieve the record using the obfuscated ID.

Conclusion

We went from example.com/posts/123 to something like example.com/posts/5sQ1BZoD.

Sqids offer a practical solution for obfuscating database IDs in a Rails application. They allow you to hide the actual IDs from users, while still being able to reverse the process internally. Compared to UUIDs, SQIDs provide a more user-friendly, compact, and efficient approach.

It’s important to note that while Sqids obfuscate the IDs, they do not encrypt them. If you require encryption for your IDs, you’ll need to look into more robust security measures. However, for most applications, SQIDs strike a good balance between security and usability.

Learn more about Insecure Direct Object Reference
Learn more about Sqids | GitHub repository

Top comments (0)