grails - controlling access of asset resources - grails

I want to have control who can and can not access a specific folder in the assets folder.
I actually want to look in the database if the user can access that folder.
I am using the grails spring security plugin.
In the config file I declared assets as a permitAll because there are also resources that should be public available. I looked into the filtering of the plugin but most that I found was a custom authentication filter. I don't want to touch the auth. I just want to do some check additionally / on top
edit:
I also tried normal grails filters- I put the file "AssetsFilter.groovy" in the conf folder. But they are never called:
class AssetsFilter {
def filters = {
allURIs(uri: '/**') {
log.debug "aaa"
println "aaa1"
before = {
log.debug "bbb"
println "bbb1"
}
}
}
}

Related

Grails 3 Spring Security Pre Authentication

The application I have in works uses Grails 3. I am attempting to do Pre-Authentication, as described in this article , but am having a hard time as I cannot figure out how to disable the regular authentication provided by the grails 3 spring security plugin.
Here is my current scenario: User A hits my webpage. I want to parse the headers of the request and take out the roles and username information. If the username or roles are empty, I will redirect the user to some gateway. In simple terms, I want to use spring security for authorization only, by invoking the static rules provided by the plugin. i.e
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
[pattern: '/serviceb/**', access: "hasAnyRole('ROLE_COOL','ROLE_UNCOOL')"],
[pattern: '/cools/**', access: ['ROLE_ADMINS']],
[pattern: '/*', access: 'isAuthenticated()']
]
This is the reason I do not need spring security to do any login functionality, as the first article states, we can use it for authentication only.
What I have tried:
First, I removed all authentication related calls in my application.groovy file (created by default when running the quick start for the plugin) i.e, connection strings, search filters, but not static rules
Next, I tried to use a solution provided by these two posts: on stack and this on blog.
I created a Filter to extend the AbstractPreAuthenticatedProcessingFilter
package Cool.service.authentication
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter
import javax.servlet.http.HttpServletRequest
class CGAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter {
#Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) { "username" }
#Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) { "N/A" }
}
My Boot config now looks like this:
import grails.plugin.springsecurity.SecurityFilterPosition
import grails.plugin.springsecurity.SpringSecurityUtils
class BootStrap {
def init = { servletContext ->
SpringSecurityUtils.clientRegisterFilter('CGAuthenticationFilter', SecurityFilterPosition.PRE_AUTH_FILTER.order)
}
}
And my Spring resources look like this:
import Cool.service.authentication.CGAuthenticationFilter
beans = {
myAuthenticationFilter(CGAuthenticationFilter) {
authenticationManager = ref('authenticationManager')
checkForPrincipalChanges = true
}
}
And lastly, added this line to my application.groovy configuration for spring security plugin:
grails.plugin.springsecurity.providerNames = ['preAuthenticatedAuthenticationProvider', 'anonymousAuthenticationProvider']
However, I am getting a super geneirc error when trying to run-app, where the server "fails" to start and java returns a non zero value back. This makes me believe I am headed in the wrong direction, and the implementation is completely wrong
To solve the problem, I had to change a few files. First, my Bootstrap file now contains the following init block:
SpringSecurityUtils.clientRegisterFilter('requestHeaderAuthenticationFilter', SecurityFilterPosition.PRE_AUTH_FILTER)
My beans (resources.groovy) file now contains:
userDetailsService(grails.plugin.springsecurity.userdetails.GormUserDetailsService) {
grailsApplication = ref('grailsApplication')
}
userDetailsByNameServiceWrapper(org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper) {
userDetailsService = ref('userDetailsService')
}
preAuthenticatedAuthenticationProvider(org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider) {
preAuthenticatedUserDetailsService = userDetailsByNameServiceWrapper
}
requestHeaderAuthenticationFilter(Cool.service.authentication.GCHeaderAuthenticationFilter) {
authenticationManager = ref('authenticationManager')
}
Other than that, the rest of the configuration is correct.

Externalized Grails 3 Spring Security Config

