# Passwordless Rails authentication with emailed sign-in links

> Passwordless adds email-based magic-link authentication to an existing Rails application without imposing a user model. It fits Rails developers who want Passwordless to manage sign-in sessions and routes while keeping control of user records.

**mikker/passwordless** — 🗝 Authentication for your Rails app without the icky-ness of passwords

- Repository: https://github.com/mikker/passwordless
- Stars: 1,342 · Forks: 90
- Language: Ruby
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/mikker-passwordless

## Email-based sign-in for an existing Rails user model

Passwordless addresses the problem of proving control of an email address without requiring a reusable site password. A visitor enters an email address, receives a token and magic link, and presents that information to create an authenticated session. The README describes this as "magic link" authentication.

The gem is intended for Rails applications that already own their identity records or can add an appropriate user model. It creates `Passwordless::Session`, but it deliberately does not supply a user model. The application must provide an authenticatable record with an email column and configure Passwordless to use that field. User creation, registration rules, roles, profile data, and account status remain under application control.

This separation also makes email delivery part of the authentication path. An inaccessible inbox, delayed message, failed Action Mailer delivery, or incorrect URL host can prevent a user from signing in. The README does not document an offline token, hardware credential, or alternate identity provider. Applications that cannot depend on email should therefore treat Passwordless as the wrong base for their authentication design.

## Passwordless session lookup and route mounting

Passwordless mounts an engine into the host application's routes. The basic declaration derives its paths and helpers from the resource supplied to `passwordless_for`. Starting with the standard `/users/sign_in` route also requires an existing `User` model whose email field has been registered with `passwordless_with`.

The engine uses the named user class when resolving a Passwordless session. The application, rather than the gem, defines `current_user`. Its implementation calls `authenticate_by_session(User)` and can use Passwordless controller helpers to save the location that prompted authentication. This avoids imposing one host-application convention on every Rails codebase, but it also places an important consistency requirement on the application: every protected controller must invoke its authentication guard.

Route constraints offer an additional condition. `Passwordless::Constraint.new(User)` checks for an authenticated `User`, while `Passwordless::ConstraintNot.new(User)` applies the opposite condition. The `if:` block receives the authenticatable record, which permits application-specific checks such as an email-domain rule. The README does not describe role-based authorization in these constraints, so controller-level permission checks remain necessary for access to protected data and actions.

## Installing Passwordless and copying its migrations

The documented installation path uses Bundler and copies the engine migrations into the Rails application. Run these commands from the application project:

```bash
$ bundle add passwordless
$ bin/rails passwordless_engine:install:migrations
```

The first command adds Passwordless to the bundle. The second copies its migrations. The application should then process the generated migration files through its normal Rails migration workflow. The README does not print the generated migration body, so the copied files are the source for reviewing the required schema.

After installation, connect the engine to the application's user class. The model must have a real email column because the configuration points to that field:

```ruby
class User < ApplicationRecord
  passwordless_with :email
end
```

Mount the engine in `config/routes.rb`:

```ruby
Rails.application.routes.draw do
  passwordless_for :users
end
```

This configuration creates a separate Passwordless sign-in flow. It does not replace the application's existing user registration route or automatically attach authorization behavior to unrelated controllers.

## First sign-in flow and protected-controller setup

Passwordless provides two action views. The first accepts an email address, and the second accepts the token delivered to that address. A bundled text mailer view contains the token and magic link. Once the token is accepted, `Passwordless::Session` represents the authenticated session for the application's user record.

The application must expose that session through its own controller API. The following example includes `Passwordless::ControllerHelpers`, defines `current_user`, and saves the requested location when authentication is missing:

```ruby
class ApplicationController < ActionController::Base
  include Passwordless::ControllerHelpers

  helper_method :current_user

  private

  def current_user
    @current_user ||= authenticate_by_session(User)
  end

  def require_user!
    return if current_user
    save_passwordless_redirect_location!(User)
    redirect_to root_path, alert: "You are not worthy!"
  end
end
```

A protected controller then invokes that guard before it loads application data:

```ruby
class VerySecretThingsController < ApplicationController
  before_action :require_user!

  def index
    @things = current_user.very_secret_things
  end
end
```

The names and redirects are examples from the README. Passwordless does not choose the root path, define authorization roles, or create `current_user`. Those decisions remain visible in host-application code.

## Action Mailer hosts and customizable sign-in views

