Intégration iframe dans l'ENT

Pascal.Rigaux @ univ-paris1.fr

Beurk, des iframes...

Plein de problèmes !
  • mixed content (https/http)
  • third party cookies
  • login CAS dans l'iframe
  • ascenseurs en pagaille ou contenu tronqué (sur mobile)
  • double habillage

Tous ces problèmes ont des solutions...

Mixed content (https/http)

Vous avez des applications en http ?

Sachez que firefox (par défaut) conserve tous les cookies non-"secure" sur le disque, même après avoir quitté.

Les principaux navigateurs refusent les "active" http dans les pages https.

⇒ Mettez un reverse proxy !

Third party cookies

Safari a ouvert le bal en acceptant uniquement les cookies « des sites visités ». Firefox devrait bientôt faire pareil :

cookies acceptés pour le même domaine que l'url affichée dans le navigateur.

2 solutions pour application externe à l'université :

  • https://ailleur.com/login?then-go=https://ent.univ.fr/force-canal-ailleur-com
  • mettre un reverse-proxy
    (nb : très difficile pour shibboleth car les assertions sont signées avec la clé du SP)

login CAS dans l'iframe

Pour éviter que les applications ne demandent l'authentification dans l'iframe, il faut augmenter le temps de session de CAS pour qu'il soit comparable à celui de l'ENT.

Ascenseur horizontal

Pour supprimer l'ascenseur horizontal : responsive web design !

Ici le tableau force une largeur importante, explosons le :


@media screen and (max-width: 600px)  {
  td { display: block; }
}

Ascenseur vertical

Sur l'évènement onload, l'application informe le portail de sa taille via postMessage :

window.addEventListener("load", function() {
    parent.postMessage(getDocumentHeight(), "*");
});
le portail reçoit la taille :

function receiveIframeHeight(frameWindow, height) {
    $("iframe").each(function () {
        if (this.contentWindow === frameWindow) this.height = height;
    });
};
window.addEventListener("message", function (e) {
    receiveIframeHeight(e.source, e.data);
});
Pour la fonction getDocumentHeight, apache shindig fournit du code compliqué mais marchant bien sur tous les navigateurs.

Ça marche !

problème : si on élargit l'iframe, l'application est moins haute mais pas l'iframe.

Gérer l'évènement resize


window.addEventListener("resize", function() {
    parent.postMessage(getDocumentHeight(), "*");
});

Gérer l'évènement resize

Attention aux boucles infinies :
quand le code change la taille de l'iframe, cela génère un évènement resize.

⇒ variable resizedByUs pour ignorer cet évènement.

Retour d'expérience

A l'université Paris 1, nous insérons la ligne suivante dans toutes les applications en iframe :

<script src="https://xxx.univ.fr/zzz/postMessage-resize-iframe-in-parent.js"></script>
Si besoin nous utilisons mod-substitute d'apache :

FilterDeclare replace
FilterProvider replace SUBSTITUTE Content-Type $text/html
FilterChain replace
Substitute "s|<body>|<body><script src=\"https://xxx.univ.fr/zzz/postMessage-resize-iframe-in-parent.js\"></script>|"

Retour d'expérience

Une fonctionnalité supplémentaire utilisée : avoir du CSS spécifique quand l'application est intégrée en iframe

<script>
window.cssToLoadIfInsideIframe = "https://xxx.univ-paris1.fr/zzz/FNAME.css";
</script>

Cela permet de cacher le bandeau de l'application, le bouton de déconnection, de supprimer des width/padding excessif...

Retour d'expérience

Cette solution est utilisée avec succès depuis 2 ans à l'université Paris 1 sur de nombreuses applications.

Problèmes avec certaines applications (nuxeo, glpi, compilatio 2013-09) :
  • appels ajax pour charger du contenu
  • ouvertures de popups en javascript

Web 2.0

Comment gérer les modifications qui interviennent après l'évènement onload ?

Mutation Observers !
  • testé avec succès sur une application AngularJS.
  • problème sur compilatio qui change le DOM tout le temps

⇒ à tester sur plus d'applications.

Conclusion

L'intégration iframe offre plusieurs avantages :
  • intégration d'applications existantes
  • bootstrap compatible
  • pas de conflits CSS
  • moins de charge sur uportal.

Pour les problèmes de double-ascenseur, une solution existe dans google gadgets.* API (et donc dans OpenSocial gadgets) : l'application en iframe prévient le portail via postMessage quand elle se redimensionne.

En pratique pour des applications avec peu de javascript, l'insertion d'une simple ligne <script> dans l'application suffit... sans modifier le comportement de l'application hors iframe !

Liens concernant les iframes

Sur la liste esup-utilisateurs :

Proposition

  1. esup-uportal : ajouter receiveIframeHeight (20 lignes de javascript)
  2. applications : faire une page recensant comment rendre l'appli "compatible ENT en iframe sans double-ascenseurs"