I don’t believe email confirmation or password confirmation are desirable in web apps for early-stage startups.
We wrote and maintain a user authentication and authorization Rails engine called Clearance. It serves a narrow focus for users to sign up, sign in, sign out, and reset their password, all using their email address and a password of their choice.
Clearance is almost 3 years old but we still use it on almost all of our projects. Each new project is an opportunity to re-evaluate what’s good and what sucks about Clearance.
Early on, our goal was mostly a great experience for developers, seen in things like:
Lately, our goal is a great experience for users, seen in things like:
See the CHANGELOG for more. The most unusual decisions were the confirmation decisions.
When you sign up, you’re interacting with the product for the first time. Maybe you’ve heard good things from friends and have skimmed the landing page. Now, you want to try it. Your purpose is to get your hands on it.
So, you enter your email and password, then press “sign up”. If you’re presented with a screen like “please check your email to confirm your account”, you’re kind of bummed.
Maybe you have GMail open in another tab or maybe you’re an ⌘+Tab master and you flick over to Mail.app real quick, see the confirmation email, open it, click the confirmation link, which opens a new tab in your browser, signing you in and presenting you with a screen like “thanks for confirming your account”.
You just took about five actions, made about three decisions, and this is if you’re very savvy and already have your email client open. That, to me, is a burden. Why would you want to get your relationship started with a potential customer by burdening them?
We have numbers that show you lose customers this way. In one example, we have a consumer app with 9,204 email sign ups, but only 4,607 confirmations.
That’s a 50% conversion rate between a user declaring their intent to try the product and actually trying it.
By removing the email confirmation step, our conversion rate goes to 100%. Meanwhile, the user has only had to enter two fields, press “enter” or a “sign up” button, and they’re immediately signed in and using the product.
We think what we’ve provided now is a good user experience but you could argue that making sure the app can easily recover when someone mistypes their email address is also providing a good user experience.
For the moment, I’m trying to not let edge cases dictate how the majority of users interact with the library.
It’s not a problem yet. As an early-stage startup, your problem is attracting, converting, and retaining users. Focus on that problem first, and deal with spam later.
Have you ever enjoyed typing your password twice when you signed up for a product? The answer for most people is “no”, and that should drive this decision.
By default, Clearance signs users in for a year. How often will people need to use their password? It depends on your app, but likely very rarely.
There’s also a password reset, which incidentally does rely on email confirmation. In this case, I hope the extra steps evoke more of a feeling of “that makes sense, they’re securing my account for me, someone who’s invested time into their product”.
We’ll continue to test how people feel about the experience in each real product where we use Clearance. If my hypothesis that people feel good about the email confirmation on password reset turns out to be incorrect, I’ll experiment with the default copy in the flash messages and email body to see if we can move the needle on user’s feelings that way before changing the feature.
I’m excited about these user experience-driven changes to our open source library and I hope you’ll put them to the test.
If you’re already using an old version of Clearance, please read the upgrade instructions. Please also follow Clearance on Github.
Happy coding.
Written by Dan Croak.
I’ve written before about lightweight access control using inherited_resource’s begin_of_association_chain and raising a 404.
I still prefer this approach in the vast majority of apps I work on, but it doesn’t work in the case where there is no relationship between a user and an object other than access control.

