Manuel:SessionManager et AuthManager
SessionManager et AuthManager sont deux environnements traitant de l'authentification introduite dans MediaWiki 1.27 et qui doivent remplacer le caractère « il ne doit y en avoir qu'un seul ! » de AuthPlugin (le précédent système d'authentification), l'incapacité d'avoir une méthode de connexion fédérée (par exemple « se connecter avec son compte Google ») sans utiliser diverses accroches pour patcher le focus de MediaWiki sur l'authentification basée sur un mots de passe, et l'incapacité de faire la gestion des sessions avec autre chose que les cookies sans de nouveau avoir recours aux différentes accroches pour patcher la confiance de MediaWiki sur les sessions PHP basées sur les cookies.
Ce qu'ils font
Le SessionManager (gestionnaire de session) a la charge de récupérer une requête entrante et de la relier à une session utilisateur, c'est à dire au fait que la requête vient d'un utilisateur connecté (ou pas) avec toutes les données devant persister durant l'ensemble des requêtes comme le $_SESSION
de PHP.
Généralement cela suppose l'existence de cookies contenant la « clé de session » , l'ID et le jeton de l'utilisateur, mais cela pourrait aisément s'appuyer sur les données des entêtes OAuth ou un certificat de client TLS.
Le AuthManager (gestionnaire d'authentification) a la charge de la connexion en fournissant les informations à Special:UserLogin ou similaire, et de créer les comptes avec les nouvelles informations. Cela comprend le formulaire habituel avec le nom d'utilisateur et le mot de passe, mais aussi les mécanismes tels que la connexion via Google, Facebook, ou autres services d'authentification tiers, l'authentification multi-facteurs, ainsi que d'autres contrôles fait au moment de la connexion tels que la réinitialisation du mot de passe, les CAPTCHAs, etc.
Comment les utiliser
En tant qu'administrateur système
Les fournisseurs de session disponibles sont configurés via $wgSessionProviders
.
Pour les détails, voir la documentation des fournisseurs de cette session globale et des sessions individuelles.
Les fournisseurs d'authentification disponibles sont configurés via $wgAuthManagerConfig
.
Pour les détails, voir la documentation des fournisseurs de cette authentification globale et des authentifications individuelles.
Pour gérer les opérations où l'on demande à l'utilisateur d'entrer son mot de passe actuel pour le confirmer, AuthManager nécessite que cet utilisateur se soit activement connecté récemment durant la session actuelle.
Pour configurer ce que l'on entend exactement par « récemment » , utilisez $wgReauthenticateTime
pour définir le temps maximum de chaque opération.
Pour déterminer ce qui se passe lorsque l'utilisateur utilise quelque chose comme OAuth où chaque requête est authentifiée individuelement et que se connecter n'est pas possible, utilisez $wgAllowSecuritySensitiveOperationIfCannotReauthenticate
.
En tant que consommateur
Sessions
Pour accéder à la session actuelle à partir de votre code, le mécanisme le plus simple est d'utiliser la méthode getSession()
sur votre objet WebRequest
.
L'objet MediaWiki\Session\Session
résultant possède des méthodes pour accéder aux données auxquelles dans le passé, vous auriez accédé en utilisant $webRequest->getSessionData()
et ->setSessionData()
ou directement en accédant à $_SESSION
.
Pour vérifier qu'une session est actuellement active à l'endroit où vous auriez utilisé précédemment un code comme session_id() !== ''
, récupérez l'objet Session et utilisez sa méthode ->isPersistent()
.
Pour vérifier que la session est persistante, récupérez-la et utilisez sa méthode ->persist()
au lieu de wfSetupSession()
.
Si vous devez accéder aux données session dans un contexte différent de celui d'une requête client, par exemple vous avez sauvegardé l'identifiant de la session pour exécuter une tâche en arrière plan et vous devez mettre à jour l'état dans les données session, utilisez MediaWiki\Session\SessionManager::singleton()->getSessionById()
.
Authentification
Si vous effectuez une action sensible à la sécurité qui demanderait traditionnellement le mot de passe de l'utilisateur pour vérification, utilisez MediaWiki\Auth\AuthManager::singleton()->securitySensitiveOperationStatus()
pour vérifier si l'utilisateur s'est authentifié suffisamment récemment et si nécessaire, redirigez-le par Special:UserLogin pour être ré-authentifié.
SpecialPage
peut gérer ceci pour vous si SpecialPage::getLoginSecurityLevel()
renvoie une valeur différente de false
.
En dehors de cela, la plupart des consommateurs de code n'auront pas besoin d'interagir directement avec AuthManager, car vous ne devriez pas vraiment avoir à implémenter votre propre flux d'authentification.
Pour déterminer si un utilisateur est connecté, utilisez les méthodes habituelles telles que getUser()
sur IContextSource
.
Pour savoir si un utilisateur est authentifié, laissez-le se connecter avec la méthode habituelle.
Mais si vous insistez vraiment: l'authentification dans AuthManager est un processus en plusieurs étapes semblable à ceci :
- Appeler
$authManager->canAuthenticateNow()
pour déterminer si l'authentification est même possible. - Appeler
$authManager->getAuthenticationRequests( AuthManager::ACTION_LOGIN )
pour déterminer les sous-classes AuthenticationRequest nécessaires; convertissez les en champs de formulaire et présentez-les à l'utilisateur. - Une fois que l'utilisateur a soumis le formulaire, utilisez
AuthenticationRequest::loadRequestsFromSubmission()
pour remplir les requêtes avec les données et passez-les à$authManager->beginAuthentication()
. - Les actions à entreprendre sont fonction de l'état de AuthenticationResponse:
- Pour l'interface utilisateur de l'état, convertir les demandes d'authentification AuthenticationRequests nécessaires en champs de formulaire, les présenter à l'utilisateur, et quand elles seront fournies, utiliser
AuthenticationRequest::loadRequestsFromSubmission()
pour remplir les nouvelles demandes avec les données et les passer à$authManager->continueAuthentication()
et gérer la nouvelle réponse. - Pour l'état REDIRECT, rediriger l'utilisateur vers l'URL spécifiée. Eventuellement l'utilisateur doit être redirigé sur une étape antérieure, dans laquelle les AuthenticationRequest doivent être remplis avec les données puis passés à
$authManager->continueAuthentication()
. - Pour l'état PASS, l'authentification a réussi.
- Pour l'état RESTART, l'authentification avec un service tiers a réussi mais ces informations ne sont pas associées à un compte local. A traiter soit comme UI ou FAIL.
- Pour l'état FAIL, l'authentification a échoué. La réponse peut contenir un AuthenticationRequest supplémentaire que vous pouvez passer dans
$authManager->beginAuthentication()
ou$authManager->beginAccountCreation()
pour préserver l'état.
- Pour l'interface utilisateur de l'état, convertir les demandes d'authentification AuthenticationRequests nécessaires en champs de formulaire, les présenter à l'utilisateur, et quand elles seront fournies, utiliser
Les processus sont similaires pour la création de compte et pour lier des données de connexion venant d'une partie tierce.
En tant que fournisseur
Si vous écrivez du code qui va fournir de nouvelles fonctionnalités pour SessionManager ou AuthManager, vous devez d'abord décider quel type de chose vous fournirez :
- Si vous implémentez une nouvelle façon de prendre un WebRequest et de déterminer l'utilisateur authentifié et les données de session à partir de celui-ci, vous devez implémenter
MediaWiki\Session\SessionProvider
.- Si vous faites quelque chose comme une connexion, un SessionProvider n'est pas ce qu'il vous faut. Vous souhaitiez probablement un PrimaryAuthenticationProvider.
- If you want to generically add additional checks to the process of getting a Session from a WebRequest, you'll likely want to look at the SessionMetadata and SessionCheckInfo hooks. Le premier permet d'ajouter des métadonnées supplémentaires à enregistrer avec la session, tandis que le second vous permet de voir les métadonnées d'un objet Session chargé et, si nécessaire, d'interdire son utilisation.
- Si vous implémentez une nouvelle façon de vous connecter, vous pouvez utiliser
MediaWiki\Auth\PrimaryAuthenticationProvider
.- Si ce que vous faites ne ressemble pas à une manière de se connecter mais plutôt est une nouvelle façon d'être simplement connecté comme le confirment les clients OAuth ou TLS client, vous ne voulez pas cela. Vous souhaitiez probablement un SessionProvider à la place.
- Si vous implémentez un nouveau contrôle que l'utilisateur doit passer avant de pouvoir se connecter, comme un CAPTCHA, vous pouvez utiliser
MediaWiki\Auth\PreAuthenticationProvider
. - Si vous implémentez une séquence qui doit se produire après la connexion, y compris le test d'un deuxième facteur, vous pouvez implémenter
MediaWiki\Auth\SecondaryAuthenticationProvider
.
Dans tous les cas, les fournisseurs sont construits en utilisant ObjectFactory
de $wgSessionProviders
ou $wgAuthManagerAutoConfig
et ont ensuite des dépendances injectées par les méthodes set.
SessionProvider
Documentation des classes : MediaWiki\Session\SessionProvider
Il existe principalement trois types de fournisseurs de sessions, basés sur deux capacités :
- La possibilité de sauvegarder n'importe quel ID de session généré aléatoirement, par rapport à l'ID basé sur les propriétés de la requête qui ne peuvent pas être modifiées.
- La possibilité d'être associé à tout utilisateur arbitraire qui se connecte, par rapport à avoir un utilisateur qui est intrinsèquement associé à la requête.
- Cette dernière propriété est parfois désignée comme rendant la session mutable (c'est à dire modifiable) par rapport à non mutable.
Les trois types résultants sont :
- Les fournisseurs qui peuvent enregistrer n'importe quel identifiant de session généré aléatoirement et peuvent également être associés à n'importe quel utilisateur arbitraire. Un exemple remarquable de cela sont les sessions traditionnelles basées sur les cookies.
- Il n'est pas nécessaire que le fournisseur fasse actuellement quelque chose pour sauvegarder l'identité de l'utilisateur; tant que l'identifiant de session est fourni, l'utilisateur peut être déterminé à partir des métadonnées enregistrées.
- Fournisseurs qui ont un utilisateur et un identifiant de session intrinsèquement associé à la requête. De bons exemples sont les certificats des clients OAuth et TLS : Les entêtes OAuth ou le certificat du client TLS sont dédiés à un utilisateur particulier et vous ne pouvez pas simplement les modifier arbitrairement pour les associer à un autre utilisateur.
- Fournisseurs qui ont un utilisateur intrinsèquement associé à la requête, mais pouvant enregistrer n'importe quel identifiant de session généré aléatoirement. Un exemple pourrait être l'authentification HTTP Digest qui utilise le champ opaque pour conserver l'identifiant de session.
- Vous pouvez souvent adopter une méthode avec un utilisateur intrinsèque et aucune capacité à enregistrer les identifiants de session générés aléatoirement et utiliser un cookie pour lui donner cette capacité; la classe de base
MediaWiki\Session\ImmutableSessionProviderWithCookie
implémente la partie cookie d'un tel fournisseur.
- Vous pouvez souvent adopter une méthode avec un utilisateur intrinsèque et aucune capacité à enregistrer les identifiants de session générés aléatoirement et utiliser un cookie pour lui donner cette capacité; la classe de base
Il est également possible d'avoir un fournisseur avec la capacité d'être associé à un utilisateur arbitraire quelconque mais n'ayant pas la capacité de sauvegarder un identifiant de session généré aléatoirement. Mais ceci ne semble pas avoir de sens particulier.
Un fournisseur de session fournit des sessions en renvoyant un objet MediaWiki\Session\SessionInfo
soit à partir de provideSessionInfo()
(pour la session associée à une WebRequest) ou de newSessionInfo()
(pour une nouvelle session non encore associée à aucune WebRequest).
Les propriétés de SessionInfo sont :
- La priorité de SessionInfo : si, par hasard, plusieurs fournisseurs trouvent les données de session dans la même requête, celle qui possède la plus haute priorité est utilisée. S'il y a un noeud, le gestionnaire de session génèrera une erreur. Généralement, un fournisseur utilisera toujours soit SessionInfo::MAX_PRIORITY (c'est-à-dire vous devez utiliser ce SessionInfo) ou prendra la priorité souhaitée comme paramètre pour son constructeur.
- ID de session. Il est normal pour un fournisseur de renvoyer SessionInfo sans fournir d'identifiant quand cela n'identifie pas un utilisateur.
- Indique si la requête identifie un utilisateur, et si cet utilisateur est authentifié ou simplement nommé. Utiliser les sessions basées sur les cookies comme exemple,
- « No user » (aucun utilisateur) se produit lorsque le cookie UserID ou UserName n'est pas présent dans la requête. L'utilisateur sera déterminé à partir des métadonnées de session enregistrées.
- « Unauthenticated user » (utilisateur non authentifié) se produit lorsque le cookie UserID ou UserName est présent, mais que le cookie de jeton « Token » est absent. Tous identifiant d'utilisateur ou son nom sont publiquement disponibles, donc sans le jeton, nous ne pouvons pas savoir que ce n'est pas une tentative de substitution.
- Cela vaut toujours la peine, puisque nous pouvons vérifier que les métadonnées de session enregistrées identifient le même utilisateur, d'empêcher quelqu'un d'utiliser un identifiant de session qui a expiré et uqi a été réaffecté à un utilisateur différent.
- « Authenticated user » (utilisateur authentifié) se produit lorsque le cookie UserID ou UserName est présent et que le cookie de jeton « Token » est également présent, et
hash_equals( $user->getToken(), $cookieToken )
renvoietrue
. Comme le jeton est supposé être secret, nous pouvons supposer qu'un jeton correct correspond à un utilisateur connu.- Les jetons qui viennent de la WebRequest doivent toujours être vérifiés à l'aide de
hash_equals
pour éviter les attaques de timing.
- Les jetons qui viennent de la WebRequest doivent toujours être vérifiés à l'aide de
- Il n'existe pas de cas où le cookie UserID ou le cookie UserName et le cookie Token sont présents, et que
hash_equals( $user->getToken(), $cookieToken )
renvoiefalse
. Si cela se produit, le fournisseur ne doit donner aucun SessionInfo.
- Indique si différents bits sont présents dans le WebRequest : l'ID de session, le jeton de l'utilisateur et le drapeau forceHTTPS.
- Toute métadonnée supplémentaire que le fournisseur souhaite associer à la session. Ceci est souvent utile si le fournisseur réalise aussi l'autorisation (droits OAuth) en plus de l'authentification.
Le fournisseur de session est également responsable de la persistance des sessions à une réponse web, ce qui se fait en appelant persistSession()
.
Si le fournisseur a la possibilité d'enregistrer les identifiants de session générés aléatoirement, il le fera ici.
S'il est capable de sauvegarder indépendamment l'identité de l'utilisateur, il doit toujours enregistrer l'identifiant ou le nom de l' utilisateur, mais ne doit enregistrer le jeton de l'utilisateur que si la méthode ->shouldRememberUser()
de la session renvoie true
.
Pour un comportement de mise en cache correct, le fournisseur de session doit utiliser getVaryHeaders()
et getVaryCookies()
pour indiquer les en-têtes de requête et les cookies qu'il utilise pour déterminer le SessionInfo.
Il doit fournir également des messages pour identifier ses sessions dans les messages d'erreur et pour renseigner sur la raison de ne pas maintenir les sessions lorsqu'elles devraient l'être (par exemple, parce que le navigateur est configuré pour rejeter les cookies).
PreAuthenticationProvider
Documentation des classes : MediaWiki\Auth\PreAuthenticationProvider, MediaWiki\Auth\AbstractPreAuthenticationProvider
Un fournisseur de pré-authentification peut fournir des champs pour le formulaire de connexion ou de création de compte et effectuer les contrôles lors d'une tentative de connexion ou de création de compte avant qu'une authentification réelle ne se produise. Par exemple, il peut limiter les tentatives de connexion par adresse IP ou présenter un CAPTCHA qui doit être résolu pour créer le compte.
PrimaryAuthenticationProvider
Documentation des classes : MediaWiki\Auth\PrimaryAuthenticationProvider, MediaWiki\Auth\AbstractPrimaryAuthenticationProvider
Un fournisseur primaire d'authentification est responsable de l'authentification de l'utilisateur actuel.
- Prendre les informations du formulaire de connexion, déterminer quel utilisateur essaie de se connecter et authentifier cet utilisateur.
- Vérifier que l'utilisateur créé sera capable de se connecter ultérieurement.
- Tester si un nom d'utilisateur existe déjà dans l'espace de stockage d'authentification du serveur.
- Modifier les données d'authentification associées à un utilisateur existant, ou ajouter et supprimer les associations avec les comptes des fournisseurs d'authentification tiers.
AuthManager peut être configuré pour utiliser plusieurs fournisseurs d'authentification primaire. Lors de la soumission initiale du formulaire, chaque fournisseur principal est à son tour essayé, et s'il renvoie un résultat ABSTAIN, le suivant est essayé jusqu'à ce que soit l'un de ces fournisseurs renvoie une réponse différente de ABSTAIN ou qu'il n'y ait plus de fournisseurs (dans ce cas, il génère un FAIL).
Le processus d'authentification pour un fournisseur se fait aussi en plusieurs étapes : les réponses autres que ABSTAIN comprennent le PASS et FAIL habituels, mais aussi UI pour présenter un formulaire de saisie supplémentaire à remplir par l'utilisateur et REDIRECT pour envoyer le navigateur vers des parties tierces qui vont éventuellement revenir en arrière et continuer le processus d'authentification.
SecondaryAuthenticationProvider
Documentation des classes : MediaWiki\Auth\SecondaryAuthenticationProvider, MediaWiki\Auth\AbstractSecondaryAuthenticationProvider
Un fournisseur d'authentification secondaire est appelé après que l'utilisateur ait été appelé par un fournisseur primaire. Par exemple, on peut demander un deuxième facteur pour une authentification multi-facteurs, demander à l'utilisateur de modifier son mot de passe, ou vérifier que l'utilisateur n'est pas bloqué. Les fournisseurs secondaires sont aussi appelés à la création du compte pour pouvoir intervenir et configurer l'authentification multi-facteurs.
AuthManager peut être configuré avec plusieurs fournisseurs d'authentification secondaires, auquel cas tous sont exécutés et doivent renvoyer PASS ou ABSTAIN pour que le processus d'authentification réussisse. Comme les fournisseurs principaux, ils peuvent répondre avec UI et REDIRECT pour interagir avec l'utilisateur.
Communication entre fournisseurs d'authentification
AuthManager fournit un support pour la communication entre les modules des fournisseurs pendant le processus d'authentification.
Par exemple, les fournisseurs d'authentification primaire basée sur le mot de passe qui ont le concept d'expiration du mot de passe peuvent appeler $this->getManager()->setAuthenticationSessionData( 'reset-pass', $data )
, ce qui fera que le fournisseur d'authentification secondaire MediaWiki\Auth\ResetPasswordSecondaryAuthenticationProvider
demandera à l'utilisateur de modifier son mot de passe.
Il appartient à chaque fournisseur de documenter les clés des données d'authentification qu'il utilise et quelles données il doit recevoir pour réaliser sa tâche.
Voir aussi
- Manual:SessionManager and AuthManager/Adding fields to the registration form
- Manual:SessionManager and AuthManager/Linked accounts
- Manual:SessionManager and AuthManager/Updating tips
- Manual:SessionManager and AuthManager/Troubleshooting
- Manual:SessionManager and AuthManager/SessionProvider examples
- Tâches démarrées : T89459, et la demande de commentaires originale (RFC).
Support du code
- Maintenu par MediaWiki Platform Team.
- Discussion en direct (IRC): #mediawiki-core connecter
- Suivi des problèmes : Phabricator mediawiki-auth (rapporter un problème)