Connect to Cloudant CouchDB with Node.js? - javascript

I am trying to connect to my CouchDB database on Cloudant using Node.js.
This worked on the shell:
curl https://weng:password#weng.cloudant.com/my_app/_all_docs
But this node.js code didn't work:
var couchdb = http.createClient(443, 'weng:password#weng.cloudant.com', true);
var request = couchdb.request('GET', '/my_app/_all_docs', {
'Host': 'weng.cloudant.com'
});
request.end();
request.on('response', function (response) {
response.on('data', function (data) {
util.print(data);
});
});
It gave me this data back:
{"error":"unauthorized","reason":"_reader access is required for this request"}
How do I do to list all my databases with Node.js?

The built-in Node.js http client is pretty low level, it doesn't support HTTP Basic auth out of the box. The second argument to http.createClient is just a hostname. It doesn't expect credentials in there.
You have two options:
1. Construct the HTTP Basic Authorization header yourself
var Base64 = require('Base64');
var couchdb = http.createClient(443, 'weng.cloudant.com', true);
var request = couchdb.request('GET', '/my_app/_all_docs', {
'Host': 'weng.cloudant.com',
'Authorization': 'Basic ' + Base64.encode('weng:password')
});
request.end();
request.on('response', function (response) {
response.on('data', function (data) {
util.print(data);
});
});
You will need a Base64 lib such as one for node written in C, or a pure-JS one (e.g. the one that CouchDB Futon uses).
2. Use a more high-level Node.js HTTP client
A more featureful HTTP client, like Restler, will make it much easier to do the request above, including credentials:
var restler = require('restler');
restler.get('https://weng.cloudant.com:443/my_app/_all_docs', {
username: 'weng',
password: 'password'
}).on('complete', function (data) {
util.print(data);
});

There are lots of CouchDB modules for Node.js.
node-couch - a CouchDB connector
node-couchdb - A full API implementation
node-couchdb-min - Light-weight client with low level of abstraction and connection pooling.
cradle - a high-level, caching, CouchDB client

Just wanted to add
nano - minimalistic couchdb driver for node.js
to the list. It is written by Nuno Job, CCO of nodejitsu, and actively maintained.

This answer is looking a bit dated. Here is an updated answer that I verified using the following Cloudant Supported NPM Node Client library that works.
https://www.npmjs.com/package/cloudant#getting-started
And to answer his question on how to list his databases use the following code.
//Specify your Cloudant Database Connection URL. For Bluemix format is: https://username:password#xxxxxxxxx-bluemix.cloudant.com
dbCredentials_url = "https://username:password#xxxxxxxxx-bluemix.cloudant.com"; // Set this to your own account
// Initialize the library with my account.
// Load the Cloudant library.
cloudant = require('cloudant')(dbCredentials_url);
// List the Cloudant databases
cloudant.db.list(function(err, allDbs) {
console.log('All my databases: %s', allDbs.join(', ')) });

Related

sending a websocket request through a proxy server in nodeJS [duplicate]

Generalizing that would be the question... how to make websockets to go through a proxy in node.js?
In my particular case I'm using pusher.com with the node.js client library they recommend. Looking inside the code I would like to know some hints on what I should change in order to make this library to work with a proxy... you can take a look in the code here
Maybe I should somehow replace or modified the websockets module that is being used by the library?
EDIT
Thanks for your answers/comments! A couple of things to take into consideration (excuse me if I'm wrong with some/all of them, just learning):
I don't want to create a proxy server. I just want to use an existent proxy server within my company in order to proxified my websockets requests (particularly pusher.com)
Just to let you know, if I use a proxifier like the one for windows Proxifier and I set up the rule to inspect for all connections to port 443 to go through the proxy server proxy-my.coporate.com:1080 (type SOCKS5) it works like a charm.
But I don't want to go this way. I want to programatically configuring this proxy server within my node js code (even if that involved to modified the pusher library I mentioned)
I know how to do this for HTTP using Request module (look for the section that mentions how to use a proxy).
I want a similarly thing for websockets.
From
https://www.npmjs.com/package/https-proxy-agent
var url = require('url');
var WebSocket = require('ws');
var HttpsProxyAgent = require('https-proxy-agent');
// HTTP/HTTPS proxy to connect to
var proxy = process.env.http_proxy || 'http://168.63.76.32:3128';
console.log('using proxy server %j', proxy);
// WebSocket endpoint for the proxy to connect to
var endpoint = process.argv[2] || 'ws://echo.websocket.org';
var parsed = url.parse(endpoint);
console.log('attempting to connect to WebSocket %j', endpoint);
// create an instance of the `HttpsProxyAgent` class with the proxy server information
var options = url.parse(proxy);
var agent = new HttpsProxyAgent(options);
// finally, initiate the WebSocket connection
var socket = new WebSocket(endpoint, { agent: agent });
socket.on('open', function () {
console.log('"open" event!');
socket.send('hello world');
});
socket.on('message', function (data, flags) {
console.log('"message" event! %j %j', data, flags);
socket.close();
});
Using a proxy for websockets should work roughly the same as for https connections; you should use the CONNECT method. At least that's what both the HTTP and HTML5 specs say. So if your proxy implements CONNECT, you're good to go.
Try node-http-proxy
It allows you to send http or websocket requests through a proxy.
var http = require('http'),
httpProxy = require('http-proxy');
//
// Create a basic proxy server in one line of code...
//
// This listens on port 8000 for incoming HTTP requests
// and proxies them to port 9000
httpProxy.createServer(9000, 'localhost').listen(8000);
//
// ...and a simple http server to show us our request back.
//
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2));
res.end();
}).listen(9000);
Source: link
Most web proxies don't support websockets yet. The best workaround is to use encryption by specifying wss:// (websocket secure protocol):
wss://ws.pusherapp.com:[port]/app/[key]

