Grails acegi plugin user recommendation - security

I'm about to add security to my Grails App, and I'd like to know from your experiences what's the best approach:
To add fields to the Person Domain class (such as phone, address, etc.)
To create an independent Domain class and map it one to one to the Person class

We are using a data model that has separate domain classes for Phone, Address and other related properties and associate them to the User domain using lazy loading. This accomplishes the accessibility that we needed while keeping the object size under control.

I suggest you use the http://grails.org/plugin/acegi plugin and add properties to the User class if they are directly related to the concept of an account and where it makes sense to have them loaded every time you access the user.
Remember that the user object is going to exist in the session for as long as a user is logged in and this means that it will become disconnected from the hibernate session (you can't just call save on it) and will also need to be serializable if you cluster the app.
I would not add phone number or address to my user object but I might add email address (you'll probably have to search users by email at some point) or a link to a profile picture (as you might be displaying this all over your site and not want to keep loading it).
I like to keep the user object small and avoid the temptation to add accessors for every table that contains a user id.

Related

Which back-end design choice is better for handling guest users? Storing guests as users with is_guest feild, or storing guest data on the session?

I am building an ecommerce website which should be able to handle guest checkout. When a user visits the website, they are considered "Guests" unless they register / log-in to their account.
However, even as a guest, certain information needs to be stored about that visitor (partially incase they make an account in the furture, but also just for the website to function for them) like their prefered currency, email (if provided), cart and its contents, and an order_id (if they placed an order)
My question is which of the following choices would be better for handling this?
By the way: I am using NodeJS's express-session in this project.
Creating a "User" object for all new visitors and adding the user_id to the session. In this case that user object would need a feild called is_guest: true/false to tell the two apart, and it would also need a is_logged_in: true/false feild so the front-end can tell whether to load the log-in form or the profile page because a user object would always be present.
Only creating a "User" object after an account has been registered through the register form, and storing all data about the cart and email ect. for guests on the session object instead.
I can see problems with both. 1) could result in a really large database if all new visitors create a user object. 2) could result in information being scattered more and the session object becoming cluttered (especially if the cart becomes large). Having never done something like this before, I would appriciate any ideas about objections or solutions to the approaches and what you think would be the best.
Both solutions are fine, and I've seen both being used.
I would guess that storing things in the database is more common. Since you will probably be logging user interactions in your database anyways, it won't take up much more data. Secondly it's slightly simpler to use the same function to render pages for logged-in and logged-out users.
If you don't use a database, you may wish to use LocalStorage instead of a cookie since there are size limits to cookies (although few carts will get large enough to reach that limit).

symfony user login restrict to subsite

I've got a Symfony application that has multiple subsites.
Each site has it's own set of users, but all users are stored in the same table. All users are linked to 1 subsite, never 2 or more.
Allowing a user to use a single account on multiple sites is not an option given the use-case of this website.
I've got a RequestSubscriber which figures out what site is currently being requested (based on hostname) and pushes some extra information into the Request object attributes.
When a user attempts to login Symfony should only attempt to load users from the current subsite, not all users.
I've got a Doctrine Repository class that implements the loadUserByUsername method, but this only receives the requested username.
What would be the best way to adjust my UserProvider so only users from the current site are attempted to be loaded?
Can I configure the security in such a way additional information is passed?
One possible solution I've already got is to inject the RequestStack into the Repository class, and use that to add additional parameters to my query.
I would need to write a decorator for the Doctrine EntityManager to make sure it is injected when the Repository is requested, but that is not really a problem.
I don't really like this solution, so I'm looking for better alternatives (if any).

Kentico ECommerceContext.CurrentShoppingCart for guest and authenticated user

Is it possible to have the same ECommerceContext.CurrentShoppingCart object returned irrespective of whether the user is logged into Kentico or not ? Currenty the object and consequently the contents of the of the shopping cart changes when the user logs in or out.
There is no out of the box functionality to override this behavior. I definitely wouldn't recommend to override UserInfo.IsPublic(). You'll have to create your own class and re-implement the CurrentShoppingCart property. Have a look in the source code or use some .NET reflector to see the actual implementation. As far as I can see there are no private members that you wouldn't be able to access so it should be piece of cake.
You can set or clear the CustomerID associated with the Cart on log in/log out respectively if you want to synchronise the state of the cart with the identity of whoever is/isn't authenticated.

parse.com security

