Secure client-side couchApp / couchDB user authentication - authentication

Background research:
User Signup in Couchapp/CouchDB through jquery.couch.js or Otherwise
http://blog.couchbase.com/what%E2%80%99s-new-couchdb-10-%E2%80%94-part-4-security%E2%80%99n-stuff-users-authentication-authorisation-and-permissions
https://issues.apache.org/jira/browse/COUCHDB-1175 - specifically "Ari Najarian" 's posts
Question:
To paraphrase the SO question I posted above:
"Essentially I want to have a signup form for registering an account in couchdb for a couchapp. This would entail creation of a new user in the couchdb _users database, and the creation of a new database, with the new user assigned the role of database admin. All that requires server admin credentials."
The answer to the previous question involved using an external separate server that was logged in to couchdb as admin to monitor couchdb and modify couchdb as desired in response to certain data events coming from a client.
My question is - is that the only way? Doesn't that defeat the whole purpose of couchdb's 2-tier web stack? Is there some way to modify a couchdb database from within a validation function which checks for "type == user" document while "internally"/separately logged in as an admin maybe?
I apologize if there is some straightforward way to do this and I just didn't find the right documentation.
Extra Problem Clarification:
There is the couchdb instance sitting at an internet address.
This couch database serves to a random client an html page and embedded javascript script that contains a signup/login form.
The client enters signup info (name, password) and submits
The JS script uses the XMLHttpRequest object to open a connection to the couchdb instance and sends...PROBLEM!
Problem #1 - If the credentials are stored in the code (to be sent as verification for new user database), then anyone could "view html source" and take over the database.
-OR-
Problem #2 - If credentials are not supplied and the request is sent anonymously, then a new user will be created in the _users database and a success reply message will be sent. But no new database was created for the user (and can't be without admin credentials) which the user can interact with for application-specific purposes (e.g. add/delete data). And - from the above couchbase blog link - if you have secured your database with roles/names against anonymous readers and validation functions to prevent anonymous writes, then an anonymous-made user account (e.g. a client who wants to register database space to use the app) can not do anything because an anonymous user cannot, for obvious security reasons, specify whatever roles they wish to have. Which means that the only way to have -functional- users is to create user accounts + associated databases as admin beforehand and then hand out these user credentials - so like a private invite system, yes?
To reiterate, is there any way, using ONLY couchdb and some combination of couchdb's authentication handlers, design document functions, client-side ajax, etc. for a connecting client to register and get a personal database (and ONLY that database obviously) they have access to and can interact with?

This isn't a PURE couch solution, but it's couch + node, and solves your problem:
Hi I haven't been around in awhile and didn't realize this was edited / link removed (plus policy of links not being answers! sorry...). I have been using couchdb on a project very similar to what you are trying to do, and unfortunately there is no way to do what you want to accomplish without tacking on another service to handle the admin-level access and creation of user database. Syncpoint-API can be used to facilitate this, but it is actually a nodejs service handling the signup/login and dedicated database setup.
So far though, Syncpoint has proven to not be 100% reliable and it does appear to be an abandoned project, due to CouchBase sucking all the r+d resources away from CouchDB dev.
I'm now moving to nodejs + socket.io as a transport layer, using node to handshake and assign a DB, and then further watching the couch _changes api on the server (via yet another node process) to then forward _changes through socket.io to the client. Also I have some "pure" couchapps running that serve public data mixed in with the private data.
My conclusion? CouchDB is a great product and has some great features, but for the more complex login/authorization schemes and other general application needs required in real-world dev, it's just not ready yet.

Related

Restrict access of a connected app (Salesforce)

