Extension:CentralAuth/control flow
This is (hopefully) accurate as of April 2015, just before the SUL finalization. It was originally written as a set of notes for writing a patch, so it's not reader-friendly, and omits various details (the focus is on how user accounts and authentication data in the DB/sessions/memcache/cookies is handled), but should still be better than no documentation at all.
Registration flow
edit- user opens registration form on Special:UserLogin?type=signup; session cookie ({$wiki}Session) and CSRF token are set
- user posts the form; LoginForm::addNewAccount() (or LoginForm::addNewAccountMailPassword()) is invoked
- various checks (form validation, CSRF, IP blacklist, AbortNewAccount hook, throttling...)
- CentralAuth prevents registration via AbortNewAccount if the global account is not free
- AuthPlugin::addUser() is invoked
- CentralAuth adds a globaluser record, attaches local account
- user is written into user table, user_properties rows are added if needed, a bunch of hooks related to validation/change of User fields are invoked in the process)
- AuthPlugin::initUser() is invoked with autocreate=false
- user table is updated with hook/AuthPlugin changes
- password or email validation link is mailed, some further tweaking of user preferences might happen
- if this is a normal registration (not by another user, not with mailed password): user id and name are stored in session and cookie, login token is stored in session and user table, UserSetCookies hook is invoked
- CentralAuth removes login token from local session, stores global auth token in memcache and the globaluser table, stores session id and user name in second-level domain cookies
- RequestContext::$user is set
- AddNewAccount hook is invoked
- CentralAuth adds user name to localnames table
- various checks (form validation, CSRF, IP blacklist, AbortNewAccount hook, throttling...)
- if this is a normal registration and local session cookie is not set (ie. cookies disabled), redirect to Special:UserLogin?wpCookieCheck=new; LoginForm::onCookieRedirectCheck() is invoked, forces successful login with cookies enabled before process can continue
- if this is a normal registration, LoginForm::successfulLogin() is invoked, runs UserLoginComplete hooks
- CentralAuth does the login sequence
Login flow
edit- user opens login form on Special:UserLogin; session cookie and CSRF token are set
- user posts form, LoginForm::processLogin() is invoked
- various checks (CSRF, throttling...)
- run LoginUserMigrated hook
- CentralAuth uses this to abort login if the user has been renamed and tries to log in with the old name
- if there is no local user by that name, but login is valid for the global user, try to autocreate
- run AbortAutoAccount hook
- CentralAuth uses this, as above
- treat this as a registration, save user (as in the registration flow 2.3-2.5)
- run AbortAutoAccount hook
- log the user in
- run AbortLogin hook
- used by CentralAuth when user is renamed or globally locked
- more checks (password validation/expiration)
- run AuthPlugin::updateUser()
- CentralAuth uses this to replace the user object for migrated users and/or update the email address to keep in sync with the global one
- set RequestContext::$user
- run AuthPluginAutoCreate hook
- run LoginAuthenticateAudit hook
- set cookies (as in registration flow 2.7)
- renew local session id
- run AbortLogin hook
- final steps are same as for registration, from step 3
Logout flow
edit- run UserLogout hook
- CentralAuth clears the cookies on the second-level domain, deletes session from memcache, regenerates global login token in DB and memcache
- set user id to 0 in session
- clear session cookies (UserID, Token)
- run UserLogoutComplete hook
- CentralAuth displays icons for each second-level domain and for large standalone wikis, pointing to Special:CentralAutoLogin/deleteCookies on those wikis; for each of those requests:
- clear data for each domain/wiki, as in step 1.1
- CentralAuth displays icons for each second-level domain and for large standalone wikis, pointing to Special:CentralAutoLogin/deleteCookies on those wikis; for each of those requests:
CentralAuth login sequence
edit- invoked after successful logins/registrations from the UserLoginComplete hook, via CentralAuthHooks::doCentralLoginRedirect()
- store a random login attempt secret in the session
- store the login attempt secret and user details in memcache, under a random key (additional data can be added via CentralAuthLoginRedirectData hook)
- redirect to Special:CentralLogin/start?token={$key} on loginwiki, SpecialCentralLogin::doLoginStart() is invoked
- retrieves memcache data, looks up user
- if the user already has a full session on loginwiki, send back to Special:CentralLogin/status on the initiating wiki; SpecialCentralLogin::showLoginStatus() is invoked
- call PostLoginRedirect hook
- CentralAuth might use this to add a link to Special:SulRenameWarning
- show login success page with autologin icons
- call PostLoginRedirect hook
- create a stub session for the user with name/id, set User cookie, set empty Token cookie
- store session id and login attempt secret in memcache, under a random key
- run CentralAuthSilentLoginRedirect hook
- redirect to Special:CentralLogin/complete?token={$key} on the initiating wiki,
- fetch memcache data via token, validate login attempt secret, drop temporary session data
- update global session id in memcache (this will also replace the stub session with a full session, and load the global login token into it) and in second-level domain cookie
- set RequestContext::$user
- run CentralAuthPostLoginRedirect hook
- if this was a registration and centralauth-welcomecreation-msg exists, show it and show autologin icons
- otherwise set edge login flag in session and redirect to page given by returnTo
- PostLoginRedirect hook is invoked, can modify redirect _target
- on next page (via onBeforePageDisplay), unset flag and show autologin icons
CentralAuth autologin icons
edit- invoked via CentralAuthHooks::getDomainAutoLoginHtml() (visible favicons) or CentralAuthHooks::getEdgeLoginHTML() (invisible pixels)
- create a bunch of images referencing Special:CentralAutoLogin/start?from={$current_wiki} for each second-level domain (.wikipedia.org, .wikibooks.org etc) and for big multilang sites like meta, mw.org, Commons; for each of those requests:
- redirect to Special:CentralAutoLogin/checkLoggedIn?wikiid={$current_wiki} on loginwiki
- store global user id under a random memcache key (to do that, it will create the user object from the loginwiki session, thus verifying logged-in status)
- redirect to Special:CentralAutoLogin/createSession?token={$key} on the initiating wiki
- replace global user id in memcache with guid+wikiid under a new random key, store that key in the session
- redirect to Special:CentralAutoLogin/validateSession?token={$key}&wikiid={$current_wiki} on loginwiki
- pop guid+wikiid from memcache, validate them
- write user name, auth token, "central session id" (memcache key for auth data, stored in cookie) and misc data into memcache, under {$key}
- redirect to Special:CentralAutoLogin/setCookies on the initiating wiki
- get key from session which was stored in createSession step, use it to pop data from memcached
- verify guid-username match, validate auth token
- reset session, set username and global auth token in memcached, set username and maybe (depending on "remember me" pref) global auth token in second-level domain cookies
- set edge login flag in session (???)
- actually return the icon/pixel
- redirect to Special:CentralAutoLogin/checkLoggedIn?wikiid={$current_wiki} on loginwiki
- create a similar image for Special:CentralAutoLogin/refreshCookies?wikiid={$current_wiki} on loginwiki
- fetch "central session" data from memcached
- write the data into the second-level domain cookies
- create a bunch of images referencing Special:CentralAutoLogin/start?from={$current_wiki} for each second-level domain (.wikipedia.org, .wikibooks.org etc) and for big multilang sites like meta, mw.org, Commons; for each of those requests:
Loading user data
edit- from DB: when creating a UserArray, CentralAuth uses the UserArrayFromResult hook to extend the results; it looks up the users in the globaluser table, and sets $user->centralAuthObj to the global user object
- from session (invoked when RequestContext::$user is lazy-loaded): CentralAuth uses the UserLoadFromSession hook to replace normal logic
- try to get username and auth token from centralauth cookie, fall back to "central session" key in memcache; if both unsuccessful, abort and fall back to normal User logic
- load central user data from DB or memcache; if it does not exist/global auth token does not validate, abort and fall back to normal User logic
- load local user id
- abort and fall back to normal User logic if local id exists but local user is not attached
- if local user does not exist, try to autocreate it:
- check conditions (blocked, etc)
- run AbortAutoAccount hook
- add user to local DB
- run AuthPlugin::initUser()
- run AuthPluginAutoCreate hook
- CentralAuth will attach the local user to the global one
- otherwise load local user data from DB
- set up the session
- store the global auth token in the session; if it had a different token before, touch the user and invalidate its cache
- set $user->centralAuthObj to the central user object
CentralAuth actions on every pageview (via BeforePageDisplay)
edit- for anons with non-JS browsers: send a request to Special:CentralAutoLogin/start on the current wiki via an invisible autologin icon
- for anons with normal browsers:
- skip if CentralAuthAnon cookie or localStorage flag is set
- load a script from Special:CentralAutoLogin/checkLoggedIn?type=script&wikiid={$current_wiki} on loginwiki
- this will go through the steps of the CentralAuth autologin sequence until /setCookies on the local wiki, but return and execute some JS code instead of an icon
- if the login failed, set CentralAuthAnon localStorage or cookie flag
- try to autocreate the user (as in onUserLoadFromSession 5.1)
- if the local user is not attached, set CentralAuthAnon localStorage or cookie flag
- if there is a returnto url param, clear CentralAuthAnon from cookie and localstorage and redirect via JS
- otherwise, manipulate the DOM to make the page appear logged-in without a page reload, and add autologin icons for other sites
- for logged-in users:
- clear CentralAuthAnon from cookie and localstorage
- display autologin icons if the edge login session flag is set