Подтвердить что ты не робот

Rails api и аутентификация собственного мобильного приложения

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

Мой вопрос прост: есть ли хороший способ аутентифицировать пользователей из родных приложений для Android и iPhone с помощью Rails 4? Кто-нибудь знает хорошие учебники или статьи, которые предоставляют решение?

Адам Уайт Добавляет награду:

Я только что открыл 500 бонусов по этому вопросу, потому что я не могу найти правильную практику для аутентификации пользователя из приложения iOS в Rails API в любом месте. Это то, что я рассматривал, но понятия не имею, безопасно это или нет?!:

Предположим, что у нас есть запись User. Пользователь зарегистрировался для учетной записи, которая создала запись User в базе данных с столбцом email и столбцом password_digest.

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

Я предполагаю, что нам понадобится аутентификация на основе токенов. Я бы, возможно, создал запись ApiKey при создании User и сохранил ее как ассоциацию в записи User.

Когда пользователь подписывается в/вверх, ответ будет содержать токен API (что-то вроде SecureRandom.hex), которое будет сохранено в iOS Keychain и использовано со всеми последующими запросами, чтобы проверить пользователя, передав его в заголовке и проверяя это, используя что-то вроде:

before_filter :restrict_access

private

def restrict_access
authenticate_or_request_with_http_token do |token, options|
  ApiKey.exists?(access_token: token)
end

Это безопасно? Должен ли я обновлять токен с каждым запросом и включать его в ответ?

Какие еще варианты у меня есть? Что делают Facebook, Twitter и Pinterest?

Я знаю OAuth2.0, но разве это не для предоставления внешних приложений?

Есть ли камень, который управляет этим?

Извините, совершенно не уверен здесь.

500 к лучшему ответу.

4b9b3361

Ответ 1

Суть решения из моих исследований. Не стесняйтесь редактировать, исправлять, аннулировать и т.д.

SessionsController < ApplicationController
  skip_before_filter :authenticate_user, :only => [:create]
  def create
    user = User.where("username = ? OR email = ?", params[:username_or_email], params[:username_or_email]).first
    if user && user.authenticate(params[:password])
      api_key = user.find_api_key
      if !api_key.secret_key || api_key.is_expired?
        api_key.set_expiry_date
        api_key.generate_secret_key
      end
      api_key.save
      render json: api_key, status: 201     
    else
      status: 401
    end
  end

Обратите внимание на ApiAuth.authentic? метод и объект запроса. Запрос должен быть подписан с алгоритмом HMAC на клиенте.

ApplicationController < ActionController::Base
  respond_to :json
  force_ssl
  protect_from_forgery with: :null_session 
  before_filter :authenticate_user
  private
  def authenticate_user
    if authenticate_user_from_secret_key
      return true
    else
      head :unauthorized 
    end
  end
  def authenticate_user_from_secret_key
    userid = ApiAuth.access_id(request)
    currentuser = userid && User.find_by_id(userid)
    if ApiAuth.authentic?(request, currentuser.find_api_key.secret_key)
      return true
    else
      return false
    end
    false
  end

Создание/регистрация пользователей

UsersController < ApplicationController
  skip_before_filter :authenticate_user, :only => [:create]
  def create
      user = User.create(user_params)
      if !user.new_record?
        render json: user.find_apit_key, status: 201

      else
       # error
      end
  end

Модель ключа Api. Как и в ключевой модели api в # 352, railscast имеет только различие в генерации ключей ApiAuth.

class ApiKey < ActiveRecord::Base
  before_create :generate_secret_key, :set_expiry_date
  belongs_to :user   
  def generate_secret_key
    begin
    self.secret_key = ApiAuth.generate_secret_key
    end while self.class.exists?(secret_key: secret_key)
  end

Модель пользователя.

class User < ActiveRecord::Base
  has_secure_password
  before_save :ensure_api_key 
  has_many :api_keys 
  def find_api_key
   self.api_keys.active.ios.first_or_create
  end

На клиентской стороне алгоритм HMAC должен использоваться для подписи запросов.

Код от: [SHA1 HMAC Генерация ключей/аутентификация] https://github.com/mgomes/api_auth [Контроллеры и модели] https://github.com/danahartweg/authenticatable_rest_api

Ответ 2

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

Изменяя токен в каждом запросе, вы устраняете проблему перехвата, но как только кто-то перехватил токен, он может впоследствии использовать систему, продолжая ее перехватывать и даже модифицируя ответ. Одним из решений этого является использование HMAC (который используется веб-службами Amazon). Это алгоритм, который обеспечивает подпись (хэш) для вашего запроса, который является уникальным для каждого запроса, не требует изменения ключа и не может быть предсказан для будущих запросов.

Существует рубиновая жемчужина для рельсов, которая реализует HMAC на стороне сервера для подписания запросов HMAC, а также генерирует их при взаимодействии между серверами. Для запросов "клиент-сервер", как в вашем случае, вам необходимо сгенерировать подпись на стороне iOS или Android и аутентифицировать их на сервере.

Рассмотрим камень ApiAuth, чтобы выполнить работу на стороне сервера. На стороне клиента iOS рассмотрите библиотеку HBHMAC для генерации подписи. Взгляните на конкретную реализацию ApiAuth, поскольку она добавляет временную метку к данным для предотвращения повторных атак, поэтому вам может понадобиться добавить поле к вашим данным, прежде чем передавать его в HBHMAC.

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

Ответ 3

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

Как минимум для iOS, устройство будет обрабатывать сеансы для вас, а это означает, что если пользователь в приложении iOS делает запрос POST на /users/sign_in с параметрами

user: { 
  password: 'mypassword',
  email: '[email protected]',
  remember_me: true # optional
}

устройство iOS будет хранить сеанс для вас безопасно и настойчиво.

Теперь, если вы хотите пойти по маршруту OAuth 2, я фактически поддерживаю жемчужину для рельсов 4 под названием OAuth 2, которые я добавил довольно классную функцию, которая позволяет вам пройти через экран авторизации, потому что, очевидно, если вы разработали программное обеспечение, вам не нужен пользователь, чтобы подтвердить, что они вам доверяют.

Если вы решите использовать OAuth 2, вам нужно будет использовать то, что называется неявным токеном доступа. Это длинная и очень скучная спецификация OAuth2 для этого

Проект рельсов 4 можно найти на github https://github.com/bwheeler96/devise-oauth2-provider-rails4

Если вы не на рельсах 4, вы можете использовать оригинальный камень https://github.com/socialcast/devise_oauth2_providable

Кстати, драгоценный камень нуждается в работе, поэтому, если кто-нибудь читает это, кто хочет помочь сделать его лучше, пожалуйста, непременно fork этот репозиторий

Ответ 4

Если вы хотите использовать OAuth2.0 в рубине на рельсах, вы будете использовать Doorkeeper, здесь вы можете увидеть пример (не бесплатный):

http://railscasts.com/episodes/353-oauth-with-doorkeeper

Но вы можете использовать токен с SecureRandom.hex, пример (не бесплатный) для этого здесь (на уровне 6):

https://www.codeschool.com/courses/surviving-apis-with-rails

Я надеюсь, что мой ответ поможет вам!