What is the best way to restrict the scope of a connected app to a set of objects? My current solution is to use the Manage user data via APIs scope but that still grants more access than required.
A solution I see frequently is to create a user with a restricted profile and connect with that user but then you lose context of actions made by users in the connected app so this solution doesn't work
Tricky, you typically don't. (consider posting on https://salesforce.stackexchange.com/, there might be a clever way I didn't think of).
You can flip the connected app from "all users can self authorise" to "admin-approved users are preauthorised" and then allow only certain profiles / permission sets to use the app. But the bulk of it is "just" enabling the connection via API and cutting it to say Chatter only or OpenId identifiers. And that's already an improvement compared to SOAP APIs where you don't have scopes and the app can completely impersonate the user, do everything they can do in UI.
Profiles/permission sets/sharing rules are "the" way even in not immediately obvious situations like Lighting Connect Salesforce to Salesforce or Named Credentials access to another org.
If you can't restrict the visibility with profiles and access to all tables user can see is not acceptable...
you could create series of Apex classes exposing certain queries, updates etc and grant profile access to these classes - but without full api access? You could even let them pass any SOQL (evil) but use with sharing, WITH SECURITY_ENFORCED, stripInaccessible + custom restriction on tables before returning results
you could look into https://developer.salesforce.com/docs/atlas.en-us.238.0.apexref.meta/apexref/apex_class_Auth_ConnectedAppPlugin.htm although I suspect it's run only on connect, not on every request. So at best you could deny access if user has right to see some sensitive data, not great
if there are few objects you need to block updates if done via app - Quiddity might be the way to go. Throw error in a trigger if action started from REST context?
give the Transaction Security trailhead a go. If it looks promising (there's way to check "application" and "queried entities" according to this) - might be a solution. You'll likely have to cough up $ though, last time I checked the cool bits of event monitoring & transaction security were hidden behind an extra paid addon (standalone or bundled with platform encryption and Field Audit Track into Salesforce Shield solution)
2 logins? dedicated user for querying stuff but inserts/updates running as your end user?

Authenticating Cloudant one db per user

I apologies in advance - for this question needs a bit of background, which is likely to be long winded:
I'm trying to build an app which works offline with PouchDb. PouchDb will sync with Cloudant.
Technologies used:
Hapi, SQL, Vue, Cloudant, PouchDb
I have built a little hapi.js service to sign up / authenticate users. When an "account owner" signs up - they are added as a new user to a SQL database.
Using Cloudants API, I provision a new database (with a random name), and set security on the database so the new user has access.
I save the security (DB name, User name, and password) as metadata back to the user in the SQL database.
A very similar approach to here: https://www.bennadel.com/blog/3208-provisioning-cloudant-couchdb-databases-from-auth0-for-a-database-per-user-architecture-in-angular-2-4-1.htm (indeed, I based the above on this).
When the "account owner" logs in, the SQL DB is queried - the MetaData retrieved and sent down to the client side vue app. The PouchDB remote string is then populated with the Cloudant DB name, User name, and password.
eg:
const remoteDB = new PouchDB(`https://${name}:${pass}#0000-0000-bluemix.cloudant.com/${DBname}`);
This all works: PouchDB can talk to Cloudant - and data is going to and from without issue.
The "Account owner" is able to give read/write access to other people ("Staff") to their cloudantDB. When they add a new Staff Member, the Staff Member is added to the SQL DB. Using cloudants API, I create new security credentials for this user so that they can access the DB- (I do NOT create a new DB) and save them to the Staff Member in the SQL db as metadata...
The new staff member is sent an email - they set their username and password on the SQL db, and can log in. The Cloudant meta stuff is picked up... etc etc... PouchDB / Couchdb talks to each other - this also works.
Initially I was a bit concerned about sending this meta / credentials down to the client - I wanted to use a JWT or something... But then I saw this answer to another question:
https://stackoverflow.com/a/30417620/714950
So passing credentials down seems to be how its done in Pouch/Couch/Cloudant etc. I've got to be honest - I find the whole thing works like 'magic' - like its too good to be true, and that worries me a bit as I don't really understand it. I might be doing something terribly wrong.
Now for my question(s):
I'm passing these credentials down - is this safe? How would I reset / time out the username and password.
When they log out, I wipe the data from Pouch?
Can a user be 'logged in' and lose connection? Will pouch sync when they reconnect?
If pouch has NOT synced - and they log out (and I wipe Pouch) that would mean they would lose their data? so I guess I would need to persist the data in Pouch for when they log in again?
But what if they are using a shared computer? This data would be sat in Pouch DB waiting for someone to log in?
I'm also unsure how I validate the data... making sure that which gets saved to the DB is valid etc...
I suppose I'm just trying to get my head around this - I've been googling and reading everything I can, but it doesn't quite answer my questions.
Thanks
[** Just had a thought...
Thinking about it, I don't actually need to create the staff user within the SQL DB.
The Account Owner is set up - the DB is created in Cloudant, and credentials applied.
Not just had a thought: Theoretically, when a staff member is added - I only need to set them up inside Cloudant, and write their ID to the "Account Owner" as meta data so that they can be removed etc.
This way, a staff member could log in directly to the Cloudant DB.
However, I generate the security credentials using Cloudants API - so the staff member won't know what their username and password is. I don't want to send the username and password in an email.
Is there a way I can handle this? Am I able to specify a username and password when creating the security credentials? How do I handle things like password resets on cloudant?]
Thanks
I'm passing these credentials down - is this safe?
If your site is served out over HTTPS, then a bad actor would find it difficult to glean the Cloudant username & password in flight. Your client-side app needs to retain the credentials for your app to be "logged in" (for it to retain the right to sync with the server). I like to retain the data in a PouchDB document (e.g. _local/auth - local documents are not replicated so reside only on the device you create them on). You are right to be concerned, however, about having database credentials floating about on a client-side computer. Some folks decide that that is not acceptable and implement their own middle layer. If you don't need sync (that is data can be altered at both client and server side), you might use PouchDB as a buffer for unsynced data and push it to your own API when you're online. You can then control authentication, timeout and access to the database from your own server-side code.
How would I reset / time out the username and password.
You can "log out" by:
deleting your client-side state e.g. deleting the _local/auth document.
making the key/password have no permissions on the client side. Without _reader/_writer/_replicator rights, a Cloudant api key and password is useless
Alternatively you could transmit the username & password to the client which could use them against the Cloudant POST /_session endpoint which gives the web browser a time-limited cookie. Your app could then "forget" the credentials until it needs them again.
When they log out, I wipe the data from Pouch?
Yes.
Can a user be 'logged in' and lose connection? Will pouch sync when they reconnect?
If you write your client side app correctly, it could function perfectly well with its local PouchDB data, whether it has an internet connection or not. This is known as an Offline First approach. As long as your credentials are still valid, your app can sync when a connection is re-established.
If pouch has NOT synced - and they log out (and I wipe Pouch) that would mean they would lose their data?
Correct. If you have only one copy of some data and delete it, you lose data :)
But what if they are using a shared computer? This data would be sat in Pouch DB waiting for someone to log in?
Correct. On a shared computer, another user's data may be visible to the second user. Just as if I left my Facebook session logged in on a shared computer.

