The point of a framework is to help automate common work, right? So why is building your application’s authentication system so repetetive? The Merb framework does a lot of useful things and, thankfully, finally includes core patterns and support for user authentication within the framework. It’s called merb-auth, it just moved into town, and it is already beating up other frameworks and stealing their lunch money. And dating your daughter.
You should use merb-auth because:
So let’s build a quick merb app to test it with:
merb-gen app merb-auth-playground
cd merb-auth-playground
merb-gen resource secret
merb-gen resource user
# Add this to config/dependencies.rb if not already present
dependency "merb-auth-core"
What happened? Nothing you can see just yet. This is because, as with all merb components that offer a “core” package, the core contains only structure upon which to hang your own code. merb-auth-core doesn’t care about or do anything to your app. It just provides some hooks for you to start using. What merb-auth-core actually gives us is:
# In any of your controllers
if session.user
"You're logged in as user ID #{session.user.id}"
else
"You're logged out, so you don't get an ID. You don't deserve one."
end
Strategies look like this:
# This is an example strategy
class Merb::Authentication
module Strategies
class MyCustomStrategy
def run!
do_something_that_returns_either_a_user_or_nil_or_false
end
def strategy_error_message
"AND THEN THERE WAS FAIL"
end
end
end
end
You can register and activate them like this:
# In config/init.rb:
Merb::Bootloader.after_app_loads do
Merb::Authentication.register :custom_strategy, Merb.root / "path/to/your/strategy.rb"
Merb::Authentication.activate! :custom_strategy
end
class Secrets < Merb::Controller
before :ensure_authenticated
def index
"lol, juicy secrets"
end
end
There’s also one very important thing that merb-auth does not give you. Merb-auth is Bring Your Own Model code, which means you’re expected to write your own user model. If your user class is called User, which it probably is, then merb-auth will find it just fine with zero configuration. If your user class is called something else, then you’re a masochist, and you should add this to your init.rb:
# config/init.rb:
Merb::BootLoader.after_app_loads do
Merb::Authentication.user_class = MyCustomUserClass
end
Adding merb-auth-core to our app got us all this sweet structure and architecture for free - we can trade authentication strategies with other developers, pretty much any merb developer we hire can understand our authentication system and we still get to define business logic ourselves. But what if we want to use merb-auth-core to do something totally basic that every developer has to build at least over 9000 times in their lifetime, like basic password auth? Enter merb-auth-more. Merb-auth-more doesn’t contain any new architecture over and above merb-auth-core, but it what it does include is a package of ready-made auth strategies that work wonderfully right out the box. Let’s use merb-auth-more to add simple login form support to our application:
# Add this to config/dependencies.rb if not already present
dependency "merb-auth-more"
And if we didn’t already, let’s craft a really simple user model including merb-auth-more’s salted, hashed password module.
merb-gen resource user
# In app/models/user.rb
require 'merb-auth-more/mixins/salted_user'
class User
include DataMapper::Resource
include Merb::Authentication::Mixins::SaltedUser
property :id, Serial
property :email, String, :format=>:email_address
property :login, String, :nullable=>false
# You do not have to define password or password_confirmation attributes - the SaltedUser mixin does this for you.
# You do not have to define the ::authenticate! method - SaltedUser does this for you.
end
If you don’t want to use :login and :password as the params for logging in, or you want users to login using another property, you can easily customise this behaviour with this code:
# config/init.rb:
Merb::BootLoader.after_app_loads do
Merb::Plugins.config[:"merb-auth"][:login_param] = :email
Merb::Plugins.config[:"merb-auth"][:password_param] = :secret_squirrel_decoder_ring
end
Woot! Full authentication from controller to model is ours to use, enjoy and love, with little to no maintenance or hassle. But we don’t have any views set up to allow users to log in, which is somewhat problematic. But don’t panic, honey. Merb’s got your back.
Merb-slices are awesome. They’re little apps designed to run inside your main apps - they can have their own controllers, models, helpers and views, which your main application can override on a file-by-file basis. They’re plugins on steroids - essentially the best way to refactor and share complex behaviour from one merb app to another. Merb-auth-slice-password is a merb slice built on top of merb-auth-core and -more which uses merb-auth-more’s auth strategies to provide a simple login/logout mechanism for your app. Let’s get it running:
# Add this to config/dependencies.rb if not already present
dependency "merb-auth-slice-password"
# In your config/router.rb
# This will 'mount' the slice within your app's URL structure.
# The :path_prefix option tells the router not to mount the slice at a subfolder like /merb-auth-slice-password/login.
# below: Merb::Router.prepare do
add_slice(:MerbAuthSlicePassword, :path_prefix => nil)
# above: end
rake slices:merb-auth-slice-password:install
rake db:automigrate
Let’s try booting up the app! Use the merb command to fire it up and check it out in a web browser. Hit http://localhost:4000 and you should see the merb welcome screen:

However, hit the protected controller we made at http://localhost:4000/secrets and hot diggity damn, free login functionality!

Now the login you have here follows a pattern called exceptional authentication. Merb-auth considers you being logged out (when you need to be logged in) to be an exception, just like NotFound or any other exception. So instead of needing to bounce users to Sessions#new when the user visits a protected URL, we raise an exception and display the login page right there. A single specific URL with a :return_to param is still used to start the session as merb URLs can perform differently depending on the request method used, and we most likely want to render the GET version of the URL upon successful login.
Let’s finish you up by making some changes to the somewhat simplistic login form provided by slice-password. Because we’re dealing with a slice here, we can easily provide new templates for the slice. Check out the directory structure of your project - since you installed that slice, you’ve got a slices folder in the root. Within it, a folder for each of your slices, gloriously arranged for your inspection. Each folder empty, awaiting your instructions. With any slice, you can override views on a per-file basis. Unfortunately due to this bug in Merb 1.0, we have to go about this in a slightly askew fashion for slice-password. In terminal:
rake slices:merb-auth-slice-password:freeze
This will copy the slice files into your slices folder for you to tweak. I’m also going to force the slice files to render inside my main application’s layout:
#in config/init.rb
Merb::Slices::config[:merb_auth_slice_password][:layout] = :application
I’ll restart the slice to see what happened:

Awesome.