AngularAtlaséd. 22.2

Chap. 17Sécurité et internationalisation74 / 75

OAuth 2.1 et OpenID Connect avec PKCE

Le flux authorization code avec PKCE, pas à pas : verifier et challenge, state et nonce, l’ID token, et pourquoi un BFF est plus sûr.

architecture ~0 min de lecture

Se connecter avec Google, Microsoft, Keycloak ou Auth0 signifie que votre application ne voit jamais le mot de passe. Elle envoie l’utilisateur chez le fournisseur d’identité, qui le renvoie avec un code à usage unique ; l’application échange ce code contre des tokens. OAuth 2.1 — la version nettoyée d’OAuth 2.0 — garde un seul flow pour les applications dans le navigateur : l’authorization code avec PKCE.

PKCE (Proof Key for Code Exchange, prononcé « pixy ») résout un problème précis. Une application single-page est un client public : elle n’a aucun secret à cacher, car tout ce qu’elle livre peut être lu. Il lui faut donc un autre moyen de prouver que celui qui échange le code est celui qui l’a demandé. Les démos de cette page utilisent une vraie cryptographie (Web Crypto), pas une imitation.

Si vous utilisez encore l’implicit flow
L’implicit flow (response_type=token, tokens dans le fragment de l’URL) a disparu d’OAuth 2.1 : les tokens dans les URL finissent dans l’historique du navigateur, dans les logs et dans les en-têtes Referer. Passer au code flow avec PKCE est en général un changement de configuration dans votre bibliothèque et chez le fournisseur.

Le flow, en sept étapes

L’application prépare quelques valeurs aléatoires, envoie le navigateur chez le fournisseur, reçoit un code en retour et l’échange — avec une preuve — contre des tokens. Seule la dernière étape concerne votre API. Parcourez-le dans la démo ; cochez « attaquant » pour voir ce qu’arrête la vérification de state.

app (browser)                         fournisseur d’identité                 API
  │ 1. verifier, challenge = S256(verifier), state, nonce                     │
  │ 2. GET /authorize?…&code_challenge&state&nonce ─▶│                         │
  │                                  3. connexion, MFA, consentement           │
  │◀─ 4. 302 /callback?code=…&state=…  (vérifier state !)                      │
  │ 5. POST /token  code + code_verifier ────────────▶│ S256(verifier) == challenge?
  │◀─ 6. access_token, id_token, refresh_token ───────│                         │
  │ 7. GET /orders  Authorization: Bearer <access_token> ─────────────────────▶│
LiveAuthorization code avec PKCE, étape par étape
1verifier, challenge, state, nonce
2GET /authorize
3connexion, MFA, consentement
4302 /callback?code&state
5POST /token + verifier
6access, ID, refresh token
7GET /api … Bearer
Appuyez sur « Suivant » à travers les sept étapes. Cochez ensuite « Callback falsifié » et recommencez : le flow s’arrête à l’étape 4.

PKCE : prouver que c’est vous qui avez demandé

Avant la redirection, l’application génère un code_verifier aléatoire et n’envoie à /authorize que son hash, le code_challenge. Le fournisseur le garde à côté du code. Quand l’application échange le code sur /token, elle envoie le verifier lui-même ; le fournisseur le hache et compare. Celui qui intercepte le code — une application malveillante enregistrée sur la même redirection, un log, une extension de navigateur — n’a pas le verifier, et le code ne lui sert à rien.

/** base64url sans padding (RFC 4648 §5), comme l’exige PKCE */
function base64url(bytes: Uint8Array): string {
  let binary = '';
  for (const b of bytes) binary += String.fromCharCode(b);
  return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

/** 32 octets aléatoires → 43 caractères (le minimum autorisé est 43, le maximum 128) */
export function createVerifier(): string {
  return base64url(crypto.getRandomValues(new Uint8Array(32)));
}

/** code_challenge = BASE64URL(SHA-256(code_verifier)), méthode S256 */
export async function challengeFor(verifier: string): Promise<string> {
  const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier));
  return base64url(new Uint8Array(digest));
}

// RFC 7636, annexe B :
// challengeFor('dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk')
//   → 'E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM'
LiveVerifier, challenge et la vérification sur /token
  1. 1L’application génère un verifier

    0 caractères · entre 43 et 128 sont autorisés

    code_challenge…
  2. 2Seul le challenge part vers /authorize

    Le fournisseur n’a encore rien reçu.

  3. 3Échanger le code sur /token
