L'application mayan/apps/authentication/ gère la connexion, déconnexion, changement de mot de passe et l'usurpation d'identité (impersonation) dans Mayan EDMS. Elle utilise un système de backends pluggables qui permet de remplacer le mécanisme d'authentification sans toucher aux vues.
AuthenticationBackendClasse de base (hérite de BaseBackend) pour tous les backends d'authentification Mayan. À ne pas confondre avec les AUTHENTICATION_BACKENDS Django — Mayan a sa propre couche au-dessus.
class AuthenticationBackend(BaseBackend):
_loader_module_name = 'authentication_backends'
form_list = () # liste de formulaires pour le wizard MFA
login_form_class = None # formulaire de la vue de login principale
def initialize(self): ... # appelé au démarrage (ex. : configure AUTHENTICATION_BACKENDS)
def get_user(self, request, form_list, kwargs): ... # OBLIGATOIRE : retourne l'utilisateur
def process(self, request, form_list, kwargs): ... # optionnel : ex. session TTL
def get_form_list(self): ...
def get_condition_dict(self): ... # conditions par étape du wizard
def get_context_data(self): ... # contexte supplémentaire pour le template
AuthenticationBackendRememberMeMixinMixin qui gère la durée de session selon l'option "Se souvenir de moi" :
remember_me=True → session longue (maximum_session_length, défaut : 30 jours)remember_me=False → session expirée à la fermeture du navigateur (set_expiry(0))remember_me=None → comportement Django par défaut| Backend | Identifiant (à mettre dans la config) | Description |
|---|---|---|
AuthenticationBackendModelDjangoDefault |
mayan.apps.authentication.authentication_backends.AuthenticationBackendModelDjangoDefault |
Comportement Django standard (défaut) |
AuthenticationBackendModelUsernamePassword |
mayan.apps.authentication.authentication_backends.AuthenticationBackendModelUsernamePassword |
Login par nom d'utilisateur + mot de passe |
AuthenticationBackendModelEmailPassword |
mayan.apps.authentication.authentication_backends.AuthenticationBackendModelEmailPassword |
Login par email + mot de passe |
L'app
authentication_oidc(forkegyptian) ajoute un backend OIDC supplémentaire.
L'app configure aussi settings.AUTHENTICATION_BACKENDS Django lors de l'initialize() :
| Backend Mayan | Backend Django configuré |
|---|---|
...UsernamePassword |
django.contrib.auth.backends.ModelBackend (standard) |
...EmailPassword |
DjangoAuthenticationBackendModelEmail (lookup par email au lieu de username) |
DjangoAuthenticationBackendModelEmail exécute systématiquement un hash factice même si l'utilisateur n'existe pas (protection contre la découverte de comptes par timing).
Navigateur → MayanLoginView
→ get_form_class() ← AuthenticationBackend.get_login_form_class()
→ form_valid()
→ process() ← gestion "remember me"
→ Django login()
→ redirection
MayanLoginView.form_valid()
→ stocke l'user_id en session (SESSION_MULTI_FACTOR_USER_ID_KEY)
→ redirige vers MultiFactorAuthenticationView
MultiFactorAuthenticationView (SessionWizardView)
→ form_list = backend.get_form_list() # étapes dynamiques
→ condition_dict = backend.get_condition_dict() # conditions par étape
→ done()
→ process() ← gestion session TTL
→ get_user() ← récupère l'user depuis la session
→ Django login()
La clé de session _multi_factor_user_id stocke temporairement l'ID de l'utilisateur identifié à la première étape (avant complétion du MFA).
MultiFactorAuthenticationViewVue wizard (SessionWizardView) dont la form_list et le condition_dict sont des propriétés dynamiques calculées à chaque request depuis le backend actif. Cela permet de changer le backend sans redémarrer le serveur.
Dans config.yml :
AUTHENTICATION_BACKEND: mayan.apps.authentication.authentication_backends.AuthenticationBackendModelEmailPassword
AUTHENTICATION_BACKEND_ARGUMENTS:
maximum_session_length: 2592000 # 30 jours en secondes
AUTHENTICATION_DISABLE_PASSWORD_RESET: false
| Variable d'environnement | Défaut | Description |
|---|---|---|
MAYAN_AUTHENTICATION_BACKEND |
...DjangoDefault |
Backend d'authentification à utiliser |
MAYAN_AUTHENTICATION_BACKEND_ARGUMENTS |
{maximum_session_length: 2592000} |
Arguments passés au backend |
MAYAN_AUTHENTICATION_DISABLE_PASSWORD_RESET |
false |
Masque le lien "Mot de passe oublié" |
Permet à un administrateur de se connecter sous l'identité d'un autre utilisateur sans connaître son mot de passe. Utile pour le support et le débogage.
ImpersonateMiddlewareIntercepts chaque requête et remplace request.user si une session d'impersonation est active.
Démarrer : requête GET/POST avec _user_impersonate_id=<pk> (optionnel : _user_impersonate_permanent).
Arrêter : requête GET/POST avec _user_impersonate_end=.
Modes de session :
_user_impersonate_permanent).Sécurité : l'impersonation est filtrée par ACL (permission_users_impersonate). On ne peut pas impersonner un superuser ou soi-même.
| Vue | Description |
|---|---|
UserImpersonateFormStartView |
Formulaire de sélection de l'utilisateur à impersonner |
UserImpersonateStartView |
Démarre l'impersonation depuis le profil d'un utilisateur (URL avec user_id) |
UserImpersonateEndView |
Redirige vers l'accueil avec _user_impersonate_end pour terminer la session |
| Événement | Moment |
|---|---|
event_user_impersonation_started |
Démarrage de l'impersonation |
event_user_impersonation_ended |
Fin de l'impersonation |
MayanPasswordChangeViewVue de changement du mot de passe de l'utilisateur courant. Bloquée si user_options.block_password_change = True (option configurable par l'admin).
UserSetPasswordViewPermet à un admin de réinitialiser le mot de passe d'un autre utilisateur (avec permission permission_user_edit). Affiche un avertissement si la cible est staff ou superuser (la modification est bloquée pour ceux-ci via l'interface).
Géré par les vues Django standard (PasswordResetView, etc.), encapsulées dans views/password_reset_views.py. Peut être désactivé via AUTHENTICATION_DISABLE_PASSWORD_RESET.
get_random_password()from mayan.apps.authentication.secrets import get_random_password
password = get_random_password(length=10)
Génère un mot de passe aléatoire sécurisé (django.utils.crypto.get_random_string).
| Événement | Déclencheur |
|---|---|
event_user_logged_in |
Signal Django user_logged_in |
event_user_logged_out |
Signal Django user_logged_out |
event_user_impersonation_started |
Démarrage d'une impersonation |
event_user_impersonation_ended |
Fin d'une impersonation |
| Permission | Usage |
|---|---|
permission_users_impersonate |
Impersonner d'autres utilisateurs |
authentication_backends.py dans une app custom.AuthenticationBackend (et AuthenticationBackendRememberMeMixin si besoin).get_user() et éventuellement initialize(), process().form_list avec les formulaires d'étapes supplémentaires.MAYAN_AUTHENTICATION_BACKEND.class AuthenticationBackendMySAML(
AuthenticationBackendRememberMeMixin, AuthenticationBackend
):
label = 'SAML 2.0'
login_form_class = SAMLInitiateForm
def initialize(self):
# configure AUTHENTICATION_BACKENDS si nécessaire
...
def get_user(self, request, form_list=None, kwargs=None):
user_id = request.session[SESSION_MULTI_FACTOR_USER_ID_KEY]
return get_user_model().objects.get(pk=user_id)