認証機能再発明するべからずは有名な鉄則ですが、まるで知らないままというのもマズイので実装を読むことでお茶を濁していきたい。
salt
やSCrypt
の運用、persistence_token
の更新などで比較的安全にいけるのでは。
salt
Authlogic::Random.friendly_token
def friendly_token
# use base64url as defined by RFC4648
SecureRandom.base64(15).tr('+/=', '').strip.delete("\n")
end
暗号化
authlogic/lib/authlogic/crypto_providers
以下に、各種Cryptorをラップしたアダプターがある。
SCrypt
ならAuthlogic::CryptoProviders::SCrypt#encrypt(*tokens)
で暗号化パスワードを得られる。
*tokens
には[password, salt]
が入り、salt
は保存されてログイン時のパスワード一致を見る時に使われる。
生パスワードは勿論破棄される。
パスワード確認
各種Cryptorの比較演算子を使ったりする。
# ユーザーのレコードから得る
salt = user.password_salt
encrypted = user.encryped_password
# 入力
password = 'aaaaaaaa'
# 比較
SCrypt::Password.new(encrypted) == Authlogic::CryptoProviders::SCrypt.encrypt(password, salt)
cookie
などの値を得るために、Controller
インスタンスを持つアダプターが必要になる。
Controller
経由では、初期化時に自動的に付与されるAuthlogic::ControllerAdapters::RailsAdapter
が設定する。
Authlogic::Session::Base.controller = RailsAdapter.new(self)
それ以外で使いたい場合は、必要な値を返すなにかを用意する。
class ControllerLike
def initialize(request)
@request = request
end
def cookies
@request.cookies
end
def params
@request.params
end
def session
@request.session
end
def responds_to_last_request_update_allowed?
true
end
def last_request_update_allowed?
false
end
def method_missing(*args)
false
end
end
Authlogic::Session::Base.controller = ControllerLike.new(request)
開始
create
時にユーザーレコードにpersistence_token
を保存する。
クッキーにはそのpersistence_token
とユーザーのid
を、後にsplit
可能な形で保存する。[persistence_token, id].join('::')
など。
復元
保存しておいたクッキーの値のid
からユーザーを検索、persistence_token
と一致するか見る。