I want to use the following plugin to Authenticate Users on PouchDB/Sync Gateway combination:
Will this plugin work to authenticate on Sync Gateway?
I want to use the following plugin to Authenticate Users on PouchDB/Sync Gateway combination:
Will this plugin work to authenticate on Sync Gateway?
Iâve tried using it to figure out the difference between using this plugin with CouchDB and with Sync Gateway. It wonât work because the API to login with SG is not the same as the one this plugin expects.
http://localhost:4984/_session
but SG expects a database in the path http://localhost:4984/{db}/_session
.You can follow this blog post to get the code to set up an app server (reverse proxy) to expose the admin rest api endpoint to client apps to register users. The blog post shows how to sign up the users in an Android app but the same concept applies to web clients (itâs the same HTTP request).
James
Thank you so much James. After reading the blog following is my understanding, is it correct?
1)- If we want to use custom authentication, user can only be created using the admin REST api which is not public and can only be called from server
2)- We will have to create a proxy server on port e.g. 8000 which redirects all requests to sync gate way on normal port:4984 except for the /signup request.
3)- /signup request makes a post request to syncgateway admin REST api on port:4985. The POST Api call will be /dbname/_user
4)-We will be using the 8000 port proxy url for all pouchDb references for web, Android and iOS
5)- Our architecture will be that web browser pouchdb client, Android client and iOS client all connect to the proxy server (node.js). The node.js/ proxy server forwards all requests to the sync gate way and the sync gate way talks to the couchbase except for signup.
Yes thatâs correct.
Let me know if you have questions about the implementation or if things are not working as expected.
James
Thereâs one thing I donât get from the code in the blog post:
How can the proxy work for login if it uses the admin port?
I tried it and it worked for me, but why?
Shouldnât I need to create a '/login'
URL with POST
to redirect the request to the admin port? In the code from the blog, it redirects all requests to the public port, 4894. Both the curl
version and the Java version do the same. Why is it working?
Good question, because the session endpoint to login is actually also available on the public facing port. I think the docs donât make this clear enough (actually they donât mention it at all). Weâre fixing that. Sorry for the confusion.
James
Thanks for the clarification.
So the _session
endpoint is available both in the public and admin ports? Is there any difference in behaviour between the two?
The _user
and _role
endpoints are still only available in the admin port, correct?
Yes, itâs the same functionality on both ports.
Yes
Incidentally, the docs have a short note on the public _session
endpoint (itâs under REST API, so I assume itâs about the public port):
Yes thanks - were you looking in the Authentication section? http://developer.couchbase.com/documentation/mobile/1.1.0/develop/references/sync-gateway/rest-api/authentication/index.html I think thatâs the right place to put it.
Yes, I guess that would be better.
Also, make it more explicit that it works on the public port =]
Actually, those endpoints do the same thing (create a session for a user) but with different responses.
On the public port, the sync gateway cookie is returned as a header
Set-Cookie: SyncGatewaySession=7da94f20380a41d09ab6e382a0c28a12a05861e0; Path=/sync_gateway/; Expires=Thu, 24 Sep 2015 16:38:18 UTC
And on the admin port, itâs returned in the message body:
{
"session_id":"6e3251294a734b99b821e9031fc446bd2dc679f5",
"expires":"2015-09-24T17:38:09.23133207+01:00",
"cookie_name":"SyncGatewaySession"
}
James, I have being working with the reverse proxy as you suggested. The issue is that pouchdb is not sending any request to the reverse proxy. When I use the sync gateway URL everything is working fine. The only code I change on the client is the reverse proxy URL and it stops working because no messages are being received on the reverse proxy from the pouchdb. It seems pouchdb is using some other way to communicate with the sync gateway e.g. a socket. My be I am doing something wrong? I have been trying different code combinations this is one of them:
var express = require(âexpressâ),
session = require(âexpress-sessionâ),
cookieParser = require(âcookie-parserâ),
bodyParser = require(âbody-parserâ),
hbs = require(âhbsâ),
request = require(ârequestâ).defaults({json: true}),
httpProxy = require(âhttp-proxyâ);
app = express();
// Allow origins
app.use(function(req, res, next) {
res.header(âAccess-Control-Allow-Originâ, âhttp://localhost:8081â);
res.header(âAccess-Control-Allow-Originâ, âhttp://localhost:3984â);
res.header(âAccess-Control-Allow-Originâ, âhttp://localhost:3985â);
res.header(âAccess-Control-Allow-Originâ, âhttp://91.123.200.21:8091â);
res.header(âAccess-Control-Allow-Originâ, âhttp://91.123.200.21:8093â);
res.header(âAccess-Control-Allow-Credentialsâ, âtrueâ);
res.header(âAccess-Control-Allow-Originâ, âhttp://locahost:8091â);
res.header(âAccess-Control-Allow-Originâ, âhttp://localhost:9000â);
res.header(âAccess-Control-Allow-Methodsâ, âGET,PUT,POST,DELETEâ);
res.header(âAccess-Control-Allow-Headersâ, âOrigin, X-Requested-With, Content-Type, Acceptâ);
next();
});
app.set(âview engineâ, âhtmlâ);
app.set(âviewsâ, __dirname + â/app/viewsâ );
app.set(âpartialsâ, __dirname + â/app/views/partialsâ );
app.engine(âhtmlâ, hbs.__express);
//Register Handlebar Helper.
hbs.registerHelper(âdebugâ, function(optionalValue) {
console.log(âCurrent Contextâ);
console.log("====================");
console.log(this);
if (optionalValue) {
console.log(âValueâ);
console.log("====================");
console.log(optionalValue);
}
});
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Serve static.
app.use(express.static(__dirname + â/publicâ));
app.use(express.static(__dirname + â/public/appâ));
app.use(express.static(__dirname + â/public/bowerâ));
require(â./app/amazonServices/routeManagerâ).setupRoutes(app);
require(â./app/amazonServices/profilePictureManager/profilePictureManagerâ).init();
require(â./app/controllers/indexâ)(app);
require(â./app/controllers/subscriptionsâ)(app);
app.use(â/signupâ, bodyParser.json());
app.post(â/signupâ, function (req, res) {
console.log(âits signup timeâ);
var json = req.body;
var options = {
url: 'http://127.0.0.1:3985/horsetest/_user/',
method: 'POST',
body: json
};
request(options, function(error, response) {
res.writeHead(response.statusCode);
res.end();
});
});
app.all("*", function(req, res) {
var url = âhttp://127.0.0.1:3984â + req.url;
console.log(req.url)
req.pipe(request(url)).pipe(res);
//request(url).pipe(res);
})
app.listen(9000);
console.log(â[Application] is listening on port: 9000â);
//Client code
var db = new PouchDB(âhorsetestâ);
var remoteCouch = "http://127.0.0.1:9000/horsetest/"
db.replicate.to(remoteCouch, {live:true}, function(e){
console.log(e)
});
db.replicate.from(remoteCouch, {live:true}, function(e){
console.log(e)
});
//The output on the console while logging against console.log(req.url)
âC:\Program Files (x86)\JetBrains\WebStorm 10.0\bin\runnerw.exeâ âC:\Program Files\nodejs\node.exeâ app.js
aws-sdk Initialized.
[Application] is listening on port: 9000
/api/notifications
/horsetest/_facebook
/horsetest/_facebook
/horsetest/?_nonce=1443648295706
/horsetest/?_nonce=1443648295709
/horsetest/_changes?timeout=25000&style=all_docs&since=0&limit=100&_nonce=1443648295770
/horsetest/_local/bQttFoY6B53pDZ37EEStJQ%3D%3D?_nonce=1443648296038
/horsetest/_changes?timeout=25000&style=all_docs&since=2&limit=100&_nonce=1443648296068
/horsetest/?_nonce=1443648296088
/horsetest/_changes?timeout=25000&style=all_docs&feed=longpoll&since=2&limit=100&_nonce=1443648296089
/horsetest/_revs_diff?_nonce=1443648296111
/horsetest/_local/YRtE4dLpEDOZ27ctzt1yEw%3D%3D?_nonce=1443648296107
/horsetest/_revs_diff?_nonce=1443648296111
/horsetest/_local/YRtE4dLpEDOZ27ctzt1yEw%3D%3D
/horsetest/_local/YRtE4dLpEDOZ27ctzt1yEw%3D%3D
/horsetest/_changes?timeout=25000&style=all_docs&feed=longpoll&since=2&limit=100&_nonce=1443648321151
/horsetest/_changes?timeout=25000&style=all_docs&feed=longpoll&since=2&limit=100&_nonce=1443648346223
/horsetest/_changes?timeout=25000&style=all_docs&feed=longpoll&since=2&limit=100&_nonce=1443648372208
/horsetest/_changes?timeout=25000&style=all_docs&feed=longpoll&since=2&limit=100&_nonce=1443648398210
Can you try using a vanilla XMLHttp request to create the user on :8000/signup
and login on :8000/{db}/_session
For the login request for example:
function startSyncGatewaySession(accessToken) {
var request = new XMLHttpRequest();
request.open('POST', SYNC_GATEWAY_URL + '/_session', true);
request.setRequestHeader('Content-Type', 'application/json');
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
console.log('New SG session, starting sync!');
// start the sync, replication requests should now be authenticated
};
request.withCredentials = true;
request.send(JSON.stringify({"name": name, "password": password}));
}
James
James,
Just a quick question, we are right now creating sessions as per suggestions, but it is not checking the authentication. The documentation clearly states that we have to use your own authentication:
http://developer.couchbase.com/documentation/mobile/1.1.0/develop/guides/sync-gateway/administering-sync-gateway/authenticating-users/index.html#custom--indirect--authentication
I am reading this line from documentation âApp server authenticates the credentials however it wants (LDAP, OAuth, and so on).â
From this my understanding is that the api will create the session but we need to check password ourselves?
Thanks
If you call the /_session
endpoint on the admin port (4985) then the password isnât checked. But for logging users in with a name/password you can call /_session
on 4984 anyways which is easier.
The /_session
endpoint on 4985 is typically used for other auth types as mentioned where youâd want to create a session once you have verified the custom user credentials (access tokenâŚ).
James
James,
Iâm using couchbase lite for Android : https://github.com/couchbase/couchbase-lite-android
I have followed this thread to setup Node server for custom email/password singup.
Now I want to authenticate user using couchbase lite from mobile to direclty on sync gateway and Iâm unable to find any suitable api or process that allow me to authenticate user using userid/password.
I have found one link which is : http://developer.couchbase.com/documentation/mobile/current/get-started/get-started-mobile/todo-lite/login-and-sync/index.html
But it also does not explain how to implement login process using couchbase lite, can you please guide me?
Thanks,
Aijaz
Hi @AijazAliShah,
Sorry for the late reply - only just saw this :/.
The simplest way is to use the :4984/_session
endpoint with {"name": "james", "password": "letmein"}
in the request body. It returns a 401 or 200. If itâs a 200 then you can create a basic authenticator with the createBasicAuthenticator
method passing the user name and password. The replicator will take care of renewing the cookie sessions as well when they expire.
James
Thank you @jamiltz for the great answer, This working perfectly for me.
I know itâs a late answer but with latest PouchDB you connect with sync gateway like this:
var remote = new PouchDB("http://user:pass@localhost:4984/bucket/");
sync gateway version is 1.5, not sure if this works with latest sync gateway