【Devise3.2 + Rails4】authentication_tokenでiOSからユーザー認証
iOSとRuby on Rails4 + Deviseで、
ユーザー認証機能を持ったiOSアプリを作ろうとしたら、
Deviseからauthentication tokenが消えていました。
どうやら3.1から消えたみたい?
Deviseの開発チームのコメントによると、
このやり方はセキュアじゃないので、Deviseのユーザーの選択肢から消すために
dupricatedにした、とのこと。
じゃあどうすればいいんやろ。と思ってたら実装方法書いたGistを発見。
#josevalim / 1_unsafe_token_authenticatable.rb
https://gist.github.com/josevalim/fb706b1e933ef01e4fb6
こんな感じ。
前提 : DeviseでUserモデルを作成済
Userモデルにauthentication_tokenカラムを追加
rails g migration AddAuthenticationTokenToUser authentication_token
class User < ActiveRecord::Base before_save :ensure_authentication_token # authentication_tokenが無い場合は生成して設定 def ensure_authentication_token if authentication_token.blank? self.authentication_token = generate_authentication_token end end private def generate_authentication_token loop do token = Devise.friendly_token break token unless User.where(authentication_token: token).first end end end
ApplicationControllerをオーバーライドする
1. セキュアじゃない例
class ApplicationController < ActionController::Base # Deviseの認証ヘルパーメソッドの前にこのメソッドを呼ぶ before_filter :authenticate_user_from_token! # Deviseの認証ヘルパーメソッド before_filter :authenticate_user! private # この例はシンプルに、パラメータからtoken authenticationを取得している。 # が、ヘッダからtokenを取得する形にしてもOK def authenticate_user_from_token! user_token = params[:user_token].presence user = user_token && User.find_by_authentication_token(user_token.to_s) if user # store: falseにしているので、 # セッション内にユーザーは保存されず、リクエストする度にトークンが毎回必要。 # サインインtokenみたいな働きをするtokenが欲しければ、store: false を記述しなければ良い sign_in user, store: false end end end
2. セキュアな例
class ApplicationController < ActionController::Base before_filter :authenticate_user_from_token! before_filter :authenticate_user! private def authenticate_user_from_token! user_email = params[:user_email].presence user = user_email && User.find_by_email(user_email) # タイミング攻撃を防ぐためにトークンの照合にDevise.secure_compareを使う if user && Devise.secure_compare(user.authentication_token, params[:user_token]) sign_in user, store: false end end end