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.
Related
I've been working on a authorization service. It's a somewhat complex project, so I think it'll look good on a portfolio, but also it is a way to remove the reused code for every app I build. Just one central app where users are created, edited, allowed to set up security preferences and select what information to share. Users can have an account on my auth app, and share some info with other apps.
So not only do I have a create users, I've also given them the ability to create organizations and control certain requirements for auth on their apps, as well as create roles for users that have created an account on their app. This is where I'm having some issues. I'm using access and refresh tokens, rsa key pairs and jwts to authenticate each users on my site, but when creating an organization, I want to allow users to have multiple organizations if they want, and each organization should have it's own set of keys. While each individual org can set up their own authorization implementation after obtaining user info, they can only get that user info from the authorization server if they have the key associated with that app.
My problem is I don't know how I should implement this. I feel like I'll have to generate rsa keys, save one key to a database and have the organization save the other as a env variable. But should I save the public key to a db or the private? How do I even save a pem file to a db without changing the value? I'm just a bit lost on how this process can be accomplished with security in mind, but also while being dynamic. If I have to store private keys in my db then I'm very concerned about security as well. Can anyone break this down for me?
TLDR: trying to make google style universal login, need help storing and verifying rsa keys for organizations.
In Laravel, you can restrict access to some Controllers (eg. Admin-related controllers such as Admin/UsersController, Admin/SettingsController, etc.) to specific user sessions. Because it's server-side, the user has no-way to snoop-out about such controllers unless authenticated.
In the case of AngularJs's, the code resides in the browser. Thus, anyone can get a look at the javascript source codes and might figure-out the behaviour of the app. Say he might discover that there are controllers that manage admin-related data. Or anyone might try to brute-force-search the app's URL for javascript files to observe. Say he looks at http://myapp.com/AdminSettingsController.js in which authenticated users should only be able to see or should not at all.
Going back to the main question, how do you resolve such issues?
This problem has only one solution. Treat JavaScript as language for your User Interface only. Nothing more than that. Don't store any sensitive data in browser, don't store any sensitive logic (e.g. database queries) either. There is no way to hide network traffic or source code from client.
I usually create some sort of user object on client side, which contains users role for resolving permissions, and I use the permission for display controls, e.g. show some buttons only to admin etc. BUT, this only affects the displaying of the page, If user interacts with that controls, the controls rely on the server and if the user does not have proper permissions on the server as well, the interaction with the control fails, so if anyone with some knowledge change the user object on the client and grants him administrator role, he only sees the control what the administrator would see, but he can not make administrator actions nor he sees any sensitive data.
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.
What is the standard practice in Meteor for controlling users access for certain sensitive pages? For example, only users with Admin level can access CRUD operations, so what is the best method to block/allow users access these pages?
I know that we can use publish to limit the user accessibility to data, but for pages, what is the best way?
I am thinking of checking the user level during the rendered but again, I am not sure if this method is safe.
There is currently no method of denying access to a page, as the whole client code is packed and sent as one application. Since the code for restricted page is in the browser, user can access the page easily.
What you can do is to restrict access to data displayed on those pages. There are two things to be done:
Specify what data the user can see. This is done via the publish and subscribe methods. In the Meteor.publish method you can check user privileges and decide which objects user can see, and which fields of those objects.
Specify what data the user can change. This, as stated in the other answer, is achieved by Collection.allow and Collection.deny methods, which allow you to check user privileges on each CRUD operation and decide whether it's allowed.
The only places you need to control the user's level are in publish and in allow/deny callbacks. By controlling it in publish, you make sure the user does not receive any information it shouldn't know, and by controlling it in allow/deny callbacks, you make sure the user does not add/edit/delete information it's not allowed to.
If you're using custom methods for CRUD operations (on the server), this is a third place where you need to control the user's level (allow/deny callbacks are only checked against CUD operations made on the clients!).
Edit
For examples on how to use the allow callback, see http://docs.meteor.com/#allow The deny callback works in a similar (but opposite) way. At least one allow callback must return true and all deny callbacks must return false in order for operation to be granted.
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.