When I'm connecting to database in node, I have to add db name, username, password etc. If I'm right every user can access js file, when he knows address. So... how it works? Is it safe?
Node.js server side source files should never be accessible to end-users.
In frameworks like Express the convention is that requests for static assets are handled by the static middleware which serves files only from a specific folder in your solution. Explicit requests for other source files that exists in your code base are thus ignored (404 is passed down the pipeline).
Consult
https://expressjs.com/en/starter/static-files.html
for more details.
Although there are other possible options to further limit the visibility of sensitive data, note that anyone on admin rights who gets the access to your server, would of course be able to retrieve the data (and this is perfectly acceptable).
I am assuming from the question that the DB and Node are on the same server. I am also assuming you have created either a JSON or env file or a function which picks up your DB parameters.
The one server = everything (code+DB) is not the best setup in the world. However, if you are limited to it, then it depends on the DB you are using. Mongo Community Edition will allow you to set up limited security protocols, such as creating users within the DB itself. This contains a {username password rights} combination which grants scaled rights based upon the type of user you set up. This is not foolproof but it is something of protection even if someone gets a hold of your DB parameters. If you are using a more extended version of MongoDB then this question would be superfluous. As to other DB's you need to consult the documentation.
However, all that being said, you should really have a DB set up behind a public server and only allow SSH into it, with an open port to receive information from your program. As the one server = everthing format is not safe in the end run, though it is fine for development.
If you are using MongoDB, you may want to take a look at Mongoose coupled with Mongoose Encryption. I personally do not use them but it may solve your problem in the short run.
If your DB is MySQL etc. then I suggest you look at the documentation.
Related
I'm using Azure Mobile Services and I want to clear local database, how can I do that?
I have a problem with my local database. When I logout in app and login with other user, the data of the previous user is loaded for current user and I don't have idea why this occurs. I use debug on server side and the server return correct data, then I believe that the problem is the local Database.
I'm using Azure Mobile Services and I want to clear local database, how can I do that?
For deleting your SQLite file, you could follow Deleting the backing store. Also, you could leverage the capability provided by IMobileServiceSyncTable to purge records under your offline cache, details you could follow Purging Records from the Offline Cache.
When I logout in app and login with other user, the data of the previous user is loaded for current user and I don't have idea why this occurs. I use debug on server side and the server return correct data
Since you did not provide details about your implementations (e.g. user log in/log out, user data management,etc), I would recommend you check whether your server/client side both enable per-user data store. You could use fiddler to capture the network traces when other user logging in, and make sure that the correctly user identifier (e.g. UserId) is returned, then check the query against your local database. Moreover, I would recommend you follow adrian hall's book about Data Projection and Queries.
You can delete all of the local DB files by doing the following.
var dbFiles = Directory.GetFiles(MobileServiceClient.DefaultDatabasePath, "*.db");
foreach (var db in dbFiles)
{
File.Delete(db);
}
However, this would delete all data each time and cause performance issues, as every time after you did this, you'd be getting a fresh copy of the data from your Azure DB, rather than using the cached copy in the device's SQLite DB.
We typically only use this for debugging, and the reason it's in a foreach is to capture all databases created (refer to my last suggestion)
There are a few other things you could try to get around your core issue of data cross-over.
There's another reason you might be seeing this behaviour. With your PullAsync, are you passing it a query ID? Your PullAsync line should look similar to this.
GetAllFoo(string userId)
{
return await fooTable.PullAsync("allFoo"+userId,fooTable.Where(f=>f.userId == userId));
}
Note that the query ID will be unique each time (or at least, for each user). This is used primarilly by the offline sync portion of Azure, but in combination with the Where statement (be sure to import System.Linq), this should ensure only the correct data is brought back.
You can find more information about this here.
Also, some things you may want to consider, store a separate database for each userId. We're doing this for our app (With a company ID) - so that each database is separate. If you do this, and use the correct database on logging in, there's no chance of any data cross over.
This is more of an architecture question involving nodejs as implementation.
I have on a folder not exposed by the webserver files that I want to offer to the user.
The way nodejs should expose the resource to the end user is via a one shot link, that once is consumed is no longer available.
The user through the entire experience should never know the real location of the file.
I'm sure this is a common architecture pattern, but I have never implemented something similar.
Looking at scalability, the resource shouldn't be copy either on HD or RAM, and if possible the solution should not relay on a DB token tracking system.
I don't necessary need a code implementation, but a detail explanation on how I should implement it
Thank you so much
Give user a cookie
Create a temporary association (in db) between cookie and a generated ID for the user (or the hash of it, if you want to be fancy)
Give user the ID
When user requests resource by ID:
Test to see if the ID (or its hash, if you want to be fancy) is in the DB
If it is, give the user the resource and destroy the association between the user and the resource ID
There's a db token tracking system. Hey, that's the only way.
One way to avoid depending on a DB, would be to maybe create a symbolic link in the filesystem (based on the token), that would be removed after a request for it. Would not work satisfactory on windows though.
Example (psuedo):
Create token (guid, or similar)
symlink guid -> actual file
once request is completed, remove symlink
However, I don't think there is a reliable way of knowing if the file was successfully downloaded, so you better prepare for that. Some sort of pingback when the file was completely downloaded is probably the most reliable way that I can think of right now.
For scalability, make sure that the symlink is on a shared file system. Clustered node.js instances on the same server, will be fine though.
If this needs to be restricted to an authenticated user, you could combine the guid with your auth token, and prepend/append it before looking for a file.
In my couchapp two databases are being used
1 Is for application data
2 Is "_users" database.
In my application In one form I'm trying to implement autocomplete where data source is a "view" created in "_users" database.
Now when I login with normal user id other than admin. While trying to access the view inside "_users" database I'm getting the error 403 which is :
{"error":"forbidden","reason":"Only admins can access design document actions for system databases."}
Is it possible for me to allow and limit the access for non admin users to that view only ? So I can get the list of users from _users database into my application.
I've never been able to do many tasks that require much custom with CouchDB by itself. I've always needed a script somewhere else that gives me the info that I need.
What works for me is this setup:
A gatekeeper Sinatra app that has admin access to my CouchDB
Using CouchDB's config to proxy to my Sinatra app. httpd_global_handlers _my_service {couch_httpd_proxy, handle_proxy_req, <<"http://127.0.0.1:9999">>}
The reason for the proxy is because any request that comes through to your gatekeeper will have the AuthSession token set. Inside your gatekeeper, you can GET localhost:5984/_session passing the AuthSession cookie along, it will tell you who is making the request, allowing you to look them up and see if they have access, or just give everyone access to whatever you like. Another reason for the proxy is to avoid any CORS nonsense since you're making the request to yourserver:5984/_my_service.
Update
A purely client-side/javascript solution means that it will be fundamentally insecure at some point, since well, everything is on the client-side. But perhaps your application, doesn't need to be that secure. That's up to you.
One workaround could be to make your application authenticate as a predefined admin, and then create more admin users that way. You could authenticate once when your application boots or on an as needed basis.
The "problem" is that CouchDB sees the _users database as fundamentally special, and doesn't give you the opportunity to change the credential requirements like other databases. Normally you would be able to use the _security document to give role based or user based access. But that's not possible with _users.
An alternative implementation might be to keep track of your own users and forgo the _users database altogether. In that case you could set your own cookies and have your own login and logout methods that don't depend on CouchDB's authentication scheme. You could query your own _view/users because it would be in your main database. Things wouldn't be locked down tight but they would work fine as long as no one was interested in hacking your system. :)
Here's the situation: we have a common library which can retrieve database connection details from a central configuration store that we have setup. Each application uses this library when working with a database.
Basically, it will call a stored procedure and say "I am {xyz} application, I need to connect o " and it will return the connection details for that applications primary database (server, instance, database, user, and password).
How would one go about locking that down so that only application {xyz} can retrieve the passwords for {xyz} databases (there is a list of database details for each application... i just need to secure the passwords)?
The usual way is to have a different config store per app and give each app a different user/password to connect to the config store.
That doesn't prevent anyone from changing the app and replacing the user/password for app X with the values from app Y but it's a bit more secure, especially when you compile this data in instead of supplying it via a config file.
If you want to be really secure, you must first create a secure connection to the store (so you need a DB drivers that supports this). This connection must be created using a secure key that is unique per application and which can be verified (so no one can just copy them around). You will need to secure the executable with hashes (the app will calculate its own hash somehow and send that to the server who will have a list of valid hashes for each app).
All in all, it's not something trivial which you can just turn on with an obscure option. You will need to learn a lot about security and secure data exchange, first. You'll need a way to safely install your app in an insecure place, verify its integrity, protect the code against debuggers that can be attached at runtime and against it running in the virtual machine, etc.
Off the top of my head, try PKI.
Are you trying to protected yourself from malicous programs, and is this a central database that these applications are connecting to? If so you should probably consider a middle layer between your database and application.
I'm not sure this applies to your case, depending on how what your answers to the abovementioned would be, but by the comments it sounds like you are having a similar case to what this question is about.
Securing your Data Layer in a C# Application
The simplest/most straightforward way would be to store the passwords in encrypted format (storing passwords in plaintext is just plain bad anyhow, as recently demonstrated over at PerlMonks) and make each application responsible for doing its own password encryption/decryption. It would then not matter whether an app retrieved another app's passwords, as it would still be unable to decrypt them.
One possibility is to keep the passwords in the database in an encrypted form, and convey the encryption key to the allowed application(s) in a secure connection.Then, only the application with the encryption key can actually get the passwords and not others.
CouchDB access as a rest service seems insecure. Anyone can hit the database and delete/add documents once it is exposed.
What strategies are there to secure the CouchDB?
A lot has changed since 2009, so I'm going to throw an answer in here. This answer is drawn from this page on the wiki.
CouchDB has a _users database that serves the purpose of defining users. Here's the gist straight from the wiki:
An anonymous user can only create a new document.
An authenticated user can only update their own document.
A server or database admin can access and update all documents.
Only server or database admins can create design documents and access views and _all_docs and _changes.
Then, for any given database you can define permissions by name or by role. The way authentication is implemented is through a _session Database. Sending a valid username and password to the _session DB returns an authentication cookie. This is one of several option for CouchDB Authentication. There're a few more options:
This option is a little old 1.0 was a few months back, we're on 1.2 as of today. But it's still very well outlined.
And this one from "The Definitive Guide"
Also, depending on which hosting service you might be using, you'll have the option to restrict access to couch over SSL.
Between Node, Couch, and a variety of other technologies that effectively scale horizontally (adding more servers) there's an interesting kind of pressure or incentive being put on developers to make applications that scale well in that manner. But that's a separate issue all together.
The only thing which really works currently security wise is something like this in your CouchDB configuration.
[couch_httpd_auth]
require_valid_user=true
[admins]
admin = sekrit
This puts basic HTTP auth on all of CouchDB. Even this is not well supportet in client libraries. For python e.g. you need a patched library.
The second approach is to put a proxy in front of CouchDB and let the proxy do the authentication and authorization work. Due to CouchDB's RESTful design this is quite easy.
All other approaches must be considered up to now highly experimental.
This may be a little different from your original question. If your couchdb is only a back-end store for a full server app, you can make a special account for the server app to use and require those credentials for access to couchdb.
On the other hand, a pure couch app that people hit directly through a javascript client needs a lot of care to be secure.
Using rewrites is not optional. You need a vhosts config that forces requests to your domain through your rewrites.
Rewrite routes */_all_docs and /*/_design/* to a 404 page. Otherwise users can list every document or get your whole app.
Rewrite generic object access, ie /dbname/:id to a show that can deny access if the user is not allowed to see the document. Unfortunately there is no equivalent workaround for doc-based access control of attachments.
We used haproxy to filter GET requests on _users. There is no legit reason for someone from outside to get a user record or list all your users. We want users to be able to register so we need write access. Currently couch cannot block read access to a db and simultaneously allow writes. It's a bug. Filtering with something like haproxy is our best workaround for now.
Use your own database to keep contact information that is in addition to what is provided by _users. This allows more control over access.
validate_doc_update should carefully reject any writes that should not be allowed.
In every case you need to imagine what someone who understood the system could do to subvert it and lock down those avenues of attack.
CouchDB does cookies, SSL, oauth, and multi-users just fine:
Here's some actual code in python:
from couchdb import Server
s = Server("https://user:password#example.com:6984")
Request the cookie: url encoded above and below, of course
You have to put the credentials twice to get started with the first cookie
Both in the Server() constructor as well as the _session POST body
code, message, obj = s.resource.post('_session',headers={'Content-Type' : 'application/x-www-form-urlencoded'}, body="name=user&password=password")
assert(code == 200)
Now you have received a cookie, extract it
cookie = message["Set-Cookie"].split(";", 1)[0].strip()
Now, exit python and restart
Next, Request a server object, but without the username and password this time
s = Server("https://example.com:6984")
s.resource.headers["Cookie"] = cookie
Yay, no password, try to access the database:
db = s["database"]
Optionally set the "persistent" cookie option on the server side to make the cookie last longer.
Have you read CouchDB documentation http://couchdb.apache.org/docs/overview.html? It has a "Security and Validation" section that addresses some of your concerns.