I am working on externalizing the .YML file in Grails 3.x. The code to make this work, is as follows:
In my Application.groovy, I am implementing the setEnviroment method form the EnvironmentAware interface.
#Override
void setEnvironment(Environment environment) {
try {
String configPath = System.properties["local.config.location"]
def ymlConfig = new File(configPath)
Resource resourceConfig = new FileSystemResource(ymlConfig)
YamlPropertiesFactoryBean ypfb = new YamlPropertiesFactoryBean()
ypfb.setResources(resourceConfig)
ypfb.afterPropertiesSet()
Properties properties = ypfb.getObject()
environment.propertySources.addFirst(new PropertiesPropertySource("local.config.location", properties))
} catch (Exception e) {
log.error("unable to load the external configuration file", e)
}
}
I have edited the bootRun task in the build to this:
bootRun {
jvmArgs = ['-Dlocal.config.location=external-config.yml']
}
When printing out the values in the setEnvironment method, the properties are indeed being read and added from the loaded object.
Now, for the fun part. When I add this code to my original application.yml file:
---
grails:
plugin:
springsecurity:
securityConfigType: 'InterceptUrlMap'
interceptUrlMap: [
{pattern: '/**', access: ['permitAll']}
]
providerNames: ['ldapAuthProvider', 'anonymousAuthenticationProvider']
ldap:
context:
managerDn: 'uid=admin,ou=system'
managerPassword: 'secret'
server: 'ldap://localhost:10389'
authorities:
groupSearchBase: 'ou=Groups,dc=aye,dc=com'
retreiveGroupRoles: true
retreiveDatabaseRoles: false
groupSearchFilter: 'member={0}'
search:
base: 'ou=Users,dc=aye,dc=com'
password:
algoritham: 'SHA-256'
---
Everything works just fine. When I cut and paste it out into the external yml file, I get this beautiful error in Firefox.
I can tell that the configuration is correct in the provided code, as I can add more roles and filters, and everything works just fine when in original application.yml file. It is only when reading from the external file does this fail. If I remove the security code from both .yml files, .ofc, my page looks strange but the firefox error disappears.
Has anyone got an idea as to why this can be the case?
One thing you can attempt to test if it will work, is rename your external-config.yml file to application.yml. I believe that the default name should be application, unless otherwise specified.
This article here shows a good example of its correct use
When you do that, try to read the properties in one of your classes, to make sure that the yml files are merging. You can read these properties using a command like this:
grailsApplication.config.getProperty("grails.plugin.springsecurity.securityConfigType")
Or, you can print out all of them, using the Holders utility
def config = Holders.config

Grails Spring Security UI Plugin - Does It Support Groups?

