secure grails spring security controllers - grails

I am using spring security plugin in my Grails project. In order to secure the URLs, I am using interceptUrlMap.
My User and Role classes are User.groovy and Role.groovy respectively. Based on these classes, the s2-quickstart script has generated the UserController.groovy and RoleController.groovy
The problem arises when I want to secure UserController.groovy. My requirement is that I cannot permit all users to create a new user. Therefore certain actions of the UserController need to be blocked for users with the proper role privileges.
However no matter how I try to restrict access, I see that all the actions of UserController are always accessible.
Could anyone please explain where I am going wrong. Any help is highly appreciated.

Better use annotations instead of defining rules in Config.groovy. That helps in two ways i.e. first, hot reloading will always work and second you can override any rule easily in Config.groovy. That means you can use both annotation and plain rules in Config.groovy.
So change this in Config.groovy
grails.plugin.springsecurity.securityConfigType = "Annotation"
and start protecting your controller or actions like:
import grails.plugin.springsecurity.annotation.Secured
#Secured(["ROLE_MRU"])
class UserController {
def edit() {
// action code
}
#Secured(["ROLE_ADMIN"])
def show() {
// action code
}
}

I have managed to solve the issue. The problem was that I was editing Config.groovy while the application was still running. Hot deployment was not taking place.
Once I restarted the application, the functionality started working.
Thanks for all the help.

Related

Spring OAuth2 - custom "OAuth Approval" page at oauth/authorize

what is recommended way to create custom pages OAuth Approval page:
I have to completely override the stuff on the page, need to add styles, branding etc. What is the right way to achieve that? Where could I see the source of the default page to use it as a starting point?
I also need to override the /login page but I think the approach of overriding it is going to be pretty much the same.
The recommended way is to provide a normal Spring MVC #RequestMapping for the "/oauth/confirm_access". You can look at WhitelabelApprovalEndpoint for the default implementation. Don't forget to use #SessionAttributes("authorizationRequest") in your controller.
In addition to #DaveSyer's answer, which should work for the most of the cases. Sometimes based on configuration and customization the aforementioned method may not work, if Framew‌orkEndpointHandlerMa‌pping from Spring Security OAuth package has higher order than RequestMappingHandlerMapping of your application. If this is the case, then servlet dispatcher will never reach you mapping and will always show the default page.
One way to fix it is to change the order of mappers, given that Framew‌orkEndpointHandlerMa‌pping's order is Order.LOWEST_PRECEDENCE - 2.
Another way is to set the approval page to a custom URL, not mapped by Framew‌orkEndpointHandlerMa‌pping, thus servlet dispatcher will reaches you application's mapping
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthorizationEndpoint authorizationEndpoint;
#PostConstruct
public void init() {
authorizationEndpoint.setUserApprovalPage("forward:/oauth/custom_confirm_access");
authorizationEndpoint.setErrorPage("forward:/oauth/custom_error");
}
}
With such a configuration mappings of /oauth/custom_confirm_access and /oauth/custom_error will be used as a confirmation page and an error page respectively.

HTTP Method Security