A magic link must contain an absolute URL that reaches the Rails deployment that issued it. The README therefore specifies both Action Mailer host configuration and a routing host default. It gives this example for an application served from `www.example.com`:

```ruby
config.action_mailer.default_url_options = {host: "www.example.com"}
routes.default_url_options[:host] ||= "www.example.com"
```

The first line affects URL generation in mailer views. The second supplies a route-level default. Missing or incorrect host configuration can generate links that point to the wrong environment or fail outside the application's usual request context.

The default mount point follows the resource name passed to `passwordless_for`. Applications can instead select `/` and use the `auth` helper prefix:

```ruby
passwordless_for :users, at: '/', as: :auth
```

Passwordless bundles an email form at `app/views/passwordless/sessions/new.html.erb`, a token form at `app/views/passwordless/sessions/show.html.erb`, and a text email at `app/views/passwordless/mailer/sign_in.text.erb`. The command `rails generate passwordless:views` copies the bundled views into the application. Once copied, the application owns their presentation and must keep any required passwordless fields and token behavior intact.

## Registration, token configuration, and upgrade boundaries

User registration remains ordinary Rails application work. The README shows a controller saving a new `User`, creating a Passwordless session for it, and signing that session in:

```ruby
class UsersController < ApplicationController
  include Passwordless::ControllerHelpers

  def create
    @user = User.new(user_params)

    if @user.save
      sign_in(create_passwordless_session(@user))
      redirect_to(@user, flash: { notice: 'Welcome!' })
    else
      render(:new)
    end
  end
end
```

Passwordless configuration belongs in `config/initializers/passwordless.rb` inside `Passwordless.configure`. The README identifies delivery method, token generation, timeout and expiry, redirect behavior, and user lookup as configurable areas. The visible configuration example is truncated before individual keys and defaults appear, so exact values cannot be reproduced responsibly. Those options should be read from the initializer or versioned source rather than guessed.

The README links to `docs/upgrading_to_1_0.md` for a major-version upgrade. That file, `CHANGELOG.md`, and the repository history are more useful here than a release page, because the repository has no GitHub releases. The upgrade surface includes copied migrations, initializer settings, route behavior, and controllers that depend on `Passwordless::ControllerHelpers`. Existing installations should compare those integration points before changing the resolved gem version.

## Conventional authentication and operational constraints

The main alternative is conventional password authentication implemented in the Rails application or through another authentication library. The approaches differ in how each sign-in proves identity. A password flow submits a credential and verifies it against stored password material. Passwordless sends a proof to an email address and associates successful presentation of that proof with `Passwordless::Session`.

This is not a complete account-security package. The README does not document account enumeration policy, breached-password checks, password rotation, hardware-token support, certificate authentication, or multi-factor authentication. It also does not present Passwordless::Session as the application's durable user record. Authorization remains tied to the user model and application controllers.

Operationally, teams must keep Action Mailer configured, monitor delivery failures, ensure links use the correct host, and review token timeout and expiry behavior. The repository is not archived, and its last push was on 2026-06-22. The project uses the MIT license. No GitHub releases are listed, so its recent repository activity should not be interpreted as a published release cadence or a promise of upgrade support for a particular Rails version.

## Conclusion

Passwordless suits Rails applications that already have a user model with an email field and can deliver transactional mail reliably. It does not fit products that require conventional password authentication or a non-email identity system. Before adoption, verify that Action Mailer can generate links for the production host, that the copied migrations fit the existing schema, that token expiry meets the application's risk requirements, and that Passwordless::Session can resolve the application's user class. Once those checks pass, the model and route integration are explicit enough to adopt.

## FAQ

### Does Passwordless create a Rails user model?

No. It creates `Passwordless::Session` and expects the application to provide an authenticatable model with an email field. The README links to its wiki for guidance on creating that model.

### How does a Passwordless application obtain the current user?

The application includes `Passwordless::ControllerHelpers` and calls `authenticate_by_session(User)` in a `current_user` method. Passwordless does not define `current_user` automatically.

### What setup is required before Passwordless can send sign-in links?

The application needs a user email field, the copied Passwordless migrations, an Action Mailer host, and a routing host suitable for generated URLs. Its existing mail delivery configuration must also be able to deliver the message.

## Sources

- [Issues](https://github.com/mikker/passwordless/issues)
- [License: MIT](https://github.com/mikker/passwordless/blob/master/LICENSE)
- [mikker/passwordless on GitHub](https://github.com/mikker/passwordless)
- [README](https://github.com/mikker/passwordless/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/mikker-passwordless