I'm getting ready to implement the Spring Security UI plugin (we've already implemented the Spring Security Core plugin). I know the core plugin has support for users, roles, and groups, however, I don't see any mention of groups in the Spring Security UI plugin's documentation. Does Spring Security UI plugin not support creating, edition, etc. groups? Anyone tried adding this functionality?
A late response, but I had the same question so I thought I would just try it.
I have just attempted this myself and I believe the the answer is No. (out of the box)
The spring security ui plugin doesn't take the groups into consideration. If you try to edit a user
myapp/user/edit/1
you will recieve some sort of error like:
Class groovy.lang.MissingPropertyException
Message
No such property: authority for class: com.myapp.security.SecGroup Possible solutions: authorities
I'm curious if you found a way around this? Or we will have to customize the the plugin.
As Julian noted the UI doesn't provide support for groups out of the box. To avoid the error you can do the following (customize the plugin):
Copy the User controller into your project to override the plugin's controller:
grails s2ui-override user <your-package-for-controller>
Copy the "buildUserModel" from the plugin code in UserController and edit the userRoleNames field:
import grails.plugin.springsecurity.SpringSecurityUtils
class UserController extends grails.plugin.springsecurity.ui.UserController {
protected Map buildUserModel(user) {
...
// Added so that when using groups doesn't cause an error
Set userRoleNames
if (SpringSecurityUtils.securityConfig.useRoleGroups) {
String groupAuthorityFieldName = SpringSecurityUtils.securityConfig.authority.groupAuthorityNameField
userRoleNames = user[authoritiesPropertyName].collect { it[groupAuthorityFieldName].collect { it[authorityFieldName] } }
} else {
userRoleNames = user[authoritiesPropertyName].collect { it[authorityFieldName] }
}
...
}

How to dynamically generate urls used by grails.plugins.springsecurity?

This is not one of the simple questions.. So let me explain it in detail...
The background:
In my grails application I have this mapping:
class UrlMappings {
static mappings = {
"/$storeId/$controller/$action?/$id?"
...
}
}
This means that all url's my application will process has preceding url parameter "storeId". All controllers will use this parameter to render content and perform other actions...
Also I have controller with annotation
#Secured(['IS_AUTHENTICATED_REMEMBERED'])
class SomeController {
def index = {
// ...
}
}
Let's say user is trying to access this page:
/555/some/index
If this is unauthenticated user, security-plugin will redirect him to the
/login/auth
The issue is:
When spring-security will redirect to this page, user will see 404. This happens because login controller will handle only urls like
/555/login/auth
The question is:
What should I do to dynamically build this url?
p.s.
It turns out that:
There is config param for
spring-security, called
"auth.loginFormUrl". But this is just
static text. And I need to build this
url based on what url influenced this
redirection
The redirection is done (I'm not 100%
sure) in org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint#commence.
But how to override it?
Typically that's a static value, but it's called from LoginUrlAuthenticationEntryPoint.getLoginFormUrl(), so you could subclass that and do a dynamic calculation of the url in an overridden method. The plugin already subclasses it with org.codehaus.groovy.grails.plugins.springsecurity.AjaxAwareAuthenticationEntryPoint so you should extend that.
To register your implementation instead of the plugins, add a bean override in grails-app/conf/spring/resources.groovy:
import com.yourcompany.yourapp.YourAuthenticationEntryPoint
beans = {
authenticationEntryPoint(YourAuthenticationEntryPoint) {
loginFormUrl = '/login/auth' // has to be specified even though it's ignored
ajaxLoginFormUrl = '/login/authAjax'
portMapper = ref('portMapper')
portResolver = ref('portResolver')
}
}
You don't have direct access to the request in this method, but it's available in a thread-local - call org.codehaus.groovy.grails.plugins.springsecurity.SecurityRequestHolder.getRequest().

Grails webflow url rewriting

Want to make the URLs SEO friendly when using grails webflow. It is quite limiting with the convention grails uses and hard to go around the way it's built.
For example, i have a flow called fooProcess in the controller called FooController, when i trigger the flow i would like the display: /foo/bar/test, instead of /foo/fooProcess?excecution=e1s2
class FooController {
def fooProcessFlow {
showFoo {
}
}
}
I tried using redirect and specify the uri but that's not supported, grails complains that the page isn't found
fooProcessFlow {
showFoo {
redirect(uri:"/foo/bar/test")
}
}
grails/foo/fooProcess.dispatch/externalRedirect:/foo/bar/test
Also, a redirect is an end state in a flow, if I only want to render the page, i have to use the render method and specify the view name or structure my views according to webflow convention.
fooProcessFlow {
showFoo {
render(view:"/foo/bar/test")
on "add".to "add"
}
}
The url will be in this case
/foo/fooProcessProcess?execution=e6s1
Anyone dealt with this case before ?
Did anyone use UrlRweriteFilter with webflows in grails
http://code.google.com/p/urlrewritefilter/
ken
You can use URLMappings Grails Plugin
See: http://grails.org/doc/latest/ref/Plug-ins/URL%20mappings.html
Edit this file: grails-app/conf/UrlMappings.groovy
Putting something like this inside:
class UrlMappings {
static mappings = {
"/foo/bar/test" (controller: "foo", action: "fooProcessFlow")
"/$controller/$action?/$ids?"{
constraints {
}
}
}
}

Resources