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

  1. user opens registration form on Special:UserLogin?type=signup; session cookie ({$wiki}Session) and CSRF token are set
  2. user posts the form; LoginForm::addNewAccount() (or LoginForm::addNewAccountMailPassword()) is invoked
    1. various checks (form validation, CSRF, IP blacklist, AbortNewAccount hook, throttling...)
      1. CentralAuth prevents registration via AbortNewAccount if the global account is not free
    2. AuthPlugin::addUser() is invoked
      1. CentralAuth adds a globaluser record, attaches local account
    3. 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)
    4. AuthPlugin::initUser() is invoked with autocreate=false
    5. user table is updated with hook/AuthPlugin changes
    6. password or email validation link is mailed, some further tweaking of user preferences might happen
    7. 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
      1. 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
    8. RequestContext::$user is set
    9. AddNewAccount hook is invoked
      1. CentralAuth adds user name to localnames table
  3. 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
  4. if this is a normal registration, LoginForm::successfulLogin() is invoked, runs UserLoginComplete hooks
    1. CentralAuth does the login sequence

Login flow edit

  1. user opens login form on Special:UserLogin; session cookie and CSRF token are set
  2. user posts form, LoginForm::processLogin() is invoked
    1. various checks (CSRF, throttling...)
    2. run LoginUserMigrated hook
      1. CentralAuth uses this to abort login if the user has been renamed and tries to log in with the old name
    3. if there is no local user by that name, but login is valid for the global user, try to autocreate
      1. run AbortAutoAccount hook
        1. CentralAuth uses this, as above
      2. treat this as a registration, save user (as in the registration flow 2.3-2.5)
    4. log the user in
      1. run AbortLogin hook
        1. used by CentralAuth when user is renamed or globally locked
      2. more checks (password validation/expiration)
      3. run AuthPlugin::updateUser()
        1. 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
      4. set RequestContext::$user
      5. run AuthPluginAutoCreate hook
      6. run LoginAuthenticateAudit hook
      7. set cookies (as in registration flow 2.7)
      8. renew local session id
    5. final steps are same as for registration, from step 3

Logout flow edit

  1. run UserLogout hook
    1. CentralAuth clears the cookies on the second-level domain, deletes session from memcache, regenerates global login token in DB and memcache
  2. set user id to 0 in session
  3. clear session cookies (UserID, Token)
  4. run UserLogoutComplete hook
    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:
      1. clear data for each domain/wiki, as in step 1.1

CentralAuth login sequence edit

  1. invoked after successful logins/registrations from the UserLoginComplete hook, via CentralAuthHooks::doCentralLoginRedirect()
    1. store a random login attempt secret in the session
    2. store the login attempt secret and user details in memcache, under a random key (additional data can be added via CentralAuthLoginRedirectData hook)
  2. redirect to Special:CentralLogin/start?token={$key} on loginwiki, SpecialCentralLogin::doLoginStart() is invoked
    1. retrieves memcache data, looks up user
    2. if the user already has a full session on loginwiki, send back to Special:CentralLogin/status on the initiating wiki; SpecialCentralLogin::showLoginStatus() is invoked
      1. call PostLoginRedirect hook
        1. CentralAuth might use this to add a link to Special:SulRenameWarning
      2. show login success page with autologin icons
    3. create a stub session for the user with name/id, set User cookie, set empty Token cookie
    4. store session id and login attempt secret in memcache, under a random key
    5. run CentralAuthSilentLoginRedirect hook
  3. redirect to Special:CentralLogin/complete?token={$key} on the initiating wiki,
    1. fetch memcache data via token, validate login attempt secret, drop temporary session data
    2. 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
    3. set RequestContext::$user
    4. run CentralAuthPostLoginRedirect hook
    5. if this was a registration and centralauth-welcomecreation-msg exists, show it and show autologin icons
    6. otherwise set edge login flag in session and redirect to page given by returnTo
      1. PostLoginRedirect hook is invoked, can modify redirect target
      2. on next page (via onBeforePageDisplay), unset flag and show autologin icons

CentralAuth autologin icons edit

  1. invoked via CentralAuthHooks::getDomainAutoLoginHtml() (visible favicons) or CentralAuthHooks::getEdgeLoginHTML() (invisible pixels)
    1. 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:
      1. redirect to Special:CentralAutoLogin/checkLoggedIn?wikiid={$current_wiki} on loginwiki
        1. 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)
      2. redirect to Special:CentralAutoLogin/createSession?token={$key} on the initiating wiki
        1. replace global user id in memcache with guid+wikiid under a new random key, store that key in the session
      3. redirect to Special:CentralAutoLogin/validateSession?token={$key}&wikiid={$current_wiki} on loginwiki
        1. pop guid+wikiid from memcache, validate them
        2. write user name, auth token, "central session id" (memcache key for auth data, stored in cookie) and misc data into memcache, under {$key}
      4. redirect to Special:CentralAutoLogin/setCookies on the initiating wiki
        1. get key from session which was stored in createSession step, use it to pop data from memcached
        2. verify guid-username match, validate auth token
        3. 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
        4. set edge login flag in session (???)
        5. actually return the icon/pixel
    2. create a similar image for Special:CentralAutoLogin/refreshCookies?wikiid={$current_wiki} on loginwiki
      1. fetch "central session" data from memcached
      2. write the data into the second-level domain cookies

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
    1. 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
    2. 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
    3. load local user id
    4. abort and fall back to normal User logic if local id exists but local user is not attached
    5. if local user does not exist, try to autocreate it:
      1. check conditions (blocked, etc)
      2. run AbortAutoAccount hook
      3. add user to local DB
      4. run AuthPlugin::initUser()
      5. run AuthPluginAutoCreate hook
        1. CentralAuth will attach the local user to the global one
    6. otherwise load local user data from DB
    7. set up the session
    8. store the global auth token in the session; if it had a different token before, touch the user and invalidate its cache
    9. 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:
    1. skip if CentralAuthAnon cookie or localStorage flag is set
    2. load a script from Special:CentralAutoLogin/checkLoggedIn?type=script&wikiid={$current_wiki} on loginwiki
    3. 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
    4. if the login failed, set CentralAuthAnon localStorage or cookie flag
    5. try to autocreate the user (as in onUserLoadFromSession 5.1)
    6. if the local user is not attached, set CentralAuthAnon localStorage or cookie flag
    7. if there is a returnto url param, clear CentralAuthAnon from cookie and localstorage and redirect via JS
    8. 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:
    1. clear CentralAuthAnon from cookie and localstorage
    2. display autologin icons if the edge login session flag is set