So, let's say I'm going to build a Stack Exchange clone and I decide to use something like CouchDB as my backend store. If I use their built-in authentication and database-level authorization, is there any reason not to allow the client-side Javascript to write directly to the publicly available CouchDB server? Since this is basically a CRUD application and the business logic consists of "Only the author can edit their post" I don't see much of a need to have a layer between the client-side stuff and the database. I would simply use validation on the CouchDB side to make sure someone isn't putting in garbage data and make sure that permissions are set properly so that users can only read their own _user data. The rendering would be done client-side by something like AngularJS. In essence you could just have a CouchDB server and a bunch of "static" pages and you're good to go. You wouldn't need any kind of server-side processing, just something that could serve up the HTML pages.

Opening my database up to the world seems wrong, but in this scenario I can't think of why as long as permissions are set properly. It goes against my instinct as a web developer, but I can't think of a good reason. So, why is this a bad idea?

EDIT: Awesome discussion so far, and I appreciate everyone's feedback! I feel like I should add a few generic assumptions instead of calling out CouchDB and AngularJS specifically. So let's assume that:

The database can authenticate users directly from its hidden store

All database communication would happen over SSL

Data validation can (but maybe shouldn't?) be handled by the database

The only authorization we care about other than admin functions is someone only being allowed to edit their own post

We're perfectly fine with everyone being able to read all data (EXCEPT user records which may contain password hashes)

Administrative functions would be restricted by database authorization

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

Not exactly pure "client side to database", but have you looked at Parse and Firebase? (and also Meteor to some level), all of them have somewhat relevant concepts, and all handle security in creative ways. e.g. see this: blog.firebase.com/post/38234264120/…
–
Eran MedanDec 19 '12 at 18:59

Yes! I'd heard of Parse before but not Firebase. Very interesting, and definitely along the lines of what I was thinking.
–
Chris SmithDec 19 '12 at 20:53

How would your database protect against SQL injection or XSS being sent from the JavaScript? Pretty much anything sent from the client you have to assume it's unsafe, so what provisions are there in that database you can use to filter the data to make sure it's valid and insert data with prepared statements?
–
zuallauzDec 20 '12 at 3:45

"We're perfectly fine with everyone being able to read all data (EXCEPT user records which may contain password hashes)" Even data miners assuming a stack exchange maybe about the latest stock tips or somesuch?
–
Erik ReppenDec 20 '12 at 7:36

I have launched a similar project based on a MySQL database. I am absolutely sure (OK as sure as I can be) that I know my user base (+/- 200 Employees) and they must authenticate to do anything. Is my application still vulnerable? should I ask this as a separate question? Thanks
–
SydwellDec 20 '12 at 8:27

11 Answers
11

Doing as you suggest creates a tight(er) coupling between your client side language and your database.

That can be okay - there's less code to write and maintain, and in theory debugging could / should go a little quicker.

On the other hand, it makes other aspects more difficult. If / when you need to change either of those technologies, you'll have a harder time because of the tight coupling between them.

Protecting yourself against attacks will be (quite) a bit more difficult. You're assuming that the client will always present nicely formatted requests to the database. That presumes no one will ever hack the client side code to insert malicious statements. In other words, they'll "borrow" your authentication mechanisms and replace the normal client code with theirs.

I wouldn't recommend it, and many would vehemently tell you not to. But it can be done.

Interesting. How might an attacker borrow my authentication mechanism? I wouldn't be trusting the client to authenticate. The database would simply take an HTTPS POST to the session endpoint that would hash the POSTed password and check that it's valid. If it is, then it would return a session cookie to be used in future requests.
–
Chris SmithDec 19 '12 at 15:15

1

All I need is the session cookie, right? I use your client to auth and get my session cookie. Then I steal the session cookie with my client and send up badly formatted requests to cause havoc. Remember that it's all on my machine, so I don't even need a MiTM attack.
–
GlenH7Dec 19 '12 at 15:33

4

@ChrisSmith - so long as you feel you're addressing the security concerns then you're handling the primary objection to what you suggested. If you've got them handled or think you do then go for it. The simple version of your question is this: You asked why people don't do ABC. The primary answer is security and tight-coupling. Address those concerns and code away.
–
GlenH7Dec 19 '12 at 16:14

2

Not to mention you don't have a place to cache frequently-requested data, so you'll have to hit the DB every time. Sure, maybe your DB driver does some caching, but how tunable is it? Will it share across threads?
–
TMNDec 19 '12 at 17:18

1

I'm uncomfortable allowing direct access to my sql databases via direct sql statements from web clients because you never know what type of requests they'll be making. Will they run delete, update, or insert statements? If they do, will they provide the data your application expects? Will unexpected deletions happen? Unexpected database changes will usually break your application. It's best to minimize the commands going to your database so you can more easily sanitize the inputs you receive so your application has a better chance of working right.
–
Nathan PillingDec 19 '12 at 18:19

Since this is basically a CRUD application and the business logic consists of "Only the author can edit their post" I don't see much of a need to have a layer between the client-side stuff and the database. I would simply use validation on the CouchDB side to make sure someone isn't putting in garbage data and make sure that permissions are set properly so that users can only read their own _user data.

Well, placing your authorization (the security concerns) and logic validation away from Database provides separation of concerns in your software system. Thus you may test, maintain, scale and reuse your logical code blocks with less risks of braking the functionality in the system.

Providing ability for client input directly communicate with Database has very big potential to screw up the data.

This also means that avoiding/removing tight coupling make your software system more maintainable and SOLID.

I would normally agree with this, but I can test, maintain and scale code blocks within the client-side code just as easily as server-side. Doing it all in Javascript wouldn't be an excuse not to use proper separation of concerns. I'm simply moving the actual processing from the server to the client. So what is having the layer in between buying me?
–
Chris SmithDec 19 '12 at 15:18

2

Having client-side validation is nice for client, but having it in place on your server side is more critical than ever. Because, your client side request can be easily simulated. Having logical separations and/or tiers helps in sociability and maintainability.
–
YusubovDec 19 '12 at 15:24

So, playing devil's advocate: As I mentioned below, I could use CouchDB's validation functions to determine whether data being submitted is valid. Whenever you try to add or update a document, it would check that you're allowed and that it's correctly formatted. It puts more processing on the database side, but it is fairly lightweight and I need to consider scaling the data side anyway. Wouldn't this address the concern?
–
Chris SmithDec 19 '12 at 15:33

No, i don't think so. Placing your validation and authorization logic in DB is going to be performance hit on your system, once record numbers start to grow and you get more users on your system.
–
YusubovDec 19 '12 at 16:15

The DB engines are meant to store and retrieve the data, not to manipulate or validate it. Of course you can do it your way, but it is not the efficient way to follow.
–
YusubovDec 19 '12 at 16:16

Letting the user interact with the database directly seems really dangerous to me.

Is the authentication mechanism of CouchDB really so sophisticated that you can isolate the read- and write access of a user only to the data it is supposed to read and write (we are talking about per-document, maybe even per-document-field access privileges here)? What about "communal" data which is shared by multiple users? Doesn't this exist at all in your application design?

Do you really want the user to be able to change its data in ANY way? What about XSS injections, for example? Wouldn't it be better to have a server layer to filter those before they get into the database?

You bring up good points, and I thought the same thing. I came to the conclusion that in this (hypothetical) application, I'm okay with anyone reading anything EXCEPT user records. They can only write to documents that they have originally created (which is the only "business logic" I mentioned above). CouchDB seems to have the ability to do both of these things through their internal _users database and validation functions.
–
Chris SmithDec 19 '12 at 16:44

If your security checks and business logic are contained in your client side javascript, they can be overridden by a malicious user. As an alternative, you can leverage a JavaScript based server-side technology (like Node.JS) to handle validation, authorization, and the like.

Authentication and authorization would be handled by the database itself, so I wouldn't be trusting the client at all in that regard. CouchDB has built-in validation functions that fire whenever you try to update a document so I would use those to check that what is being submitted is valid.
–
Chris SmithDec 19 '12 at 15:30

The question was in fact about CounchDB so no sql to run here. Yet the idea is the same. I would presume that any non trivial application depends on data to respect some consistency rules that are checked/enforced by the application code. A malicious user can modify the client code to save data in a form that violates your business rules and might cause havoc in your application.

If your site considers all possible data states to be valid from a business perspective then by all means go this route but if this is not the case (likely) then you would want to have the guarantee that any data that gets stored is generated by your code and according to your rules.

CouchDB wouldn't know what to do with that, but I get your point. If permissions are set properly, the response to such a thing would be a 401 Unauthorized.
–
Chris SmithDec 19 '12 at 16:46

-1, when you post SQL code you obviously don't even know what CouchDB is. Also, just by creating an admin account on CouchDB you already prevent any other user from performing the most dangerous operations.
–
PhilippDec 19 '12 at 16:47

fair enough. i skipped the part on CouchDB in the question and only registered it as "access data store from client side JS directly". I'll edit response.
–
AZ01Dec 19 '12 at 16:51

1

+1, SQL or not, his point still holds. A JS debugger could be used to alter how data is accessed.
–
GrandmasterBDec 19 '12 at 16:55

I think that, given all of your assumptions, it's feasible to go directly from the client to the database. However, it's reasonable to look at whether your assumptions are valid, and are likely to remain so in the future.

I would be worried that in the future it might not be OK for everyone to read all the data, and especially that it might develop more business logic in the future. Both of these are more likely if the project is successful.

As long as you leave yourself a way to deal with these problems in the future when and if you actually need to deal with them I think your design will work. I think you will need to be extra careful to separate concerns in the JavaScript code, and some of it might end up be rewritten on the server later.

But I could definitely see where it might be worth a risk of maybe doing that later vs. the benefit of fewer moving parts today.

But what i would suggest is; Always try to maintain a segregation between your 3 layers. which are Presentation/Business and Database or DAO because that will be the best practice in those kinds of requirements and setups where there will be lots of changes every day.

In simple worlds your Presentation layer should not know about Database layer i.e. Format of some date type fields might be different from presentation layer and database layer so that user can have a freedom to select suitable format of the date as per his/her needs.

And Business Logic must act like a coupling between presentation layer and database/Dao layer like casting of the fields, some business validations, etc should be handled on Business Layer rather than in Javascript section as per your question.

This segregation will provide you great ease and comport during complex scenarios, functionality-es and even complex validations.
The best advantage is: you can have different technologies to implement these layers and can be changed as per the business needs or scope.

If you would like to build SQL in JavaScript and send it to the database, which verify the rights etc., than from security reason it would be a disaster. Simply because when you build an API, and build queries yourself, you have to analyse from the point of view of the security only the limited number of queries. If the queries are built outside your system, you have potentially unlimited number of tricks that someone could do.

But it's not the case since you are using key-value database (as fair as I understand, CouchDB generally falls into that category). The database interface itself is a kind of middle layer, and it is tested for security reasons by Apache team. Because of relatively simple JavaScript API this is even easier to analyse for potential flaws than such complicated interfaces that JSF applications have.

This can be a secure solution, if you do complex security tests. This can be even easier as when using frameworks such as JSF, which are often using hardly readable API behind. Security by obscurity is considered no solution.

Relating to your question, it won't be direct access to database anyway. Direct access would be the building SQL queries in JavaScript (unfortunatelly, I've seen such solutions). In your case the CouchDB itself provides the isolation layer. You could of course wrap it in your API to harden it, but as long as you can easily test what can particular user do and if the security constraints are working for you, you will have secure and robust solution without additional layers.

2. TMI Security Issue: Reveals way too much about how stuff works. Auth might still be an obstacle but finding an exploit is a Hell of a lot easier when you know exactly what's happening on the server-side.

Eh, not too worried about this. Most of the web now relies on Javascript anyway. I might just have to break out the <noscript> tags and tell them they need to turn it on if they want my site (and 80% of the other ones out there) to work.
–
Chris SmithDec 19 '12 at 15:19