
Devlog #1 â Roadmap & authentification sĂ©curisĂ©e
- William Leemans
- Pathfinder , Devlog
- 02 Apr, 2024
đ Focus fonctionnel : Les premiĂšres briques
Voici les premiĂšres briques / milestones du projet :
1. Clean Init
Reprise de zĂ©ro : recrĂ©ation dâun monorepo sain avec une structure claire (apps/api, apps/web, packages/âŠ), et mise en place des bases pour la qualitĂ© :
- Frameworks Ă jour
- Des tests unitaires avec des examples
- Une suite de test e2e avec Playwrigt
- Une base solide de documentation
- Une authentication propre et sécurisée en place (plus sur ce sujet dans le focus technique du jour !)
2. Profil
Chaque JetPeople aura un espace personnel, oĂč il pourra bientĂŽt consulter son level, ses compĂ©tences, ses objectifs, son historique⊠Câest la base de tout lâaccompagnement personnalisĂ© Ă venir.
3. Journal de bord
Câest le module qui regroupera tous les entretiens rĂ©alisĂ©s : annuels, professionnels, sexennaux et suivis de mission. Un espace clair, centralisĂ©, accessible Ă tout moment.
Avec cette premiĂšre âvraieâ feature, je compte dĂ©jĂ mettre le suivi de chacun au centre du projet et permettre Ă tout le monde de se familiariser avec la plateforme.
4. Trajectoires de carriĂšre
CĆur du projet : la mise en place des Jobs et de leurs spĂ©cialitĂ©s sous forme de Job Ladder.
Exemples :
- Software Engineer â Frontend, Backend, Fullstack, Mobile
- QA Engineer â Manual, Automation
- Design â UI, UX, Research
Chaque niveau est découpé avec des objectifs clairs et actionnables, permettant de comprendre comment progresser et se situer à tout moment.
5. Galaxie des compétences
Un outil interactif pour cartographier son parcours au sein de la galaxie des compĂ©tences, le but est de pouvoir explorer/dĂ©couvrir des nouveaux sujets Ă apprendre, pouvoir visualiser oĂč lâon en est, mais aussi dâavoir une cartographie complĂšte pour Jetdev. Je pense vraiment que cet outil va nous aider Ă voir plus clair sur comment et vers quoi progresser et crĂ©er beaucoup dâĂ©change du fait que nous allons complĂ©ter cette galaxie ensemble.
đ€ Pour les geeks qui me lisent, je vois ce module comme le manuel de potions du Prince de Sang-MĂȘlĂ© dans Harry Potter, un recueil de connaissances que lâon va pouvoir annoter graçe Ă nos diverses experiences.
6. Kickstart du MVP
DĂ©marrage officiel en production mĂȘme si jâespĂšre que des premiers utilisateurs auront dĂ©jĂ commencĂ© a sâapproprier lâoutil au cours du dĂ©veloppement du MVP.
đ Focus technique : Authentification et choix dâarchitecture
Quand on manipule des donnĂ©es RH, la sĂ©curitĂ© est non nĂ©gociable (non, personne nâaura accĂšs Ă la base de prod đ).
La premiĂšre brique posĂ©e cĂŽtĂ© technique, câest donc lâauthentification via Google OAuth2.
Mini ADR â Google OAuth vs Firebase Auth
Si tu as vu mon talk sur la Hype tu sais que les ADR câest mon kiff, et jâai donc profiter de lâoccasion pour te faire un exemple đ.
Contexte
Pour Pathfinder, on a besoin dâun systĂšme dâauthentication sĂ©curisĂ© pour que les JetPeople puissent se connecter via leur compte Google â une maniĂšre simple et centralisĂ©e de gĂ©rer les accĂšs.
Plusieurs options on été envisagées :
- Firebase Authentication : SDK cotĂ© frontend + VĂ©rification cotĂ© backend via lâAdmin SDK)
- Google Oauth2 - Utilisation du token Google : Auth.js Authorization Code avec PKCE coté NextJS et Verification cÎté NestJS
- Google Oauth2 - Token custom : Authentication gérée complÚtement dans par back-end avec notre propre logique de gestion de session / refresh tokens grùce notamment à @nestjs/jwt et Passport.
Comparatif
Option | Avantages | Inconvénients |
---|---|---|
1. Firebase Authentication | â
IntĂ©gration rapide â Pleins dâexemples chez Jetdev â Dashboard de gestion intĂ©grĂ© | â ïž DĂ©pendances supplĂ©mentaires â Vendor lock-in (Firebase) â On nâa besoin que de la partie Google |
2. Google OAuth2 â Token Google (PKCE) | â
Standard OAuth2 â IntĂ©gration rapide avec Next.js (Auth.js) â Pas de projet firebase Ă maintenir | â ïž Moins de contrĂŽle sur les sessions/tokens â ïž Un token Google circle entre le back et front (pas idĂ©al) |
3. Google OAuth2 â Token custom (backend-controlled) | â
ContrĂŽle total (JWT, refresh tokens, rĂŽles) â Base pour auth centralisĂ©e multi-apps â Pas de projet firebase Ă maintenir | â Plus complexe Ă mettre en Ćuvre â NĂ©cessite une logique de session robuste cĂŽtĂ© backend |
Décision
AprĂšs comparaison, jâai optĂ© pour la solution 2, qui offre un bon compromis entre rapiditĂ© de mise en place et Ă©volutivitĂ©.
Cette solution repose sur :
- Lâutilisation de Auth.js cĂŽtĂ© Next.js pour gĂ©rer le flow OAuth2 avec PKCE.
- La rĂ©cupĂ©ration de lâid_token Google lors du login.
- Lâenvoi de lâid_token dans le header Authorization pour chaque appel frontend â backend.
- Une vérification du token cÎté NestJS, via la bibliothÚque google-auth-library.
Pourquoi avoir fait ce choix ?
- IntĂ©gration super rapide (ndlr: jâai mis une bonne heure de taf).
- Pas besoin de gĂ©rer et intĂ©grer la partie Firebase (mĂȘme sâil ne sâagit pas dâune grosse charge).
- Je suis ok avec le fait que le backend nâĂ©met pas de JWT interne : il fait confiance au token Google directement.
Une solution simple mais extensible avec la possibilitĂ© dâĂ©voluer vers une stratĂ©gie de tokens personnalisĂ©s plus tard si besoin.
Voici le flow complet :
Comment on implémente ça ?
Coté Next.js
- CrĂ©ation dâun OAuth 2.0 Client ID dans la console Google Cloud
- Mise en place de Auth.JS avec le provider Google en suivant le guide
- Ajout de callbacks pour rendre lâid token dispo dans la session JWT
- Ajout dâune callback sur le sign pour synchroniser lâutilisateur dans le backend
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [Google],
callbacks: {
async signIn({ profile }) {
const res = await fetch(
`${process.env.BACKEND_URL}/auth/internal/users/sync`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.INTERNAL_SECRET}`,
},
body: JSON.stringify({
providerId: profile?.sub,
email: profile?.email,
firstName: profile?.given_name,
lastName: profile?.family_name,
}),
},
);
return res.ok;
},
async jwt({ token, account }) {
if (account?.id_token) {
token.idToken = account.id_token;
}
return token;
},
async session({ session, token }) {
session.idToken = token.idToken;
return session;
},
},
});
Coté NestJS
- Ajout dâun AuthModule dans lâAPI
- CrĂ©ation dâun Guard qui utilise google-auth-library pour vĂ©rifier le token
@Injectable()
export class GoogleAuthGuard implements CanActivate {
constructor(private reflector: Reflector) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
context.getHandler(),
context.getClass(),
]);
if (isPublic) {
return true;
}
const request: Request = context.switchToHttp().getRequest();
const authHeader = request.headers["authorization"];
if (!authHeader || authHeader.startsWith("Bearer ")) {
throw new UnauthorizedException(
"Missing or invalid Authorization header",
);
}
const idToken = authHeader.split(" ")[1];
try {
const ticket = await client.verifyIdToken({
idToken,
audience: process.env.GOOGLE_CLIENT_ID,
});
const payload = ticket.getPayload();
if (!payload || !payload.email) {
throw new UnauthorizedException("Invalid token payload");
}
request["user"] = {
email: payload.email,
sub: payload.sub,
name: payload.name,
picture: payload.picture,
};
return true;
} catch (error) {
throw new UnauthorizedException("Invalid Google ID Token");
}
}
}
Ce que ça apporte au projet
- Authentification sécurisée et centralisée
- Gestion des utilisateurs synchronisée entre frontend et backend
- Base prĂȘte pour restreindre des fonctionnalitĂ©s ou visualiser un espace personnel
Pistes dâamĂ©lioration
Changement de la stratégie de session
Auth.js propose deux stratégies de session, la stratégie basée sur les JWT est actuellement mise en place, car elle ne nécessite pas de connexion à la base de donnée, ce qui permet de conserver NestJS comme unique connexion à la base de donnée.
Basculer sur la stratĂ©gie base de donnĂ©e nous permettrait de limiter lâexposition des tokens et dâajouter des features comme pouvoir invalider des sessions (sign out everywhere par exemple).
đŹ Prochain devlog :
Je vous parlerai des trajectoires de carriĂšre chez Jetdev et de la stratĂ©gie de tests âš Rejoins le salon #pathfinder-discovery pour suivre lâaventure et nâhĂ©site pas consulter le projet sur Github đ