July 10, 2014

Multiple authentication ways in one application

I was recently working on one simple application and I needed to create REST API for all user actions. Users were authenticated with standard HTML signin forms, but this was not possible for API.

So I decided to add HTTP basic authentication to my application, but just for API calls. Implementation was pretty simple. authenticate method checks request type and then decide which type of authentication will be used.

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  skip_before_action :verify_authenticity_token, if: :json_request?

  before_action :authenticate

  attr_reader :current_user
  helper_method :current_user

  private

  def authenticate
    if json_request?
      authenticate_user_with_http_basic
    else
      authenticate_user_with_html_auth
    end
  end

  def authenticate_user_with_http_basic
    user = authenticate_with_http_basic do |email, password|
      user = User.find_by_email(email)
      user.authenticate(password) if user
    end

    if user
      @current_user = user
    else
      request_http_basic_authentication
    end
  end

  def authenticate_user_with_html_auth
    unless @current_user = User.find_by(id: session[:user_id])
      if request.xhr?
        redirect_via_turbolinks_to signin_path
      else
        redirect_to signin_path
      end
    end
  end

  def json_request?
    request.format.json?
  end
end

For more information check ActionController::HttpAuthentication::Basic documentation.

Hey there!

My name is Patrik Bóna and I am the only programmer at Memberful. This blog is kind of dead, but I just started my own Ruby on Rails screencast. Follow me on Twitter if you want to be notified about my newest videos.