couchdb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Yaron Goland <yar...@microsoft.com>
Subject Standardizing providing authentication credentials/ids in _replicate requests
Date Thu, 01 May 2014 17:51:57 GMT
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.

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message