Go to Hackademy website

Administration des accès Doorkeeper

Numa Claudel

Posté par Numa Claudel dans les catégories outils

Doorkeeper est un provider OAuth 2 pour votre application Rails. Ce provider sert à définir un SSO (Single Sign On) permettant à un utilisateur de se connecter une fois pour toutes sur les applications auxquelles il a accès.

La mise en place d’un SSO nécessite un dialogue entre vos applications clientes et votre provider pour savoir si l’utilisateur doit se connecter ou s’il l’est déjà. Bien entendu ces échanges doivent se faire en toute transparence pour celui-ci. Si vous souhaitez en savoir plus, je vous laisse consulter la présentation de Martin à ce sujet.

Doorkeeper se chargeant de la machinerie coté provider, la mise en place d’un SSO en est grandement simplifié, d’autant plus que Doorkeeper ne se contente pas de gérer les authentifications utilisateurs, mais gère aussi les applications à partir desquelles les utilisateurs pourront se connecter. Une interface est d’ailleurs dédiée à la création / modification / suppression d’applications.

Les autorisations d’accès entre utilisateurs et applications sont aussi de la partie, mais par défaut c’est l’utilisateur lui même qui s’autorise à accéder à une application. Le but de cet article est donc d’aborder une solution pour ne permettre cette gestion des applications et des accès qu’à un administrateur.

Installer Doorkeeper dans l’application

Comme indiqué sur leur Github, ajoutez au Gemfile :

gem 'doorkeeper'

Un bundle, puis exécutez :

rails generate doorkeeper:install

Cette commande aura pour effet de générer un fichier config/initializers/doorkeeper.rb, ainsi que d’ajouter use_doorkeeper à votre fichier de routes. Vous avez donc maintenant une liste de routes générées par Doorkeeper, que nous modifierons pour l’adapter à nos besoins.

GET       /oauth/authorize/:code
GET       /oauth/authorize
POST      /oauth/authorize
DELETE    /oauth/authorize
POST      /oauth/token
POST      /oauth/revoke
resources /oauth/applications
GET       /oauth/authorized_applications
DELETE    /oauth/authorized_applications/:id
GET       /oauth/token/info

Enfin utilisez cette commande pour générer la migration :

rails generate doorkeeper:migration

Cette migration créera trois tables oauth_access_grants, oauth_access_tokens et oauth_applications, qui servent respectivement à la gestion des autorisations d’accès, des jetons d’accès et des applications. Un accès autorisé à une application pour un utilisateur est représenté par une entrée dans la table oauth_access_grants. Lorsque l’utilisateur essaye de se connecter par le biais d’une application, Doorkeeper regarde donc si un accès existe entre cet utilisateur et cette application. Si c’est le cas, alors un jeton d’accès est généré pour une certaine durée. Une entrée est alors créée dans la table oauth_access_tokens avec ces données.

Il ne reste plus qu’à ajouter une migration pour la table users et nous en avons fini pour la partie préparation.

Modifier le comportement par défaut

Les modifications vont consister à remplacer le contrôleur Authorizations de Doorkeeper ainsi que les routes qui correspondent.

Commencez par ajouter un dossier oauth au dossier controllers dans lequel vous ajoutez un contrôleur Authorizations :

module Oauth
  class AuthorizationsController < Doorkeeper::AuthorizationsController

  end
end

L’administrateur doit pouvoir créer des accès et les supprimer, il faut alors définir les méthodes create et destroy. Doorkeeper::AccessGrant est le modèle qui sert à la gestion des autorisations :

def create
  @access_grant = Doorkeeper::AccessGrant.where(access_grant_params).first_or_initialize
  @access_grant.redirect_uri = @access_grant.application.try(:redirect_uri)
  @access_grant.expires_in = 0 # access granted until deleted

  if @access_grant.save
    redirect_to :back
  else
    render :edit
  end
end

def destroy
  @access_grant = Doorkeeper::AccessGrant.find(params[:id])
  @access_grant.destroy
  redirect_to :back
end

private

def access_grant_params
  params.require(:doorkeeper_access_grant).permit(:application_id, :resource_owner_id)
end

Pour commencer, réutilisez un accès s’il a déjà été défini, de cette manière l’administrateur crée un accès pour un utilisateur ou le retire. Il n’est pas nécessaire de gérer plusieurs accès à une application par utilisateur, ce qui est le cas de base avec Doorkeeper. Ensuite redirect_uri et expires_in étant deux attributs obligatoires, le redirect_uri de l’accès sera le même que celui de l’application et attribuons à expires_in la valeur 0. expires_in est utilisé de base par Doorkeeper pour limiter la durée des autorisations. Pour nous, cet attribut ne nous servant pas, la valeur 0 sert seulement à indiquer que l’accès n’a pas de limite de durée.

Enfin pensez à bien faire parvenir au contrôleur les deux paramètres qui vont servir à créer l’autorisation, à savoir application_id et resource_owner_id.

Il faut maintenant indiquer à Doorkeeper d’utiliser notre contrôleur Authorizations :

use_doorkeeper do
  controllers authorizations: "oauth/authorizations"
end

Conclusion

Nous avons maintenant un SSO géré par un administrateur et les utilisateurs n’ont plus qu’à se connecter par le biais des applications auxquelles ils ont accès, ou bien de cliquer sur le lien d’une des applications parmi la liste qui leur sera affichée après connexion directe au SSO.

Je n’ai pas traité ici la partie authentification, car mon but était de vous donner une manière d’adapter Doorkeeper pour ajouter la notion d’administration des accès au provider. Mais cela pourra faire l’objet d’un prochain article.

L’équipe Synbioz.

Libres d’être ensemble.

Articles connexes

Un plugin Vim à la mimine

03/01/2019

Dans l’article précédent, intitulé une assez bonne intimité, je vous présentais GPG et le chiffrement de courriels. Nous avons alors remarqué que le contenu d’un courriel était encodé de sorte que le...

Une assez bonne intimité

20/12/2018

Si vous êtes utilisateur de MacOS, il y a de fortes chances que vous utilisiez Apple Mail pour échanger des courriels. Et comme vous êtes sensible à la confidentialité des informations que vous...

Tests end to end avec Jest et Puppeteer

05/07/2018

Dans cet article, on va partir sur des tests end to end. Pour planter le décor, un test end to end (e2e) est un test logiciel qui a pour but de valider que le système testé répond correctement à un...

Chasser les requêtes N+1 avec Bullet

05/04/2018

Aujourd’hui nous allons parler des requêtes N+1 dans une application Rails : vous savez ces lignes quasiment identiques, qui s’ajoutent de manière exponentielle aux logs, dès lors que l’on appelle...