Remote access to laravel models

Is it possible that a website uses the models of another lavarel website to access the database, without the first website having the sql credentials hardcoded. But with the credentials to log into the second lavarel website hardcoded.
This way the first website doesn't have to have the sql credentials on it's ftp server, but can still access the databases through the other website (with their personal login of that website).
If that is impossible, I am wondering, is there a way to access a databases without having to hardcode the credentials anywhere.
UPDATE (the actual problem)
Only a part of the database should be visible to a particular user, so i can provide different users with different credentials and they all see something different in the database
What you are talking about is an API. So you'd build out the entire infrastructure on the first website, then on the second website, it would make some kind of calls to the first website to get back the information it needs, usually using some kind of credentials or access token.
This way, you can allow anyone in the world to communicate with your website, kind of like how Facebook, or Twitter does.
As far as accessing your database, you would need to tell your app somewhere the credentials to use, so technically, you do need to hardcode them somewhere as they can't just magically make up some credentials somehow to access a database.
if your different users are defined:
use laravel model/db event to replicate the data to a database by
user.
Or sync each database with a cron job..
These have benefits to avoid security transport problems.

Website and Native app user authorization

I wish to create a functionality that is very similar to facebook or pokerstars if you have used them before. Basically the apps require the user to login and their information can be accessed from both browsers and native and web apps.
How can I go about achieving this? Please advice on what services to research on to accomplish this. To my current understanding. I would be creating the website in html and php and creating a webservice using RESTful protocols and hosting them on amazon aws servers. I can then connect to these servers in the native apps? I am not very clear on how the native apps will interact with the servers
If you know of any particular protocol or a better server hosting service please let me know.
If I'm interpreting your question correctly, you are looking for something like this:
The user starts either your browser app or your native app (perhaps a mobile app)
Since the user does not have an account yet, you present them with the appropriate dialog to create said account.
You then ask the "Identity Service" to create a profile for that user
The identity service returns a token for access
This is something we do in the mobile network industry all the time. Technically, we have TAC/ACS or HSS profile services, but in either case, it's the same thing -- a dedicated service and network process that:
Accepts connections from various clients (web, mobile, desktop...)
Has various primitives along the database CRUD (Create, Read, Update, Delete) model
Answers requests the database
If you want a pre-configured solution, you could just use any networked database with a RESTstyle connector for example (MongoDB maybe?) But you could also just through this in a process that talks to a NoSQL or SQLLite database. The end result is the same.
For commercial solutions, I might like at OpenStack as you can run your code on it and they have identity brokers you might be able to CoOpt.
Personally, I'd just have a datastore running on a cloud somewhere like Amazon's EC2 which answers RESTful requests such as:
Create a user with a given profile set, return a unique token
Delete a user given a token
Update elements of the profile for a given token
I'm leaving out the necessary things like security here, but you get the idea.
This also has the advantage that you can have a single identity service for all of your applications/application services. The specifics for a given application element are just sub-fields in the profile. This gives you, not only a common identity broker for web, desktop and mobile, but a single-sign-on for all your applications. The user signs in once and is authenticated for everything you have. Moving from site to site, now just became seamless.
Lastly, you place your identity management, backup, security token management, etc OUTSIDE of your application. If you later want to add Google Authenticator for second-factor authentication, you don't have to add it to every application you have.
I should also add that you don't want to keep the identity database on the direct internet connection point. Someone could make your life difficult and get ahold it later on. Rather, you want your identity server to have a private link to it. Then do something like this:
When the account is created, don't store passwords, store hashes -- much safer
Have your application (web or otherwise) compute a key as the login
In this case, the user might enter a username and password, but the application or website would convert it into a token. THAT is what you send across.
Next, using that token (and suitable security magic), use THAT as the owner key
Send that key to the datastore and retrieve any needed values
Encrypt them back into a blob with the token
Send the block
THe application decrypts the blob to get at values
Why do we do this?
First, if someone were to try to get at your identity database, there's nothing useful. It contains only opaque tokens for logins, and blobs of encrypted data. Go ahead -- take the database. We don't care.
Second, sniffing the transport gets an attacker nothing -- again, it's all encrypted blobs.
This means later on, when you have five applications using the broker, and someone hacks the network and steals the database, you don't care, because your users never gave out logins and passwords in the first place, and even if they did, the data itself is garbage to anyone without the user key.
Does this help?

