04/06/2018
Limiter l'accès à une seule session par utilisateur (Rails)
Comment limiter l'accès à une seule session utilisateur à la fois, avec le Gem Devise ?
Il arrive parfois que dans des milieux très sensibles à la sécurité, comme la santé, il soit nécessaire de s'assurer qu'un utilisateur est connecté à votre application RoR une seule et unique fois.
Le principe est de générer un token unique à chaque nouvelle session et de l'associer à l'utilisateur. Si l'utilisateur tente de se connecter depuis un autre navigateur, c'est le dernier token généré qui sera alors associé à l'utilisateur. La session précédente sera détruite car le token sera obsolète.
Partant du principe que vous avez utilisé Devise pour gérer l'authentification, il vous est alors possible de contrôler qu'un utilisateur n'a qu'une session active en utilisant l'extension "devise_security_extension" (https://github.com/phatworx/devise_security_extension ) comme suit :
Ajoutez le gem à votre Gemfile
gem 'devise_security_extension'
Après avoir fait le rituel bundle install, lancez l'installation de l'extension :
rails g devise_security_extension:install
Lancez ensuite la migration
rails g migration AddSessionLimitableToUsers unique_session_id
Modifiez le fichier de migration pour limiter la taille du champ unique_session_id (and be a good citizen :)
class AddSessionLimitableToUsers < ActiveRecord::Migration
def change
add_column :users, :unique_session_id, :string, limit: 20
end
end
Lancez la migration
rake db:migrate
Modifiez le model User afin d'ajouter l'option ' :session_limitable' à la suite de vos options Devise
# app/models/user.rb
class User < ActiveRecord::Base
devise :session_limitable # à la suite de vos options existantes et actives
... / ...
end
C'est terminé.
Si maintenant un utilisateur tente de se connecter depuis un autre navigateur, il en sera informé et sa précédente session sera fermée.
Bonus
Pour limiter la session d'un utilisateur dans le temps, il suffit d'ajouter l'option Devise :timeoutable et de définir le temps d'inactivité en ajoutant à votre model User avec la méthode suivante :
def timeout_in
15.minutes
end