Aller au contenu

Liens partageables

Après une connexion par la bibliothèque (EZproxy) ou par OpenAthens, l’utilisateur revient directement sur votre site. L’URL de la barre d’adresse n’est pas partageable : elle ne fait pas repasser un collègue par l’authentification de son établissement.

Pour permettre le partage, ProxyNinja peut vous remettre, au moment de la connexion, un gabarit de lien partageable propre à l’établissement de l’utilisateur. Votre site affiche ce lien, par exemple derrière un bouton « Partager », en y insérant la page courante. Le lien vient uniquement de votre site : aucun générateur de liens n’est proposé aux bibliothécaires.

Claim Type Exemple Rôle
share_link_template chaîne voir Exemples gabarit contenant exactement une fois {target}
access_mode ezproxy ou openathens ezproxy mode d’accès utilisé à la connexion
establishment_uai chaîne 0123456A identifiant de l’établissement
establishment_name chaîne Médiathèque Exemple nom de la bibliothèque ou de l’établissement
identity_provider chaîne ezproxy fournisseur d’identité ProxyNinja utilisé
  • Présents dans l’ID token et dans la réponse userinfo, jamais dans l’access token.
  • Tous présents ou tous absents.
  • Portés par un client scope dédié, attaché à votre seul client OIDC.

Le lien s’obtient en remplaçant une seule fois {target} par la cible de la page courante, encodée comme encodeURIComponent (en PHP, rawurlencode). Le gabarit est le même pour tous les utilisateurs d’un établissement : ce n’est pas un lien par page ni par personne. Validez la cible au moment de l’affichage (règles ci-dessous).

const ORIGINES_AUTORISEES = ['https://www.ressource.example'];
const INTERDITS = /[\u0000-\u001f\u007f\\]/; // caractères de contrôle et antislash
function cibleValide(target) {
if (typeof target !== 'string' || target === '' || INTERDITS.test(target)) return null;
if (target.startsWith('/')) {
// Chemin relatif : chaque forme décodée (jusqu'à 3 niveaux, au-delà refus) doit
// commencer par un seul « / », sans contrôle, antislash ni segment « .. ».
let forme = target;
for (let niveau = 0; ; niveau++) {
const chemin = forme.split(/[?#]/)[0];
if (forme.startsWith('//') || INTERDITS.test(forme) || /(^|\/)\.\.(\/|$)/.test(chemin)) return null;
let decodee;
try { decodee = decodeURIComponent(forme); } catch { return null; }
if (decodee === forme) return target;
if (niveau === 3) return null;
forme = decodee;
}
}
let url;
try { url = new URL(target); } catch { return null; }
if (url.protocol !== 'https:' || url.username || url.password) return null;
if (!ORIGINES_AUTORISEES.includes(url.origin)) return null;
return url.href;
}
function lienPartageable(gabarit, target) {
const cible = cibleValide(target);
if (!cible || typeof gabarit !== 'string' || gabarit.split('{target}').length !== 2) return null;
return gabarit.replace('{target}', encodeURIComponent(cible));
}

Ce filtre sert à l’affichage, il ne protège pas. Le lien est public et modifiable : n’importe qui peut fabriquer …?target=%2F%2Fsite-tiers.example. Votre point d’entrée doit donc valider target côté serveur, avec les mêmes règles, avant toute redirection : voir Accès granulaire.

  • Chemin relatif recommandé, commençant par un seul /, par exemple /cours/42?saison=2026. Il reste relatif dans le lien : le domaine de destination vient de l’URL de retour configurée pour votre ressource. Le même lien fonctionne donc en préproduction et en production.
  • URL absolue acceptée seulement en https et sur une origine que vous autorisez.
  • Refusés : chemin sans / initial ; formes //, y compris encodées (/%2F%2Fhote) ; antislash ; remontée .. ; caractères de contrôle ; identifiants dans l’URL ; autre schéma que https (javascript:, data:, http:…) ; toute autre origine.

Page courante : /cours/42?saison=2026.

EZproxy (bibliothèque dont l’EZproxy est ezproxy.bibliotheque.example) :

share_link_template = https://ezproxy.bibliotheque.example/login?url=https://landing.proxyninja.fr/votre-route-ezproxy?target={target}
lien affiché = https://ezproxy.bibliotheque.example/login?url=https://landing.proxyninja.fr/votre-route-ezproxy?target=%2Fcours%2F42%3Fsaison%3D2026

OpenAthens (organisation dont l’IdP est https://idp.institution.example/entity) :

share_link_template = https://connect.openathens.net/votre-domaine.example/<id-application>/login?entity=https%3A%2F%2Fidp.institution.example%2Fentity&target={target}
lien affiché = https://connect.openathens.net/votre-domaine.example/<id-application>/login?entity=https%3A%2F%2Fidp.institution.example%2Fentity&target=%2Fcours%2F42%3Fsaison%3D2026

Pour une organisation OpenAthens à sous-organisations (IdP partagé), le lien ne porte que l’entity de l’organisation, jamais le scope.

EZproxy

  1. L’EZproxy de la bibliothèque authentifie l’utilisateur.
  2. EZproxy ouvre la landing ProxyNinja depuis la sortie réseau de la bibliothèque ; la landing transmet target.
  3. ProxyNinja reconnaît la bibliothèque par cette adresse de sortie.
  4. L’utilisateur revient sur votre point d’entrée avec target.

OpenAthens

  1. OpenAthens dirige l’utilisateur vers l’IdP de son organisation (entity).
  2. Après authentification, OpenAthens renvoie vers la landing ProxyNinja avec la cible dans target_link_uri.
  3. La landing reprend target_link_uri comme target, sur les routes configurées pour cela (voir Accès granulaire). Sinon, l’utilisateur est connecté et arrive sur votre accueil.
  4. Selon votre intégration, ProxyNinja vérifie que l’organisation est autorisée.
  5. L’utilisateur revient sur votre point d’entrée avec target.

Construire le lien ne vérifie aucun abonnement : l’accès est contrôlé au clic, comme pour toute connexion.

  • Votre point d’entrée accepte target, y compris relatif si vous utilisez des chemins relatifs (Accès granulaire).
  • EZproxy : la stanza de la bibliothèque autorise l’hôte de la landing ProxyNinja (Accès par EZproxy).
  • OpenAthens : le retour à la page précise suppose une route landing configurée par ProxyNinja pour reprendre target_link_uri.

Si share_link_template est absent (fonction non activée, établissement non configuré, contrôle de sécurité non passé), masquez le bouton de partage ou affichez un message neutre. Ne bloquez jamais l’accès de l’utilisateur connecté.

  • Le lien ne contient aucun identifiant d’utilisateur, jeton, code d’autorisation, nonce ni identifiant de session : seulement l’hôte EZproxy de la bibliothèque et la landing (EZproxy), ou le domaine OpenAthens, l’identifiant d’application et l’entityID de l’organisation (OpenAthens).
  • ProxyNinja vérifie le gabarit avant de vous le remettre : https sans identifiants, {target} une seule fois comme valeur de target, aucun paramètre de session, de jeton ou d’identifiant.
  • La validation de la cible reste à votre charge : au moment de l’affichage, et surtout côté serveur avant toute redirection, car un lien peut être fabriqué ou modifié à la main.