android - qué - Rails api y autenticación de aplicaciones móviles nativas
framework aplicaciones hibridas (4)
Está en el camino correcto, pero el token del usuario solo debe usarse para identificar qué usuario realiza la solicitud. Aún necesita algún tipo de autenticación ya que, como especula con el cambio del token en cada solicitud, un pirata informático podría interceptar el flujo de datos, obtener el token y luego "ser" ese usuario en las solicitudes posteriores.
Al cambiar el token en cada solicitud, elimina el problema de intercepción, pero una vez que alguien ha interceptado el token, puede explotar aún más el sistema al continuar interceptándolo e incluso modificando la respuesta. Una solución para esto es usar HMAC (que es utilizado por Amazon Web Services). Es un algoritmo que proporciona una firma (hash) para su solicitud que es única para cada solicitud, no requiere un cambio de clave y no se puede predecir para futuras solicitudes.
Hay una gema de rubíes para rieles que implementa HMAC en el lado del servidor para firmar las solicitudes de HMAC, así como generarlas cuando se realizan comunicaciones de servidor a servidor. Para solicitudes de cliente a servidor como en su caso, necesita generar la firma en el lado de iOS o Android y autenticarlas en el servidor.
Considere la gema de https://github.com/mgomes/api_auth para hacer el trabajo en el lado del servidor. En el lado del cliente iOS, considere la biblioteca HBHMAC para generar la firma. Eche un vistazo a la implementación específica de ApiAuth, ya que agrega una marca de tiempo a los datos para evitar ataques de reproducción, por lo que es posible que deba agregar un campo a sus datos antes de pasarlos a HBHMAC.
En resumen, el uso de la autenticación HMAC evitará los ataques de personas en el medio y los ataques de repetición utilizando un algoritmo de hashing de una sola vía que evita que los atacantes generen solicitudes auténticas, incluso si son capaces de interceptar solicitudes válidas.
Sé que hay mucha información sobre este tema, pero no puedo encontrar ninguna que esté actualizada. Veo temas como este relacionados con la autenticación de Android y rieles, pero veo que TokenAuthenticatable
ahora se ha eliminado del TokenAuthenticatable
.
Mi pregunta es simple: ¿existe una buena manera de autenticar a los usuarios desde aplicaciones nativas de Android y iPhone usando Rails 4? ¿Alguien sabe de buenos tutoriales o artículos que proporcionan una solución?
Adam Waite Añadiendo una recompensa:
Acabo de abrir una recompensa de 500 en esta pregunta porque no puedo encontrar la práctica correcta para autenticar a un usuario desde una aplicación de iOS a una API de Rails en cualquier lugar. Esto es lo que estaba considerando hacer pero no tengo idea si es seguro o no?
Supongamos que tenemos un registro de User
. Un usuario se ha registrado en una cuenta que ha creado un registro de User
en la base de datos con una columna de email
y una columna password_digest
.
Cuando el usuario inicie sesión, me gustaría que ese usuario permanezca autenticado en la aplicación móvil hasta que cierre la sesión explícitamente.
Me imagino que vamos a necesitar una autenticación basada en token. Tal vez crearía un registro de ApiKey cuando se creara el User
y lo guardaría como una asociación en el registro de User
.
Cuando el usuario SecureRandom.hex
/ SecureRandom.hex
, la respuesta contendrá un token de API (algo así como SecureRandom.hex
) que se guardará en el llavero de iOS y se usará con todas las solicitudes posteriores para verificar al usuario pasándolo en un encabezado y verificándolo mediante algo como:
before_filter :restrict_access
private
def restrict_access
authenticate_or_request_with_http_token do |token, options|
ApiKey.exists?(access_token: token)
end
¿Es esto seguro? ¿Debo actualizar el token con cada solicitud e incluirlo en la respuesta?
¿Qué otras opciones tengo? ¿Qué hacen los Me gusta de Facebook, Twitter y Pinterest?
Soy consciente de OAuth2.0, pero ¿no es eso para otorgar aplicaciones externas?
¿Hay una gema que maneja algo de esto?
Lo siento, completamente inseguro aquí.
500 a la mejor respuesta.
He tenido este problema, soy un desarrollador de API. Puede hacerlo de la manera difícil con tokens y autorización personalizada, pero le diré lo que hacemos con nuestra aplicación, que sirve a los usuarios en la cifra de seis dígitos.
Al menos para iOS, el dispositivo manejará las sesiones por usted, lo que significa que si un usuario en una aplicación de iOS realiza una solicitud POST a /users/sign_in
con los parámetros
user: {
password: ''mypassword'',
email: ''[email protected]'',
remember_me: true # optional
}
El dispositivo iOS almacenará la sesión para usted, de forma segura y persistente.
Ahora, si desea ir a la ruta OAuth 2, en realidad mantengo una gema para los rieles 4 llamada OAuth 2 providable, a la que agregué una característica bastante interesante que le permite al usuario pasar por la pantalla de "autorización", porque obviamente Si desarrolló el software, no necesita que el usuario confirme que confía en usted.
Si decide usar OAuth 2, deberá usar lo que se llama el token de acceso implícito. Esta es la larga y muy aburrida especificación de OAuth2 para eso.
El proyecto de Rails 4 se puede encontrar en github https://github.com/bwheeler96/devise-oauth2-provider-rails4
Si no está en los rieles 4, puede usar la gema original https://github.com/socialcast/devise_oauth2_providable
Por cierto, la gema necesita trabajo, así que si alguien está leyendo esto y quiere ayudar a mejorarla, por favor, bifurque https://github.com/bwheeler96/devise-oauth2-provider-rails4
Si desea utilizar OAuth2.0 en ruby on rails, usaría Doorkeeper, puede ver un ejemplo (no gratis) aquí:
http://railscasts.com/episodes/353-oauth-with-doorkeeper
Pero puedes usar un token con SecureRandom.hex, un ejemplo (no gratis) para esto aquí (en el nivel 6):
https://www.codeschool.com/courses/surviving-apis-with-rails
Espero que mi respuesta te ayude!
Una solución de mi investigación. Siéntase libre de editar, corregir, invalidar, etc.
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
Tenga en cuenta el ApiAuth.authentic? Método y el objeto de solicitud. La solicitud debe estar firmada con un algoritmo HMAC en el cliente.
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
Creación / registro de usuarios
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 modelo clave. Al igual que el modelo de api key en la diferencia única de # 352 railscast es la generación de claves de 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
Modelo de usuario.
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
En el lado del cliente, el algoritmo HMAC debe usarse para firmar solicitudes.
El código es de: [SHA1 HMAC Key generación / autenticación] https://github.com/mgomes/api_auth [Controladores y modelos] github.com/danahartweg/authenticatable_rest_api