Requests for comment/Service-oriented architecture authentication

Problem statement
With many more entry points and the need for inter-service authentication, a service-oriented architecture requires a stronger authentication system.

Goals

 * Single sign-on support
 * Support a relatively timely revocation of rights (minutes)
 * Minimize the risk & impact of exploits:
 * Principle of least privilege: for example, most services should not have direct access to sensitive user information (password hashes etc)
 * Minimize the risk of confused deputy attacks and attack surface by primarily trusting unforgeable user capabilities rather than services, and always checking capabilities at the lowest possible layer (example: storage service)
 * Be efficient for high request volumes (APIs)
 * No synchronous checking with other services required for common requests
 * Reads in particular; All on private wikis & all private user-specific info like notifications, watchlist, deleted revisions etc on public ones.
 * Small token size to minimize network overhead in particular for non-SPDY clients
 * Follow best security practices, use established standards & existing implementations
 * Support derivative and asynchronous requests like link updates
 * But don't allow them directly

Proposed implementation
A rough summary of what we (Chris & Gabriel) came up with.

We will start by phasing in the "Auth Service" as backend for CentralAuth. We can migrate pieces of CentralAuth to either use the existing code and db backend, or use the service, based on a configuration flag. This lets us move the most sensitive pieces to the new service while allowing us to revert quickly if we encounter unexpected problems.

The "Auth Service" will have two components:
 * The service will generate assertions about the MediaWiki user's identity. These assertions will be set in a user's cookie, and can be used by other services to identify the user. They will have a short validity period (< 1 minute), and should only be used by services that can tolerate a potentially out-of-date identity claim. E.g., having a token that allows read access to a private wiki for up to 1 minutes after the user logs out is acceptable, while the ability to edit should be able to be revoked in less than 1 minute.
 * The service will handle password-based authentication, so that password hashes can be moved from the main mediawiki database into one that has less access.

Implementation phases
Initially (phases 1-3), we will focus on identifying the user in other services, then (phased 4 & 5) moving the authentication (password and token verification) and session management into the service. We will use the MediaWiki plugins and hooks that CentralAuth already implements. This will hopefully ensure that changes to the authentication system in mediawiki (i.e., Requests_for_comment/AuthStack) integrates with our work, and other mediawiki auth backends could potentially use this Auth Service too.

Longer term, we would like the Auth Service to also handle authorization for mediawiki, but since this will require significant changes to core, we will delay specifying that now and may make that a separate RFC.

Phase 1: Signed JWTs in cookie, testing only

 * add capability to add a cookie with a signed JSON Web Token (JWT) as part of the CentralAuth session
 * Use static key initially, with key size to make this secure.
 * Validate this in services on request (check signature using public key & timestamp using JWT library)
 * this means that read requests for content accessible to the 'users' group could now be authenticated & authorized without sessions or db
 * if timed out, call authentication service API end point (likely part of core initially) with old token in order to get a fresh token & refresh the cookie with set-cookie header
 * don't rely on any of this in production yet

Phase 2: Key distribution from auth service

 * Distribute set of rolling public keys to services including MW core
 * in advance, by time range
 * signed by authentication service using long-lived service key
 * Widen testing, but not yet production

Phase 3: Support advanced operations in auth service

 * auth service provides end points and extension mechanisms for more complex authorization needs
 * End point to swap token against list of rights per wiki
 * ideally using existing libraries -- e.g. passport
 * Start use in production

Phase 4: Passwords and Token checking in service

 * Service will support setting and checking passwords, and CentralAuth will have the option of delegating those functions to the service.
 * Probably all of the global_user table data will be moved, so Locking/hiding, etc will be handled too?
 * Service will support generating and checking authentication tokens.
 * Possibly handling all session verification, and managing all session information?
 * Once this is reliably handling all authentication checks, we can remove passwords and tokens from the centralauth database
 * The Auth Service is the only code with access to CentralAuth's security-critical data

Phase 5: Groups and wiki associations moved to service

 * Global groups (and wikisets), and account attachments (if still relevant after SUL finalization?) are moved into the service.

Phase 6: Use auth service exclusively

 * auth service becomes the only service with access to sensitive user data
 * Ability to execute SQL in random code doesn't imply access to user table any more
 * used by both MW core & services
 * remove session cookie

Security implications
For the identity assertions we will use a JSON Web Token (JWT) (or a more general JWS structure if needed) for the assertion
 * We will use rsa or ecdsa signatures that provide about 120 bits (~2048 bit rsa key) of security for short-lived signing keys, or 140 bits (~4096 bit key) for long-lived keys.
 * This will theoretically decrease the amount of work an attacker needs to perform to impersonate a user without knowing the user's cookies. Currently we use 256 random bits (256 bits of security), but 2048 bit rsa keys are currently considered to be safe for the next 5-10 years.

Status quo
The MediaWiki PHP codebase performs all authentication and authorization checks internally.

It provides:
 * Account creation and autocreation
 * Authentication (password, or plugin based)
 * Authorization / session management
 * Sets up the appropriate User object (e.g., $wgUser) for each request, before MediaWiki processes the request
 * MediaWiki uses the User object for most code that determine authorization
 * The User object tracks if the user has been blocked, and can validate anti-CSRF tokens for the user's session
 * Logout (destroy the session)

This RFC is about handling these tasks in a service with a well-defined interface.