I'm working with a network of sites currently around 30 that will be expanding into the hundreds. Since each retrieving site has a different domain, to use Key authentication, I will need a different API key for each domain accessing the central content distribution site.
This issue exists because content_retriever.module's _content_retriever_xmlrpc_key_args() wants to determine $domain based on environmental data, such as the SERVER_NAME. While this may often be a fine behavior, my scenario warrants a different setup wherein each retriever site could have a domain configured manually (or in my case, via configuration scripts).
I do not believe this arrangement results in any less security. If I needed hundreds of API keys, compromise of a single one of them would be the same as compromising all of them, since they must all be configured in an identical manner.
I propose that there be a new configuration option available on the connection settings tab of the content retriever configuration where the API domain may be configured. API calls would be made with this domain to form the hash. If left blank, content_retriever would use the current method of determining the domain to use for the API call.
Patch forthcoming.
| Comment | File | Size | Author |
|---|---|---|---|
| #1 | content_distribution-821700.patch | 3 KB | Josh Benner |
Comments
Comment #1
Josh Benner commentedPatch for described changes attached here.
Comment #2
Josh Benner commentedComment #3
joachim commentedI'm not sure this'll work, as Services module always looks at the domain the request is coming from to figure out the key.
Comment #4
Josh Benner commentedActually, the domain is more like a user name, and services does not automatically try to determine the domain. Rather, the call to the service includes the domain as a parameter.
services_keyauth.inc, near line 184 begins _services_keyauth_authenticate_call(), which is triggered to validate the credentials used to make the API call. You'll see that the hash, as well as its component parts (domain, timestamp, nonce) are all sent as parameters of the call (also evidenced by the guide for calling a service with an API key: http://drupal.org/node/774298).
Furthermore, near line 113 of services_keyauth.module, function services_get_hash() (which is called by _services_keyauth_authenticate_call()) takes the domain as an argument, which it uses to determine which api_key to use in generating the hash.
This is done because the requests cannot be expected to always come from a normal domain. For instance, if I have a calendar site, and I want to build an iPhone application that uses my API to display calendar entries in the iPhone app, the domain would not be predictable for requests from each iPhone. Same thing for desktop applications, flash applications (which are executed on the client), JavaScript, etc.
Comment #5
joachim commentedUh.... so what's the point of the domain API key? I thought it was to give an extra layer of security so the API key only allows a call from a particular domain. If that can be spoofed... ?!?!
Comment #6
greg.harveyJosh is right and yes, domain is pointless when it comes to authentication really. I suspect at some point there's an intention to make that cleverer with the Services team. At the moment it compares your domain to the stored value, which is silly. To my mind, the Services module should read the referrer information and use that to check your hash. Still spoofable, but much more difficult to spoof.
So, question is, do we accept this patch (thus relying on a quirk/hole in the Services module) or do we raise a bug with the Services team and reject this patch on the basis that spoofing the domain should *not* be possible, and that it *is* possible is rather an academic point...?
If we do the former, we'll have to be on our toes if/when Services is fixed.
Comment #7
Josh Benner commentedCertainly not a bad idea to get the Services guys' input on this. I've attempt to drum up some discussion: #830252: Domain not checked against caller origin
Comment #8
joachim commentedWell based on the response from heyrocker at that issue, I guess we can go ahead and make this change here.
When key authentication goes to a separate module we'll have to figure out how to do authentication here -- and this may change at that point to be done via Clients module anyway.
Comment #9
joachim commentedOk I've tested this by making the following changes to the master site's services API key settings and the retriever site's retriever settings domain field that this patch adds, and then testing the user login on the manual control page.
- setting the same arbitrary domain string in both: user logs in ok.
- setting different arbitrary string: log in fails
- setting master back to the original setting, and setting the retriever's value to blank: user logs in ok.
All works as expected. Committed with minor whitespace and comment tweaks. Thanks!
#821700 by Josh Benner: Added configurable API key domain on retriever rites.