CORS : appeler TOSIAM depuis une autre origine
Sur cette page
Un navigateur ne laisse une page appeler une autre adresse en JavaScript que si cette adresse l’autorise : c’est le CORS (Cross-Origin Resource Sharing). Une application Angular ou React servie sur https://app.example.com qui appelle le point des jetons ou userinfo de https://sso.example.com a donc besoin d’une configuration CORS dans TOSIAM.
Pas besoin de CORS quand :
- la page est servie par TOSIAM lui-même, ou par un CDN placé sur la même adresse (voir CDN sur le même domaine) ;
- seul un serveur appelle TOSIAM, comme une application Spring Boot qui échange le code contre des jetons.
Ce que TOSIAM vérifie#
Le filtre CORS couvre toutes les adresses de TOSIAM. Il ne s’occupe que des requêtes qui portent un en-tête Origin différent de l’adresse de TOSIAM.
- Aucune configuration active (commutateur global désactivé, ou aucune configuration activée) : TOSIAM n’ajoute aucun en-tête CORS, et le navigateur bloque les appels venus d’une autre origine.
- Au moins une configuration active : une requête venue d’une origine qu’aucune configuration n’accepte est refusée (403).
Avant une requête qui n’est pas « simple » (un POST en JSON, un en-tête authorization…), le navigateur envoie une pré-vérification : une requête OPTIONS qui annonce la méthode (Access-Control-Request-Method) et les en-têtes (Access-Control-Request-Headers) de la vraie requête. TOSIAM y répond 200 avec les en-têtes Access-Control-Allow-* si une configuration accepte l’origine, la méthode annoncée et tous les en-têtes annoncés ; sinon 403.
Les réglages#
Dans la console, Services globaux › CORS configuration :
| Réglage | Attribut | Rôle |
|---|---|---|
| Activer CORS | forgerock-am-cors-config-enable-all-cors | Commutateur global. Sans lui, aucune configuration n’est appliquée. |
Puis une configuration par application, sous Sous-configurations › Nouvelle configuration :
| Réglage | Attribut | Rôle |
|---|---|---|
| Activer cette configuration CORS | forgerock-am-cors-config-enable-cors | La configuration n’est appliquée que si elle est activée. |
| Origines acceptées | forgerock-am-cors-config-accepted-origins | Schéma, nom et port, exactement comme le navigateur les envoie, sans / final : http://localhost:3000, https://app.example.com. * accepte toutes les origines, mais pas avec les identifiants. |
| Méthodes acceptées | forgerock-am-cors-config-accepted-methods | Les méthodes des vraies requêtes : GET, POST… |
| En-têtes acceptés | forgerock-am-cors-config-accepted-headers | Les en-têtes que la page envoie : authorization, content-type. Depuis la version 3.38.0, la casse ne compte pas (Authorization convient aussi) ; avant, saisissez-les en minuscules. |
| En-têtes exposés | forgerock-am-cors-config-exposed-headers | Les en-têtes de la réponse que la page peut lire. |
| Autoriser les identifiants (cookies) | forgerock-am-cors-config-allow-credential | À activer quand la page envoie le cookie de session (credentials: 'include'). |
| Durée de mise en cache (max-age) | forgerock-am-cors-config-max-age | Durée, en secondes, pendant laquelle le navigateur garde la réponse de la pré-vérification. |
Les en-têtes à accepter dépendent de ce que la page appelle :
| Appels depuis la page | En-têtes acceptés |
|---|---|
Point des jetons (/oauth2/.../access_token), en application/x-www-form-urlencoded | aucun |
userinfo, introspection, API protégées par un jeton | authorization |
| Requêtes en JSON | content-type |
API /json/... (par exemple /json/authenticate) | content-type, accept-api-version, x-requested-with ; et les en-têtes de connexion que la page utilise, comme x-openam-username et x-openam-password |
Configurer avec ssoadm#
Un fichier de données pour l’application, app_cors.properties :
forgerock-am-cors-config-enable-cors=true
forgerock-am-cors-config-accepted-origins=https://app.example.com
forgerock-am-cors-config-accepted-methods=GET
forgerock-am-cors-config-accepted-methods=POST
forgerock-am-cors-config-accepted-headers=authorization
forgerock-am-cors-config-accepted-headers=content-typePuis le commutateur global et la configuration :
ssoadm set-attr-defs -s iPlanetCORSConfig -t global \
-a forgerock-am-cors-config-enable-all-cors=true \
-u amadmin -f /chemin/vers/pwd.txt
ssoadm create-sub-cfg -s iPlanetCORSConfig --subconfigid CorsList --subconfigname app \
--datafile app_cors.properties -u amadmin -f /chemin/vers/pwd.txtPour la retirer : ssoadm delete-sub-cfg -s iPlanetCORSConfig --subconfigname app.
Les changements s’appliquent sans redémarrage, depuis la console comme avec ssoadm. Depuis la version 3.38.0, c’est vrai aussi du commutateur global posé par set-attr-defs ; avant, il n’était pris en compte qu’au redémarrage ou à la modification suivante d’une configuration.
Vérifier avec curl#
Une pré-vérification comme celle du navigateur, pour un POST avec un en-tête authorization :
curl -s -o /dev/null -D - -X OPTIONS \
-H "Origin: https://app.example.com" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: authorization" \
https://sso.example.com/tosiam/oauth2/realms/root/userinfoRéponse attendue (l’ordre des valeurs peut varier) :
HTTP/1.1 200
Access-Control-Allow-Methods: POST,GET
Access-Control-Allow-Headers: authorization,content-type
Access-Control-Allow-Origin: https://app.example.comAvec une origine, une méthode ou un en-tête absent de la configuration, la réponse est 403, sans en-tête Access-Control-Allow-*.
En cas de problème#
| Ce que l’on voit | Cause probable |
|---|---|
Erreur CORS dans la console du navigateur, réponse sans Access-Control-Allow-Origin | Commutateur global désactivé, ou configuration non activée |
set-attr-defs … enable-all-cors=true ne change rien | La page CORS configuration a déjà été enregistrée : sa valeur l’emporte sur la valeur par défaut. Activez le commutateur dans la console |
Pré-vérification en 403 | Origine, méthode annoncée ou un des en-têtes annoncés absent de la configuration. Avant la version 3.38.0 : un en-tête saisi avec des majuscules (Authorization) ; saisissez-le en minuscules |
Requêtes d’une autre application refusées en 403 depuis qu’une configuration CORS existe | Son origine n’est dans aucune configuration : ajoutez-la, ou créez une configuration pour elle |
| Le navigateur refuse la réponse, avec un message sur les identifiants | La page envoie le cookie (credentials: 'include') et Autoriser les identifiants est désactivé |
Mis à jour le