I'm working on building a simple HATEOAS REST service with Spring Boot.
I have a MongoDB repository and resource where I would like to allow GET, but disallow all else. (POST, UPDATE DELETE, etc.)
The general idea is to allow a "USER" to do as it wishes with the resoure and allow "PUBLIC" read-only access.
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends MongoRepository<Person, String>
{
#Secured("ROLE_USER")
public void delete(Person person);
#Secured("ROLE_USER")
public Person save(Person person);
#Secured("ROLE_USER, ROLE_PUBLIC")
public Person findOne(String id);
}
I don't feel I'm approaching this at the right angle. What's the preferred way of doing this?
I'm guessing you're using spring-data-rest and skipping controllers entirely.
First thing you're having a problem with is that #Secured takes an array of roles...so i think your check on findOne is looking for a role ROLE_USER, ROLE_PUBLIC not either of those roles. Changing it to:
#Secured({"ROLE_USER", "ROLE_PUBLIC"})
might solve your problems.
After that you have a few options to consider
Option 1: Switch to ROLE_ANONYMOUS instead of ROLE_PUBLIC which is the default role anonymous users are assigned in Spring Web w/ spring security.
Option 2: Make sure anonymous users have the ROLE_PUBLIC (which they won't by default, they have ROLE_ANONYMOUS by default). There's a lot of ways to do this, see http://docs.spring.io/spring-security/site/docs/3.0.x/reference/anonymous.html
Option 3: Switch to #PreAuthorize annotations for securing methods and use the EL expression like:
#PreAuthorize("hasRole('ROLE_USER') or isAnonymous()")
see http://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html note you have to enable pre-post annotation processing.
Final note, ROLE_USER is not a default role...it's DEFAULT_USER for most stuff.
this is a very open ended question and there's a lot of solutions, you'd have to give more context as to your desires to narrow it down.

How to change Grails Spring Security Cookie Path

I've got two grails applications using spring security:
Core
Module (user and role tables mapping to Core db tables)
I want to have a single sign on functionality using "remember me". The problem is that the cookies are stored in different paths "/Core" and "/Module" which I'm guessing is the reason why it isn't working.
Does anyone know how to change the cookie path to be "/"?
Notes:
Do I need to make a change in Spring Security or the Tomcat server configuration (using intellij)
I want to avoid setting up a CAS server if possible
I'm looking into plugins as an alternative
Thanks any help would be greatly appreciated
When the remember-me filter creates the remember-me cookie, it sets the cookie path to the context path obtained from the request object (see related source code here). If you want to customize this behavior, you'll need to override the setCookie() and cancelCookie() methods of the remember-me service implementation your application uses (either TokenBasedRememberMeServices or PersistentTokenBasedRememberMeServices) in a subclass, and configure the RememberMeAuthenticationFilter to use your custom implementation.
Here's how I impltemented it.
create a new service with extends TokenBasedRememberMeServices
override setCookie and cancelCookie method to set cookie path.
Add cookiePath variable and add method to setCookepath()
Update resources.groovy
rememberMeServices(YourTokenBasedRememberMeServices) {
userDetailsService = ref("userDetailsService")
key = conf.rememberMe.key
cookieName = conf.rememberMe.cookieName
alwaysRemember = conf.rememberMe.alwaysRemember
tokenValiditySeconds = conf.rememberMe.tokenValiditySeconds
cookiePath = some config variable
}

Access/check Spring Security hierarchical roles programmatically

In my Grails project I defined multiple hierarchical roles using the Spring Security plugin e.g. ROLE_USER > SOME_OTHER_ROLE. When securing controller methods using the #Secured annotation it works just fine. However, I also would like to check the role programmatically in my code for one use case. Using the following approach I always get a false even though the user inherits the role through hierarchical role definition:
request.isUserInRole('SOME_OTHER_ROLE')
Also the following calls never directly return the inherited roles:
SecurityContextHolder.context?.authentication?.authorities
springSecurityService.getPrincipal().getAuthorities()
Is there a way of checking if the user also has the inherited role?
This seems like a bug (or at least an omission) in SecurityContextHolderAwareRequestWrapper which adds a request wrapper to implement the isUserInRole method.
You can use the roleVoter bean's extractAuthorities method. Add a dependency injection for it (def roleVoter) and then call
def allRoles = roleVoter.extractAuthorities(
SecurityContextHolder.context.authentication)

Grails Plugins Requiring External Relationships

I posted this on the Grails mailing list yesterday and haven't had any hits. Figured I'd try here as well today.
I'm considering writing a grails plugin but this plugin would require some sort of relationship to an account / user object. However, I don't want to force a particular security model on the plugin. For example, say was writing a comment system plugin (I'm not). I'd have a comment object...
class Comment {
String comment
Date dateCreated
// etc etc
}
The comment is missing a couple of things:
Who added the comment
What the comment was added to.
I'd like to first focus on #1. So someone might be using the Spring security plugin and use the default Person object, or maybe they changed that to User. Who knows. Is there any way that anyone can think of to configure that relationship without hard coding it in the plugin?
One thing I've thought about was to have the grails app extend the plugin's domain classes to add this relationship. so I might do something like...
class ArticleComment extends Comment {
static belongsTo = [user:User]
}
But in a larger plugin, that might be a lot of inheritance requirements. Not the end of the world, but just looking for other possible options.
You can use the same technique employed by the Commentable plugin:
The user of your plugin will need to declare a closure in Config.groovy to evaluate the logged user:
grails.myplugin.user.evaluator = { session.user }
And you can use something like this in your plugin's code to call the user configured closure:
def evaluateUser() {
def evaluator = grailsApplication.config.grails.myplugin.user.evaluator
def user
if(evaluator instanceof Closure) {
evaluator.delegate = this
evaluator.resolveStrategy = Closure.DELEGATE_ONLY
user = evaluator.call()
}
if(!user) {
throw new Exception("No [grails.myplugin.user.evaluator] setting defined or the evaluator doesn't evaluate to an entity. Please define the evaluator correctly in grails-app/conf/Config.groovy")
}
if(!user.id) {
throw new Exception("The evaluated user is not a persistent instance.")
}
return user
}
I think you can do it like SpringSecurity do. Instead of let people extend your Comment class, You can write 2 class CommentUser & CommentPlace; then let others extends them. I think it's more simple.

Resources