# Pretender for Rails: Controlled User Impersonation

> Pretender gives Rails applications a small API for administrators to view the application as another user while retaining access to the administrator's identity. It supports configurable authentication roles, Action Cable, and audit integrations with limited application code.

**ankane/pretender** — Log in as another user in Rails

- Repository: https://github.com/ankane/pretender
- Stars: 1,425 · Forks: 56
- Language: Ruby
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/ankane-pretender

## Pretender's Rails Impersonation Boundary

Pretender solves a specific administrative support problem: viewing a Rails application through the permissions and state of another user. The README frames this as letting an administrator see exactly what another user sees. That distinction matters because application behavior can depend on the authenticated record, authorized routes, rendered data, and connection-specific identity rather than on a query parameter or a special preview mode.

The gem is aimed at Rails applications with an administrative person who must inspect a user session without replacing the entire authentication flow. Its documented integrations mention Devise, Authlogic, and Sorcery, while also stating that Pretender works with any authentication system. That makes it more suitable as an identity switch layered over an existing authentication mechanism than as a full authentication library.

Pretender does not decide whether an administrator may impersonate a particular account. The sample controller explicitly applies `before_action :require_admin!`, described in the README as the application's authorization method. Pretender then accepts the selected user and changes the method used by the application. Access control remains the responsibility of the host application. This separation can produce a small implementation, but it also makes route protection an adoption requirement rather than an optional detail.

## Inside Pretender's User State Swap

After an application declares `impersonates :user`, Pretender creates a default impersonation interface centered on three methods. Calling `impersonate_user(user)` changes what `current_user` returns. Calling `true_user` retrieves the real authenticated user, which remains available even while the selected user is active. Calling `stop_impersonating_user` ends the impersonation state.

The default configuration exposes that relationship through a lookup callable:

```ruby
impersonates :user,
             method: :current_user,
             with: ->(id) { User.find_by(id: id) }
```

This is more configurable than a hard-coded user switch. The example shows an alternative called `account`, with `authenticated_account` as the application method and `EnterpriseAccount.find_by(id: id)` as the lookup. According to the configuration documentation, declaring it creates `true_account`, `impersonate_account`, and `stop_impersonating_account`. The README also states that multiple roles can be impersonated at the same time.

The documentation does not specify the internal session key, serialization format, expiration policy, or persistence mechanism. Those details should not be inferred from the public API alone. What can be confirmed is the observable contract: an application-facing method changes identity, a corresponding true-identity method remains available, and a stop method reverses the state. Existing authentication can still perform the initial sign-in, after which Pretender controls the selected application identity.

## Installing Pretender in a Rails Controller

The documented installation path is through the application's `Gemfile`. Pretender is a Ruby gem, and the README does not provide a manual installation command or version constraint.

```ruby
gem "pretender"
```

After adding that line, declare the role in `ApplicationController`. This gives the controller hierarchy access to the generated methods:

```ruby
class ApplicationController < ActionController::Base
  impersonates :user
end
```

A first real use requires an administrator-only interface. The sample creates a controller with `require_admin!`, loads all users, starts impersonation from a member route, and exposes a collection route for stopping it:

```ruby
class UsersController < ApplicationController
  before_action :require_admin! # your authorization method

  def index
    @users = User.order(:id)
  end

  def impersonate
    user = User.find(params[:id])
    impersonate_user(user)
    redirect_to root_path
  end

  def stop_impersonating
    stop_impersonating_user
    redirect_to root_path
  end
end
```

Replace the sample's authorization method and routes with application-specific equivalents. `require_admin!` is illustrative, not a method supplied by Pretender. The host application must define it and ensure both actions are protected.

## Wiring Pretender Routes and an Impersonation Screen

The README defines the two controller operations through nested Rails routes. The member action receives a user identifier, while the collection action has no user parameter because it only stops the current impersonation:

```ruby
resources :users, only: [:index] do
  post :impersonate, on: :member
  post :stop_impersonating, on: :collection
end
```

A minimal index view can submit the corresponding forms. The `data: {turbo: false}` option is present in the documented view, so readers following that example retain the submitted non-Turbo behavior:

```erb
<ul>
  <% @users.each do |user| %>
    <li>Sign in as <%= button_to user.name, impersonate_user_path(user), data: {turbo: false} %></li>
  <% end %>
</ul>
```

The layout should make the impersonation visible. This is more than cosmetic: an administrator operating under another identity can otherwise lose track of whose permissions are active. The documented comparison is `current_user != true_user`.

```erb
<% if current_user != true_user %>
  You (<%= true_user.name %>) are signed in as <%= current_user.name %>
  <%= button_to "Back to admin", stop_impersonating_users_path, data: {turbo: false} %>
<% end %>
```

