Tag: authlogic (1 posts)
En busca de la feature perdida en Authlogic
Publicado el 26 Feb 2010
El otro día me tope con algo, cuanto menos curioso. Acababa de poner una aplicación todavía en desarrollo en staging, es decir, había colgado una versión preliminar bajo usuario y clave. Ésta autenticación, un basic http, la había puesto en el servidor web por comodidad, en mi caso apache.
Mi aplicación a su vez cuenta con un back de administración, dónde uso authlogic para la autenticación, y para evitar problemas a la persona que iba a verificar el correcto funcionamiento de todo el site, decidí crear el usuario admin de mi aplicación en base de datos, con los mismo datos de acceso que los usados por la autenticación http del apache.
Cual fué mi sorpresa, cuando una vez deployada mi aplicación, accedí a mi url provisional, puse el usuario y contraseña en la autenticacion que me pedia mi navegador, la del apache, y vi que estaba logado en la aplicación como administrador. Pensé, upss, que extraño, e intenté cerrar sesión. Y digo intente, porque aunque daba a cerrar sesión, yo seguia siempre logado como administrador, y aparentemente la aplicación me estaba borrando mi sesión bien: en los logs la peticion al destroy de mi user_session se procesaba sin problemas, y me sacaba el típico mensaje de flash como que habia sido deslogueado de la aplicación, pero no era asi, yo seguia logado.
Y efectivamente, éste es el momento en el que todos decimos: ¡Cachis!, mi primer bug, no se donde está, pero seguro que es un bug.
Pero no era así, no había ningún bug ni en mi aplicación, ni en authlogic ni mucho menos. Era tan simple como que authlogic, por defecto, da soporte para autenticación http. Por lo tanto, estaba ocurriendo lo siguiente: yo, al meter las credenciales en mi navegador para la autenticación http, estaba mandando en cada petición que se hacía las credenciales, que por casualidad eran las mismas que las de el usuario administardor de base de datos. Authlogic, el muy listo de él, en Authlogic::Session::Base carga los siguientes modulos en éste orden:
include Params
include Cookies
include Session
include HttpAuth
Entonces, por orden, authlogic lo primero que hace es intertar autenticar al usuario por Params, es decir, intenta autenticar al usuario através de una url única generada para ese fin. Si ese no es el caso, entonces intenta autenticarlo por cookies, sino lo intenta por sesión, y por ultimo lo intenta por autenticación http.
En mi caso, yo estaba simplemente accediendo a la home, por lo que no estaba accediendo con una url única de inicio de sesión, ni tenia cookies para autenticar la usuario, ni estaba intentado crear una sesión para el. Simplemente, mi señor navegador, en cada request estaba mandando las credenciales de la autenticacion al apache, que se propagan evidentemente hasta mi app, y el authlogic las ve, e intenta buscar el usuario recibido y autenticarlo con la clave recibida. Como he dicho, yo tenia mi usuario en base de datos, que era administrador, con las mismas credenciales, y acababa siempre logado como tal :). Una buena feature de authlogic.
Se me ocurren varias utilidades de ésta feature, pero la mas evidente y rapida, es la posibilidad de autenticar a los usuarios de nuestra aplicacion sin necesidad de tener un controlador asociado a ello. Solo con tener nuestro modelo 'User' y 'UserSession':
class User < ActiveRecord::Base
acts_as_authentic
end
class UserSession < Authlogic::Session::Base
end
y en nuestro application_controller :
def current_user_session
return @current_user_session if defined?(@current_user_session)
@current_user_session = UserSession.find
end
def current_user
return @current_user if defined?(@current_user)
@current_user = current_user_session && current_user_session.user
end
podemos automaticamente poner una autenticacion http en nuestro servidor web, y authlogic se encargara de recibir esas credenciales, que van en cada request, y establecer un current_user si procede (si encuentra un usuario en nuestra BD y lo puede autenticar), con lo que conseguimos un sistema de autenticación rapido y ligero. Incluso si no queremos tener la autenticacion en el servidor web, con mandar las credenciales en cada peticion también nos valdria:
http://username:password@example.com
Asi a bote pronto, se me ocurre que es un método rápido para usar autenticación en cualquier tipo de API ligera.
Ultimamente me ha pasado también que a veces, tienes un site en staging o preprodución, con una autenticacion en tu apache, pero necesitas que ciertas acciones no lleven esa autenticación para poder hacer ciertas pruebas de una nueva feature, como por ejemplo, una nueva mega aplicación de facebook que has integrado dentro de tu aplicación rails, y quieres probar contra tu servidor de staging, para lo que necesitas dar acceso a ciertas acciones a las peticiones de facebook. Pues simplemente quitando la autenticacion del apache y con un before_filter se me ocurre que esto se podria conseguir facilmente:
before_filter :authorize_request
private
def authorize_request
return false unless current_user || params[:controller] == 'facebook_controller'
end
Si depués de todo ésto, decidís que viviríais mas tranquilos sin esta featura simplemente podéis desactivarla:
class UserSession < Authlogic::Session::Base
allow_http_basic_auth = false
end