PouchDB security concerns, client-side permission logic - electron

I'm new to PouchDB but want to use it in my recent project. The main concern is of course security. I'd like to build a multiuser, desktop app (Electron-based) that allow users to modify documents in the same pouch/couch DB.
Because of some workflows some parts of the same documents should only be change by particular users. As I understand the only way to do it in Javascript/Pouchdb app is to add permission logic to client side JS, and that dosen't sound secure at all. Am I right? What is the real thread here? How easy it is to bypass client-side js permissions and change pouchdb document in an unauthorize way?
thanks for clearing that up

Once you give open code to end-user side (which is JS case) you should be ready to accept possibility of malicious code change client-side, that's obvious.
Since CouchDB manage write permissions on per-DB basis - malicios user will write to all docs in that DB if he has write permission there.
Consider per-user DBs and then combine your multipart final docs server side only or consider other DB.

Related

Use CloudKit Web Services' authentication flow in combination with Zapier

I'm developing a Mac app that uses CloudKit as its back-end. Some of my users are requesting the ability to ingest and extract data via an automation/integration service such as Zapier. For this, I need to introduce a web API.
I am planning to use CloudKit Web Services to access the app's data. This data is user-specific and hence, resides in a private database. As a result, CloudKit requires user authentication as described here.
Essentially the user needs to be redirected to an Apple-hosted authentication page. After successful authentication, an authentication token is provided that can be used for data operations. Similar to how OAuth2 works, but different enough to not work with Zapier's (or probably any other similar services) supported authentication schemes.
Who has done something similar? What are my options? I want to keep things as simple as possible and make my web API's implementation as thin as possible.
Thanks.
Niels
This is definitely doable and you are on-track with your thinking. Here's how I envision it working:
You could do all of this with a front-end web app (no server-side app needed). I personally prefer Vue.js but you probably have something in mind already.
Your app will need to authenticate the user to CloudKit using the flow you mentioned. I highly recommend you use the Web Services API and not try to wrestle Apple's neglected CloudKit JS API. For this, you are going to need to generate an API token in the CloudKit Dashboard.
You app would then prompt the user to authenticate to Zapier.
You should now have user credentials for both CloudKit and Zapier in place in the user's browser cache (you can save, for example, the CloudKit token to sessionStorage and likewise with Zapier).
Make API calls to Zapier, pull down the data, and then save it to CloudKit all within your JS app. It's all API transactions at this point. I'm a fan of Axios for making the HTTP requests.
If you are downloading files, transacting huge amounts of data, or doing processor-intensive stuff, you might consider using a server for that work. But if you just need a place to pull and push reasonable chunks of data, I see no reason why you can't do it all in a front-end app.
Alternatively, if you don't want a web app at all, and want to only have the user work in the Mac app, that can be done, too. Just make API calls directly to Zapier from within your Cocoa app. Whether or not this is feasible depends some on how you want it to work.
If you have more specific questions or need help with any of the implementation details, feel free to add a follow-up comment or ask a new question.
Good luck!
I think the other answer is mostly correct. I don't know much about CloudKit, but we can talk through what you'd need for it to work.
Let's say you had a simple iOS app that stored contacts. On the iOS side, Apple presumably abstracts the upload and download operations.
If you wanted to make a web viewer for synced contacts using CloudKit, you'd need an endpoint to fetch all rows belonging to the authenticated user (each of which would have a UUID, name, and a phone number). I believe that's possible with CloudKit code Apple provides (but let me know if I'm off base).
Now, we want to integrate with Zapier. Say, a "New Contact" trigger. You make some sort of authenticated HTTP request from Zapier to Apple on behalf of an authenticated user. It gives back a list of contacts and Zapier can trigger on the ones it hasn't seen before. To do that, Zapier needs some sort of user token.
That's where the little front-end page the other answerer mentioned comes into play. If you've got a web page that can surface a user's token to them, they can paste it into Zapier and all of the above becomes possible. I'm not sure what the lifespan of the token is, but hopefully it can be automatically refreshed as needed (rather than the user needing to take any manual action).
I'm not sure if what I've described is possible, but do let me know if it is. It would be huge if it were possible to integrate Zapier and the iOS ecosystem!
Edit to respond to comments:
Zapier won't be able to interact with CloudKit in a way sufficient for me (some minor business logic is needed)
I'm not sure what that entails for you, but it's common to put logic in the Zapier integration to structure data in a way Zapier expects. There's a full Node.js execution environment, so the sky's the limit here.
I don't think Zapier can authenticate against CloudKit as it uses a non-standard authentication scheme
Once you've got a user's token (described above, which is unusual), you will almost certainly be able to use it in requests to cloudkit. Zapier provides a "custom" authentication scheme which lets you do basically anything you want. So unless Apple uses something that fetch can't handle (unlikely), it should be fine (once you get the token).
I would like to push data directly from my app into Zapier and have it done whatever magic the user has configured
This is also probably possible. Zapier ingests data in two ways:
polling, where Zapier frequently makes a web request, store the IDs of items we've seen before, and act on the new ones. You can read more about that here. Assuming you can work your business logic into the integration, this is doesn't require an external server besides Apple's
webhooks, where Zapier registers a subscription with you and you send new data, on demand, to that address. This would probably require a webserver on your end to handle. It's optional though - you can do polling instead.
Hopefully this cleared it up a bit. Feel free to reach out to partners#zapier.com and reference this question to talk more about it.

Prevent attacker from decompiling iOS app and getting database access

According to this post, it's possible to decompile an iOS application.
How can I prevent an attacker from gaining access to my AWS DynamoDB database? Just having the access keys out in the open like shown on the Amazon developer guide doesn't seem like it would be very safe.
I would think that I could use keychain to store the keys, but I feel like there would be an easy way to get past this for a motivated attacker, given they have the app's assembly source code.
Currently, I connect using Amazon Cognito. All I have to use to connect are the identity ID and the role name. I don't see anything stopping an attacker from simply getting those values and connecting to the database.
For example, what stops an attacker from decompiling the Facebook iOS app code and deleting all of the users?
How can I prevent attackers from decompiling my iOS application and getting access to the database access keys, or at least prevent them from doing any major damage, such as deleting users?
Based on my admittedly limited experience, I'd say that a really motivated attacker will always be able to retrieve the credentials you use to access your database regardless of what you do to your executable. I would, however, question why you application needs to have direct access to your database in the first place.
The usual way to safeguard your serverside data is to use a web service to access it. App contacts web service with request, service contacts db, gets data, sends it back. Since the web service and the db are both hosted on your server and only the web service needs direct access to your db, there is no need to store db access info in your app. Problem solved.
It's impossible. In order for your program to do something, it must contain the instructions that allow the computer to follow to do that thing, which means anyone else can also follow those instructions to learn how to do the exact same thing.
You can use SQLCipher and use your auth's userToken and/or userId as cipher keys.

Is it possible to substitute a server backend using Dropbox?

I am developing an iOS application (to be deployed on the App Store) that requires content updates on a weekly basis.
I understand that the best way to achieve this would be to use a server, where the app would query for new data and download responses in JSON. However I am not knowledgeable when it comes to HTML, PHP or MySQL and therefore am endeavoring to find an alternative.
Here's an idea: using Dropbox to substitute for a server backend. My app connects to one central Dropbox account, checks for new files, and downloads them if present.
Is this idea feasible? If not, are there any alternatives?
Dropbox cannot be a dependable substitute for your server/backend for following reasons:
Dropbox uses OAuth for authentication, which needs user interaction. You do not want your app users to go through Dropbox authentication with your 'common' credentials.
Users who have a Dropbox account or the app installed, will most likely use their own credentials to login which completely breaks your flow.
Drobox, although a good way of sharing and syncing files is not meant for more meaningful data like web services etc or user/database interaction etc. Just syncing JSON file may suffice your app's needs for now but from a long term perspective you want a proper back end.
As suggested in the comment by #tkanzakic you can use one of the substitution services if you don't want to get too technical on the backend.
I am pretty late to the party, but this is possible and not necessarily a stupid idea (though this depends on what you need). You might want to have a look at remote storage for example, which allows you to use Dropbox among other providers as backend.
For sure, you can use the Dropbox Sync API to achieve this (https://www.dropbox.com/developers/sync).

Dart Web App with Access Control Measures

So I am currently evaluating Dart's use as a potential language to re-write a campus organization's website. One critical aspect of this website is it's access control policies. It seems that anything written within the Dart web apps could potentially be compromised, and thus led me to asking the following question.
Is it possible to securely implement access-control to pages in Dart, using either just a web app or a combination of a web app and a dart-implemented server? Could it also be possible to implement that same concept using Apache with a proxy-passthrough to dart?
I don't understand what you actually want to achieve with a proxy-passthrough.
When you create a single page app in Dart all client code is loaded to the client. This is normally no security concern. When a view is shown it usually loads data from a server. Here you enforce security.
You can require the user to authenticate and decide in the server code if or which data you serve for this user or what update command you allow the user to execute. You can just return an error when the user invokes a function that he is not allowed to use.

Using OAuth in free/open source software

I'm now reading some introduction materials about OAuth, having the idea to use it in a free software.
And I read this:
The consumer secret must never be
revealed to anyone. DO NOT include it
in any requests, show it in any code
samples (including open source) or in
any way reveal it.
If I am writing a free client for a specific website using OAuth, then I have to include the consumer secret in the source code, otherwise making from source would make the software unusable. However, as it is said, the secret should not be release along with the source.
I completely understand the security considerations, but, how can I solve this dilemma, and use OAuth in free software?
I thought of using an external website as a proxy for authentication, but this is very much complicated. Do you have better ideas?
Edit:
Some clients like Gwibber also use OAuth, but I haven't checked its code.
I'm not sure I get the problem, can't you develop the code as open source retrieve the customer secret from a configuration file or maybe leave it in a special table in the database? That way the code will not contain the customer secret (and as such will be "shareable" as open source), but the customer secret will still be accessible to the application.
Maybe having some more details on the intended platform would help, as in some (I'm thinking tomcat right now) parameters such as this one can be included in server configuration files.
If it's PHP, I know a case of an open source project (Moodle), that keeps a php (config.php) file containing definitions of all important configurations, and references this file from all pages to get the definition. It is the responsibility of the administrator to complete the contents of this file with the values particular to that installation. In fact, if the application sees that the file is missing (usually on the first access to the site) it will redirect to a wizard where the administrator can fill the contents in a more user friendly way. In this case the customer secret will be one of these configurations, and as such will be present in the "production" code, but not in the "distributable" form of the code.
I personally like the idea of storing that value in the database in a table designed for it and possibly other parameters as the code needs not be changed. Maybe a installation wizard can be presented here ass well in the case the values do not exist.
Does this solve your problem?
If your service provider is a webapp, your server needs consumer signup pages that provides the consumer secret as the user signs up their consumer. This is the same process Twitter applications go through. Try signing up there and look at their workflow, you'll have all the steps.
If your software is peer-to-peer, each application needs to be both a service provider and a consumer. The Jira and Confluence use cases below outline that instance.
In one of my comments, I mention https://twitter.com/apps/new as the location of where Twitter app developers generate a consumer secret. How you would make such a page depends on the system architecture. If all the consumers will be talking to one server, that one server will have to have a page like https://twitter.com/apps/new. If there are multiple servers (i.e. federations of clients), each federation will need one server with this page.
Another example to consider is how Atlassian apps use OAuth. They are peer-to-peer. Setting up Jira and Confluence to talk to one another still has a setup page in each app, but it is nowhere near as complex as https://twitter.com/apps/new. Both apps are consumers and service providers at the same time. Visiting the setup in each app allows that app to be set up as a service provider with a one-way trust on the other app, as consumer. To make a two-way trust, the user must visit both app's service provider setup page and tell it the URL of the other app.

Resources