Use git credential manager to fetch azure devops api instead of personal access token

I am trying to fetch git azure devops api to get information about repositories and branches in js.
In order to achieve that, I made a little application with the following code :
$(document).ready(function() {
var personalToken = btoa(':'+'<personnalAccessToken>');
fetch('https://dev.azure.com/<company>/<project>/_apis/git/repositories?api-version=5.1', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
'Authorization': 'Basic '+ personalToken
}
}).then(function(response) {
return response.json();
}).then(function(repositories) {
console.log("There are "+repositories.count+" repositories");
}).catch(function(error) {
console.log('Fetch error: ' + error.message);
});
This code is working great but as you can see there is my personnalAccessToken writen directly inside the code... which is really bad...
When I am using git in command line, I don't have to specify any credential information because I use git credential manager for windows. Which means my personnalAccessToken is already stored, cached and automatically used everytime I use a git command, like clone, etc.
So, I would like my js code to use the same thing, I would like it to use my stored credentials automatically to fetch the api without being required to set my personnalAccessToken in code.
I have already searched for hours but can't find out if it is possible.
I have already searched for hours but can't find out if it is
possible.
Sorry but as I know it's impossible. The way you're calling the Rest API is similar to use Invoke-RestMethod to call rest api in Powershell.
In both these two scenarios, the process will try to fetch PAT for authentication in current session/context and it won't even try to search the cache in Git Credential Manager.
You should distinguish the difference between accessing Azure Devops service via Rest API and by Code:
Rest API:
POST https://dev.azure.com/{organization}/{project}/{team}/_apis/wit/wiql?api-version=5.1
Request Body:
{
"query": "Select [System.Id], [System.Title], [System.State] From WorkItems Where [System.WorkItemType] = 'Task' AND [State] <> 'Closed' AND [State] <> 'Removed' order by [Microsoft.VSTS.Common.Priority] asc, [System.CreatedDate] desc"
}
Corresponding Code in C#:
VssConnection connection = new VssConnection(new Uri(azureDevOpsOrganizationUrl), new VssClientCredentials());
//create http client and query for resutls
WorkItemTrackingHttpClient witClient = connection.GetClient<WorkItemTrackingHttpClient>();
Wiql query = new Wiql() { Query = "SELECT [Id], [Title], [State] FROM workitems WHERE [Work Item Type] = 'Bug' AND [Assigned To] = #Me" };
WorkItemQueryResult queryResults = witClient.QueryByWiqlAsync(query).Result;
Maybe you can consider using a limited PAT, limit its scope to Code only:
I know there exists other Authentication mechanism
:
For Interactive JavaScript project: ADALJS and Microsoft-supported Client Libraries.
You can give it a try but I'm not sure if it works for you since you're not using real Code way to access the Azure Devops Service... Hope it makes some help :)
If you have the script set up in an Azure Runbook you can set it as an encrypted variable there and have it pull it from there before running rather than having it directly written into the code.
$encryptedPatVarName = "ADO_PAT"
$adoPat = Get-AutomationVariable -Name $encryptedPatVarName
$adoPatToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($adoPat)"))
$adoHeader = #{authorization = "Basic $adoPatToken"}
The above is the Powershell version of it. I have seen some people do it with other

Node.js server-to-server encryption

