ンンンパ

ふとしです

移転しました

Authlogicに関するメモ

認証機能再発明するべからずは有名な鉄則ですが、まるで知らないままというのもマズイので実装を読むことでお茶を濁していきたい。

saltSCryptの運用、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と一致するか見る。