HTML5 Web Database Security

Should the HTML5 database be used to store any form of private information?
Say we have the following scenario;
You're browsing a web-mail client, that uses the web database to store mail drafts after you've written some information you close the web browser. What's to stop me from getting access to this information?
If the webpage tries to clean out old information when opened a user-script could easily prevent the website from fully loading and then search through the database. Furthermore the names of databases and tables are easily available through the web-mail client's source.
W3C Draft
The only way an external party could access the user's database is via direct access to the user's computer, or if your web app has a security vulnerability (such as XSS - Cross Site Scripting). Otherwise standard browser security dictates that only scripts running in web pages from a certain domain can access databases that were created/stored on that same domain (same origin-policy), same thing that stops you making cross-domain Ajax requests, or reading other website's cookies, all of which can be overcome via an XSS attack.
To me, storing a draft email seems reasonably sensible, whereas things like credit card details, passwords etc. should be stored exclusively server-side. You'll need to make a call as to what should be stored where, based on what you're going to store.
Should the HTML5 database be used to store any kind of private information?
Depends on how sensitive the information is. I wouldn't want to leave credit card details lying around anywhere.
You're browsing a web-mail client, that uses the web database to store mail drafts after you've written some information you close the web browser. What's to stop me to get access to this information?
Assuming you don't have physical access to the computer (in which case the user needs to take relatively extreme security measures) and you don't run the email service (in which case you need to have access to emails) then standard browser security stops you.