Générez un verifier, envoyez le challenge, puis échangez le code des deux façons. Chargez l’exemple de la RFC 7636 pour vérifier l’implémentation par rapport au standard.

Utilisez S256, jamais plain (avec plain, le challenge est le verifier, donc qui voit la redirection a tout). Le verifier reste dans sessionStorage — cet onglet seulement — et est supprimé dès que le code est échangé.

state, nonce et redirect_uri

  • state — une valeur aléatoire enregistrée avant la redirection et vérifiée dans /callback. Sans elle, un attaquant peut envoyer la victime sur votre callback avec le code de l’attaquant, et la victime se retrouve connectée au compte de l’attaquant (login CSRF). PKCE bloque aussi cela, mais les fournisseurs exigent quand même state, et vous en avez de toute façon besoin pour transporter votre propre contexte.
  • nonce — une valeur aléatoire envoyée à /authorize qui doit revenir dans l’ID token. Elle prouve que l’ID token a été émis pour cette connexion et non copié d’une précédente.
  • redirect_uri — enregistrée chez le fournisseur exactement, sans wildcards. Et la destination après la connexion (returnTo) est enregistrée par votre application avant la redirection ; ne la prenez jamais d’un ?returnUrl= dans la barre d’adresse, sinon votre page de connexion devient un open redirect.
import { challengeFor, createVerifier } from './pkce';

const AUTHORIZE = 'https://id.example.com/authorize';

export async function login(returnTo = '/'): Promise<void> {
  const verifier = createVerifier();
  const state = createVerifier(); // aléatoire, à usage unique
  const nonce = createVerifier();

  // sessionStorage : cet onglet seulement, effacé quand l’onglet se ferme
  sessionStorage.setItem('oauth', JSON.stringify({ verifier, state, nonce, returnTo }));

  const url = new URL(AUTHORIZE);
  url.search = new URLSearchParams({
    response_type: 'code',
    client_id: 'atlas-spa',
    redirect_uri: `${location.origin}/callback`, // enregistrée EXACTEMENT, sans wildcards
    scope: 'openid profile email',
    code_challenge: await challengeFor(verifier),
    code_challenge_method: 'S256',
    state,
    nonce,
  }).toString();
  location.assign(url);
}

Trois tokens, trois rôles

La réponse de /token contient jusqu’à trois tokens, et les confondre est l’erreur la plus fréquente. L’ID token dit à l’application qui s’est connecté. L’access token dit à l’API ce que l’appelant peut faire. Le refresh token obtient de nouveaux access tokens sans nouvelle connexion. Décoder un JWT dans le navigateur est utile pour l’affichage, mais ce n’est pas une validation : la signature se vérifie avec les clés publiques du fournisseur (JWKS), et c’est le travail d’une bibliothèque.

ID tokenAccess tokenRefresh token
Lu parvotre applicationvotre APIle fournisseur
Envoyé ànulle part — il reste dans l’applicationseulement l’origine de votre APIseulement le /token du fournisseur
Durée de viequelques minutes5 à 60 minutesdes heures à des jours, renouvelé à chaque usage

Plus sûr : un BFF garde les tokens

Après l’étape 6, les tokens vivent dans le navigateur — exactement là où une XSS peut les atteindre. Le document de l’IETF sur OAuth pour les applications navigateur décrit une option plus solide : un Backend for Frontend. Un petit serveur sur votre propre site fait l’échange du code, garde les tokens côté serveur et ne donne au navigateur qu’un cookie de session HttpOnly, que JavaScript ne peut pas lire.

browser (SPA)                BFF (votre serveur, même site)             fournisseur d’identité
  │ GET /auth/login ──────────▶│ PKCE + state + nonce, côté serveur ────────▶│ /authorize
  │◀─ 302 vers le fournisseur ─│                                             │
  │                    …connexion chez le fournisseur, retour au BFF…        │
  │                            │ code + verifier ──────────────────────────▶│ /token
  │                            │◀── access, id, refresh (restent ICI) ───────│
  │◀─ Set-Cookie: session=…; HttpOnly; Secure; SameSite=Strict               │
  │ GET /api/orders (cookie) ─▶│ ajoute Authorization: Bearer … ──▶ API      │

La SPA appelle /api sur sa propre origine ; le BFF ajoute l’access token et gère le refresh. Une XSS peut encore faire des requêtes tant que la page est ouverte, mais elle ne peut pas voler de tokens pour s’en servir ailleurs. Le prix : un composant de plus à faire tourner, et une protection CSRF pour le cookie (SameSite, un en-tête anti-CSRF). Pour les tokens gardés dans le navigateur, l’intercepteur avec file d’attente et refresh est sur la page tokens et refresh.

