# Intégrer le 2-man-rule sur votre backend

Comme expliqué dans le guide de gestion des identités la protection en 2-man rule nécessite quelques modifications sur votre backend.

Plus précisément, deux choses doivent être modifiées :

  • la génération et stockage d'une clé twoManRuleKey secrète associée à un utilisateur de votre application, remise lors de l'authentification ;
  • une interaction avec le service Seald Secure Key Storage (SSKS) pour que l'utilisateur puisse s'authentifier auprès de SSKS.

On notera :

  • Utilisateur : l'utilisateur de l'application dont on veut protéger l'identité ;
  • Identité : une identité cryptographique Seald de l'Utilisateur (décrite dans le guide dédié) ;
  • Frontend : le frontend de l'application dans laquelle le SDK est intégré ;
  • Backend : le backend de l'application dans laquelle le SDK est intégré, il stockera twoManRuleKey, la clé permettant de déchiffrer encryptedIdentity ;
  • SSKS : une instance de Seald Secure Key Storage, il stockera encryptedIdentity non déchiffrable sans la twoManRuleKey ;

L'objectif est de donner à l'Utilisateur les deux "morceaux" de son identité Seald (twoManRuleKey et encryptedIdentity) par authentification, tout en empêchant SSKS et le Backend de pouvoir chacun indépendamment accéder à l'identité de l'utilisateur.

# Préalable

Pour communiquer avec le serveur SSKS, votre Backend aura besoin de :

  • l'URL du serveur SSKS : l'instance mutualisée par défaut est https://ssks.seald.io/ ;
  • ssksAppId : correspond au appId utilisé pour le SDK ;
  • ssksAppKey : permet à votre Backend de s'authentifier auprès du serveur SSKS.

Cette ssksAppKey peut être générée ou renouvelée sur le tableau d'administration.

Aller sur la page de gestion du SDK
1. Aller sur la page de gestion du SDK
Générer la clé
2. Dans la partie "Clé serveur SSKS-2MR", cliquer sur le bouton "Générer la clé"
Clé générée
3. Vous pouvez copier la clé générée. Attention, vous n'y aurez plus accès plus tard ! Enregistrez-la maintenant !

# Protocole

Le protocole s'effectue en deux étapes :

  1. la protection initiale de l'identité qui n'arrive normalement qu'une seule fois immédiatement après sa génération ;
  2. la récupération de l'identité qui arrive à chaque fois que l'Utilisateur veut récupérer son identité localement.

TIP

La protection d'une identité en 2-man rule est usuellement couplée à une base de données locale persistante pour "mettre en cache" l'identité de l'Utilisateur et éviter qu'il ait à nouveau besoin de la récupérer à chaque fois qu'il ouvre l'application.

Le protocole pour effectuer la protection initiale d'une identité notée identity de l'Utilisateur est le suivant :

uml diagram

TIP

Dans le cas où une identité a déjà été stockée sur SSKS avec cette adresse email, le serveur SSKS demandera alors une authentification par challenge email, en envoyant mustAuthenticate à true.

Dans ce cas, l'utilisateur recevra un challenge valable 6h par email, et devra le répéter dans le front-end pour pouvoir s'authentifier sur SSKS avant de stocker sa nouvelle identité.

Pour récupérer l'identité identity de cet Utilisateur lors d'une autre session, le protocole est le suivant :

uml diagram

Les flèches rouges dans le schéma indiquent les opérations à implémenter dans l'application utilisant le SDK Seald et le mode de protection en 2-man rule. Les flèches noires indiquent ce qui est déjà implémenté par le SDK, le plugin de protection en 2-man rule @seald-io/sdk-plugin-ssks-2mr ou SSKS.

# Protection de l'identité

Avant d'appeler la méthode saveIdentity exposée par le plugin @seald-io/sdk-plugin-ssks-2mr, il faut les éléments suivants :

  • userId : un identifiant unique de l'utilisateur dans l'application ;
  • email : adresse e-mail de l'utilisateur utilisée pour l'authentification par challenge, doit être répété ou vérifié par l'utilisateur pour s'assurer que le backend n'essaye pas de réaliser une attaque MITM (opens new window) ;
  • twoManRuleKey : la clé connue du backend permettant de chiffrer / déchiffrer l'identité ;
  • sessionId : l'identifiant de session généré par SSKS et transmis par le backend au SDK ;
  • si le serveur à envoyé mustAuthenticate à true, challenge : un jeton aléatoire envoyé par SSKS par e-mail à l'utilisateur pour l'authentifier, valable 6h, ne doit jamais être révélé au backend ;

