L’authentification sans mot de passe devient un choix de plus en plus populaire pour les développeurs. Même des noms notables comme Slack, Notion et PayPal passent tous aux SMS, aux e-mails ou aux connexions sociales pour leur authentification.
Un facteur déterminant de son adoption croissante est qu’il est intrinsèquement moins sujet aux cyberattaques. Étant donné que même les hachages de mots de passe ne sont pas stockés dans une base de données (qui ont des degrés de sécurité variables en fonction du schéma de hachage et de salage utilisé), il n’y a pas de surface d’attaque exposée avec des informations d’identification d’utilisateur pour les acteurs malveillants à cibler.
Il y a quelques inconvénients au sans mot de passe. UX devient plus compliqué lorsque l’utilisateur quitte la page. De plus, certaines implémentations entraînent des coûts accrus (par exemple, avec des jetons physiques), et bien sûr, aucun système n’est complètement infaillible contre les acteurs malveillants.
Si vous cherchez une bonne introduction aux différentes options possibles avec passworldess, vous pouvez vous référer à ce guide.
Pour les besoins de cet article, nous allons nous concentrer sur une implémentation logicielle – dans notre exemple, ce sera avec des liens magiques par e-mail.
Le TL; DR
Voici ce que nous devons faire pour que l’authentification sans mot de passe soit opérationnelle :
- Créer une méthode pour générer des jetons
- Créez un point de terminaison pour envoyer votre lien magique
- Créer un point de terminaison pour vérifier les jetons
- Mettre tous ensemble
1. Créer une fonction pour générer des jetons
Par souci de simplicité, nous utiliserons JWT comme jeton.
Le pseudo-code :
function generateToken(){
/* Create the token with your preferred JWT library. We recommend you add
a timeout for best security practices
*/
const token = jwt.sign(
{ user_id: user._id, email },
process.env.TOKEN_KEY,
{
expiresIn: "10m",
}
);
return token;
}
2. Créez un point de terminaison pour envoyer votre lien magique
La création du lien magique lui-même est assez simple – le jeton lui-même sera dans le paramètre de requête du lien que nous générons. Nous allons appeler la méthode que nous venons d’écrire pour générer le jeton.
app.get('/send-link', (req, res) => {
// generate the token
const token = generateToken();
// store the token in your database if you'd like to invalidate older tokens for multiple requests
//db_saveNewVerificationToken(req.query.email, token);
// create the verification link using your generated JWT
const magicLink = 'https://example.com/auth/verify-login?token=' + token;
const mailConfigurations = {
from: 'example@example.com',
to: req.query.email,
subject: 'Log into Example',
text: magicLink };
// send the email to your user's inbox
sendMail(mailConfigurations);
res.status(200);
res.json({ emailSuccess: true });
res.end();
});
3. Créer un point de terminaison pour vérifier les jetons
app.get('/verify-token', (req, res) => {
// if only looking for the latest, look up the saved token via the user's email
//const signature = db_lookupVerificationToken(req.query.email);
// using the secret key, verify the token by comparing the token to a test signature generated from the header and payload
const decode = jwt.verify(token);
if(decode === true){ // Return response with status
res.status(200);
res.json({
//create a new session here
data: decode
});
res.end();
}
else {
res.status(401);
res.json({
login: false,
data: decode
});
res.end();
}
// Return response with decode data
});
4. Tout mettre ensemble
Maintenant que vous avez tous les éléments, vous pouvez connecter votre interface aux deux méthodes d’API backend pour authentifier l’utilisateur lorsqu’il se connecte.
- Lorsque l’utilisateur soumet le formulaire avec son e-mail pour se connecter, l’appel du point de terminaison d’envoi du lien enverra un e-mail avec le lien magique vers sa boîte de réception – invite l’utilisateur à vérifier sa boîte de réception.
- Une fois qu’ils ont ouvert l’e-mail, cliquer sur le lien devrait ouvrir une page de vérification dédiée ou leur page de destination telle qu’un tableau de bord.
- Avec le jeton extrait de la requête, l’interface doit appeler le point de terminaison de vérification du jeton.
- Dès réception d’une réponse indiquant une vérification réussie, une session est créée et l’utilisateur se voit accorder l’accès à votre application. Sinon, un flux doit être établi pour rediriger l’utilisateur vers la page de connexion pour réessayer.
Cas Edge
Quelques détails à garder à l’esprit :
- Auto-consommation par les clients de messagerie. Il s’agit d’un problème particulièrement courant lors de la connexion sur mobile, où les clients de messagerie utilisent souvent le cookie de session au lieu du navigateur d’origine. La solution la plus simple consiste à inviter l’utilisateur à cliquer sur un bouton sur le client avant de consommer le lien magique au cas où le navigateur dans lequel il a ouvert le lien n’est pas le même que celui dans lequel il a lancé son flux d’origine.
- Réconcilier deux navigateurs différents. Dans le cas de deux navigateurs différents, beaucoup choisissent de se connecter en utilisant la session du navigateur d’origine, mais cela présente une vulnérabilité de sécurité dans laquelle un attaquant peut envoyer un lien à l’utilisateur. Lorsque l’utilisateur clique sur le lien, l’attaquant se connecte également.
Pour cette raison, il est préférable de se connecter à la nouvelle session du navigateur, mais cela pourrait conduire à une mauvaise UX où l’utilisateur est connecté à un appareil différent de celui qu’il a prévu. Un compromis consiste à informer l’utilisateur aux deux endroits de l’appareil qui a initié le flux et à lui permettre d’approuver la connexion – lorsque l’utilisateur revient naturellement à sa session de navigateur prévue, cela offre la meilleure UX parmi les trois options.
Considérations de sécurité
Selon la façon dont vous décidez d’implémenter la connexion, il y a quelques considérations à garder à l’esprit.
- Dans cet exemple, nous avons choisi JWT pour notre jeton. Alternativement, vous pouvez utiliser un jeton opaque qui est stocké dans votre base de données – bien que la mise en œuvre soit plus complexe, elle est également plus sécurisée car il n’y a pas de clé secrète unique.
- C’est une bonne idée de limiter le nombre de tentatives (avec une fonction de verrouillage) pour empêcher les attaques par force brute.
- Utilisez le cryptage SSL/TLS lors de l’envoi sécurisé de l’e-mail de lien pour vous assurer que la charge utile de l’e-mail, y compris le lien magique, ne peut pas être altérée.
- Choisissez un délai d’attente aussi court que possible pour votre jeton afin de limiter la fenêtre d’opportunité dont dispose un attaquant pour utiliser le jeton. Si le jeton n’expire jamais, le jeton sera disponible pour un attaquant à utiliser à tout moment.
Conclusion
Bien que nous vous encourageons à vous y référer en tant que guide général pour la mise en œuvre de l’authentification sans mot de passe, la sécurité est un élément essentiel à la mise en œuvre de toute forme d’authentification.
Pour plus de détails et pour vous lancer dans l’authentification sans mot de passe en quelques minutes, nous vous invitons à tester la recette des SuperTokens sans mot de passe
Bonne construction !