ボクココ

個人開発に関するテックブログ

Rails の認証で Devise ではなく Sorcery という選択

現在 AngularJS と Ruby on Rails 間の認証の仕組みを実装しようとしている。

この際問題になるのは、デフォルトのRails認証の仕組みは、HTMLベースであるため AngularJS で必要とされる JSON でのレスポンスが受け取れない、という点がある。

もちろん、Devise による認証でも Devise::Controller 系を継承することで独自のコントローラをカスタマイズすることが可能だ。だが、これは Devise 側のソースコードを理解し、適切なコードとレスポンスを Devise の慣習にそって実装する必要がある。これがなかなか大変。

 

そこで登場するのが Sorcery . これは簡単にいえばシンプルな認証の仕組みだけを提供してくれるものだ。 個人的に最も大きな違いといえば、Devise は devise_for :user や devise_for :admin といったパラメータの指定によって authenticate_user などのメソッドを動的に生成している。つまり、サンプルコードを動かし、Devise のソースのどこにこれがあるのかを探すのがかなり大変になる。 Ruby の魔術を多用しているのだ。

その反面、 Sorcery のソースは簡潔で読みやすい。 むしろ Sorcery は Devise::Controller などのようなクラスを継承する必要は無い。提供されているのは、 current_user, login, logout, require_login といった認証で必須のメソッドのみ。ということで 純粋なApplicationController を継承するだけでOKだ。

 

下記のサンプルは普通にERBを使う例だが、コレを元にレスポンス用のJSONを作るのは容易なはずだ。

サンプル

class UsersController < ApplicationController
  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to root_url, :notice => "welcome"
    else
      render :new
    end
  end
 
private
  def user_params
    params.require(:user).permit(:email, :password, :password_confirmation)
  end
end
 
class SessionsController < ApplicationController
  def create
    user = login(params[:email], params[:password], params[:remember_me])
    if user
      redirect_back_or_to root_url, :notice => "Logged in!"
    else
      flash.now.alert = "Email or password was invalid."
      redirect_to root_url
    end
  end
end

class User
  include Mongoid::Document
  # initialize fields by sorcery
  authenticates_with_sorcery!

  validates_confirmation_of :password
  validates_uniqueness_of   :email
  validates_presence_of     :email
end

sorcery

Sorcery の使い方を調べるには、 RailsCast が最も始められやすい。自分は mongid を利用して開発しているが、スムーズに開発できている。

 

JSON を返す認証の仕組みを作るなら、Sorcery で自分で構築する方が早いだろう。