I am using the Grails security plugin on a project. I am using the annotations on controller actions to restrict access to certain classes of users such as 'ROLE_ADMIN' or 'ROLE_USER'.
(using this as the basis for what I am doing: http://grails-plugins.github.com/grails-spring-security-core/docs/manual/guide/5%20Configuring%20Request%20Mappings%20to%20Secure%20URLs.html#5.1%20Defining%20Secured%20Annotations)
My question is, how do I restrict an action so a user can only see information about themselves. For instance, lets say I have a user with id = 1. If I have an action that shows information about the user at:
mySite/User/Show/1
how do I prevent that same user with id=1 from being able to access
mySite/User/Show/2
? Is there a simple way to do this?
You can also use Grails controller interceptor if you want to apply same logic to multiple actions
class SomeController {
def beforeInterceptor = [action: this.&checkUser ]
def springSecurityService
def checkUser() {
User user = User.get(params)
User logged = User.get(springSecurityService.principal.id)
if (user.id != logged.id) {
{
redirect(action: "accessDenied", controller='access' id: params.long("id")) //re-direct accessDenied page
return false
}
return true;
}
}
Class AccessController{
def accessDenied= {
render(view: "accessDenied")
}
}
What will be the problenm with the following?:
class SomeController {
springSecurityService
// other stuf ...
def show () {
User user = User.get(params)
User logged = User.get(springSecurityService.principal.id)
if (user.id != logged.id) {
flash.message = "You can't see the profile of other users"
redirect action:"list" // You can redirect to other controller/action
return //Since grails 2 this is needed
}
// Logic for display your user
}
// other stuf ...
}
what you are asking is part of your business rules. So you are supposed to take care of these scenarios in your code rather than looking out for some plugin or helper code.
What you can do for this is, make sure id of the user accessing the user details is same as id of the user whose details are being questioned.
You can also make this check at object level but that will mean an extra query to database to fetch the user details.
Hope this helps.
I have to agree that you are trying to implement a business rule with a security aspect. If a user created some kind of document, you would not use authorization to select what is visible on their profile page, would you?
You have to draw a line on where the authorization aspect reaches and where business rules start.
In my experience, to avoid blurring the lines, i always use authorization roles as types of users associated to a set of functionality. A specific user type can have access to a series of stories, or use cases. These use cases are constrained to specific roles.
If you start asking questions about data visibility (what is hidden on a page, depending on whatever business factor), then you should stay clear of your security framework
I would disagree that you need to redefine your business logic vs security logic. It is a common use case and authorization should cover it. This is why Grails has filters. Use an authorization filter to add functionality like this:
class AuthorizationFilters {
def filters = {
userCheck(controller: 'user', action: '*') {
before = {
// Check current user id is param.id here
}
}
}
}
Thus your security logic is outside your controller. You could add other controllers if they pass in a user id or even other methods that check if a domain class is owned by the current user here.