Dans Angular : une bibliothèque, un guard et un intercepteur

N’implémentez pas le protocole vous-même. Des bibliothèques certifiées comme angular-auth-oidc-client ou angular-oauth2-oidc gèrent la découverte du fournisseur, PKCE, la validation de l’ID token signature comprise, le refresh et la déconnexion. Le code de cette page montre ce qu’elles font, pour que vous puissiez les configurer et les déboguer en connaissance de cause. Votre part :

  • La configuration : authority, client id, redirect_uri, scopes et le code flow avec PKCE — en général par défaut.
  • Un guard sur les routes privées, qui lance la connexion et retient où revenir. Voir guards & resolvers.
  • Un intercepteur qui n’ajoute l’access token que pour l’origine de votre API. Un token envoyé à toutes les URL finit chez des tiers ; voir la sécurité pour le reste du tableau.

Quand OUI, quand NON

OAuth / OIDC
  • Une connexion via un fournisseur d’identité externe : SSO d’entreprise, Google, Microsoft, Apple.
  • Plusieurs applications qui partagent la même connexion et les mêmes utilisateurs.
  • MFA, passkeys et récupération de compte, que vous préférez laisser à des spécialistes.
Quelque chose de plus simple
  • Une seule application avec ses propres utilisateurs et son backend : un cookie de session classique peut suffire. Les tokens et le refresh ont leur propre page.
  • Les appels de serveur à serveur : c’est le flow client credentials, sur le serveur, jamais dans le navigateur.
  • Écrire le protocole vous-même en production : utilisez une bibliothèque certifiée.

Pièges fréquents

  • L’implicit flow, ou des tokens dans l’URL. Ils finissent dans l’historique, les logs et l’en-tête Referer.
  • Ne pas vérifier state. Le callback accepte un code que votre application n’a jamais demandé.
  • L’ID token envoyé à l’API. Il est pour l’application ; l’API prend des access tokens, avec la bonne audience.
  • Décoder au lieu de valider. Sans vérification de la signature, n’importe qui peut écrire un JWT avec n’importe quels claims.
  • Le verifier dans localStorage, gardé après usage. Sa place est dans sessionStorage, et il meurt avec l’échange.
  • Un ?returnUrl= pris dans la barre d’adresse. Votre page de connexion devient un open redirect utilisé pour le phishing.

Aide-mémoire

SPA (OAuth 2.1)           authorization code + PKCE, rien d’autre (pas d’implicit flow)
code_verifier             43 à 128 caractères aléatoires, dans sessionStorage, supprimé après usage
code_challenge            BASE64URL(SHA-256(verifier)), méthode S256 (jamais "plain")
state                     aléatoire, vérifié sur /callback : bloque le login CSRF
nonce                     aléatoire, doit figurer dans l’ID token : bloque les tokens rejoués
redirect_uri              enregistrée exactement, sans wildcards ; returnTo enregistré AVANT la redirection
ID token                  qui s’est connecté (pour l’app) ; valider iss, aud, exp, nonce, signature
access token              ce que vous pouvez appeler (pour l’API) ; seulement vers l’origine de votre API
refresh token             renouvelé à chaque usage, ou pas du tout dans le navigateur
le plus sûr               un BFF : tokens sur le serveur, un cookie HttpOnly dans le navigateur
déconnexion               session locale + end_session_endpoint du fournisseur
ne pas l’écrire soi-même  bibliothèques certifiées : angular-auth-oidc-client, angular-oauth2-oidc

Chap. 17 · 0 sur 4 terminées

Leçon terminée ?

Marquez-la : elle apparaîtra sur votre carte, dans le sommaire et sur la page d’accueil.

Se marque toute seule une fois la leçon lue en entier.

  1. Sécurité : XSS, sanitisation et CSP
  2. Authentification : tokens et refresh
  3. OAuth 2.1 et OpenID Connect avec PKCE
  4. Internationalisation (i18n)
Voir toute votre carte

