I have been learning with Angular.js and used Parse as the back-end service. To post data to the Parse RESTful API, you would pass REST API key and App ID in the header of the request like this:
var config = {headers: {"X-Parse-REST-API-Key":"someapikey", "X-Parse-Application-Id":"someappid"}};
$http.post("https://api.parse.com/1/classes/myobject", obj, config).success (
function(data) {console.log(data);}
);
While this is great for learning, I am wondering how would the RESTful API for Parse or any other Backend-as-Service vendor work in a real html application. The API key and application Id would be exposed in JavaScript and anyone smart enough to view source could modify data to your account.
The only way I can image this to work would involve a proxy server that adds to Api Key/App Id header. However, this would defeat the purpose of not having to run your own back-end server. Am I missing something here?
Here's what you're missing :)
The Parse.com REST/JavaScript keys are designed to be "out-in-the-wild." With these keys it's not possible to get around object access rules or beforeSave validations. Only the master key can do this. Protect the master key. A useful analogy is public-key encryption: you need share your public key but protect the private key.
Can anyone modify your data? Yes, but only if you let them. Can users query data belonging to other users? Yes, but again only if you let them. Parse has a few ways to ensure data integrity and security.
The first is per-object permissions. Use the Parse.com web interface to set a) whether or not classes can be created on the fly and b) CRUD permissions for existing classes. One of the easier steps to securing an app is to disable any class permissions not explicitly required. For example, objects created on the back-end which do not need to be writable (or perhaps readable) by end users.
The second is access control lists (ACLs). ACLs are set on each record. They specify which users or roles can read or write the record. Records without an ACL are public (any user can find it). If Sue creates a record that should be private to her, set an ACL as such. Tom won't be able to find it without the master key.
The third is Cloud Code. You're able to enforce mission critical business rules and data validations using beforeSave/afterSave functions. Determine what is truly important, and make sure it's validated against in these functions. It's also a good idea to set the ACL explicitly in these functions. ACLs can be passed in when creating the object, but it's possible for the end user to tamper with these.
Here is are summary rule of thumbs for security and integrity.
Object permissions should only be as open as necessary to support your requirements.
Every record should have an ACL, unless you're sure it shouldn't.
Most ACLs should be set with before/afterSave functions.
Any validations that must be enforced should checked for in before/afterSave functions.
Last thing: it's temping to think of all business logic as "important" and insist on "perfect integrity." This is overkill for many apps. Make sure you have enough server-side protection in place such that one user can never cause harm to you or to your other users. There is not much sense in worrying much beyond this (other than support costs). If someone is experimenting with your app but is prevented from intentionally or unintentionally interfering with others, maybe they'll find a whole new way to use it :).
Parse provides several access keys that can be used via different APIs:
Client key (for use from iOS and Android applications)
Javascript key
Windows key
REST key
Master key (to be used for REST API access, but not conforming to object ACL permissions)
When accessing Parse from client-side javascript, you should use the javascript API with the Javascript access key.
In terms of security, you will not be able to prevent users from using an access key that is used by client side javascript. Parse provides powerful access control via ACLs attached to each object, allowing you to restrict read/write access to each class to specified users. You can also prevent clients from creating new classes in the settings of your app. Take a look at the security guide here.
Related
I am still new to Angular apps and wonder about some security concerns and would appreciate some tips on how to handle this.
Lets say I access my Amazon S3 Server from my Angular Application. That for I need to write somewhere my bucketname, accesskey and secret key... but since it is all visible to the user everybody can see the secret key which does not make him anymore secret of course.
I can also not use something like a SALT etc. to create user passwords for the same reason. All is visible in the end and even with minify and uglify anybody can reverse it as well.
What is the best approach to do things like this? So far I can only think of one thing and this is to not use javascript or angular at all in this cases and for example only access my S3 bucket via PHP. But this cant be the only way I hope?
For Firebase it looks the same problematic since everybody can see all infos right away and can connect basically to my DB and than add for example information he want to. Of course I can setup rules and make certain things obligated but this can be also sniffed out easy inside my code at the end which seems all pretty unsafe if I compare this to a php/mysql backend.
You can use the Cordova SecureStorage plugin to store access and/or session tokens:
https://github.com/Crypho/cordova-plugin-secure-storage
Since the Android implementation of this secure storage uses the KeyStore, the users must have a secure screen-lock set (like fingerprint, pattern or PIN). The plugin provides functions to check this, so you will be able to give a warning (or block login) if this is not the case. Without a locked screen there is no way to save your keys in a secure way on Android.
I'm setting up parse framework in javascript. I notice that I need to call
Parse.initialize("app", "secret")
Since this is in the page source, couldn't anyone take this and make calls against my account?
Is there a more secure way to store this info?
As per Parse Security Guide your JavaScript key is NOT secret:
When an app first connects to Parse, it identifies itself with an Application ID and a Client key (or REST Key, or .NET Key, or JavaScript Key, depending on which platform you're using). These are not secret and by themselves they do not secure an app. These keys are shipped as a part of your app, and anyone can decompile your app or proxy network traffic from their device to find your client key. This exploit is even easier with JavaScript — one can simply "view source" in the browser and immediately find your client key.
So yes, anyone who found your key can make calls.
But you can (and should) restrict what such anyone can do.
Using Class-Level Permissions you restrict what can be done with individual classes.
Using Object-Level Permissions you restrict what can be done with selected objects.
See also Roles and Roles Hierarchy for simultaneously setting permissions for a group of several users.
For instance, you can restrict access to only specific users. Only if one of those users is logged in, the access is granted. Any other "hacker" can try to use your keys but the request will be rejected by Parse.
We have used CouchDB in production, mainly building apps in controlled environments. Most times, we use a middle-ware library to make direct calls onto couchdb/cloudant, hence avoiding direct (Front-End JavaScript calls direct onto CouchDB/Cloudant).
For security reasons, it is obvious that for an authenticated CouchDB database: http://{username}:{password}#IPAddress:Port/DB OR for cloudant: https://{username}:{password}#username.cloudant.com/DB ,
If the call is directly made from JavaScript, Developer tools in the browsers today enable a person to realise this call and hence has access to your database entirely.
Attachments are usually painful when handled in the middle-ware. It is advantageous to make cloudant handle the caching and serving of the attachments directly to the front end hence relieving our middle ware from that. However, on the web and with a huge audience, making direct calls to our cloudant environment is tricky.
We started out by first of all having a separate cloudant account for all attachments such that, an inquisitive boy will not tamper with the actual meta-data or information of our users. So, the only cloudant account they can have access to is that of the attachments since we are making direct JavaScript calls to our database.
Question: How do we find a way in which we hide the Username and Password of our cloudant environment thereby allowing us to securely make direct JavaScript calls onto cloudant ? Our infrastructure is entirely in the cloud, so we don't have proxies and stuff to work with. We have heard of Url shortening services, CDNs e.t.c. but, we have not come up with a really conclusive solution.
Try using the _session endpoint. This will set up cookie authentication.
How do we find a way in which we hide the Username and Password of our cloudant environment thereby allowing us to securely make direct JavaScript calls onto cloudant ?
As far as I know you can't do that without using a middleware or some kind of proxy. But that does not mean we are completely defenceless. couchdb gives us some spears to poke inquisitive boy :)
So a good thing that you have done is to make the attachments database seperate. You don't mention in your question if you are using couchdb authorization scheme so I going to assume that you are not. So the first step is to create a user in couchdb _users database and then assign it as a member in the attachments database. More details here and here.
After this step you should have a member on attachments database. The reason we want a member and not an admin is that members do not have permissions to write or read design documents.
It's a start but it's not enough since a member can still read via _all_docs and that is a dos attack right there. So the problem we face now is that we do this at the moment
https://{username}:{password}#username.cloudant.com/DB
A very good move would be to change it to
https://{username}:{password}#someurl.com/
What's the difference between these two? Well it hides the location of your database and makes accessing built in methods harder. This can be accomplished with the help of vhosts configuration and some rewrite rules. Some very good stuff is on Caolan's blog too
With this in place you have got two things going for you.
The stalker inquisitive boy will be clueless where the calls go to.
There will be no way he can get the contents of unknown documents by making direct calls. He can only access your database through the rules that you set.
Still not 100% secure but it's okay as far as read level security goes. Hope this helps.
I'm trying to write a javascript single-page-app that allows users to login and then, once logged in, create/modify records in a database. I'd like to avoid having my own server side scripts if possible, instead using something like Parse.com, Kinvey.com, or Cloudmine.me.
My issue is that these services have user login capacity but use API keys to determine whether your app has write access. They don't seem to let you have write access once your user is logged in. The only way I can think of to accomplish this is to store a write-access API key in the user's user data, so I'd have the user login, fetch the hidden API key, then change the API key of the app to use that one, so they'll have write access. Obviously this isn't very secure because once that API key is sent over the network, that user will have write-access even if we delete their account or they change their password.
Perhaps I'm going about this the wrong way, so feel free to let me know. Hopefully this made sense. Thanks!
You should be able to restrict access to a group of users using Parse.ACL: http://www.parse.com/docs/js/symbols/Parse.ACL.html
If you want to control access on a per user basis then you will have to maintain a custom property on the user object. Then you can check the custom property in the BeforeSaveRequest() function and decide whether the user has write access: http://www.parse.com/docs/js/symbols/Parse.Cloud.BeforeSaveRequest.html
By default, most BaaS providers should provide collection level security and some even offer per entry security via ACL's (Access Control Lists).
Kinvey for instance has several variations on collection level security:
http://devcenter.kinvey.com/html5/guides/security#Collectionlevelpermissions
The default security level of Shared make it so the user has access to read everything in the collection but can only write to their own items. You may also want to use the Private security level to make it so you can only read and write to your own items.
If you want to have more fine-grained control over security you can utilize entry level permissions:
http://devcenter.kinvey.com/html5/guides/security#Entitylevelpermissions
With entry level permissions you can give fine grained access to a specific user or groups of users that you manage. You can even determine what level of security a user has to your entry, read or write. If you have a need to go even finer with control you have full access to write your own security utilizing Business Logic.
Full Disclosure - I am an engineer at Kinvey.
I am about to publish a demo JavaScript application based on eBay finding API on my personal website; I was wondering if there is a way to prevent my AppID from being read and exploited.
Is it possible to associate the AppID to a specific domain ? I haven't been able to find an answer neither on eBay Developer Forums nor in the official documentation.
If you send data to the client, the client can read the data. There is no way to prevent this (if JavaScript can decode it, so can the user). In order to avoid that, you need to keep the data (your AppID) on your site, and process the request on your server. So the JavaScript needs to talk to your server, and your server will then pass on the request to eBay, adding the AppID, and then pass the results back to the JavaScript.
To answer your question...
It doesn't seem possible to restrict AppIDs as the limits don't work on a per-site basis like that and you usually have just one AppID for all your uses/sites. See this comprehensive thread from 2010 (quoted below), I doubt much has changed. The end result is it basically doesn't matter for a read-only application such as search results on your website.
More generally about securing JSON API calls in-browser
Checking the referrer is the best way to secure an otherwise public API. This is how Google restricts their API keys for maps, for instance: https://developers.google.com/maps/documentation/javascript/tutorial
About the only thing that will prevent fraud is activity monitoring, given that the API is called from third-party computers, one would have to track trends for abuse, perhaps by comparing a list of calls to other website activity, or by using JSONP to inspect the browser's properties with AJAX. Google can cross-reference their API calls with their Google Analytics calls, for example, though there could always be false positives.
In the end, if the fear is CSRF, there's this: How to reliably secure public JSONP requests?
Quoting verbatim from the eBay thread in case the URL changes again:
There is one DevID per developer account.
There could be multiple AppID, but these are only available via paid support ticket.
Each AppID can have multiple CertID. The CertID determines your call limits.
You can generate unlimited tokens for each AppID. Each token is a pairing of AppID, UserID, and the associated eBay user's password. Tokens are currently active for 18 months. They must then be regenerated. Tokens can also be prematurely 'revoked' either via the API or website preferemces.
For the API families that require a token, you can use a single token based on your own UserID to retrieve most public information. However, private transaction details are only available when you use a token generated for the target UserID. Some calls actually derive the UserID from the token.
If multiple applications share the same AppID, they will both contribute towards the daily call limits. That's why you might want to request a separate AppID.
https://www.x.com/developers/ebay/ebay-api-call-limits
The limits shown in the chart are 'aggregate' for the given API family. There's an implicit per-AppID. For the Trading API, eBay further limits use on a per-call or per-time-interval basis. Some calls like AddItem have higher limits. GetApiAccessRules will return your actual limits and usage.
Per-IP-address means the IP address of the calling machine. If you were to rotate through multiple IP addresses, you'd actually multiply your limit. There are many read-only 'widgets' written in JavaScript or Flash which run in the client browser and thus use the client IP to make the calls. In that case, the call limit is pretty insignificant.
AppID, DevID and CertID belong to the creator of the developer account. That creator is bound by the API license provisions.
As the owner of the keys, you are not to allow any 3rd-party programmatic control of the API. Strictly speaking, that means that both the keys and any token derived from those keys should remain private (i.e. under your exclusive control).
Obviously, eBay does not enforce that strict interpretation since FetchToken is suggested for client-side applications. A sophisticated user could easily grab the token coming or going. What harm can someone do with a token based on their own UserID?
Burn through your daily call limit
Create an API application that violates the license
For more of the debate, see this earlier thread. (Link broken)
Once your application passes the eBay Compatible Application Check, you can request either 1.5M shared or 20K calls per user.
For further information about eBay's APIs, I suggest asking on their forum.