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.

Reply via email to