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.
Claims reçus
Section intitulée « Claims reçus »| 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.
Construire le lien affiché
Section intitulée « Construire le lien affiché »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.
Règles pour la cible (target)
Section intitulée « Règles pour la cible (target) »- 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
httpset 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 quehttps(javascript:,data:,http:…) ; toute autre origine.
Exemples
Section intitulée « Exemples »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%3D2026OpenAthens (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%3D2026Pour une organisation OpenAthens à sous-organisations (IdP partagé), le lien ne
porte que l’entity de l’organisation, jamais le scope.
Parcours au clic
Section intitulée « Parcours au clic »EZproxy
- L’EZproxy de la bibliothèque authentifie l’utilisateur.
- EZproxy ouvre la landing ProxyNinja depuis la sortie réseau de la
bibliothèque ; la landing transmet
target. - ProxyNinja reconnaît la bibliothèque par cette adresse de sortie.
- L’utilisateur revient sur votre point d’entrée avec
target.
OpenAthens
- OpenAthens dirige l’utilisateur vers l’IdP de son organisation (
entity). - Après authentification, OpenAthens renvoie vers la landing ProxyNinja avec
la cible dans
target_link_uri. - La landing reprend
target_link_uricommetarget, sur les routes configurées pour cela (voir Accès granulaire). Sinon, l’utilisateur est connecté et arrive sur votre accueil. - Selon votre intégration, ProxyNinja vérifie que l’organisation est autorisée.
- 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.
Prérequis
Section intitulée « Prérequis »- 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.
Claim absent
Section intitulée « Claim absent »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é.
Sécurité
Section intitulée « Sécurité »- 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 :
httpssans identifiants,{target}une seule fois comme valeur detarget, 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.