# Pré-dérivation du mot de passe

Lors de l'étape précédente, nous avions intégré le SDK en protégeant l'identité par mot de passe, mais ce mot de passe est aussi utilisé pour l'authentification, ce qui n'est pas sécurisé en l'état, puisque le backend en a connaissance lors de la création de compte et à chaque connexion.

Lors de cette étape, nous ajouterons une "pré-dérivation" du mot de passe pour assurer que le backend n'a jamais accès au mot de passe.

La branche sur laquelle est basée cette étape est 1-quick-start (opens new window), le résultat final est 2-pre-derivation (opens new window).

# Explication

Usuellement l'authentification est effectuée de la façon suivante :

uml diagram

Le problème réside dans le fait que le backend reçoit dans un tel protocole le password tel quel, et pourrait donc l'utiliser pour déchiffrer l'identité protégée sur ssks.

La solution que nous préconisons est d'effectuer une étape dite de "pré-dérivation" du mot de passe pour empêcher le serveur de connaître le mot de passe tel quel, y compris lors de l'exécution.

uml diagram

Dans le cadre du projet exemple, nous allons implémenter cette pré-dérivation dans le service frontend/services/api.js et dans le fichier frontend/utils/index.js :

# Fonction de pre-derivation

La fonction de dérivation choisie est scrypt (opens new window), mais n'importe quelle fonction de dérivation de mot de passe comme pbkdf2, bcrypt, argon2 ou autre offrirait la même fonctionnalité.

Il faut commencer par installer le paquet scrypt-js (opens new window) :

cd frontend
npm install scrypt-js

Puis dans le fichier frontend/utils/index.js :

  • on définit encode qui :
  • on définit hashPassword qui encode password et salt et les dérive avec scyrpt-js configuré avec des paramètres robustes, puis retourne le résultat sous forme de Promise<Buffer>.

# Utilisation de la fonction de pre-derivation

Il faut pré-dériver le mot de passe avant la création de compte et avant la connexion.

En guise de sel, on utilise la concaténation (séparée par |) de :

  • un String arbitraire pour l'application qui sera intégré dans le code du frontend, défini via la variable de configuration APPLICATION_SALT, par défaut à 'sdk-example-project-salt' ;
  • le userId.
DETAILS

Il ne s'agit pas d'un sel aléatoire parce que:

  • le frontend n'a pas la capacité de stocker un sel aléatoire, un utilisateur peut utiliser un nouveau navigateur à tout moment ;
  • le backend est considéré comme malveillant, il n'est donc pas possible de lui faire confiance pour stocker un sel aléatoire pour chaque utilisateur, il pourrait rendre un faux sel arbitraire et obtenir le résultat, et pourrait donc déterminer si deux utilisateurs ont le même mot de passe.

# Migration côté serveur

Dans le projet exemple, aucune étape de migration n'est prévue, il faut supprimer la base de données et recréer les utilisateurs.

Si l'on souhaite effectuer une migration des mots de passe, il n'est pas possible de le faire hors-ligne puisque le serveur n'est pas censé enregistrer le mot de passe de l'utilisateur, mais une version hachée et salée.

Une stratégie envisageable est donc de forcer la réinitialisation de mot de passe pour tous les utilisateurs. Des stratégies plus fines peuvent être envisagées selon les cas.

# Conclusion

Nous avons pu ajouter une étape de pré-derivation du mot de passe pour rendre la protection par mot de passe robuste, puisque dans le projet exemple celui-ci est aussi utilisé pour l'authentification.

Il reste à intégrer avant un passage en production :

  • la persistance de l'identité à l'ouverture d'un nouvel onglet en stockant l'identité en localstorage ;
  • la génération des jetons de licence depuis le backend.