Implement User Authentication in Ruby with Sinatra
Content and profile customization is a central part of any website's success, yet implementing even basic authentication- and profile-related features can be incredibly tedious and time consuming. In recent years the various development communities have responded by implementing pluggable authentication extensions which in many cases provide all of the necessary functionality right out of the box. The Ruby community has been particularly strong in this regards, producing numerous fantastic solutions capable of not only managing users within a local database but also interacting with popular third-party user repositories such as Facebook and GitHub.
In the latest installment of this occasional series introducing the popular Ruby-based framework Sinatra, I'll show you how to easily add user authentication capabilities to your Sinatra application (be sure to also check out previous articles which show you how to create a Sinatra-based REST API and interact with a MySQL database by way of the DataMapper ORM). To accomplish this goal, we'll use the aptly-named sinatra-authentication Sinatra extension.
Installing and Configuring sinatra-authentication
The sinatra-authentication Sinatra extension is installable as a Ruby gem, meaning you can install it using the following command:
$ gem install sinatra-authentication
We'll store the user profiles in a MySQL database, and interact with them using the DataMapper ORM. (If you're not familiar with DataMapper, be sure to check out my recent article on the topic.) Additionally, we'll use convenient flash messaging to notify the user of various events such as a successful login, so be sure to install rack-flash if you haven't already done so.
Integrating User Authentication Features
Integrating user authentication features into your Sinatra application is incredibly easy.
require 'rubygems' require 'sinatra' require 'haml' require "dm-core" require "dm-migrations" require "digest/sha1" require 'rack-flash' require "sinatra-authentication" DataMapper.setup(:default, "mysql://webuser:secret@localhost/stampclub") DataMapper.auto_upgrade! use Rack::Session::Cookie, :secret => 'superdupersecret' use Rack::Flash
Save this file as
app.rb. For the purposes of this example I'm using a database named
stampclub. In order to follow along with the examples you'll need to create a database and pass along the credentials to the
DataMapper.setup method as demonstrated above.
Next, create a file named
layout.haml, saving it to a directory named
views and adding the following content to it:
!!! %html %head %title Stamp Club %body = yield
views/layout.haml in place, open a terminal window and execute the following command from within your application directory to start the Sinatra server:
$ ruby -rubygems app.rb == Sinatra/1.2.6 has taken the stage on 4567 for development with backup from Mongrel
Thanks to DataMapper's convenient schema migration capabilities, merely starting the application for the first time will result in a table named
dm_users being created within the database you specified in
mysql> describe dm_users; +------------------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | email | varchar(40) | YES | UNI | NULL | | | hashed_password | varchar(50) | YES | | NULL | | | salt | varchar(50) | YES | | NULL | | | created_at | datetime | YES | | NULL | | | permission_level | int(11) | YES | | 1 | | +------------------+------------------+------+-----+---------+----------------+
In addition to creating the
dm_users table, sinatra-authentication creates a number of routes which implement the various user registration, login, logout, profile viewing, and profile editing features. If you're familiar with REST, then these routes should make perfect sense. If you haven't yet been acquainted with REST, check out my recent article on the topic, which shows you how to implement a REST-based API using Sinatra. In any case, sinatra-authentication generates the following routes out of the box:
GET '/login' GET '/logout' GET '/signup' GET/POST '/users' GET '/users/:id' GET/POST '/users/:id/edit' GET '/users/:id/delete'