# How to Use auth_object in Ransack for Secure Authorization

> Secure Ransack searches with auth_object. Learn to selectively expose columns based on user privileges using ransackable_attributes for robust authorization.

- Repository: [ActiveRecord Hackery/ransack](https://github.com/activerecord-hackery/ransack)
- Tags: how-to-guide
- Published: 2026-02-23

---

**Pass an `auth_object` to `Model.ransack()` and override `ransackable_attributes` to selectively expose columns based on user privileges.**

Ransack, the popular querying library for Ruby on Rails maintained by activerecord-hackery/ransack, provides a built-in authorization mechanism to prevent users from filtering or sorting by unauthorized database columns. By leveraging the **`auth_object`** option, you can enforce fine-grained access control at the model level without cluttering your controllers with authorization logic.

## How auth_object Works in the Ransack Pipeline

When you initialize a search with the `auth_object` parameter, Ransack propagates this value through the entire query-building lifecycle, using it to validate each field against whitelist methods defined on your models.

### Capturing the Option in the Search Object

The authorization process begins in [`lib/ransack/search.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/search.rb), where the constructor extracts the `auth_object` from the options hash and assigns it to the search context:

```ruby

# lib/ransack/search.rb (line 34)

@context.auth_object = options[:auth_object]

```

This single assignment stores the authorization context for the duration of the search construction.

### Propagating Through the Context

The `Ransack::Context` class acts as a data holder that carries the `auth_object` through every phase of query construction. As shown in [`lib/ransack/context.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/context.rb), this object is accessible via a simple attribute accessor:

```ruby

# lib/ransack/context.rb (line 6)

attr_accessor :auth_object, :search_key

```

This context object is passed to every node factory, ensuring that authorization checks occur consistently whether you are filtering, sorting, or scoping.

## Implementing Authorization Checks

Ransack queries the target model's class methods to determine if a requested field is permissible. These methods all receive the `auth_object` as their first argument, allowing you to implement conditional logic based on the current user's role or permissions.

### Filtering Attributes and Sorts

When Ransack resolves an attribute name, it invokes `ransackable_attributes` on the parent class, passing the current `auth_object`. In [`lib/ransack/nodes/attribute.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/nodes/attribute.rb), the validation occurs at line 23:

```ruby

# lib/ransack/nodes/attribute.rb (line 23)

context.klassify(parent).ransackable_attributes(context.auth_object)

```

Similarly, sortable columns are validated in [`lib/ransack/nodes/sort.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/nodes/sort.rb) using `ransortable_attributes`, which by default delegates to `ransackable_attributes`:

```ruby

# lib/ransack/nodes/sort.rb (line 29)

context.klassify(parent).ransortable_attributes(context.auth_object)

```

If the requested field is not returned by these methods, the predicate is silently excluded from the generated SQL.

### Restricting Associations and Scopes

The authorization check extends to associations and scopes. In [`lib/ransack/context.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/context.rb) (lines 162-171), Ransack validates these against `ransackable_associations` and `ransackable_scopes`:

```ruby

# lib/ransack/context.rb (lines 162-171)

klass.ransackable_attributes(auth_object).any? … ||
klass.ransortable_attributes(auth_object).any? …
klass.ransackable_associations(auth_object).any? …
klass.ransackable_scopes(auth_object).any? …

```

You can restrict associations and scopes by overriding these methods in your model. The default implementations in [`lib/ransack/adapters/active_record/base.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/adapters/active_record/base.rb) (lines 37-61) return all columns and associations, but you should override them to enforce your security policy:

```ruby

# lib/ransack/adapters/active_record/base.rb (lines 37-61)

def ransackable_attributes(auth_object = nil) … end
def ransackable_associations(auth_object = nil) … end
def ransortable_attributes(auth_object = nil) … end
def ransackable_scopes(auth_object = nil) … end

```

## Practical Rails Implementation

To implement authorization in a Rails application, compute the appropriate `auth_object` in your controller and pass it to the Ransack initializer. Then implement the whitelist methods in your models to check this object.

### Controller Setup

Create a private method that returns the authorization context, and pass it as the second argument to `ransack`:

```ruby

# app/controllers/articles_controller.rb

class ArticlesController < ApplicationController
  def index
    @q = Article.ransack(params[:q], auth_object: ransack_auth_object)
    @articles = @q.result
  end

  private

  def ransack_auth_object
    current_user.admin? ? :admin : nil
  end
end

```

### Model Configuration

Override `ransackable_attributes` to return different column sets based on the `auth_object` value:

```ruby

# app/models/article.rb

class Article < ApplicationRecord
  def self.ransackable_attributes(auth_object = nil)
    base = %w[id title body created_at]
    auth_object == :admin ? base + %w[internal_notes status] : base
  end

  def self.ransackable_associations(auth_object = nil)
    %w[comments author]
  end

  def self.ransackable_scopes(auth_object = nil)
    auth_object == :admin ? %w[recent deleted] : %w[recent]
  end
end

```

With this configuration, non-admin users attempting to filter by `internal_notes` will have those predicates silently ignored, while admins can search all columns.

## Summary

- **Pass `auth_object`** as the second argument to `Model.ransack(params, auth_object: value)` to propagate authorization context through the query builder.
- **Implement whitelist methods** (`ransackable_attributes`, `ransackable_associations`, `ransortable_attributes`, `ransackable_scopes`) in your models to check the `auth_object` and return only permitted fields.
- **Unauthorized fields are silently ignored**, preventing SQL injection of restricted columns without raising exceptions.
- **The context stores the object** at [`lib/ransack/search.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/search.rb) line 34 and validates against it in [`lib/ransack/context.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/context.rb) during predicate resolution.

## Frequently Asked Questions

### What data type should I pass as auth_object?

You can pass any Ruby object that represents the current authorization context. Common patterns include symbols like `:admin`, the `current_user` model instance, or a custom policy object. The Ransack source code treats this as an opaque value that is simply forwarded to your model's whitelist methods.

### Why are unauthorized queries silently ignored instead of raising errors?

Ransack follows a permissive design philosophy where unknown or unauthorized attributes are filtered out during the search construction phase. This behavior, implemented in [`lib/ransack/context.rb`](https://github.com/activerecord-hackery/ransack/blob/main/lib/ransack/context.rb), prevents information leakage about which columns exist in your database while maintaining a smooth user experience. If you need strict validation, implement pre-flight checks in your controller before calling Ransack.

### Can I use auth_object with Ransack scopes?

Yes. When you define `ransackable_scopes` in your model, the method receives the `auth_object` just like the other whitelist methods. You can conditionally expose scopes based on the authorization context, ensuring that powerful query shortcuts are only available to privileged users.

### How do I test authorization with auth_object?

In your RSpec or Minitest suite, instantiate the search object directly with different `auth_object` values and inspect the resulting SQL. For example, `Article.ransack({ internal_notes_eq: 'secret' }, auth_object: nil).result.to_sql` should not include the `internal_notes` condition, while passing `auth_object: :admin` should include it.