The README does not document safeguards such as expiration, confirmation prompts, logging impersonation events, or preventing simultaneous impersonation in multiple browser sessions. Those behaviors must be verified in the host application if they are required.

## Connecting Pretender to Action Cable

Pretender also covers WebSocket identity through Action Cable. The README instructs developers to declare both `:current_user` and `:true_user` as identifiers and to call `impersonates :user` inside `ApplicationCable::Connection`. Its example then sets `current_user` from the existing verified Devise session and rejects an unauthorized connection.

```ruby
module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user, :true_user
    impersonates :user

    def connect
      self.current_user = find_verified_user
      reject_unauthorized_connection unless current_user
    end

    private

    def find_verified_user
      env["warden"].user # for Devise
    end
  end
end
```

The README states that `current_user` then returns the impersonated user in channels. It does not explain whether an existing Action Cable connection picks up an impersonation state created later in an HTTP controller session. That timing question requires verification for any application whose administrator view depends on live channel behavior.

The sample also demonstrates that Pretender must be declared separately for the HTTP controller and the cable connection. An application that omits `impersonates :user` from `ApplicationCable::Connection` will not receive the documented channel integration.

## Preserving the Real Identity for Audited

An impersonation system can become misleading when records attribute actions to the selected user even though an administrator initiated them. Pretender addresses this case for the `Audited` library. The README instructs applications to configure Audited's current user method as `true_user`:

```ruby
Audited.current_user_method = :true_user
```

This creates an explicit division between authorization context and attribution context. Application behavior can use `current_user`, which points to the impersonated user, while the audit library reads `true_user`, which remains the actual authenticated person. The README's compatibility claim for auditing tools is specific rather than general, and the concrete example only names `Audited`.

The documentation does not state how Pretender behaves in background jobs, asynchronous callbacks, mailers, or external services that have no controller or Action Cable connection. It also does not show automatic audit records for starting or stopping impersonation. Applications that attribute events outside HTTP requests must inspect those code paths directly. The practical boundary is that `true_user` works only where the Pretender state and the configured method are actually available.

## Pretender's Trade-offs and Maintenance Cost

Pretender's main advantage is its narrow surface. The README describes it as less than 100 lines and presents three central operations for each declared role. Configuration can rename the methods, choose a different model lookup, or impersonate several roles. For a Rails application whose existing authentication library supplies a stable user object, this is a direct way to add a reversible identity view.

The corresponding limitation is equally specific. Pretender does not document an administrative interface, expiration rules, session isolation, impersonation logs, or an authorization model. The sample manually protects the controller with `require_admin!`, which demonstrates that the gem expects the host application to decide who may enter the identity-switching flow. A direct custom controller that saves a selected ID in the session and swaps the current-user accessor follows a similar approach but requires maintaining session keys, lookup rules, cleanup, and stop behavior by hand. Pretender packages that common contract into a gem and adds true-user access and configuration for multiple roles.

The repository is not archived, and its last push was on 2026-04-02. However, it has no GitHub releases, so the release history and upgrade path are not documented through that channel. The README links to `CHANGELOG.md` for history. Its development commands are explicit:

```sh
git clone https://github.com/ankane/pretender.git
cd pretender
bundle install
bundle exec rake test
```

These commands cover cloning, dependency installation, and the repository's test task. The repository is licensed under MIT, as recorded in `LICENSE.txt`; that identifies the project's stated license, not an interpretation of obligations for a particular deployment.

## Conclusion

Adopt Pretender when an authenticated Rails administrator needs a documented, reversible way to inspect the application as a selected user, especially when current_user must change without losing the administrator identity. Do not choose it as a replacement for your authorization layer, permanent account switching, or identity-provider administration. Before adoption, verify that every protected controller action, background job, audit hook, and WebSocket connection consistently uses the intended Pretender methods, because the README documents controller and Action Cable integration but does not address background jobs or a complete security policy for impersonation routes.

## FAQ

### Which Rails authentication systems can work with Pretender?

The README says Pretender works with any authentication system and specifically names Devise, Authlogic, and Sorcery. Its Action Cable example retrieves the user through Devise's `warden` environment object.

### How does Pretender retain access to the administrator's identity?

While `current_user` returns the selected impersonated user, `true_user` returns the actual authenticated user. The README recommends using `true_user` as the current user method for Audited audit attribution.

### Does Pretender control whether an administrator may impersonate a user?

No such authorization policy is documented in Pretender. The sample controller uses the application's own `require_admin!` method before exposing the impersonation and stop actions.

## Sources

- [ankane/pretender on GitHub](https://github.com/ankane/pretender)
- [Issues](https://github.com/ankane/pretender/issues)
- [License: MIT](https://github.com/ankane/pretender/blob/master/LICENSE)
- [README](https://github.com/ankane/pretender/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ankane-pretender