Recently I discovered how useful and easy parse.com is.
It really speeds up the development and gives you an off-the-shelf database to store all the data coming from your web/mobile app.
But how secure is it? From what I understand, you have to embed your app private key in the code, thus granting access to the data.
But what if someone is able to recover the key from your app? I tried it myself. It took me 5 minutes to find the private key from a standard APK, and there is also the possibility to build a web app with the private key hard-coded in your javascript source where pretty much anyone can see it.
The only way to secure the data I've found are ACLs (https://www.parse.com/docs/data), but this still means that anyone may be able to tamper with writable data.
Can anyone enlighten me, please?
As with any backend server, you have to guard against potentially malicious clients.
Parse has several levels of security to help you with that.
The first step is ACLs, as you said. You can also change permissions in the Data Browser to disable unauthorized clients from making new classes or adding rows or columns to existing classes.
If that level of security doesn't satisfy you, you can proxy your data access through Cloud Functions. This is like creating a virtual application server to provide a layer of access control between your clients and your backend data store.
I've taken the following approach in the case where I just needed to expose a small view of the user data to a web app.
a. Create a secondary object which contains a subset of the secure objects fields.
b. Using ACLs, make the secure object only accessible from an appropriate login
c. Make the secondary object public read
d. Write a trigger to keep the secondary object synchronised with updates to the primary.
I also use cloud functions most of the time but this technique is useful when you need some flexibility and may be simpler than cloud functions if the secondary object is a view over multiple secure objects.
What I did was the following.
Restrict read/write for public for all classes. The only way to access the class data would be through the cloud code.
Verify that the user is a logged in user using the parameter request.user ,and if the user session is null and if the object id is legit.
When the user is verified then I would allow the data to be retrieved using the master key.
Just keep a tight control on your Global Level Security options (client class creation, etc...), Class Level Security options (you can for instance, disable clients deleting _Installation entries. It's also common to disable user field creation for all classes.), and most important of all, look out for the ACLs.
Usually I use beforeSave triggers to make sure the ACLs are always correct. So, for instance, _User objects are where the recovery email is located. We don't want other users to be able to see each other's recovery emails, so all objects in the _User class must have read and write set to the user only (with public read false and public write false).
This way only the user itself can tamper with their own row. Other users won't even notice this row exists in your database.
One way to limit this further in some situations, is to use cloud functions. Let's say one user can send a message to another user. You may implement this as a new class Message, with the content of the message, and pointers to the user who sent the message and to the user who will receive the message.
Since the user who sent the message must be able to cancel it, and since the user who received the message must be able to receive it, both need to be able to read this row (so the ACL must have read permissions for both of them). However, we don't want either of them to tamper with the contents of the message.
So you have two alternatives: either you create a beforeSave trigger that checks if the modifications the users are trying to make to this row are valid before committing them, or you set the ACL of the message so that nobody has write permissions, and you create cloud functions that validates the user, and then modifies the message using the master key.
Point is, you have to make these considerations for every part of your application. As far as I know, there's no way around this.

How can I write a "user can only access own profile page" type of security check in Play Framework?

I have a Play framework application that has a model like this:
A Company has one and only one User associated with it.
I have URLs like http://www.example.com/companies/1234, http://www.example.com/companies/1234/departments, http://www.example.com/companies/1234/departments/employees and so on. The numbers are the company id's, not the user id's.
I want that normal users (not admins) should only be able to access their own profile pages, not other people's profile pages. So a user associated with the company with id 1234 should not be able to access the URL http://www.example.com/companies/6789
I tried to accomplish this by overriding Secure.check() and comparing the request parameter "id" to the ID of the company associated with the logged in user. However, this obviously fails if the parameter is called anything else than "id".
Does anyone know how this could be accomplished?
You could have a simple #Before function, or if it is only on the view page that you want to apply the security, then you could have a simple bit of code at the beginning that checks the user's id (I assume from the session), and checks that they are allowed to access the page, by getting the User form the id in the session, and the Company from the id passed in, and checking against each other.
If security fails, then either return a badrequest instead of render, or call an action that shows a notAuthorised custom page.
You could make a SecureProfileController class that extends Controller, has a method that does the checkCompanyId-that-is-to-be-viewed against users companyId, and let the controllers that need that logic extend the SecureController.
If the method is an #Before function, like Codemwnci says, then it can intercept all the action methods in the inherited classes.
Alternatively you could have a look at Deadbolt, where you can setup roles for users and restrict access based on those roles: http://www.playframework.org/modules/deadbolt-1.0/home
Hope that helps :)

Resources