I want to make a Node.js daemon that runs on multiple computers and is able to exchange messages between the different daemons. Of course the communication should be encrypted, but I really don't know what kind of encryption I should use for server-to-server encryption. The protocol I'm using right now is TCP via net.createServer. How should I encrypt the communication assuming I have a already exchanged password on both devices? How do I make it secure to the most known attacks?
Edit:
Is using RSA combined with an "authentication password" secure? This password would then be submitted with every request, the whole message (including the password) would be encrypted with the RSA public key (which can be downloaded without encryption).
I think the right way to do this is to communicate via ssl, see here:
http://nodejs.org/docs/v0.4.2/api/tls.html
You could also do a quick and dirty encryption using the crypto module:
var crypto = require('crypto');
var algorithm = 'aes256'; // or any other algorithm supported by OpenSSL
exports.encryptString = function(text) {
var cipher = crypto.createCipher(algorithm, key);
return cipher.update(text, 'utf8', 'hex') + cipher.final('hex');
};
var key = "123456";
exports.decryptString = function(text) {
var decipher = crypto.createDecipher(algorithm, key);
return decipher.update(text, 'hex', 'utf8') + decipher.final('utf8');
};
Both servers need the public key.
You'll probably want to use JSON stringify and parse functions on top of the above (I had those lying around). You could do it in middleware that deciphers incoming requests and ciphers outgoing ones.
I take a different approach to this by doing the work outside of my application. Generally speaking, you don't want to reinvent wheels and secure encryption is a tough thing to get right.
I have a situation where several slave servers need to communicate to a master server to run jobs from a queue. For the server-to-server connection I actually just use Socket.IO (using the socket.io client NPM package and all transports disabled except for web sockets). This gives me a solid RPC, which works well for my needs. (I have since discovered rpc-stream which can give you RPC over arbitrary streams. This would be a bit more lightweight for server-to-server communication where Socket.IO is overkill.)
Now, for the encryption part... I just use a VPN set up between my servers. I took the lazy approach and used Hamachi for this, but you can certainly use OpenVPN or any other.
A second method you can use is to tunnel your connections through SSH.
In short, don't do any work you don't have to. Opt for speed, simplicity, and security. Use something off-the-shelf for this.
One option which might be easier to implement is to encrypt and decrypt all messages sent over a normal socket connection (net.createServer and net.connect), via pre-shared gpg keys using node-gpg. This requires that you have gpg in your $PATH on both client and server with a password-less private gpg key 'Server' on the server and a corresponding 'Client' on the client, with the respective public keys installed on the other end.
server.js:
var socketServer = net.createServer(function (c) {
// example of send to client
var output = JSON.stringify({"msg": "Stuff to send to client."});
encrypt(output, 'Client', function (error, cryptdata) {
c.write(cryptdata.toString());
});
// receive data sent from client
c.on('data', function (cryptdata) {
decrypt(cryptdata.toString(), 'Server', function (error, data) {
data = JSON.parse(data.toString());
// handle incoming data
});
});
});
socketServer.listen(port, function() {
});
client.js:
var socketClient = net.connect({"port": port}, function () {
// Send data to server
var data = JSON.stringify({"msg": "Data to server"});
encrypt(data, 'Server', function (error, cryptdata) {
socketClient.write(cryptdata.toString());
});
});
// Receive data from server
socketClient.on('data', function(cryptdata) {
decrypt(cryptdata.toString(), 'Client', function (error, data) {
data = JSON.parse(data.toString());
// handle data
});
});
And these were the functions I used in both server.js and client.js for encryption/decryption.
function encrypt(str, receiver, callback) {
gpg.encrypt(str, ['-r ' + receiver, '-a'], callback);
}
function decrypt(str, receiver, callback) {
gpg.decrypt(str, ['-u ' + receiver, '-a'], callback);
}
This eliminates any problem you may run into with self-signed SSL certificates and at least with my benchmarks it is a lot faster. Though, it might not be as secure.

Can a mobile service server script (schedule) access other Sql Azure databases?

