Hi all (sorry for the duplicate Gabriel),
I was going to send this to wikitech, but I wanted to get an internal opinion. We may have this documented already, but I haven't managed to find it.
tl;dr: As I'm looking at authentication for whatever "SOA" plans we have, the basic structure of how we design things will influence the best way to do authn/z. If you have strong feelings one way or the other, speak up so we can plan for it.
I wanted to get some clarity around what "SOA" means to us and our community. Aaron asked the question during the SOA kickoff, something like is everyone comfortable with making the endpoints public. I don't think there was much discussion or consensus (or I may have missed it). When I talked with Owen and Gabriel afterward, it seems like there were two definitions of "SOA" that we're dealing with:
* Hidden services: e.g., a user gets an edit page, and does an HTTP POST with action=edit, a session cookie to identify themselves, an anti-csrf token. The wiki gets the request, then calls a service to check the edit text for spam, gives the edit to a revision storage service that stores the revision, maybe generates an event that a logging service picks up and stores in the general and checkuser logs.
* Public services: A user gets an edit page from the wiki, then submits the edit to the revision service directly. The revision service may call the spam-detection service, or use a service for csrf tokens. The success / failure is passed back to the user's browser, and the edit page lets the user know the save happened, and probably shows the user the new version of the page.
Parsoid, iirc, is moving towards the later definition. Wikia is mostly looking at the first.
The answer I'm expecting is we need "both", and the distinction is probably really only important when we decide how identification and authorization work. But I want to make sure we make that decision consciously instead of accidentally.
The first case has a more straightforward implement for authentication, and I would argue is easier to secure. Http-only cookies are set and included with each call to identify the user's session. These can't be stolen via xss, and we can centrally invalidate all sessions. We have one place to check if a nonce has been used (e.g. with OAuth), and have common code for checking csrf tokens and logging.
Having a public service handle processing a user's edit would require the service to check session invalidation and nonce use, and correctly handle checking csrf tokens.
If we go the public route, we would need to decide if the various services should run on the same domain (en.wikipedia.or/revision/whatever), same top level domain (revision.wikipedia.org/whatever), or entirely different domain (revision.wikimedia.org). The same top-level domain would only work if all subdomains have the same idea of the user (at the WMF, that would mean all users are CentralAuth/global users). A different domain means either users have to go through a login process to get authentication cookies on that domain (like we use for login.wikimedia.org), or the authentication tokens have to be accessible to javascript (and vulnerable to being stolen via xss attacks). So I have a strong preference for same domain.
Does anyone have strong plans / ideas for the overall direction we want to take here?
On Wed, Apr 30, 2014 at 11:41 AM, Chris Steipp csteipp@wikimedia.org wrote:
Hi all (sorry for the duplicate Gabriel),
I was going to send this to wikitech, but I wanted to get an internal opinion. We may have this documented already, but I haven't managed to find it.
tl;dr: As I'm looking at authentication for whatever "SOA" plans we have, the basic structure of how we design things will influence the best way to do authn/z. If you have strong feelings one way or the other, speak up so we can plan for it.
I wanted to get some clarity around what "SOA" means to us and our community. Aaron asked the question during the SOA kickoff, something like is everyone comfortable with making the endpoints public. I don't think there was much discussion or consensus (or I may have missed it). When I talked with Owen and Gabriel afterward, it seems like there were two definitions of "SOA" that we're dealing with:
- Hidden services: e.g., a user gets an edit page, and does an HTTP POST
with action=edit, a session cookie to identify themselves, an anti-csrf token. The wiki gets the request, then calls a service to check the edit text for spam, gives the edit to a revision storage service that stores the revision, maybe generates an event that a logging service picks up and stores in the general and checkuser logs.
- Public services: A user gets an edit page from the wiki, then submits the
edit to the revision service directly. The revision service may call the spam-detection service, or use a service for csrf tokens. The success / failure is passed back to the user's browser, and the edit page lets the user know the save happened, and probably shows the user the new version of the page.
Parsoid, iirc, is moving towards the later definition. Wikia is mostly looking at the first.
The answer I'm expecting is we need "both", and the distinction is probably really only important when we decide how identification and authorization work. But I want to make sure we make that decision consciously instead of accidentally.
The first case has a more straightforward implement for authentication, and I would argue is easier to secure. Http-only cookies are set and included with each call to identify the user's session. These can't be stolen via xss, and we can centrally invalidate all sessions. We have one place to check if a nonce has been used (e.g. with OAuth), and have common code for checking csrf tokens and logging.
Having a public service handle processing a user's edit would require the service to check session invalidation and nonce use, and correctly handle checking csrf tokens.
If we go the public route, we would need to decide if the various services should run on the same domain (en.wikipedia.or/revision/whatever), same top level domain (revision.wikipedia.org/whatever), or entirely different domain (revision.wikimedia.org). The same top-level domain would only work if all subdomains have the same idea of the user (at the WMF, that would mean all users are CentralAuth/global users). A different domain means either users have to go through a login process to get authentication cookies on that domain (like we use for login.wikimedia.org), or the authentication tokens have to be accessible to javascript (and vulnerable to being stolen via xss attacks). So I have a strong preference for same domain.
Does anyone have strong plans / ideas for the overall direction we want to take here?
I would advocate designing all services such that they are ready to be used externally even if they are initially firewalled or proxied. I agree that making "internal only" service interfaces is much easier but over the longer term it becomes very likely that some things that were built to be internal only will be found to be useful to expose directly to the outside world. In my experience it is much trickier to graft a robust auth layer onto a service that already has multiple internal consumers than it is to build this feature into a service from the start.
Bryan
(re-send after joining the core list)
Chris & Bryan,
On 04/30/2014 10:58 AM, Bryan Davis wrote:
I would advocate designing all services such that they are ready to be used externally even if they are initially firewalled or proxied. I agree that making "internal only" service interfaces is much easier but over the longer term it becomes very likely that some things that were built to be internal only will be found to be useful to expose directly to the outside world. In my experience it is much trickier to graft a robust auth layer onto a service that already has multiple internal consumers than it is to build this feature into a service from the start.
I completely agree with this. Relying on consistent access right checking in a variety of front-ends is a brittle solution. Any exploit in one of those front-ends has potentially nasty consequences.
Here is a sketch of an authentication system that's a bit more robust, and potentially also more efficient:
* the authentication service is the only service with access to passwords and other sensitive user info
* users retrieve signed and time-limited tokens from the authentication service, for example using OAuth2; these could be transmitted using HTTP-only cookies
* most other services have no built-in privileges; they merely pass on tokens provided by users to backend services. This reduces the risk of confused deputies and helps to limit the potential impact of exploits.
* tokens ideally encode the most common rights and are signed (example: JSON web tokens in Oauth2). This allows backend services to verify their validity by checking the signature & time without needing to call back into the authentication service. More complex rights are handled by calling back into the auth service.
* all authenticated client connections are encrypted with TLS
I have started to draft an RFC on this at [2]. Please chime in if you are interested.
Gabriel
[1]: https://www.mediawiki.org/wiki/Requests_for_comment/Content_API [2]: https://www.mediawiki.org/wiki/Requests_for_comment/SOA_Authentication
mediawiki-core@lists.wikimedia.org