Vos données dans le viseur : pourquoi l'authentification en TypeScript n'est pas une plaisanterie
\n\nImaginez : vous avez créé une super application en TypeScript. Elle vole, les types sont stricts, le code est beau. Mais il y a un petit détail — l'authentification. Et c'est là que les choses deviennent intéressantes. Une seule erreur — et les données des utilisateurs fuient comme l'eau entre les doigts. Ça vous parle ?
\n\nEn 2024, l'authentification sécurisée n'est pas simplement « ajouter une connexion ». C'est toute une science. Et TypeScript est ici votre meilleur ami. Il ne vous laissera pas accidentellement transmettre un mauvais type de données, vous indiquera où vous avez oublié de vérifier un token, et vous sauvera d'erreurs stupides lors de la compilation.
\n\nDans cet article, nous allons voir comment construire une authentification sécurisée dans les applications TypeScript à partir de zéro. Pas de blabla — seulement des exemples concrets, des bonnes pratiques et une touche d'humour noir (on ne peut pas s'en passer).
\n\nJWT : un coup de foudre dès le premier token
\n\nJSON Web Token (JWT) est le standard de facto pour l'authentification dans les applications web modernes. Mais, comme le disait l'oncle Ben, « un grand pouvoir implique de grandes responsabilités ». JWT peut être à la fois un bouclier et une bombe à retardement.
\n\nComment NE PAS faire : contre-exemple
\n\nLe péché le plus fréquent des débutants — stocker le token dans localStorage et le transmettre en clair. Oui, ça fonctionne. Mais c'est comme laisser les clés de l'appartement sous le paillasson — pratique, mais n'importe quel passant peut entrer. Une attaque XSS — et tous vos tokens tombent entre les mains d'un attaquant.
\n\nGestion correcte des JWT en TypeScript
\n\nÉcrivons une enveloppe sécurisée pour travailler avec les tokens. TypeScript nous aidera à ne pas confondre les types et à ne pas oublier la validation.
\n\nimport jwt from 'jsonwebtoken';\n\ninterface TokenPayload {\n userId: string;\n role: 'user' | 'admin';\n iat?: number;\n exp?: number;\n}\n\n// Générer un token avec un typage précis\nfunction generateAccessToken(payload: TokenPayload): string {\n return jwt.sign(\n { ...payload },\n process.env.JWT_SECRET as string,\n { expiresIn: '15m' }\n );\n}\n\n// Vérifier et caster immédiatement vers notre interface\nfunction verifyAccessToken(token: string): TokenPayload | null {\n try {\n return jwt.verify(\n token, \n process.env.JWT_SECRET as string\n ) as TokenPayload;\n } catch (error) {\n console.error('Le token n\\'a pas passé la vérification :', error);\n return null;\n }\n}\n\nRemarquez : nous vérifions toujours que JWT_SECRET existe et est une chaîne de caractères. TypeScript nous y oblige — pas de undefined à l'exécution !
Hachage de mots de passe : bcrypt à la rescousse
\n\nStocker les mots de passe en clair est un crime. Même si votre base de données est mieux protégée que Fort Knox, une seule intrusion — et vous faites les gros titres comme la énième « fuite de mots de passe ». Le hachage de mots de passe est votre bouée de sauvetage.
\n\nPourquoi bcrypt plutôt que MD5 ?
\n\nMD5 est mort. SHA-256 n'est pas une option non plus. Les GPU modernes peuvent parcourir des milliards de hachages par seconde. Bcrypt est spécialement conçu pour être lent. Il utilise un sel (données aléatoires) et un facteur de coût ajustable. Plus le coût est élevé — plus le calcul du hachage est long. Et c'est une bonne chose !
\n\nImplémentation en TypeScript
\n\nimport bcrypt from 'bcrypt';\n\nconst SALT_ROUNDS = 12; // Valeur optimale en 2024\n\nasync function hashPassword(password: string): Promise<string> {\n const salt = await bcrypt.genSalt(SALT_ROUNDS);\n return bcrypt.hash(password, salt);\n}\n\nasync function comparePassword(\n password: string, \n hash: string\n): Promise<boolean> {\n return bcrypt.compare(password, hash);\n}\n\n// Fonction typée pour l'inscription\ninterface CreateUserInput {\n email: string;\n password: string;\n name: string;\n}\n\nasync function createUser(input: CreateUserInput): Promise<Omit<User, 'passwordHash'>> {\n const passwordHash = await hashPassword(input.password);\n \n // Sauvegarder dans la BDD (votre code ici)\n