TL;DR - I need to supply credentials for a server getting a _replicate request in communicating with the remote server it's to replicate with. But if these credentials are ignored bad things (TM) can happen. Is there any sane way to avoid this?
This is a request for guidance. Scenario: Client application A sends a POST request to http://a.com/_replicate asking a.com to replicate with b.com. b.com will only accept CouchDB REST requests if they are properly authenticated. Client application A has the credentials it wishes a.com to use when it communicates with b.com Question: How should Client application A provide the credentials to a.com so that a.com can use them when communicating with b.com? Who Cares?: Normally I wouldn't bother bringing something like this to this group. I would just implement something. See if it works and if it looks useful then come and suggest maybe we adopt it. But this scenario has a very particular problem that I think justifies bringing it to this group. The problem is that in general in JSON land if one gets arguments one doesn't recognize then one ignores them. This is usually a very healthy thing to do (be generous in what you accept and all that). But in security contexts it tends to lead to attacks. For example, imagine that Client application A sends the _replicate request and includes replication credentials. Now imagine that a.com doesn't recognize the JSON arguments used to move the credentials. Several unpleasant things can happen. Credentials get logged - Depending on a.com's code it might log all of its _replicate requests (quite reasonable and wickedly useful for debugging). Not recognizing that it had been sent credentials those credentials are now in the log! Data corruption - Imagine that b.com gives different responses to CouchDB requests based on the identity of the caller (e.g. they use views, for example). Client A thinks that a.com is making a request using the identity it supplied but in fact a.com makes its requests without any authentication. b.com in this case will respond but only with information that unauthenticated callers are allowed to see. So in essence Client A expects to see one thing and is going to get another. Never a happy situation. Leaked Identity - It may be that in fact a.com has credentials that it knows to use with b.com. But it turns out that client A doesn't want a.com to use those particular credentials because they would leak an identity that client A doesn't want b.com to know about. That's why Client A sent different credentials to use. But not recognizing Client A's request a.com uses the default credentials and leaks an identity. So now what?: My suspicion is that we need some way to mark that arguments in a request are 'must understand'. Of course, as the HTTP folks found out a long time ago, it's impossible to retroactively introduce 'must understand' in any way that anyone is willing to support (anybody remember the M- HTTP methods?). We could try discovery (OPTIONS the last gasp of the desperate) to see what the server supports. Another possibility is a sad one but basically we could create a completely new _replicate request body that will be failed by anyone who doesn't understand it. Of course this requires updating every couchdb client library on the planet. Another alternative is to introduce a new endpoint (_replicate2?). As near as I can tell all options suck. I suspect what I'll do is just introduce a new authentication value into the JSON request body for _replicate and hope I don't talk to the wrong end points. :( Suggestions are heartily requested! Thanks, Yaron P.S. Wait, should you really be sending credentials across the wire??!?!?!! It depends. The project I'm working on, https://thali.codeplex.com , would actually have a mutual SSL auth connection between Client application A and a.com. Inside the _replicate request body would be the public key of the identity that client A wants a.com to use in talking to b.com. In this case a.com is actually client A's personal server and it stores relevant credentials. Once a.com confirms that the requester is client A and that client A is authorized to make _replicate requests to b.com using the specified credential ID then the replicate would happen. Note that no actual credentials hit the wire. Client A only sends the ID of the credentials it wants a.com to use because a.com is the keeper of the actual credentials. But I can easily imagine other scenarios where client A might provide something like a bearer token. So long as the connection between client A and a.com is over SSL moving a limited lifetime bearer token isn't so bad. But imagine that b.com uses something like basic auth (presumably over SSL). Now what? One suspects that in that case the only sane thing to do (assuming the client A and a.com have an extremely tight relationship) is for client A to just provide the name and password over SSL to a.com who would then use it (also over SSL) with b.com. Not ideal but not unreasonable so long as client A and a.com have a high trust relationship.