I'm looking to create a scheduled job using a Azure mobile service.
Since the service will end up calling another cloud service (website), I was wondering if the mobile script could access a database the cloud service already does.
I understand you can specify a database to use for the mobile script (I selected free for logging) but can't seem to tell if you can access other databases through the API.
var todoItemsTable = tables.getTable('TodoItems');
Hypothetically...
var todoItemsTable = databases.getDatabase('NonMobileSqlDb').tables.getTable('TodoItems');
I've already checked this question (Can you mix Azure Mobile Services with Azure Cloud Services?) but it doesn't seem to cover scripts talking to databases.
Some background...
The mobile service will (on a schedule) invoke a web service (with authorisation) that performs routine actions. I'd like to lock down this service (without ssl) and one way is to generate a key the service could use that the cloud service could verify. This key would be stored in the database both can access and only be available for a short period of time.
Yes you can.
You need to connect using the following example (uses Node.js) taken from the how-to guide:
To use the node-sqlserver, you must require it in your application and
specify a connection string. The connection string should be the ODBC
value returned in the How to: Get SQL Database connection information
section of this article. The code should appear similar to the
following:
var sql = require('node-sqlserver');
var conn_str = "Driver={SQL Server Native Client 10.0};Server=tcp:{dbservername}.database.windows.net,1433;Database={database};Uid={username};Pwd={password};Encrypt=yes;Connection Timeout=30;";
Queries can be performed by specifying a Transact-SQL statement with
the query method. The following code creates an HTTP server and
returns data from the ID, Column1, and Column2 rows in the Test table
when you view the web page:
var http = require('http')
var port = process.env.port||3000;
http.createServer(function (req, res) {
sql.query(conn_str, "SELECT * FROM TestTable", function (err, results) {
if (err) {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.write("Got error :-( " + err);
res.end("");
return;
}
res.writeHead(200, { 'Content-Type': 'text/plain' });
for (var i = 0; i < results.length; i++) {
res.write("ID: " + results[i].ID + " Column1: " + results[i].Column1 + " Column2: " + results[i].Column2);
}
res.end("; Done.");
});
}).listen(port);
Many thanks to #GauravMantri & #hhaggan for their help in getting this far.

ldapjs authentification (user login setup)

So I'm currently running node.js, which has ldapjs installed. My aim is to have a system that uses ldapjs to allow users to login with a username and password.
I have been reading over the http://ldapjs.org documentation for awhile now but am struggling to understand the whole idea of ldap and ldapjs's implementation of it.
I currently have this from the documentation
var ldap = require('ldapjs');
var server = ldap.createServer();
server.bind('cn=root', function(req, res, next) {
if (req.dn.toString() !== 'cn=root' || req.credentials !== 'secret')
return next(new ldap.InvalidCredentialsError());
res.end();
return next();
});
server.listen(1389, function() {
console.log('LDAP server up at: %s', server.url);
});
Which allows me to run the below and successfully bind to the server.
ldapsearch -H ldap://localhost:1389 -x -D cn=root -w secret -LLL -b "o=myhost" objectclass=*
But I'm really unsure of where to go from here or even if this is the correct approach...
The ideal setup would be to have a range of users and passwords, and on a successful ldap connection confirm the details are correct and respond with a true, or false if the username/pass was incorrect.
Does anyone know of any good resources for finding out more about this, or better yet can suggest some basic client/server side code to give me an idea of where to go next!
Any replies would be really appreciated.
Many Thanks
I never used ldapjs, but based on what I just quickly read in its seemingly incomplete document, it can be used to implement an LDAP server or an LDAP client, which seems to be what you're trying to do (i.e., I'm assuming you want to authenticate users in your application against an existing LDAP server). Most of the examples in its document focus on creating an LDAP server that listens on a certain port and interacts with a back-end database. If you're not trying to put an LDAP-based interface between your back-end database or store of users and passwords, then you probably don't need the server API. If you already have an LDAP server running, then you will need to use its client API to do something like this:
1.Bind anonymously to the LDAP server that provides the directory services including the authentication services. It looks like you can just do this with:
var ldap = require('ldapjs');
var client = ldap.createClient({
url: 'ldap://my.ldap.server'
});
2.Search by the username (e.g., e-mail address) for the corresponding entry's DN
var opts = {
filter: '(mail=USERNAME)',
scope: 'sub'
};
client.search('ou=users,o=acme.com', opts, function(err, res) {
assert.ifError(err);
res.on('searchEntry', function(entry) {
console.log('entry: ' + JSON.stringify(entry.object));
});
res.on('searchReference', function(referral) {
console.log('referral: ' + referral.uris.join());
});
res.on('error', function(err) {
console.error('error: ' + err.message);
});
res.on('end', function(result) {
console.log('status: ' + result.status);
});
});
3.Grab the DN of the returned entry ( entry.object ). The documentation of this library doesn't talk much about how these objects can be used (e.g., what their methods, properties, etc. are). So, you will have to figure out how to actually get the DN or string representation of the DN of the entry you just retrieved from the directory server. [See the comment(s) below this answer]
4.Rebind to the server using that DN:
client.bind(DN_RETRIEVED, PASSWORD_USER_ENTERED, function(err) {
assert.ifError(err);
});
5.The result of the bind above is what you will need to use to determine whether or not the authentication was successful.
If you are trying to implement an LDAP server in front of your user/password data store for LDAP-based authentication, then you will need to follow their server examples. I personally think this is an overkill and could be problematic in terms of security.

Categories

Resources