Description
Dans le cadre d’un travail demandé par l’UMR LISA de l’Université de Corse, nous souhaitons faire évoluer mviewer studio afin qu’il puisse utiliser une authentification OpenID Connect (OIDC), par exemple avec :
- un GeoNode configuré comme fournisseur OIDC ;
- Keycloak ;
- tout autre fournisseur compatible OpenID Connect.
Actuellement, mviewer studio délègue l’authentification à geOrchestra. Le Gateway transmet au backend les informations de l’utilisateur dans les en-têtes HTTP sec-username, sec-org, sec-roles, etc.
Le backend ne réalise donc pas lui-même l’authentification : il construit l’utilisateur courant à partir de ces en-têtes. Les rôles sont retournés par /api/user, mais ne sont actuellement pas utilisés pour autoriser ou interdire des fonctionnalités.
L’objectif est d’ajouter un mode d’authentification OIDC tout en conservant la compatibilité avec geOrchestra.
La logique métier de mviewer studio devra rester indépendante du fournisseur d’identité utilisé.
Avantages
- conserver la compatibilité avec les installations geOrchestra existantes ;
- permettre un déploiement sécurisé hors geOrchestra ;
- utiliser un fournisseur standard tel que GeoNode, Keycloak ou un fournisseur Django ;
- bénéficier du SSO ;
- ne pas exposer les jetons OIDC au frontend.
Modes d’authentification
Le mode sera sélectionné par une variable d’environnement :
MVIEWERSTUDIO_AUTH_MODE=proxy
ou :
MVIEWERSTUDIO_AUTH_MODE=authlib
ou, lorsque la protection est déléguée à un reverse proxy :
MVIEWERSTUDIO_AUTH_MODE=oauth2-proxy
Le mode oauth2-proxy devra être résolu par le backend vers le mode interne proxy. La configuration geOrchestra existante devra rester prise en charge avec MVIEWERSTUDIO_AUTH_TYPE=georchestra.
Le mode authlib est réservé au client OIDC directement géré par mviewer studio. Un mode public (ou anonymous) reste disponible pour les installations non protégées ; le mode auto résout le mode à partir de la configuration et des en-têtes présents.
| Mode résolu |
Configuration recommandée |
Cas d’utilisation |
Responsable de l’authentification |
proxy (geOrchestra) |
MVIEWERSTUDIO_AUTH_TYPE=georchestra |
Installation existante avec geOrchestra Gateway et en-têtes sec-*. |
geOrchestra Gateway |
proxy (oauth2-proxy) |
MVIEWERSTUDIO_AUTH_MODE=oauth2-proxy |
Protection OIDC déportée devant mviewer studio, notamment avec Keycloak. |
oauth2-proxy et le fournisseur OIDC |
authlib |
MVIEWERSTUDIO_AUTH_MODE=authlib |
Client OIDC directement intégré à mviewer studio, par exemple avec GeoNode ou Keycloak. |
mviewer studio, via Authlib |
public |
MVIEWERSTUDIO_AUTH_MODE=public |
Instance volontairement accessible sans authentification. |
Aucun |
auto |
MVIEWERSTUDIO_AUTH_MODE=auto |
Détection technique à partir des en-têtes proxy ou de la configuration Authlib ; à réserver aux déploiements maîtrisés. |
Dépend de la détection |
proxy sera le nom interne du mode commun aux intégrations geOrchestra et oauth2-proxy. Pour une nouvelle configuration avec oauth2-proxy, utiliser la valeur explicite MVIEWERSTUDIO_AUTH_MODE=oauth2-proxy.
Mode proxy : geOrchestra Gateway ou oauth2-proxy
Le fonctionnement actuel sera conservé :
geOrchestra Gateway → en-têtes sec-* → utilisateur mviewer studio
Le Gateway reste responsable de l’authentification et de la redirection vers sa mire de connexion.
Le mode oauth2-proxy devra prendre en charge les en-têtes courants transmis par le composant tiers :
| En-tête |
Information transmise |
Utilisation dans mviewer studio |
X-Auth-Request-User |
Identifiant de l’utilisateur |
Identifiant de secours lorsque le nom d’utilisateur préféré est absent. |
X-Auth-Request-Preferred-Username |
Nom d’utilisateur préféré |
Identifiant principal de l’utilisateur. |
X-Auth-Request-Given-Name |
Prénom |
Alimentation du champ firstname. |
X-Auth-Request-Family-Name |
Nom |
Alimentation du champ lastname. |
X-Auth-Request-Groups |
Groupes ou rôles |
Alimentation de l’organisation et des rôles. |
X-Auth-Request-Access-Token |
Jeton d’accès OIDC |
Source de secours pour les claims lorsqu’ils ne sont pas fournis par les en-têtes. |
Mode OIDC
mviewer studio devient un client OpenID Connect.
L’implémentation côté backend s’appuiera sur la bibliothèque open source Authlib, notamment pour la découverte OIDC, le flux Authorization Code avec PKCE, la validation des réponses et la gestion des jetons côté serveur.
Le fournisseur devra de préférence exposer son document de découverte :
<issuer>/.well-known/openid-configuration
Un client confidentiel mviewer studio devra être déclaré avec notamment :
| Paramètre |
Description |
client_id |
Identifiant public du client OIDC déclaré pour mviewer studio. |
client_secret |
Secret associé au client confidentiel ; il est conservé exclusivement côté backend. |
redirect_uri |
URL de callback de mviewer studio, appelée après l’authentification auprès du fournisseur. |
post_logout_redirect_uri |
URL de retour vers mviewer studio après la déconnexion du fournisseur. |
Le flux utilisé sera l’Authorization Code Flow, avec PKCE lorsque cela est possible.
Les scopes par défaut seront :
Le fournisseur devra fournir les informations nécessaires à mviewer studio :
identifiant, prénom, nom, organisation et rôles
Le backend devra normaliser les aliases de claims les plus courants. La configuration d’un mapping arbitraire pour chaque attribut devra pouvoir couvrir les fournisseurs non standards.
L’organisation est particulièrement importante, car elle détermine les espaces de travail et de publication.
Déploiement avec oauth2-proxy
Le mode oauth2-proxy permet de déployer mviewer studio derrière oauth2-proxy, qui assure l’authentification OIDC et la protection des accès en amont de l’application.
Navigateur → oauth2-proxy → mviewer studio
↓
fournisseur OIDC
Dans cette architecture, mviewer studio ne réalisera ni redirection vers le fournisseur d’identité ni gestion de jetons OIDC. Il construira l’utilisateur courant à partir d’en-têtes HTTP de confiance transmis par oauth2-proxy, avec un fallback possible sur le jeton d’accès transmis par le proxy. Les noms d’en-têtes reconnus devront être configurables si nécessaire.
Le backend ne devra pas être accessible directement depuis l’extérieur afin d’empêcher l’usurpation de ces en-têtes.
Impacts dans mviewer studio
Prérequis
| Mode |
Prérequis |
| geOrchestra Gateway |
Disposer d’un Gateway geOrchestra protégeant l’accès à mviewer studio et transmettant les en-têtes sec-username, sec-firstname, sec-lastname, sec-org et sec-roles. |
authlib |
Disposer d’un fournisseur OIDC accessible avec un document de découverte, déclarer mviewer studio comme client confidentiel, configurer les URL de callback et de déconnexion, fournir les claims attendus et utiliser HTTPS en production. |
oauth2-proxy |
Déployer oauth2-proxy devant mviewer studio, le configurer avec un fournisseur OIDC et un client dédié, transmettre les en-têtes d’identité attendus et empêcher l’accès direct au backend. |
public |
Ne requiert aucun fournisseur d’identité ; ce mode doit être limité aux instances volontairement publiques. |
auto |
Réunir les prérequis du mode qui sera détecté ; ce mode est réservé aux déploiements maîtrisés afin d’éviter une sélection non souhaitée. |
Backend
Abstraction de l’authentification
Le backend devra s’appuyer sur une résolution commune des modes et des adaptateurs d’identité :
MVIEWERSTUDIO_AUTH_MODE
├── proxy → adaptateur geOrchestra ou OIDC transmis par reverse proxy
├── authlib → session OIDC gérée par l’application
└── public → utilisateur anonyme
Structure possible :
src/auth_mode.py
src/services/auth/authlib.py
src/utils/auth/georchestra.py
src/utils/auth/oidc.py
src/utils/auth/authlib_session.py
Les trois modes devront produire le même modèle utilisateur interne :
username
firstname
lastname
organisation
normalize_name
roles
Le reste du backend pourra ainsi continuer à utiliser le modèle User existant.
Routes OIDC
Les routes exposées sont :
/auth/login
/auth/callback
/logout
/api/logout
Elles permettront d’ouvrir la mire OIDC, de traiter le retour d’authentification et de fermer la session.
Ces routes doivent rester accessibles sans session. Les pages de mviewer studio et les endpoints métier seront, eux, protégés.
Le parcours attendu est :
/mviewer studio/?app=123
↓
/auth/login?next=/mviewer studio/?app=123
↓
mire du fournisseur OIDC
↓
/auth/callback
↓
/mviewer studio/?app=123
Le paramètre next devra être validé afin d’éviter les redirections vers un site externe.
Protection de mviewer studio
Le comportement attendu est :
navigation non authentifiée → HTTP 302 vers /auth/login
appel API non authentifié → HTTP 401
Cela évite qu’un appel JavaScript reçoive une page HTML de connexion à la place d’une réponse API.
En mode proxy, aucune redirection OIDC ne sera déclenchée par mviewer studio : la protection reste respectivement assurée par le Gateway geOrchestra ou par oauth2-proxy.
Sessions et jetons
Les jetons OIDC ne devront pas être exposés au frontend.
Ils seront gérés par le backend au moyen d’une session et d’un cookie configuré avec :
Secure
HttpOnly
SameSite=Lax
Le backend devra utiliser une session serveur pour stocker les jetons et les claims. La configuration explicite des attributs de cookie Secure, HttpOnly et SameSite devra être assurée pour chaque déploiement de production.
Configuration
Exemple de configuration :
MVIEWERSTUDIO_AUTH_MODE=authlib
MVIEWERSTUDIO_AUTHLIB_ISSUER=https://auth.example.org
# Ou, de façon explicite : MVIEWERSTUDIO_AUTHLIB_METADATA_URL=https://auth.example.org/.well-known/openid-configuration
MVIEWERSTUDIO_AUTHLIB_CLIENT_ID=mviewerstudio
MVIEWERSTUDIO_AUTHLIB_CLIENT_SECRET=secret
MVIEWERSTUDIO_AUTHLIB_SCOPE="openid profile email"
MVIEWERSTUDIO_AUTHLIB_GROUPS_CLAIM=groups
MVIEWERSTUDIO_AUTHLIB_ALLOWED_GROUPS=editor,admin
OIDC_END_SESSION_ENDPOINT=https://auth.example.org/logout
Les claims utilisateur reconnus nativement sont notamment preferred_username, username, email, sub, given_name, family_name, organization / organisation / org, roles, realm_access.roles et les claims de groupes usuels. Le claim de groupes peut être défini par MVIEWERSTUDIO_AUTHLIB_GROUPS_CLAIM (liste de noms séparés par des virgules).
Les chemins de claims imbriqués génériques ne sont pas pris en charge à ce jour. Le cas Keycloak realm_access.roles est pris en charge nativement.
Exemple de configuration des en-têtes transmis par un reverse proxy :
MVIEWERSTUDIO_AUTH_MODE=oauth2-proxy
MVIEWERSTUDIO_AUTH_TYPE=keycloak
OAUTH2_PROXY_OIDC_ISSUER_URL=https://auth.example.org/realms/mviewer
OAUTH2_PROXY_CLIENT_ID=mviewerstudio
Une configuration de référence Docker / reverse proxy avec oauth2-proxy devra être fournie dans la documentation.
Organisation
Le claim d’organisation devra être équivalent à l’actuel sec-org.
Deux comportements devront être configurables : utiliser DEFAULT_ORG lorsque le claim est absent, ou rendre le claim obligatoire et retourner 403 Forbidden lorsqu’il est absent ou vide.
Rôles
Les rôles seront conservés dans le modèle utilisateur et retournés par /api/user.
Dans un premier temps, aucun contrôle fonctionnel supplémentaire ne sera ajouté à partir des rôles. Ils seront conservés dans le modèle utilisateur et retournés par /api/user. Le filtrage des rôles et groupes restera assuré en amont par le Gateway ou par oauth2-proxy.
Route utilisateur
La route existante :
devra conserver le même format de réponse, que l’utilisateur provienne de geOrchestra, d’OIDC ou d’un reverse proxy.
Frontend
Le frontend devra rester indépendant du fournisseur d’identité.
Il continuera à récupérer l’utilisateur courant via :
En mode authlib :
- un appel API retournant
401 utilise l’URL login_url renvoyée par le backend ;
- la déconnexion utilise
/logout ou /api/logout ;
- aucun jeton ni secret OIDC ne sera stocké dans le navigateur.
En mode geOrchestra, les mécanismes de connexion et de déconnexion existants seront conservés.
En mode proxy, les mécanismes de connexion et de déconnexion sont ceux du composant tiers, par exemple oauth2-proxy.
Critères d'acceptation
Voici les critères que je propose :
- Un utilisateur authentifié via le Gateway geOrchestra peut accéder à mviewer studio.
- Un utilisateur non authentifié derrière geOrchestra est redirigé vers la mire geOrchestra.
- Un utilisateur authentifié via le mode
authlib peut accéder à mviewer studio.
- Un utilisateur non authentifié en mode OIDC est redirigé vers la mire du fournisseur configuré.
- Après authentification, l’utilisateur revient sur mviewer studio.
- Authlib est utilisé pour l’implémentation du client OIDC côté backend.
- Le flux Authorization Code utilise PKCE.
- Les fournisseurs GeoNode, Keycloak et tout fournisseur OIDC compatible peuvent être utilisés par configuration.
- L’accès direct aux routes métier sans authentification est impossible.
- Les appels API non authentifiés retournent 401.
- Le frontend utilise l’URL
login_url fournie par l’API après réception d’un 401 en mode authlib.
- Le paramètre
next est limité à une URL locale de mviewer studio.
- Un utilisateur authentifié mais non autorisé reçoit 403.
- Après déconnexion, l’accès à mviewer studio provoque une nouvelle redirection vers la mire.
- Le mode geOrchestra existant reste compatible via
MVIEWERSTUDIO_AUTH_TYPE=georchestra.
- Un déploiement derrière oauth2-proxy permet d’accéder à mviewer studio après authentification.
- En mode
proxy, mviewer studio ne gère ni redirection vers le fournisseur d’identité ni session OIDC locale.
- Les attributs utilisateur transmis par oauth2-proxy sont correctement convertis vers le modèle utilisateur interne.
- Le backend ne peut pas être accédé publiquement en contournant oauth2-proxy.
Description
Dans le cadre d’un travail demandé par l’UMR LISA de l’Université de Corse, nous souhaitons faire évoluer mviewer studio afin qu’il puisse utiliser une authentification OpenID Connect (OIDC), par exemple avec :
Actuellement, mviewer studio délègue l’authentification à geOrchestra. Le Gateway transmet au backend les informations de l’utilisateur dans les en-têtes HTTP
sec-username,sec-org,sec-roles, etc.Le backend ne réalise donc pas lui-même l’authentification : il construit l’utilisateur courant à partir de ces en-têtes. Les rôles sont retournés par
/api/user, mais ne sont actuellement pas utilisés pour autoriser ou interdire des fonctionnalités.L’objectif est d’ajouter un mode d’authentification OIDC tout en conservant la compatibilité avec geOrchestra.
La logique métier de mviewer studio devra rester indépendante du fournisseur d’identité utilisé.
Avantages
Modes d’authentification
Le mode sera sélectionné par une variable d’environnement :
ou :
ou, lorsque la protection est déléguée à un reverse proxy :
Le mode
oauth2-proxydevra être résolu par le backend vers le mode interneproxy. La configuration geOrchestra existante devra rester prise en charge avecMVIEWERSTUDIO_AUTH_TYPE=georchestra.Le mode
authlibest réservé au client OIDC directement géré par mviewer studio. Un modepublic(ouanonymous) reste disponible pour les installations non protégées ; le modeautorésout le mode à partir de la configuration et des en-têtes présents.proxy(geOrchestra)MVIEWERSTUDIO_AUTH_TYPE=georchestrasec-*.proxy(oauth2-proxy)MVIEWERSTUDIO_AUTH_MODE=oauth2-proxyoauth2-proxyet le fournisseur OIDCauthlibMVIEWERSTUDIO_AUTH_MODE=authlibpublicMVIEWERSTUDIO_AUTH_MODE=publicautoMVIEWERSTUDIO_AUTH_MODE=autoproxysera le nom interne du mode commun aux intégrations geOrchestra etoauth2-proxy. Pour une nouvelle configuration avecoauth2-proxy, utiliser la valeur expliciteMVIEWERSTUDIO_AUTH_MODE=oauth2-proxy.Mode proxy : geOrchestra Gateway ou oauth2-proxy
Le fonctionnement actuel sera conservé :
Le Gateway reste responsable de l’authentification et de la redirection vers sa mire de connexion.
Le mode
oauth2-proxydevra prendre en charge les en-têtes courants transmis par le composant tiers :X-Auth-Request-UserX-Auth-Request-Preferred-UsernameX-Auth-Request-Given-Namefirstname.X-Auth-Request-Family-Namelastname.X-Auth-Request-GroupsX-Auth-Request-Access-TokenMode OIDC
mviewer studio devient un client OpenID Connect.
L’implémentation côté backend s’appuiera sur la bibliothèque open source Authlib, notamment pour la découverte OIDC, le flux Authorization Code avec PKCE, la validation des réponses et la gestion des jetons côté serveur.
Le fournisseur devra de préférence exposer son document de découverte :
Un client confidentiel mviewer studio devra être déclaré avec notamment :
client_idclient_secretredirect_uripost_logout_redirect_uriLe flux utilisé sera l’Authorization Code Flow, avec PKCE lorsque cela est possible.
Les scopes par défaut seront :
Le fournisseur devra fournir les informations nécessaires à mviewer studio :
Le backend devra normaliser les aliases de claims les plus courants. La configuration d’un mapping arbitraire pour chaque attribut devra pouvoir couvrir les fournisseurs non standards.
L’organisation est particulièrement importante, car elle détermine les espaces de travail et de publication.
Déploiement avec oauth2-proxy
Le mode
oauth2-proxypermet de déployer mviewer studio derrièreoauth2-proxy, qui assure l’authentification OIDC et la protection des accès en amont de l’application.Dans cette architecture, mviewer studio ne réalisera ni redirection vers le fournisseur d’identité ni gestion de jetons OIDC. Il construira l’utilisateur courant à partir d’en-têtes HTTP de confiance transmis par
oauth2-proxy, avec un fallback possible sur le jeton d’accès transmis par le proxy. Les noms d’en-têtes reconnus devront être configurables si nécessaire.Le backend ne devra pas être accessible directement depuis l’extérieur afin d’empêcher l’usurpation de ces en-têtes.
Impacts dans mviewer studio
Prérequis
sec-username,sec-firstname,sec-lastname,sec-orgetsec-roles.authliboauth2-proxyoauth2-proxydevant mviewer studio, le configurer avec un fournisseur OIDC et un client dédié, transmettre les en-têtes d’identité attendus et empêcher l’accès direct au backend.publicautoBackend
Abstraction de l’authentification
Le backend devra s’appuyer sur une résolution commune des modes et des adaptateurs d’identité :
Structure possible :
Les trois modes devront produire le même modèle utilisateur interne :
Le reste du backend pourra ainsi continuer à utiliser le modèle
Userexistant.Routes OIDC
Les routes exposées sont :
Elles permettront d’ouvrir la mire OIDC, de traiter le retour d’authentification et de fermer la session.
Ces routes doivent rester accessibles sans session. Les pages de mviewer studio et les endpoints métier seront, eux, protégés.
Le parcours attendu est :
Le paramètre
nextdevra être validé afin d’éviter les redirections vers un site externe.Protection de mviewer studio
Le comportement attendu est :
Cela évite qu’un appel JavaScript reçoive une page HTML de connexion à la place d’une réponse API.
En mode
proxy, aucune redirection OIDC ne sera déclenchée par mviewer studio : la protection reste respectivement assurée par le Gateway geOrchestra ou paroauth2-proxy.Sessions et jetons
Les jetons OIDC ne devront pas être exposés au frontend.
Ils seront gérés par le backend au moyen d’une session et d’un cookie configuré avec :
Le backend devra utiliser une session serveur pour stocker les jetons et les claims. La configuration explicite des attributs de cookie
Secure,HttpOnlyetSameSitedevra être assurée pour chaque déploiement de production.Configuration
Exemple de configuration :
Les claims utilisateur reconnus nativement sont notamment
preferred_username,username,email,sub,given_name,family_name,organization/organisation/org,roles,realm_access.roleset les claims de groupes usuels. Le claim de groupes peut être défini parMVIEWERSTUDIO_AUTHLIB_GROUPS_CLAIM(liste de noms séparés par des virgules).Les chemins de claims imbriqués génériques ne sont pas pris en charge à ce jour. Le cas Keycloak
realm_access.rolesest pris en charge nativement.Exemple de configuration des en-têtes transmis par un reverse proxy :
Une configuration de référence Docker / reverse proxy avec
oauth2-proxydevra être fournie dans la documentation.Organisation
Le claim d’organisation devra être équivalent à l’actuel
sec-org.Deux comportements devront être configurables : utiliser
DEFAULT_ORGlorsque le claim est absent, ou rendre le claim obligatoire et retourner403 Forbiddenlorsqu’il est absent ou vide.Rôles
Les rôles seront conservés dans le modèle utilisateur et retournés par
/api/user.Dans un premier temps, aucun contrôle fonctionnel supplémentaire ne sera ajouté à partir des rôles. Ils seront conservés dans le modèle utilisateur et retournés par
/api/user. Le filtrage des rôles et groupes restera assuré en amont par le Gateway ou paroauth2-proxy.Route utilisateur
La route existante :
devra conserver le même format de réponse, que l’utilisateur provienne de geOrchestra, d’OIDC ou d’un reverse proxy.
Frontend
Le frontend devra rester indépendant du fournisseur d’identité.
Il continuera à récupérer l’utilisateur courant via :
En mode
authlib:401utilise l’URLlogin_urlrenvoyée par le backend ;/logoutou/api/logout;En mode geOrchestra, les mécanismes de connexion et de déconnexion existants seront conservés.
En mode
proxy, les mécanismes de connexion et de déconnexion sont ceux du composant tiers, par exempleoauth2-proxy.Critères d'acceptation
Voici les critères que je propose :
authlibpeut accéder à mviewer studio.login_urlfournie par l’API après réception d’un 401 en modeauthlib.nextest limité à une URL locale de mviewer studio.MVIEWERSTUDIO_AUTH_TYPE=georchestra.proxy, mviewer studio ne gère ni redirection vers le fournisseur d’identité ni session OIDC locale.