Last week, I had a need to differentiate access control to some controller actions based on whether a signed in user was a teacher or student.
This is a simple need, and I’m loathe to introduce a large gem into the app for what could just be a custom before_filter:
class CoursesController < InheritedResources::Base
actions :new, :show, :index
before_filter :authenticate
before_filter :deny_student, :only => [:new]
protected
def deny_student
deny_access if current_user.student?
end
end
However, I recently saw acl9 mentioned on a mailing list and really liked the DSL. Couldn’t we have the best of both worlds?
So, Josh Clayton and I wrote up a sub-set of acl9’s DSL that would meet my needs.
module AccessControl
def self.included(controller)
controller.extend(ClassMethods)
controller.send(:include, InstanceMethods)
end
module ClassMethods
def access_control(options = {}, &block)
before_filter(options) do |controller|
controller.authenticate
end
before_filter(options) do |controller|
controller.instance_eval(&block)
end
end
end
module InstanceMethods
def allow(role, opts = {})
if opts[:to].nil? || opts[:to].include?(action_name.to_sym)
unless current_user.send("#{role}?")
deny_access(opts[:flash])
end
end
end
def deny(role, opts = {})
if opts[:from].nil? || opts[:from].include?(action_name.to_sym)
if current_user.send("#{role}?")
deny_access(opts[:flash])
end
end
end
end
end
ActionController::Base.send :include, AccessControl

In action:
class CoursesController < InheritedResources::Base
actions :new, :show, :index
access_control do
allow :teacher, :to => [:new]
end
end
Very expressive. Nice work, Oleg Dashevskii!

UserThis will usually be included when most actions require a signed in user. Therefore, we call authenticate and allow an ugly override for edge cases:
class CoursesController < InheritedResources::Base
actions :new, :show, :index
access_control(:except => :show) do
allow :teacher, :to => [:new]
end
end
This is used with Clearance and can therefore rely on authenticate, current_user, and deny_access.

Writing code with a pretty DSL in mind is exceedingly fun. The one downside seems to be that scope can become confusing.
Yesterday I was messing with Rails app templates and read the source for the 2.3 template runner. It, like this custom access control DSL, also uses instance_eval as the key line to make things work.
In the app template example, it was hard to figure out how to get the file path of the original template.
I simply wanted to require 'helper', a separate file in the app template, but because of the scope within which it was instance_eval‘d, helper could not be found.
in_root { self.instance_eval(code) }
The solution in that case was to take advantage of other public methods and mess with the load path, which would probably an atrocious solution for a vendored gem in a Rails app, but acceptable for a one-off script to generate a Rails app:
here = File.expand_path(File.dirname(template), File.join(root,'..'))
$LOAD_PATH << here
require 'helper'
In the access control example, it was hard to figure out how to have access to flash, redirect_to, etc. from a class-level scope.
Similar to the require 'helper' example, your tests will fail if:
deny and access are defined at the class levelinstance_eval is not used to delay evaluation until runtimebefore_filter’s blockThe solution is to use blocks and lazy evaluation to control scope, but it can be confusing to get there:
before_filter(options) do |controller|
controller.authenticate
end
before_filter(options) do |controller|
controller.instance_eval(&block)
end
Every time you decide to roll your own, remind yourself that you may waste time getting lost in something like a scope problem you haven’t seen before. Then, once you get the rhythm down, be careful of a thought like “it won’t take me that long to write.” Re-inventing the wheel has to be balanced with a specific reason in addition to, “it will be fun for me.”
The third-party ecosystem of gems and plugins is one reason why Rails is awesome. However, writing custom code every now and again is worth it for programmer pleasure, fewer lines of code and dependencies, and staying focused on only what you need.
Ruby makes great DSLs, though, so don’t be afraid to take inspiration from existing code and try your hand at making beautiful code for a specific purpose.
The following describes a simple approach to Ruby on Rails authorization that re-uses the domain model to do the heavy lifting.
Routes:
resources :accounts, only: [:new, :create, :show]
resources :brands, only: [:new, :create, :show] do |brands|
brands.resources :offers, only: [:new]
end
Brands belong to accounts. Offers belong to brands. Users belong to accounts.
I prefer flat routes (and no subdomains) when at all possible. It keeps the mental overhead low everywhere in the app.
Users are authenticated using Clearance. They have a account_id foreign key.
With an authenticated user in a typical “account” application, we can lean on Clearance’s :authorize before filter and ActiveRecord finders.
class BrandsController < ApplicationController
before_filter :authorize
def new
@brand = current_user.account.brands.build
end
def create
@brand = current_user.account.brands.build(params[:brand])
# ...
end
def show
@brand = current_user.account.brands.find(params[:id])
end
end
With this pattern, the user is restricted to interacting with brands to which they have access through their account.
it 'does not find brands not associated with user' do
brand = create(:brand)
sign_in_as create(:user)
assert_raises(ActiveRecord::RecordNotFound) do
get :new, brand_id: brand.to_param
end
end
Rails returns a 404 when ActiveRecord::RecordNotFound is raised. This error will be raised in our access control scheme because there is no record of the current_user having a relationship to this brand.
Let’s get to green:
class OffersController < ApplicationController
before_filter :authorize
def new
@brand = current_user.brands.find(params[:brand_id])
@offer = @brand.offers.build
end
end
User belongs to accounts and Account has many brands. I could have said current_user.account but I kept the chain from the perspective of the controller shorter using delegation:
class User < ActiveRecord::Base
include Clearance::User
belongs_to :account
delegate :brands, to: :account
end
This will make my life easier when the rules around users’ relationship to brands get more complex.
This authorization approach requires few lines of code and no extra gem dependencies beyond Rails and Clearance. It leans heavily on the framework, stays DRY, and uses normal authentication and RESTful conventions. It’s easy to test and I know where those tests should go.
Written by Dan Croak.
On Fridays, we enjoy getting together for lunch and reviewing code which needs tender loving care. This week, our liveliest discussion surrounded responsibility for authorization logic.
You’ve come across it before ~ you have a User model and a second model for which Users must be authorized to perform certain tasks:
def show
@event = Event.find params[:id]
unless (logged_in? &&
(@event.members.include?(current_user) ||
@event.organizer.include?(current_user)) ||
current_user.admin?)
flash[:failure] = "You are not authorized to view this event."
redirect_to home_url and return
end
end
In discussion, we decided there is too much logic in the controller. We want to move the authorization into the correct place in our domain model. But where?
unless current_user.authorized_for_event?(@event)
That reads nicely in English as “Unless the current user is authorized for the event” but logically, a User should not be responsible for its own authorization. If that were the case in the real world, we’d have societal chaos:
Kaffee: Did you order the code red?!
Col. Jessep: You’re goddamn right I did!

