Replication with CouchDb per-user-database using CORS

1,225 views
Skip to first unread message

Paul Weber

unread,
Aug 7, 2013, 4:02:28 AM8/7/13
to pou...@googlegroups.com
I am getting a "401 Unauthorized" error when trying to sync PouchDb with a local CouchDb. It looks like the header {'Authorization',"Basic myBase64Credentials"} is never being set. 

I am using this function to sync:
function sync() {
   var opts = {continuous: true};
   db.replicate.to(http://testuser:testuserPassword@localhost:5984, opts);
   db.replicate.from(http://testuser:testuserPassword@localhost:5984, opts);
}

My setup:
pouchdb.nightly - 2013-07-31T02:01:34 is served from http://localhost:5000
CouchDb 1.3.0 is running on http://localhost: 5984

HOST="http://admin:password@localhost:5984"
CouchDb CORS configuration:
curl -X PUT $HOST/_config/httpd/enable_cors -d '"true"'
curl -X PUT $HOST/_config/cors/origins -d '"http://localhost:5000"'
curl -X PUT $HOST/_config/cors/credentials -d '"true"'
curl -X PUT $HOST/_config/cors/methods -d '"GET, PUT, POST, HEAD, DELETE"'
curl -X PUT $HOST/_config/cors/headers -d '"accept, authorization, content-type, origin"'

CouchDb Per-user-database setup:
curl -X POST $HOST/_users -d '{"_id":"org.couchdb.user:testuser","type":"user","name":"testuser","roles":[],"password": "testuserPassword"}' -H "Content-Type: application/json"
curl -X PUT $HOST/testdb
curl -X PUT $HOST/testdb/_security -d '{"admins":{"names":[], "roles":[]}, "readers":{"names":["testuser"],"roles":[]}}'

Isidro Vila Verde

unread,
Aug 9, 2013, 6:23:04 AM8/9/13
to pou...@googlegroups.com
I found PouchDB a few weeks ago and that occasion I read the getting start and found something like this

var mydb;
Pouch('idb://invoicesDB', function(err, db) {
            if (err) {
                console.log(err);
            }else {
                mydb = db;
                db.allDocs(function(err, response) {
                    if (err) {
                        console.log(err);
                    }else {
                        console.log('response',response.rows);
                       //do something
                    }
                });
            }
}


But yesterday when I tried it again I found there is no Pouch method and reading the documentation again I see we must open database as this

var mydb = new PouchDB('idb://invoicesDB');

This means the PoucDB is now synchronous? If so can I obtain all documents immediately?

var mydb = new PouchDB('idb://invoicesDB');

mydb.allDocs(function(err, response) {
  if (err) {
    console.log(err);
  }else {
    console.log('response',response.rows);
    //do something
  }
};

Nevertheless I try to pass a callback to the new constructor PoucDB and it still call it, but that is omitted in the API. So what is the situation? Is something missing in the API documentation or can we assume the
synchronous operation? I know, at start of API documentation it is stated "Most of the PouchDB API is exposed as fun(arg, [options], [callback])", but also states "new PouchDB([name], [options])" for create a database.

Thank you

Isidro
 

 

Dale Harvey

unread,
Aug 9, 2013, 6:35:55 AM8/9/13
to pou...@googlegroups.com
Hey Isidro

1. |Pouch()| vs new |PouchDB()| these are identical calls, |new Pouch()| would have previously worked, the constructor was added to make the documentation clearer that it was a new instance being created, PouchDB as a namespace was added to make the naming more consistent, at some point we will get rid of |Pouch| so its recommended to use PouchDB

2. The synchronous constructor was added to make a nicer api, some frameworks depend on having a synchronous constructor and in general it makes for much nicer code, it is still doing the same work behind the scenes in that it when you call a function on the database it will wait for the db construction to complete behind the scenes, you can use these independently I just didnt document the old method as I didnt see any reason to use it

Cheers for the questions
Dale




--
You received this message because you are subscribed to the Google Groups "PouchDB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pouchdb+u...@googlegroups.com.
To post to this group, send email to pou...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pouchdb/5204C308.20600%40gmail.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Isidro Vila Verde

unread,
Aug 9, 2013, 6:45:13 AM8/9/13
to pou...@googlegroups.com
Thank you Dale,  for your quick answer.

So the recommendation is for not using a callback in the construct as it is synchronous and as so the callback does not make sense anymore!?

Thank you for you time.

Isidro

Dale Harvey

unread,
Aug 9, 2013, 7:14:49 AM8/9/13
to pou...@googlegroups.com
I would suggest using it as shown on the front page
    var db = new PouchDB('dbname');

    db.allDocs(....
Unless you have any particular reason not to, 

Cheers, Dale



Isidro Vila Verde

unread,
Aug 9, 2013, 7:16:38 PM8/9/13
to pou...@googlegroups.com
Is there any chance, in a near future, to have something like this:

db.query({map: map}, {reduce: false, key: somekey }, function(err, response) { });

or even 

db.query({map: map}, {reduce: false, startkey: firsKey, endkey: lastKey}, function(err, response) { });


Thanks

Isidro

 

Isidro Vila Verde

unread,
Aug 9, 2013, 7:27:38 PM8/9/13
to pou...@googlegroups.com
Sorry. I just try it and it works. GREAT!


Isidro
Message has been deleted

Paul Weber

unread,
Aug 19, 2013, 3:26:55 AM8/19/13
to pou...@googlegroups.com
Any ideas considering my original question "Replication with CouchDb per-user-database using CORS"? Do I miss something obvious? Did anybody get replication with a non public CouchDb database via CORS to work?

Giovanni P

unread,
Aug 19, 2013, 5:43:33 AM8/19/13
to pou...@googlegroups.com
you're tryng to replicate to the server, you should write the the name of the database.

db.replicate.to(http://testuser:testuserPassword@localhost:5984/testdb, opts);


--
You received this message because you are subscribed to the Google Groups "PouchDB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pouchdb+u...@googlegroups.com.
To post to this group, send email to pou...@googlegroups.com.

Paul Weber

unread,
Aug 19, 2013, 11:24:56 AM8/19/13
to pou...@googlegroups.com, fia...@gmail.com
Yes, you are right. I am actually using the database name when I replicate to the server. I only forgot it in the example code that I posted here.

nrw

unread,
Sep 10, 2013, 3:58:33 AM9/10/13
to pou...@googlegroups.com, fia...@gmail.com
I'm experiencing the same issue.

This fails with a 401:

db.replicate.to(http://testuser:testuserPassword@localhost:5984/testdb, opts)

No "Authentication" header is set on the request.

I wasn't able to sync without using cookie auth from the cors tests. https://github.com/daleharvey/pouchdb/blob/master/tests/test.cors.js#L77

Should syncing with the server work with a password in the url?

-NRW

Giovanni P

unread,
Sep 10, 2013, 5:56:45 AM9/10/13
to nrw, pou...@googlegroups.com
Did you really tried without the quotes? You should put quotes around the name/url of the db (unlike me).
But, assuming you did it, are this user really authorized to perform these activities? Can you see the CouchDB logs?

I got replication working with a non public CouchDb database via CORS here without a problem.
I wish I could reproduce your error.

Nicholas Westlake

unread,
Sep 10, 2013, 9:31:28 PM9/10/13
to pou...@googlegroups.com, nrw, fia...@gmail.com
I failed to copy the mailing list on my reply. here's what happened:

------------------------------
Nicholas Westlake:

Yes i have quotes. Yes the user has permissions.

An identical replicate request works with curl, but not with pouch.

I started couchdb with the log level at "debug". I see that Pouch does not set the Authentication header in the replication request. There is also a preflight request that omits the Authentication header.

The Authentication header should be set, correct?

-NRW

-----------------------------
Giovanni Parra:

I don't see any Authentication header here.

Ok, I was fooled by the cookie magic. I had an 'AuthSession' cookie, that's why it was working. I think I got it from logging into CouchDB manually, in the browser, and then my app started to work forever, even with Pouch effectively wiping out the auth part of the url in each of its requests. I think it is a bug. Let's try to fix it.

Nicholas Westlake

unread,
Sep 10, 2013, 9:32:56 PM9/10/13
to pou...@googlegroups.com, nrw, fia...@gmail.com

Giovanni P

unread,
Sep 10, 2013, 10:06:08 PM9/10/13
to Nicholas Westlake, pou...@googlegroups.com

Paul Weber

unread,
Sep 19, 2013, 3:43:49 AM9/19/13
to pou...@googlegroups.com
I took another look at the authentication problem using pouchdb.nightly - 2013-08-25T17:29:48. To me it also looks like a bug in the HttpPouch function (https://github.com/daleharvey/pouchdb/blob/master/src/adapters/pouch.http.js).

I changed the URL of the remote database to "https://testdb.iriscouch.com/testdb" in the following examples because that's what I eventually what to do. PouchDb is served from "http://localhost:5000".

Solution 1:
var opts = {auth: {username: 'testuser', password: 'testuserPassword'}};

This doesn't work because opts.auth is always undefined in the HttpPouch function and therefor host.headers.Authorization is never being set.

Solution 2: 

This only works if you add the following code to the HttpPouch function as Giovanni Parra suggested:

if (host.auth) {
   var token = PouchUtils.btoa(host.auth.username + ':' + host.auth.password);
   host.headers.Authorization = 'Basic ' + token;
}

Solution 3: 
Using cookies doesn't work for me either when I try to replicate my PouchDb served from "http://localhost:5000" to "testdb.iriscouch.com/testdb". How do I let PouchDb use a cookie from "testdb.iriscouch.com" without running into any cross domain cookie issues do to the same-origin policy?

As for now I am using solution 2.



On Wednesday, August 7, 2013 10:02:28 AM UTC+2, Paul Weber wrote:

Dale Harvey

unread,
Sep 19, 2013, 6:38:07 AM9/19/13
to pou...@googlegroups.com
Hey Paul

Solution 1: So the first one wont work, the opts need to be passed to the contructor of the Pouch object

var remote = new PouchDB('http://testdb....', {

  auth: {username: 'testuser', password: 'testuserPassword'}
}};

Should do though, this is an API we could likely clean up

Solution 2: My bad, Giovanni submitted a patch which has been merged, however the nightly server wasnt running to the update wasnt applied, this should work against the latest nightly without changes

Solution 3: Cookies shouldnt have any cross domain issues, you need to have a server configured correctly so you can authorise and receive a cookie from a remote domain CORS,, but you should be receiving it for that host and it will only be sent / be valid for that host, there is some setup for CORS in http://pouchdb.com/getting-started.html

Cheers
Dale



--
You received this message because you are subscribed to the Google Groups "PouchDB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pouchdb+u...@googlegroups.com.
To post to this group, send email to pou...@googlegroups.com.

Paul Weber

unread,
Sep 20, 2013, 5:41:26 AM9/20/13
to pou...@googlegroups.com
Hi Dale,

thanks for your help. Solution 1 and 2 now work like a charm with the latest nightly (2013-09-19T10:26:58). 

I am afraid that cookie authentication with PouchDb remains a mystery to me. I did the setup for CORS as you suggested in http://pouchdb.com/getting-started.html

I can login with with jQuery.ajax and get a cookie with the name "AuthSession" back: 

function loginWithCookie() {
  $.ajax({
    cache: false,
    type: 'POST',
    dataType: 'json',
    data: {name: 'testuser', password: 'testuserPassword'},
      xhrFields: {withCredentials: true}
  }).done(function (data) {
    console.log('xhr done');
    console.log(data);
  });
}

But I still couldn't figure out how to use that cookie for PouchDb replication, or how to tell PouchDb to use cookie authentication.




On Wednesday, August 7, 2013 10:02:28 AM UTC+2, Paul Weber wrote:

Oliver Dain

unread,
Dec 16, 2013, 2:34:29 AM12/16/13
to pou...@googlegroups.com
Hey all,

I've been having the same issue. I just tried option 1 as described here and have found that it doesn't work for me. I'm using the latest nightly. I've stepped through the code in the Chrome dev tools debugger, so I'm sure that I'm passing the auth object in the options to PouchDB constructor. I've also looked at what's getting sent with Wireshark and the Authorization header is still missing.

I'm also open to other ideas. I tried doing a reverse proxy with node.js sending anything sent to http://my.domain/db on to couch, and that allowed me to view documents and such, but I couldn't get replication to work. Similarly, using express-couchdb I could view documents but replication did some really strange things. There must be some safe way to get pouchdb to replicate with couchdb, right???

Thanks,
Oliver


On Thursday, September 19, 2013 3:38:07 AM UTC-7, Dale Harvey wrote:
Hey Paul

Solution 1: So the first one wont work, the opts need to be passed to the contructor of the Pouch object

var remote = new PouchDB('http://testdb....', {
  auth: {username: 'testuser', password: 'testuserPassword'}
}};

Should do though, this is an API we could likely clean up

Solution 2: My bad, Giovanni submitted a patch which has been merged, however the nightly server wasnt running to the update wasnt applied, this should work against the latest nightly without changes

Solution 3: Cookies shouldnt have any cross domain issues, you need to have a server configured correctly so you can authorise and receive a cookie from a remote domain CORS,, but you should be receiving it for that host and it will only be sent / be valid for that host, there is some setup for CORS in http://pouchdb.com/getting-started.html

Cheers
Dale

On 19 September 2013 08:43, Paul Weber <paul....@area811.com> wrote:
I took another look at the authentication problem using pouchdb.nightly - 2013-08-25T17:29:48. To me it also looks like a bug in the HttpPouch function (https://github.com/daleharvey/pouchdb/blob/master/src/adapters/pouch.http.js).

I changed the URL of the remote database to "https://testdb.iriscouch.com/testdb" in the following examples because that's what I eventually what to do. PouchDb is served from "http://localhost:5000".

Solution 1:
var opts = {auth: {username: 'testuser', password: 'testuserPassword'}};

This doesn't work because opts.auth is always undefined in the HttpPouch function and therefor host.headers.Authorization is never being set.

Solution 2: 
Reply all
Reply to author
Forward
0 new messages