Les 75 pages · tapez pour filtrer

  • 01Nouveautés d’Angular 21 & 22Tous les changements importants de la v21 et de la v22, en bref, avec un lien vers la page qui explique chacun.Départ
  • 01Votre première application, pas à pasUne liste de lecture construite d’un composant vide jusqu’à une application terminée — signals, @for, inputs et outputs, un service et un formulaire, pas à pas.Départ
  • 01Décisions rapides« Où mettre ça ? », « Signal ou Observable ? », « Shared ou feature ? » — des réponses courtes aux questions de tous les jours.Départ
  • 01Questions d’entretien Angular60 vraies questions d’entretien pour profils junior, confirmé et senior, avec la réponse à donner, la relance et les signaux d’alerte. Plus un entretien blanc.Départ
  • 02Standalone et bootstrapComment une application démarre sans NgModule : bootstrapApplication, app.config.ts, imports dans le composant.Fondamentaux modernes
  • 02Data binding et événementsInterpolation, bindings de propriétés et d’attributs, événements avec $event et filtres de touches, et comment [( )] est construit — ce qui entre dans le DOM et ce qui en revient.Fondamentaux modernes
  • 02Control Flow : @if, @for, @switchLa syntaxe de blocs qui remplace *ngIf/*ngFor/ngSwitch, avec track, @empty et vérifications d’exhaustivité.Fondamentaux modernes
  • 02@let et les nouvelles expressions de templateVariables locales avec @let, fonctions fléchées, spread, regex, instanceof, commentaires dans les balises.Fondamentaux modernes
  • 02@defer — Lazy Loading dans les templatesChargez les composants lourds uniquement quand c’est nécessaire : triggers, prefetch, placeholder, loading, error.Fondamentaux modernes
  • 02Bindings de classe et de stylePourquoi [class.x] et [style.x] ont remplacé ngClass et ngStyle (avec migration automatique depuis la v21).Fondamentaux modernes
  • 02Styles des composants et encapsulation:host, les trois modes d’encapsulation, les thèmes avec des variables CSS, et pourquoi ::ng-deep est un dernier recours.Fondamentaux modernes
  • 02Pipes : quand et commentPipes pures vs impures, pipes personnalisées, et comment choisir entre une pipe, computed() et une méthode.Fondamentaux modernes
  • 03signal() et computed()Les primitives réactives : état modifiable, état dérivé, égalité, untracked et règles d’immutabilité.Signals et réactivité
  • 03effect() — quand OUI, quand NONEffets de bord synchronisés avec les Signals : localStorage, logs, API impératives. Et leurs pièges.Signals et réactivité
  • 03linkedSignal() — état dérivé modifiableUn signal qui se réinitialise quand sa source change, mais que vous pouvez aussi modifier à la main.Signals et réactivité
  • 03resource, rxResource, httpResourceDes données asynchrones sous forme de Signals : status, value, error, reload, annulation automatique. Stable depuis la v22.Signals et réactivité
  • 03debounced() — signals différésLa version « debounce » d’un signal, sans RxJS. Parfait pour la recherche.Signals et réactivité
  • 03Listes : rechercher, filtrer, trier, paginerUne chaîne de signals computed qui ne recalcule que ce qui a changé, avec les filtres dans l’URL pour qu’un lien rouvre la même vue.Signals et réactivité
  • 03Les Observables depuis zéroCe qu’est un Observable, subscribe et unsubscribe, les opérateurs que vous utilisez chaque semaine, froid ou chaud — et quand un signal suffit.Signals et réactivité
  • 03Signals ↔ RxJStoSignal, toObservable, takeUntilDestroyed, outputFromObservable — et quand RxJS reste le bon choix.Signals et réactivité
  • 04input() et output()Les inputs comme Signals (required, transform, alias) et les outputs typés. Les données descendent, les événements remontent.Composants : communication
  • 04model() — binding bidirectionnelLe « banana-in-a-box » [( )] avec une seule API. Quand l’utiliser, et quand input + output est préférable.Composants : communication
  • 04viewChild et contentChildLes queries comme Signals : viewChild, viewChildren, contentChild, contentChildren, l’option read.Composants : communication
  • 04Lifecycle et DestroyRefQuels hooks comptent encore à l’ère des Signals, afterNextRender, DestroyRef et ngOnChanges typé.Composants : communication
  • 04Projection de contenung-content avec select, plusieurs slots, contenu par défaut et le piège de la projection conditionnelle.Composants : communication
  • 04ng-template et ngTemplateOutletLes templates comme valeurs : les render props en Angular, contexte typé et personnalisation des composants.Composants : communication
  • 05Smart vs DumbContainer vs présentation : qui détient l’état, qui se contente d’afficher, et comment bien les séparer.Conception des composants
  • 05Composants génériques <T>Un DataTable<T> ou un Select<T> correctement typé, avec des templates pour les cellules.Conception des composants
  • 05Composants dynamiquesNgComponentOutlet, createComponent avec inputBinding/outputBinding, et un tableau de bord construit à partir d’une configuration.Conception des composants
  • 05Directives et composition d’hôteLes directives d’attribut, les métadonnées host: {} et la Directive Composition API (hostDirectives).Conception des composants
  • 05Contrôles de formulaire personnalisésFormValueControl (Signal Forms) vs ControlValueAccessor : une notation par étoiles, dans les deux variantes.Conception des composants
  • 05Change DetectionOnPush est la valeur par défaut depuis la v22, Zone.js a disparu depuis la v21. Ce qui déclenche le rendu et comment éviter les mauvaises surprises.Conception des composants
  • 06inject() et @Service()Le nouveau décorateur @Service() de la v22, inject() vs le constructeur, et le contexte d’injection.Dependency Injection
  • 06Providers et hiérarchie des injecteursRoot vs route vs composant, useClass/useValue/useFactory/useExisting, et les modificateurs optional/self/skipSelf.Dependency Injection
  • 06InjectionToken et provideX()Configuration typée, fonctions provideFeature(), makeEnvironmentProviders et initializers.Dependency Injection
  • 06injectAsync() — services en Lazy LoadingChargez un service lourd uniquement quand vous en avez besoin, avec prefetch à l’idle.Dependency Injection
  • 07Structure des dossierscore / shared / features, ce que contient chacun, et à quoi ressemble l’intérieur d’une feature.Architecture d’application
  • 07Shared vs featureQuand déplacer un composant dans shared et (surtout) quand NE PAS le faire. Une checklist concrète.Architecture d’application
  • 07Interfaces et modèlesInterface en ligne ou fichier séparé ? DTO vs modèle de domaine, type vs interface, où les ranger.Architecture d’application
  • 07State Management avec les SignalsStores simples à base de Signals, facades, état local vs global, et quand NgRx devient nécessaire.Architecture d’application
  • 07Guide de style et nommageLes conventions officielles actuelles : noms de fichiers sans suffixes, protected, readonly, ordre des membres.Architecture d’application
  • 07Barrels, alias et frontièresindex.ts, alias de chemins, API publique d’une feature et règles de dépendances vérifiables automatiquement.Architecture d’application
  • 07Erreurs : @boundary et ErrorHandlerLe nouveau bloc @boundary de la v22.2, l’ErrorHandler global, les erreurs HTTP et les erreurs de resource.Architecture d’application
  • 08Routing moderne et Lazy LoadingloadComponent, routes enfants, paramètres comme inputs et héritage des paramètres (le nouveau comportement par défaut de la v22).Routing
  • 08Guards et resolverscanActivate, canMatch, canDeactivate et resolve sous forme de fonctions, avec redirections via UrlTree / RedirectCommand.Routing
  • 09Signal Forms — les basesDes formulaires bâtis sur les Signals : form(), [formField], validation par schéma. Stable depuis la v22.Formulaires
  • 09Signal Forms — avancéValidation personnalisée et inter-champs, async/HTTP avec debounce, listes dynamiques, désactivé/masqué, schémas réutilisables.Formulaires
  • 09Reactive Forms typésFormGroup typé, nonNullable, FormArray — et leur cohabitation avec les Signal Forms.Formulaires
  • 10HttpClient, interceptors et couche d’APIHttpClient sans configuration (v21), Fetch par défaut (v22), interceptors fonctionnels et une couche d’API avec mapping des DTO.HTTP et données
  • 11Performance — une checklistCe qui compte vraiment : OnPush + Signals, track, @defer, routes en Lazy Loading, images, bundles et Hydration.Qualité et performance
  • 11Tests avec VitestVitest est le runner par défaut depuis la v21. TestBed, composants avec Signals, services, HTTP et harnesses.Qualité et performance
  • 11DevTools : regarder dans votre applicationChrome DevTools et Angular DevTools pas à pas : ce que montre chaque panneau, avec des exercices qui fonctionnent sur ce site.Qualité et performance
  • 11Angular AriaDes composants headless et accessibles que vous stylez comme vous voulez : tabs, accordion, menu, listbox...Qualité et performance
  • 12SSR, Prerendering et modes de renduQuand rendre sur le serveur, quand au build et quand uniquement dans le navigateur : RenderMode par route, app.routes.server.ts et les coûts réels.SSR et Hydration
  • 12Hydration : event replay et incrémentaleComment le navigateur reprend le HTML du serveur sans le re-rendre : Hydration complète, event replay, @defer (hydrate on …) et erreurs de mismatch.SSR et Hydration
  • 12Code compatible serveurwindow n’existe pas sur le serveur : PLATFORM_ID, afterNextRender, DOCUMENT, TransferState, le cache HTTP et PendingTasks.SSR et Hydration
  • 13Micro frontendsQuand découper une application en plusieurs déploiements vaut le coup, et quand c’est juste de la complexité : Native Federation, Module Federation, iframes, Web Components.Architecture à grande échelle
  • 13Web Components avec Angular ElementscreateCustomElement : un composant Angular utilisé comme balise HTML n’importe où, plus la communication entre applications via des événements et BroadcastChannel.Architecture à grande échelle
  • 13Monorepo, bibliothèques et frontièresUn workspace avec plusieurs applications et bibliothèques : ng generate library, Nx, points d’entrée secondaires, publication et règles de dépendances.Architecture à grande échelle
  • 13Architecture hexagonale (ports et adapters)Un domaine sans Angular, des ports sous forme de classes abstraites et des adapters interchangeables : HTTP, localStorage ou en mémoire, sans toucher à l’UI.Architecture à grande échelle
  • 14Les Signals sous le capotLe graphe réactif : producteurs et consommateurs, push-pull, pourquoi computed est lazy et sans glitch, le problème du diamant et quand les effects s’exécutent.Réactivité avancée
  • 14RxJS avancé : opérateurs d’ordre supérieurswitchMap, mergeMap, concatMap et exhaustMap sur un diagramme interactif, plus retry avec backoff, shareReplay et comment éviter les fuites.Réactivité avancée
  • 14NgRx SignalStoreState Management à grande échelle sur les Signals : withState, withComputed, withMethods, rxMethod, entités et hooks — et quand un store simple suffit.Réactivité avancée
  • 14Machines à états avec les signalsFini les états impossibles : une machine typée sur des signals, avec transitions, gardes et un diagramme d’états en direct.Réactivité avancée
  • 15WebSockets : un temps réel qui résiste au réseauUn socket typé sous forme de signals : reconnexion avec backoff et jitter, heartbeat, file d’attente hors ligne et sécurité SSR.Temps réel et hors ligne
  • 15Mises à jour optimistes et rollbackUne UI instantanée qui reste honnête : snapshot et rollback, réponses dans le désordre, clés d’idempotence.Temps réel et hors ligne
  • 15Offline-first : Service Worker et cacheLe Service Worker d’Angular : stratégies de cache, annonce des nouvelles versions et file d’attente pour les modifications faites hors ligne.Temps réel et hors ligne
  • 16Web WorkersDes calculs lourds sans bloquer l’UI : un vrai worker dans la page, l’échange de messages et quand ça n’en vaut pas la peine.UI avancée et performance
  • 16Listes géantes : virtual scroll100 000 lignes sans latence : le virtual scroll du CDK, itemSize, trackBy et les alternatives (pagination, scroll infini).UI avancée et performance
  • 16Animations modernes et View Transitionsanimate.enter et animate.leave à la place de @angular/animations (déprécié), transitions CSS et View Transitions à la navigation.UI avancée et performance
  • 16Fuites mémoire : les trouver et les corrigerAbonnements, timers et listeners qui survivent à leur composant — comment les repérer dans les DevTools et les fermer.UI avancée et performance
  • 17Sécurité : XSS, sanitisation et CSPCe qu’Angular fait automatiquement contre le XSS, quand bypassSecurityTrust devient dangereux, plus la CSP avec nonce, Trusted Types et XSRF.Sécurité et internationalisation
  • 17Authentification : tokens et refreshUn interceptor qui ajoute le token, le renouvelle une seule fois sur une 401 et rejoue les requêtes en attente — plus où conserver le token.Sécurité et internationalisation
  • 17OAuth 2.1 et OpenID Connect avec PKCELe flux authorization code avec PKCE, pas à pas : verifier et challenge, state et nonce, l’ID token, et pourquoi un BFF est plus sûr.Sécurité et internationalisation
  • 17Internationalisation (i18n)$localize, l’attribut i18n, ICU plural/select, un build par langue vs des traductions à l’exécution, et le formatage selon la locale.Sécurité et internationalisation