Accountless Auth with Rails
Recently I setup a site for my daughter where she can start to post her artwork that's hers and not festooned with ads on DeviantArt.
I wanted to give her an "admin" portal, but I really didn't want to add the typical account signup flow. It's only her logging in after all. I don't know about you, but I hate that every site I visit wants me to "sign up".
Rather than bringing in a huge gem like Devise or building some other complex "account management" system, here's how we did it.
Create a Basic Login Page and Authenticate Handler
I added a login
route with a form that accepts only a password. It posts back to an authenticate
route which is just hanging off the "welcome" controller. It permits a single parameter, :password
, and compares it against an application configuration value.
I added the following line to config/application.rb
:
config.admin_password = ENV["ADMIN_PASSWORD"] || "password"
Of course it defaults to "password" if nothing is set. I should probably change that to fail if the configuration is missing.
If it matches, I simply create a session with a fixed user id and redirect to the "admin" page.
Protect the Admin Pages
To project the pages I want to be authenticated, first I added a two methods to application_controller.rb
:
class ApplicationController < ActionController::Base
def authorize
redirect_to login_path unless logged_in?
end
def logged_in?
@current_user ||= session[:user_id] if session[:user_id]
end
helper_method :logged_in?
end
Adapting the UI
Then in the controllers that need protecting I added "before actions":
class DrawingsController < ApplicationController
before_action :authorize, only: [:edit, :update, :destroy]
...
The help method lets me hide or show UI based on the login state. For example, in view/layouts/application.html.erb
:
<% if logged_in? %>
<a class="navbar-item" href="/drawings">Drawings</a>
...
<% end %>
Make Sure You're on SSL
It may seem obvious, but only do this if your pages are secure. Once the cookie is set, anyone can just skim it if you're on an unsecured network. In config/environments/production.rb
uncomment:
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
config.force_ssl = true
Conclusion
This works and works well. Safari will even offer to remember the password. It's a braindead simple way of getting the benefit of a typical heavy-handed account management with only a couple lines of code.