Pour cela, il faut implémenter un point d'API getSSKSSession authentifié sur le backend qui :

  1. utilise le point d'API POST https://{SSKS_URL}/tmr/back/challenge_send/ pour envoyer à SSKS :
  • create_user : donner true pour créer en même temps l'utilisateur sur SSKS sinon cela devra être fait avec une requête préaable ;

  • user_id : correspond au userId dans @seald-io/sdk-plugin-ssks-2mr ;

  • email ; l'adresse e-mail de l'utilisateur sur laquelle le challenge sera envoyé ;

  • template : le template d'email à utiliser au format HTML, et qui doit contenir $$CHALLENGE$$ qui sera remplacé par le challenge.

    SSKS va retourner au backend sessionId et mustAuthenticate.

    Si mustAuthenticate est true, SSKS va envoyer un email au format de template à l'adresse email contenant challenge, valable 6h ;

  1. génère twoManRuleKey (64 octets aléatoires robustes cryptographiquement) et la stocke associé à cet utilisateur ;
  2. renvoie au frontend sessionId, mustAuthenticate, et twoManRuleKey.

TIP

Dans le cas où mustAuthenticate est true, le frontend doit bloquer et attendre que l'utilisateur entre le challenge qui lui a été envoyé par email avant d'appeler la méthode saveIdentity.

Dans le cas où mustAuthenticate est false, le frontend peut appeler la méthode saveIdentity directement.

Ensuite, le frontend peut utiliser la méthode saveIdentity de la façon suivante :

TIP

Pour une sécurité optimale, il est recommandé d'afficher en frontend l'adresse email qui va être envoyée à SSKS avant d'appeler le saveIdentity, afin de s'assurer que le backend a bien créé l'utilisateur SSKS avec la bonne adresse email, et qu'on va bien stocker l'identité de l'utilisateur associée à une adresse email qu'il maitrise.

# Récupération de l'identité

Avant d'appeler la méthode retrieveIdentity exposée par le plugin @seald-io/sdk- plugin-ssks-2mr, il faut les même éléments que pour la méthode saveIdentity décrite au paragraphe précédent.

Pour cela, on réutilise le même point getSSKSSession décrit à la partie précédente, sauf qu'il ne génère pas une nouvelle twoManRuleKey mais renvoie celle déjà générée :

  1. utilise le point d'API POST https://{SSKS_URL}/tmr/back/challenge_send/ pour envoyer à SSKS :
  • create_user : donner False, à cette étape l'utilisateur est déjà créé 

  • user_id : correspond au userId dans @seald-io/sdk-plugin-ssks-2mr ;

  • email : l'adresse e-mail de l'utilisateur sur laquelle le challenge sera envoyé ;

  • template : le template d'email à utiliser au format HTML, et qui doit contenir $$CHALLENGE$$ qui sera remplacé par le challenge.

    SSKS va envoyer un email au format de template à l'adresse email contenant challenge, valable 6h, et retourner au backend sessionId ;

  1. récupère la twoManRuleKey stockée associée à cet utilisateur (différent de la partie précédente) ;
  2. renvoie au frontend sessionId et twoManRuleKey.

Ensuite, le frontend peut utiliser la méthode retrieveIdentity de la façon suivante :

# Sécurité

La sécurité d'un tel protocole se fonde sur :

  1. le stockage sécurisé d'au moins un des morceaux de l'identité : contrairement à un stockage chez un tiers de confiance unique (coffre-fort numérique, KMS, Cloud HSM, ...), ce protocole est robuste à une compromission partielle. Il faudrait compromettre Backend et SSKS simultanément pour compromettre les identités des utilisateurs.
  2. l'indépendance des authentifications : il faut que SSKS et le Backend ne reposent pas sur les mêmes protocoles d'authentification. Si tous deux utilisent le même SSO par exemple, il suffit alors que le serveur de SSO devienne malveillant pour compromettre totalement la sécurité du protocole. Il en va de même pour les social logins.
  3. non-collusion des serveurs : il faut que SSKS et le Backend ne puissent pas avoir accès à l'autre secret, et surtout pas par API, sinon il suffit de compromettre un serveur et son secret pour obtenir l'autre secret.
  4. le "découpage" sécurisé de l'identité : le protocole choisi par Seald pour "découper" l'identité fait que connaître un "morceau" n'aide pas à accélérer une attaque par force brute, contrairement à un découpage naïf d'un string en deux.

Les limites de ce protocole sont les suivantes :

  1. si les deux protocoles utilisent les mêmes facteurs pour authentifier l'utilisateur (par exemple l'email), il suffit alors de compromettre le facteur de l'utilisateur pour compromettre l'identité (comme pour le SSO).
  2. si SSKS et Backend étaient compromis (ou perquisitionnés) simultanément, les identités des utilisateurs seraient reconstituées par l'attaquant.

WARNING

Ce protocole n'est pas strictement "de bout-en-bout", dans la mesure où l'identité de l'utilisateur peut être reconstituée sans son intervention ou l'intervention de ses appareils.

# Exemples

Les fonctions à implémenter étant relativement simples, et leur implémentation variant considérablement d'une technologie de backend à une autre, nous ne fournissons pas de bibliothèque implémentant ces fonctions.

En revanche, cette partie regroupe plusieurs exemples d'implémentation dans plusieurs langages.

# PHP (vanilla)

get_ssks_session.php :

# Python (django)

views.py :