[Ruby on Rails]sorceryによる認証 – (5)APIでの認証 #3 モデル

2015.06.10

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

前回に引き続き、APIでの認証をsorceryを使って行うサンプルについてです。今回はモデルのソースコードを取り上げます。

ソースコード

以下、モデルのソースコードになります。

User

app/models/user.rb
class User < ActiveRecord::Base
  authenticates_with_sorcery!

  has_many :api_keys, dependent: :destroy

  validates :password, length: { minimum: 3 }
  validates :password, confirmation: true
  validates :password_confirmation, presence: true

  validates :email, uniqueness: true

  def self.login?(access_token)
    api_key = ApiKey.find_by_access_token(access_token)
    return false if !api_key || !api_key.before_expired? || !api_key.active
    return !self.find(api_key.user_id).nil?
  end

  def activate
    if !api_key
      return ApiKey.create(user_id: self.id)
    else
      if !api_key.active
        api_key.set_active
        api_key.save
      end
      if !api_key.before_expired?
        api_key.set_expiration
        api_key.save
      end
      return api_key
    end
  end

  def inactivate
    api_key.active = false
    api_key.save
  end

  private

    def api_key
      @api_key ||= ApiKey.find_by_user_id(self.id)
    end
end

「validates」で始まるエラーチェックについては公式チュートリアルとほぼ変わりまりません。

login?メソッドは、クライアントから渡されるAccessTokenを引数として受け取り、該当するユーザがログイン状態かどうかを返却します。具体的にはAccessTokenに該当するApiKeyモデルを取得し、存在するか・有効期限内か・activeの値がtrueかを調べます。これらの実装は後述するApiKeyモデルを参照してください。

activateメソッドは、ユーザをログイン状態にするメソッドです。ApiKeyが存在しない場合は作成し、存在する場合はactiveをtrueにすること・有効期限の再設定を行っております。

inactivateメソッドは、activateとは逆にユーザをログアウト状態にするメソッドです。ApiKeyのactiveをfalseにしています。

ApiKey

次にApiKeyモデルです。

app/models/api_key.rb
class ApiKey < ActiveRecord::Base
  before_create :generate_access_token, :set_expiration, :set_active
  belongs_to :user

  def before_expired?
    DateTime.now < self.expires_at
  end

  def set_active
    self.active = true
  end

  def set_expiration
    self.expires_at = DateTime.now + 1
  end

  private

    def generate_access_token
      begin
        self.access_token = SecureRandom.hex
      end while self.class.exists?(access_token: access_token)
    end
end

before_expired?メソッドは有効期限内かどうかを判定して返却しています。set_activeメソッドはユーザをログイン状態とするためactiveをtrueに変更します。set_expirationメソッドは有効期限を設定しており、今回はログインから1日だけ有効としました。generate_access_tokenメソッドはAccessTokenを生成するメソッドです。ランダムでトークンを生成しています。

set_active、set_expiration、generate_access_tokenはApiKeyの生成時に実行されるよう、before_createにて呼び出されるようにしています。

まとめ

sorceryによるAPIでの認証についての主なロジックは以上となります。API固有の部分は独自に実装することになりますが、sorceryはシンプルであるため何を実装しなければならないかが分かりやすいかと思います。業務の都合上、認証についてある程度は独自に実装しなけらばならないことが分かっている場合、sorceryを検討してみてもいいかもしれません。

今回作成したソースコードは以下のGithubに置いてあります。全ソースを見たい方は参考にしてください。 sorcery_api_sample

参考サイト

今回は以下のサイトを主に参考にさせて頂きました。ありがとうございました。
Simple Password Authentication
Securing an API
Rails + Grape + API Keyの認証