Rails API: лучший способ реализовать проверку подлинности?

Я пишу приложение Rails 4, которое откроет API для мобильного приложения, которое еще не разработано. Пользователи будут аутентифицироваться с помощью электронной почты и пароля из мобильного приложения.

Пока я нашел довольно много информации по этой теме. Трудно понять, что датировано или не оптимально. Я читал об HTTP Basic Auth, который не кажется слишком безопасным, и HTTP-токена Auth, но я не уверен, как связать это с обычной аутентификацией по электронной почте и паролю (я использую Devise by путь).

Я просто хотел бы узнать, какая лучшая практика в том, как реализовать это, поэтому я обязательно вернусь.

Ответ 1

Важным моментом, с точки зрения безопасности, является обмен электронной почтой и паролем пользователя на токен один раз, а затем использование этого токена для последующих запросов. Это происходит потому, что:

  • Вы не хотите, чтобы клиентское приложение отвечало за удержание пароля пользователя, где ошибка или атака могут привести к ее утечке; и
  • Выбранный сервером токен дает вам (и вашим пользователям) возможность, при необходимости, истекать токен, например. блокировать украденное устройство или блокировать плохой клиент API.

Есть много способов сделать это с различными уровнями сложности.

Вот учебник, который является очень недавним и содержит подробное пошаговое руководство для создания API в Rails с аутентификацией на основе токенов (не используя Devise, но все еще актуальной для понимания понятий): https://labs.kollegorna.se/blog/2015/04/build-an-api-now/

Ответ 2

@Roma149 это скорее личное предпочтение, но большинство людей, которые только начинают использовать Devise, поскольку это самая легкая ИМО. OAuth2 - хороший вариант. В качестве более важной заметки вы всегда можете перейти на The Ruby Toolbox

Существует много хорошей информации о драгоценных камнях, и они даже говорят вам о возрасте и популярности драгоценного камня. Это также позволит вам различать, какие камни, которые сообщество действительно выказывает сейчас, или то, что устарело.

Помните, что в Ruby и Ruby On Rails не всегда лучше, чем лучше, но лучше всего подходит для вашего проекта!

Ответ 3

Другим вариантом является включение модуля ниже в вашу модель разработки и добавление таблицы auth_token к вам.

приложение/модели/проблемы/token_authenticable.rb

module TokenAuthenticatable
  extend ActiveSupport::Concern

  included do
    before_save :ensure_auth_token
  end

  module ClassMethods
    def find_by_token(token)
      find_by(auth_token: token)
    end
  end

  def ensure_auth_token
    self.auth_token = generate_auth_token if auth_token.blank?
  end

  private

  def generate_auth_token
    loop do
      token = Devise.friendly_token
      break token unless self.class.exists?(auth_token: token)
    end
  end
end

приложение/контроллеры/API/v1/login_controller.rb

...
 def login_user(params)
    if params[:authentication]
      @user = User.find_by(auth_token: params[:authentication])
      if @user.nil?
        render json: err('login user by token failed', ERR_USER_NOT_FOUND), status: :not_found
        event('login_user_by_auth_failed', 'token', params[:authentication])
        return
      else
        render status: :ok, json: @user
        return
      end
    else
      user = user.find_by(email: params[:email])
      if user.nil?
        event('login_user_failed_not_found', 'user_email', params[:email])
        render json: err("login user not found #{params[:email]}", ERR_USER_NOT_FOUND), status: :not_found
        return
      end
      if user.access_locked?
        event('login_user_blocked', 'user_id', user.id)
        render json: err("login user account is locked : #{user.id}", ERR_USER_LOCKED), status: :unauthorized
        return
      end
      unless user.try(:valid_password?, params[:password])
        event("login_user_password_does_not_match #{user.id}", 'user_id',  user.id)
        render json: err('login user password does not match', ERR_PASSWORD_NOT_MATCH), status: :unauthorized
        return
      end
      event('login_user_succeeded', 'user_id', user.id)
      @user= user
      if @user.save
        response.headers['authentication'] = @user.auth_token
        render status: :ok, json: @user
        return
      else
        render json: @user.errors, status: :unprocessable_entity
        return
      end
    end
  end
...

Изменить: Исправлена ​​опечатка кода

Ответ 4

Tiddle gem предоставляет стратегию разработки для аутентификации токенов в приложениях Ruby on Rails, поддерживающих API. Его главная особенность - поддержка нескольких токенов на пользователя.

https://github.com/adamniedzielski/tiddle