# 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 :
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.
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 :- normalise le mot de passe de façon canonique avec la méthode
String#normalize
(opens new window) ; - transforme le mot de passe normalisé en
Buffer
;
- normalise le mot de passe de façon canonique avec la méthode
- on définit
hashPassword
qui encodepassword
etsalt
et les dérive avecscyrpt-js
configuré avec des paramètres robustes, puis retourne le résultat sous forme dePromise<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.