在Rails API中交换令牌的用户/密码

时间:2015-07-08 00:04:06

标签: ruby-on-rails api authentication ember.js mongoid

我在确定如何为Rails API创建基于令牌的身份验证系统方面遇到了一些麻烦。

我计划构建一个Ember应用,用户应该可以通过提供密码和用户名登录。

在导轨方面,我设置了一个AuthenticationToken模型,用于检查授权令牌和非持久密钥。我根据secret和AuthenticationToken id(BSON :: ObjectId)存储加密的秘密。

基本上我的想法是,只要客户端挂起秘密,客户端就应该能够进行身份验证。然后它需要请求一个新的访问令牌。我希望通过避免会话来保持无国籍。

我很困惑路由和控制器在用户交换用户/传递访问令牌的位置应该是什么样的。正如我发现的众多博客文章/教程中遗漏了那一部分。我只是创建一个简单的POST路由,客户端发送凭据并将令牌作为JSON返回?或者我应该使用HTTP BASIC AUTH?

class User
  include Mongoid::Document
  include ActiveModel::SecurePassword
  embeds_many :tokens, class_name: 'Users::AuthenticationToken'
  field :email, type: String
  field :username, type: String
  field :password_digest, type: String
  validates :email, presence: true, uniqueness: true
  has_secure_password
end
require "securerandom"
require "bcrypt"

class Users::AuthenticationToken
  include Mongoid::Document
  embedded_in :user

  attr_accessor :secret
  field :hashed_secret

  validates :hashed_secret, uniqueness: true, presence: true
  before_validation :generate_secret

  def self.find_by_id(id)
    begin
      id = BSON::ObjectId.from_string(id) unless id.is_a?(BSON::ObjectId)
      tokens = User.find_by('tokens._id' => id).try(:tokens)
      tokens ? tokens.find_by(id: id) : nil
    rescue Mongoid::Errors::DocumentNotFound, BSON::ObjectId::Invalid
      nil
    end
  end

  # @return [Boolean]
  def has_secret? secret
    BCrypt::Password.new(hashed_secret) == secret
  end

  def authenticate!(secret)
    user if has_secret? secret
  end

  private

  def generate_secret
    self.secret = SecureRandom.urlsafe_base64(32)
    self.hashed_secret = BCrypt::Password.create secret, cost: cost
  end

  def cost
    Rails.env.test? ? 1 : 10
  end
end

我还有一个看起来像这样的身份验证方法:

def authenticate!
  token = Users::AuthenticationToken.find_by_id(token_id)
  user = token.try(:authenticate!, secret)
  user.nil? ? fail!("Could not log in") : success!(user)
end

0 个答案:

没有答案