Whether your domain model has an Event or a CodeRed, the authorization logic should be on those models, not on User. In just about every case I can think of, that will remain true.

For example, I have a ticket to a Red Sox playoff game. When I arrive on Yawkey Way, the ticket-taker will authorize me to enter the event. He or she is the Controller in our MVC pattern (and I suppose the View is the world of sight, touch, taste, sound, and smell…). The ticket-taker doesn’t need to know that I paid with a MasterCard on September 20th or that my seat is in right field or any other details. All that matters is: “is this guy authorized?”
def attend
@game = RedSoxGame.find_by_id params[:id]
unless @game.authorized?(current_user)
flash[:failure] = "You are not authorized for this game.
Watch it over a pint of Sam Adams at the Cask n' Flagon."
redirect_to home_url and return
end
end
class RedSoxGame < ActiveRecord::Base
def authorized?(user)
return false if user.nil?
self.doors_open? && self.not_rained_out?
&& user.ticket?(self) && user.not_drunk?
end
end
The authorized method is noteworthy for two reasons. First, it uses the Composed Method:
Divide your program into methods that perform one identifiable task. Keep all of the operations in a method at the same level of abstraction. This will naturally result in programs with many small methods, each a few lines long.
The authorized? method is very easy to read because it focuses on simply authorizing the user for the game. It relies on a number of other methods whose purpose is clear and are similarly of narrow focus.
The second thing to note is that authorized? actually calls methods on the User model. It may seem contradictory to call User after saying that authorization logic does not belongs there. However, it isn’t authorization logic, it’s another level of abstraction.
Most importantly, the ticket-taker will let me into the Sox game and no one gets a code red.