Conseils

Comprendre CORS sur une API REST WinDev hébergée sous IIS : retour d’expérience

Comprendre CORS sur une API REST WinDev hébergée sous IIS : retour d’expérience

Lorsque l’on développe une API REST moderne, il est quasiment impossible d’éviter la problématique CORS.

C’est encore plus vrai lorsqu’un frontend JavaScript comme React, Angular, Vue, ou une application mobile hybride consomme une API hébergée sur un autre domaine.

Nous avons récemment mis en place la gestion CORS sur une API REST WinDev hébergée sous IIS, et nous avons rencontré plusieurs difficultés techniques assez spécifiques à cette architecture.

Voici un retour d’expérience concret.

Qu’est-ce que CORS ?

CORS signifie : Cross-Origin Resource Sharing.

Il s’agit d’un mécanisme de sécurité implémenté par les navigateurs.

Par défaut, un navigateur interdit à une application web de faire des appels AJAX ou fetch vers un autre domaine que celui ayant servi la page. C’est la règle de sécurité appelée Same-Origin Policy.

Exemple :

  • Frontend : https://app.monsite.fr
  • API : https://api.monsite.fr

Même si les deux appartiennent à la même société, le navigateur considère qu’il s’agit de deux origines différentes.

Sans configuration CORS adaptée :

  • les appels sont bloqués
  • le frontend reçoit des erreurs CORS
  • les réponses HTTP existent parfois réellement, mais le navigateur refuse de les transmettre au JavaScript

Comment fonctionne CORS ?

Lorsqu’un navigateur appelle une API distante, il envoie automatiquement un header :

Origin: https://app.monsite.fr

Le serveur doit alors répondre avec :

Access-Control-Allow-Origin: https://app.monsite.fr

Si ce header correspond à l’origine appelante :

  • le navigateur autorise la requête
  • l’application JavaScript reçoit la réponse

Sinon :

  • le navigateur bloque l’accès

Le piège classique : le wildcard *

Dans de nombreux exemples sur Internet, on voit :

Access-Control-Allow-Origin: *

Cela autorise toutes les origines et l’utilisation de CORS perd de son intérêt.

Mais dans notre cas, ce n’était pas acceptable :

  • nous voulions limiter les domaines autorisés
  • certaines requêtes nécessitaient authentification et credentials
  • les navigateurs refusent certains usages CORS lorsque * est utilisé

Autre difficulté : il est impossible d’envoyer plusieurs origines dans ce header.

Par exemple, ceci est invalide :

Access-Control-Allow-Origin: https://site1.fr, https://site2.fr

Le standard CORS impose :

  • soit *
  • soit une seule origine exacte

Notre première idée : utiliser des Custom Headers IIS

La solution semblait simple :

  • ajouter les headers CORS directement dans IIS
  • configurer des Custom Headers
  • laisser IIS gérer le sujet

Exemple :

<add name="Access-Control-Allow-Origin" value="*" />

Ou même :

<add name="Access-Control-Allow-Origin" value="https://site1.fr" />

Problèmes rencontrés

Mais nous avons rapidement rencontré une limitation importante.

Le vrai problème : IIS intercepte les requêtes CORS avant WinDev

Dans IIS, dès que des headers CORS sont configurés :

  • le moteur IIS prend la main
  • les requêtes CORS sont traitées avant l’application WinDev
  • certaines requêtes n’arrivent jamais jusqu’à l’API

Même avec des règles de URL Rewriting :

  • impossible de modifier dynamiquement le header
  • impossible de renvoyer l’origine appelante
  • impossible de filtrer proprement les domaines autorisés côté application

Autrement dit :

  • IIS “court-circuite” l’API
  • le traitement CORS devient figé et statique

C’était incompatible avec notre besoin :

  • autoriser plusieurs domaines
  • répondre avec une seule origine exacte
  • le faire dynamiquement
  • uniquement si l’origine fait partie de la liste blanche

La solution retenue

La solution a finalement été de :

  • supprimer complètement les Custom Headers CORS dans IIS
  • laisser toutes les requêtes atteindre l’API WinDev
  • gérer CORS entièrement par programmation

Concrètement :

  • l’API lit le header Origin envoyé par le navigateur
  • vérifie si cette origine est autorisée
  • puis renvoie dynamiquement le header adapté
Access-Control-Allow-Origin: https://origine-autorisee.fr

Cela permet :

  • un contrôle précis
  • une whitelist dynamique
  • une compatibilité complète avec les navigateurs modernes

Le point essentiel : gérer les requêtes OPTIONS

Autre difficulté importante : les requêtes preflight.

Avant certaines requêtes HTTP comme POST, PUT, DELETE, ou avec des headers personnalisés comme Authorization, le navigateur envoie automatiquement :

OPTIONS /api/...

Cette requête sert à demander :

  • quelles méthodes sont autorisées
  • quels headers sont acceptés
  • si l’origine est valide

Si l’API ne répond pas correctement :

  • le navigateur bloque immédiatement l’appel réel

Nous avons donc dû ajouter explicitement :

  • la gestion de la méthode OPTIONS
  • sur chaque ressource REST concernée
  • la génération dynamique des headers CORS depuis WinDev

Ce qu’il faut retenir

À éviter

  • les Custom Headers CORS statiques dans IIS
  • les valeurs multiples dans Access-Control-Allow-Origin
  • le wildcard * dans les contextes sécurisés

À privilégier

  • une gestion CORS directement dans l’API
  • une whitelist des domaines autorisés
  • une réponse dynamique basée sur le header Origin
  • la gestion explicite des requêtes OPTIONS

Conclusion

Mettre en place CORS semble simple au premier abord, mais certains hébergements, notamment IIS avec une API WinDev, introduisent des comportements spécifiques qu’il faut connaître.

Le principal enseignement de notre retour d’expérience est le suivant :

Pour garder un contrôle fin et compatible avec les exigences de sécurité modernes, la gestion CORS doit être réalisée dynamiquement dans l’application, et non via des headers statiques IIS.

Cette approche demande un peu plus de développement, mais elle offre :

  • davantage de souplesse
  • une meilleure sécurité
  • un comportement parfaitement conforme aux attentes des navigateurs modernes

#CORS #WinDev #IIS #APIREST #DéveloppementWeb #SécuritéWeb #DevBooster