Blogs

SpringSource Blog

Simplified Spring Security with Grails

Peter Ledbrook

Spring Security is a powerful library for securing your applications that comes with a bewildering number of options. Based on Spring, it can be readily integrated into a Grails application. But why not save the hassle and use the new improved Grails plugin?

The plugin has gone through several evolutionary stages that started with the Acegi plugin. Its most recent incarnation is a complete rewrite for Spring Security 3 and Spring 3. One of the results of this is that the plugin will only work with Grails 1.2.2 and above. Another significant change is that there is no longer just one Spring Security plugin: some features have been broken out into optional plugins. So now you only include the features you need in your application.

So what do the plugins give you? The core provides the basics necessary for access control in an easy-to-use package based on users and roles. In fact, many applications won't need any other plugin than the core one. For those who do need something extra, here is a list of the other plugins in the family:

  • OpenID – authentication using OpenID
  • LDAP – authentication against LDAP servers
  • CAS – single sign-on using CAS
  • ACLs – access control via Spring Security's ACLs
  • UI – user interface for user and role managment, plus other features

In this article I'll show you how to secure a Grails application from scratch using the new core plugin.

Update This article now has two companion screencasts:

Spring Security Plugin Introduction

Spring Security Plugin - AJAX

Setup

As with most plugins, your first step will be to install the Spring Security plugin. Of course, you'll need a project to install it into and for this article I have provided a simple Twitter-clone called Hubbub (based on the sample application from Grails in Action). You can also get the finished project from here.

So, from within your project, run:

    grails install-plugin spring-security-core

If you look at the output generated by the plugin installation, you will see that it provides a couple of commands. The most important of these is s2-quickstart, which will help you get up and running with the minimum of fuss. It generates both the basic domain classes you need to store user information and the controllers that handle authentication.

Before you run the command, you may need to make a decision. If you already have a 'user' domain class, you will have to decide how to integrate it with the one generated by the plugin. One option is to replace the existing domain class and simply apply your customisations to the replacement. The other approach consists of making your own domain class extend the plugin's one.

Which is better? I prefer the latter because it allows you to easily update the generated user domain class if its template ever changes. It also means you don't overly pollute your domain model with Spring Security specifics. On the downside, you have to deal with domain class inheritance, although the cost is pretty minimal.

For Hubbub, we'll make the user domain class extend the generated one, which means we should use domain class names that don't conflict with the existing ones:

    grails s2-quickstart org.example SecUser SecRole

This will create three domain classes for us:

  • org.example.SecUser
  • org.example.SecRole
  • org.example.SecUserSecRole – links users to roles

and two controllers:

  • LoginController
  • LogoutController

plus their associated views. In just two commands, we have everything we need to start securing our application!

The sample application does need one more change: its URL mappings mean that the login and logout controllers can't be reached. That's simple enough to fix by adding the following two lines to UrlMappings.groovy:

"/login/$action?"(controller: "login")
"/logout/$action?"(controller: "logout")

If you don't make the change, the login page will generate a 404 error! Now let's get down to the business of protecting the application.

Adding access control

The whole point of this exercise is to limit access to certain parts of the application. For web applications this most commonly means protecting particular pages, or more specifically URLs. In the case of Hubbub, we have the following requirements:

  • The home page is accessible to everyone – /
  • Only known users can see the posts for a particular user – /person/<username>
  • Only users with a 'user' role should be able to access their own timeline – /timeline
  • Same goes for following another user – /post/followAjax
  • Only fully authenticated users with the 'user' role should be able to post a new message – /post/addPostAjax

With the Spring Security plugin this is trivial to achieve, although you do have to make a decision on which of three mechanisms to use. You can take a controller-centric approach and annotate the actions; work with static URL rules in Config.groovy; or define runtime rules in the database using request maps.

Annotations

For a controller-centric approach, you can't beat the @Secured annotation provided by the plugin. In it's simplest incarnation, you pass it a list of basic rules that define who can access the corresponding action. Here, I apply Hubbub's access control rules via annotations on the post controller:

package org.example

import grails.plugins.springsecurity.Secured

class PostController {
    ...
    @Secured(['ROLE_USER'])
    def followAjax = { ... }

    @Secured(['ROLE_USER', 'IS_AUTHENTICATED_FULLY'])
    def addPostAjax = { ... }

    def global = { ... }

    @Secured(['ROLE_USER'])
    def timeline = { ... }

    @Secured(['IS_AUTHENTICATED_REMEMBERED'])
    def personal = { ... }
}

The IS_AUTHENTICATED_* rules are built into Spring Security, but ROLE_USER is a role that must exist in the database – something we have yet to do. Also, if you specify more than one rule in the list, then the current user normally only has to satisfy one of them – as is explained in the user guide. IS_AUTHENTICATED_FULLY is a special case: if specified, it must be satisfied in addition to the other rules in the list.

The built-in rules are as follows:

  • IS_AUTHENTICATED_ANONYMOUSLY – anyone has access; no need for the user to log in
  • IS_AUTHENTICATED_REMEMBERED – only known users that have logged in or are remembered from a previous session are allowed access
  • IS_AUTHENTICATED_FULLY – users must log in to gain access, even if they checked "remember me" last time

The first two of these distinguish between known and unknown users, where known users are ones that have an entry in the 'user' database table. The last is typically applied in cases where the user is accessing particularly sensitive information, such as bank account or credit card data. After all, someone else could be accessing your application using the "remember me" cookie from the previous user.

You can also apply the annotation to the controller class itself, which results in all actions inheriting the rules defined by it. If an action has its own annotation, that overrides the class-level one. The annotation isn't just limited to a list of rules like this either: take a look at the user guide to see how to use expressions to provide greater control over the rules.

Static URL rules

If annotations aren't your thing, you can define access control rules via a static map in Config.groovy. If you like to keep your rules in one place, it's ideal. Here is how you would define Hubbub's rules using this mechanism:

import grails.plugins.springsecurity.SecurityConfigType
...
grails.plugins.springsecurity.securityConfigType = SecurityConfigType.InterceptUrlMap
grails.plugins.springsecurity.interceptUrlMap = [
    '/timeline':         ['ROLE_USER'],
    '/person/*':         ['IS_AUTHENTICATED_REMEMBERED'],
    '/post/followAjax':  ['ROLE_USER'],
    '/post/addPostAjax': ['ROLE_USER', 'IS_AUTHENTICATED_FULLY'],
    '/**':               ['IS_AUTHENTICATED_ANONYMOUSLY']
]

Notice how the most general rule comes last? That's because order is important: Spring Security iterates through the rules and applies the first one that matches the current URL. So if the '/**' rule came first, your application would effectively be unprotected since all URLs would be matched to it. Also notice that you have to explicitly tell the plugin to use the map via the grails.plugins.springsecurity.securityConfigType settings.

Dynamic request maps

Do you want to update URL rules at runtime without restarting the application? If that's the case, you'll probably want to use request maps, which are basically URL rules stored in the database. To enable this mechanism, add the following to Config.groovy:

import grails.plugins.springsecurity.SecurityConfigType
...
grails.plugins.springsecurity.securityConfigType = SecurityConfigType.Requestmap

All you then have to do is create instances of the Requestmap domain class, for example in BootStrap.groovy:

new Requestmap(url: '/timeline', configAttribute: 'ROLE_USER').save()
new Requestmap(url: '/person/*', configAttribute: 'IS_AUTHENTICATED_REMEMBERED').save()
new Requestmap(url: '/post/followAjax', configAttribute: 'ROLE_USER').save()
new Requestmap(url: '/post/addPostAjax', configAttribute: 'ROLE_USER,IS_AUTHENTICATED_FULLY').save()
new Requestmap(url: '/**', configAttribute: 'IS_AUTHENTICATED_ANONYMOUSLY').save()

Of course, there is a performance cost to this approach since it involves the database, but it is minimised through the use of caching. Take a look at the user guide for more information on this. Also, you don't have to worry about the order of the rules in this case because the plugin picks the most specific URL pattern that matches the current URL.

Which of these approaches should you use? It depends on how your application is set up and how you think about access control. Annotations make sense where rules apply on a per-controller basis and controllers have distinct URLs. If you tend to group controllers under a single URL, like /admin/ or you simply like to keep all your rules in one place, then you're probably better off with the static rules defined in Config.groovy. The third mechanism, request maps, only make sense if you want to add, change, or remove rules at runtime. A classic example where you might want to do this is in a CMS application, where URLs themselves are defined dynamically.

Whichever approach you take, once the rules are implemented your application is protected. For example, if you try to access the /timeline page in Hubbub at this point, you will be redirected to the standard login page:

Great! But who are you going to log in as? How are users going to log out? Protecting your pages is only the first step. You also need to make sure that you have the relevant security data (users and roles) and a user interface that's security aware.

Next steps

With the access control in place, you need to look at the user experience. Do you really want users clicking on links that they don't have access to? What about those roles you are using in the access control? When do they get created? Let's answer those questions now.

Security data

Some applications only care whether a user is known or not and in such cases you don't need to worry about roles because the IS_AUTHENTICATED_* rules are sufficient. But if your application needs more control over who has access to what, you will need roles. These are typically defined early in the life of the application and correspond to unchanging reference data. That makes BootStrap the ideal place to create them. For Hubbub, we add 'user' and 'admin' roles like so:

import org.example.SecRole

class BootStrap {
    def init = {
        ...
        def userRole = SecRole.findByAuthority('ROLE_USER') ?: new SecRole(authority: 'ROLE_USER').save(failOnError: true)
        def adminRole = SecRole.findByAuthority('ROLE_ADMIN') ?: new SecRole(authority: 'ROLE_ADMIN').save(failOnError: true)
        ...
    }
}

Of course, if the data already exists we don't want to recreate it, hence why we use findByAuthority().

Adding users is almost as straightforward, but there are a couple of requirements that you need to bear in mind. First, the generated 'user' domain class has an enabled property that is false by default. If you don't explicitly initialise it to true the corresponding user won't be able to log in. Second, passwords are rarely stored in the database as plain text, so you will need to encode them first using an appropriate digest algorithm.

Fortunately, the plugin provides a useful service to help here: SpringSecurityService. Let's say we want to create an 'admin' user in Hubbub's BootStrap. The code would look something like this:

import org.example.*

class BootStrap {
    def springSecurityService

    def init = {
        ...
        def adminUser = SecUser.findByUsername('admin') ?: new SecUser(
                username: 'admin',
                password: springSecurityService.encodePassword('admin'),
                enabled: true).save(failOnError: true)

        if (!adminUser.authorities.contains(adminRole)) {
            SecUserSecRole.create adminUser, adminRole
        }
        ...
    }
}

We simply inject the security service into BootStrap and then use its encodePassword() method to convert the plain text password to its hash. This approach works particularly well when you decide to change the digest algorithm you use, because the service will encode passwords using the same algorithm as the one used when comparing them for authentication. In other words, the above code stays the same no matter what algorithm is used.

Update As of version 1.2 of the Spring Security Core plugin, the generated User class automatically encodes the password when an instance is saved. Hence you no longer need to explicitly use SpringSecurityService.encodePassword()

Once the user is created, we check whether it has the 'admin' role and if it doesn't, we assign the role to the user. We do this by way of the generated SecUserSecRole class and its create() method.

With the security data in place, and the knowledge of how to create it on demand where necessary, it's time to make the user interface aware of authentication, users, and roles.

The user interface

There are two aspects of the UI I want to look at here: displaying information specific to the user and making sure that the user can only see what he's allowed to. The first of these boils down to one question: how do we get the 'user' domain instance for the currently logged in user? Consider Hubbub's timeline page, which displays all the posts of the people that the current user is following:

class PostController {
    def springSecurityService
    ...
    @Secured(['ROLE_USER'])
    def timeline = {
        def user = SecUser.get(springSecurityService.principal.id)

        def posts = []
        if (user.following) {
            posts = Post.withCriteria {
                'in'("user", user.following)
                order("createdOn", "desc")
            }
        }
        [ posts: posts, postCount: posts.size() ]
    }
    ...
}

As you can see, all we need to do is inject the security service again and use it to get hold of the principal. Unless you have created a custom version of the UserDetailsService (don't worry if you haven't come across this before), the principal will be an instance of org.codehaus.groovy.grails.plugins.springsecurity.GrailsUser whose id property contains the ID of the corresponding 'user' domain instance.

One thing you need to be aware of: if the current user is authenticated anonymously, i.e. he hasn't logged in and isn't remembered, the principal property will return a string instead. So if an action can be accessed by an unauthenticated user, make sure you check the type of the principal before using it!

What about ensuring users can only see what they are supposed to? For that, the plugin provides a rich set of GSP tags in the sec namespace. Let's say we want to add a couple of navigation links to Hubbub, but we only want to display one of them when the user isn't logged in and the other only if the user has the ROLE_USER role:

<sec:ifNotLoggedIn>
  <g:link controller="login" action="auth">Login</g:link>
</sec:ifNotLoggedIn>
<sec:ifAllGranted roles="ROLE_USER">
  <g:link class="create" controller="post" action="timeline">My Timeline</g:link>
</sec:ifAllGranted>

The markup inside the <sec:if*> tags will only be rendered to the page if the condition is satisfied. The plugin provides several other similar tags that all behave in a consistent fashion. See the user guide for more information.

The above example also shows you how to create a link to the login page. Allowing the user to log out is similarly straightforward. Hubbub provides a side panel that displays amongst other things the name of the logged in user and a link to sign out:

<sec:username /> (<g:link controller="logout">sign out</g:link>)

Easy! The combination of these tags and the security service should be more than sufficient to integrate your user interface with Spring Security. Just remember to keep your user interface elements in sync with your access control rules: you don't want bits of UI visible that result in an "unauthorised user" error.

I've now covered all the basic elements of the Spring Security plugin, but there are still two features that will affect a large number of users: AJAX requests and custom login forms.

The last pieces of the puzzle

How many web applications don't use AJAX to some degree now? And how many really want to use the stock login form for their application? It's fine for internal use, but I wouldn't recommend it for anything that's customer facing. Let's start with AJAX.

Securing AJAX requests

Dynamic user interfaces based on AJAX bring a new set of problems to access control. It's very easy to deal with a standard request that requires authentication: simply redirect the user to the login page and then redirect them back to the target page if the authentication is successful. But such a redirect doesn't work well with AJAX. So what do you do?

The plugin gives you a way to deal with AJAX request differently to normal ones. When an AJAX request requires authentication, Spring Security redirects to the authAjax action in LoginController rather than auth. But wait, that's still a redirect right? Yes, but you can implement the authAjax to send an error status or render JSON – basically anything that the client Javascript code can handle.

Unfortunately, the LoginController provided by the plugin doesn't implement authAjax at this time, so you will have to do add it yourself:

import javax.servlet.http.HttpServletResponse

class LoginController {
    ...
    def authAjax = {
        response.sendError HttpServletResponse.SC_UNAUTHORIZED
    }
    ...
}

This is a very simple implementation that returns a 401 HTTP status code. How do we deal with such a response? That depends on what you use to implement AJAX in the browser. The example Hubbub application uses adaptive AJAX tags, so I'll use that to demonstrate the kind of thing you can do. This is part of the GSP template that is used for posting new messages:

<g:form action="ajaxAdd">
    <g:textArea id='postContent' name="content" rows="3" cols="50" onkeydown="updateCounter()" /><br/>
    <g:submitToRemote value="Post"
                 url="[controller: 'post', action: 'addPostAjax']"
                 update="[success: 'firstPost']"
                 onSuccess="clearPost(e)"
                 onLoading="showSpinner(true)"
                 onComplete="showSpinner(false)"
                 on401="showLogin();"/>
</g:form>

As you can see, it has an on401 attribute that specifies a bit of Javascript that should be executed when the AJAX submission returns a 401 status code. That bit of Javascript can, for example, display a dynamic, client-side login form for the user to authenticate with. Hubbub uses the client-side code provided in the plugin's user guide to do just that.

Note Version 1.1 of the plugin will come with a default implementation of the authAjax action.

You can also customise the ajaxSuccess and ajaxDenied actions to send back whatever response you want. As you can see, the server-side AJAX handling is simple and easy to customise. The real work has to be done in the client code.

Custom login forms

It's no longer fashionable to dedicate an entire page to the login form. These days applications are more likely to have a content-rich home page with a discrete login form located somewhere on it, perhaps only made visible by some Javascript magic. It's easy enough to provide your own dedicated login page (simply edit the auth action in LoginController and its associated GSP view to your heart's content), but what about a login panel?

It's not as hard as you might think. First of all, you need to decide where users should be redirected to when authentication is required. As you've probably gathered, this is /login/auth by default. Changing that default is as easy as adding a setting to Config.groovy:

grails.plugins.springsecurity.auth.loginFormUrl = '/'

This line tells the plugin to redirect to the home page whenever authentication is required. All you then need to do is add a login panel to the home page. Here's an example GSP form that might go in such a panel:

<form method="POST" action="${resource(file: 'j_spring_security_check')}">
  <table>
    <tr>
      <td>Username:</td><td><g:textField name="j_username"/></td>
    </tr>
    <tr>
      <td>Password:</td><td><input name="j_password" type="password"/></td>
    </tr>
    <tr>
      <td colspan="2"><g:submitButton name="login" value="Login"/></td>
    </tr>
    <tr>
      <td colspan="2">try "glen" or "peter" with "password"</td>
    </tr>
  </table>
</form>

The key points here are:

  1. the form must use the POST method;
  2. the form must be submitted to <context>/j_spring_security_check;
  3. the username field must have the name 'j_username';
  4. the password field must have the name 'j_password'; and
  5. any "remember me" field must have the name '_spring_security_remember_me'.

As long as these requirements are satisfied, the login form will work perfectly. Well, not quite perfectly. If an authentication attempt fails via your login form, you will find yourself redirected back to the old login page. Fortunately, this is quickly rectified by adding another configuration setting:

grails.plugins.springsecurity.failureHandler.defaultFailureUrl = '/'

And that's all you need for a fully functioning login form! There are plenty of other options available to fine tune the behaviour, but you now have the basics on which to build.

This article has really only scratched the surface of the Spring Security plugin. I haven't mentioned HTTP Basic and Digest Authentication, events, salted passwords and more. That doesn't even include the other plugins that provide extra features such as alternative authentication mechanisms and access control lists (ACLs). But what you have read so far will enable you to get a fully working access control system up and running in no time. You will then be able to extend and customise as the need arises, knowing that Spring Security has more features than you will probably ever need.

Similar Posts

Share this Post
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • DZone
  • LinkedIn
  • Slashdot
  • Technorati
  • Twitter
 

103 responses


  1. hi peter. i installed the plugin and ran the quickstart. but i get a bunch of unable to resolve class (in the generated login controller (please see below) using very recent sts. clean an update dependencies does not help

    thanks

    import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils

    import org.springframework.security.authentication.AccountExpiredException
    import org.springframework.security.authentication.CredentialsExpiredException
    import org.springframework.security.authentication.DisabledException
    import org.springframework.security.authentication.LockedException
    import org.springframework.security.core.context.SecurityContextHolder as SCH
    import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter


  2. Thanks for the great article!

    Just wondering, what would be a good way to hook this up to facebook SSO.
    Using the Facebook JS SDK I get a signed cookie which I can deal with in a filter. But what is the right spot to hook into the spring security plugin?


  3. There's this blog post on Facebook Connect and Spring Security 3:

    http://blog.kadirpekel.com/2009/11/09/facebook-connect-integration-with-spring-security/

    You can also find out how to add authentication providers to your Grails application from the plugin's user guide:

    http://burtbeckwith.github.com/grails-spring-security-core/docs/manual/guide/10%20Authentication%20Providers.html

    The combination of the two should give you some idea. I'll also find out whether a Facebook plugin is planned – it might very well be.


  4. I believe Burt is working on an oAuth module, which would handle Facebook authenitication – http://grails.1312388.n4.nabble.com/New-and-updated-Spring-Security-plugins-td2268932.html#a2313754.

    Peter, since you are the author of the Apache Shiro plugin, will the Shiro plugin continue to be enhanced, or is the focus shifting towards Spring Security?


  5. Thanks for the info on OAuth Roshan.

    I will continue to work on the Shiro plugin when I have time, but it really needs more attention from those that actively use it. There is still a plan to create a security API that applications and plugins can work against, and hopefully both the Spring Security and Shiro plugins will implement it.


  6. Ray, not sure what the issue is there. Is Spring Security appearing in the plugin list in the Grails project explorer view? Are there any project-wide problem markers? Try refreshing the project tree. Also take a look in the "Grails dependencies" entry in the project view. The Spring Security libraries should be in there.


  7. Is there any way to inject my own PasswordEncoder? I didn't find anything about it in manual.


  8. > … Is Spring Security appearing in the plugin list in the Grails project explorer view?

    no. the plugin seems to be installed into ~\.grails\1.3.4\projects\gsec\plugins instead of ~\.grails\1.3.4\plugins. i did the create app, install the plugin, and ran s2-quickstart from the command line.

    > … Are there any project-wide problem markers?
    no.

    > … Try refreshing the project tree. Also take a look in the "Grails dependencies" entry in the project view. The Spring Security libraries should be in there.

    refreshing the project explorer nor the grails tools refresh dependencies does not help.

    doing everything from within sts gets the same results.

    thanks


  9. it must be an sts thing. i can compile and run from the command line using 1.3.4 on windoze xp.

    thanks


  10. what is this?


  11. Ray I think the problem is you don't have the zip plugin inside the folder "C:\grails\plugins" or your grails folder.


  12. > … you don't have the zip plugin inside the folder "C:\grails\plugins" or your grails folder. …

    i tried moving the plugin to ~/.grails/plugins, but no joy.

    deleting the plugins and doing a run-app in sts puts the plugins into the project directory in ~/.grails/1.3.4/projects.

    ditto for doing the run-app from the command line after deleting the plugin directories again.

    so it looks like both sts and the command line put the plugin into the same incorrect place.

    but according to the doc:

    " … Plugin Changes

    Since 1.1, Grails no longer stores plugins inside your PROJECT_HOME/plugins directory by default. This may result in compilation errors in your application unless you either re-install all your plugins or set the following property in grails-app/conf/BuildConfig.groovy:

    grails.project.plugins.dir="./plugins"
    … "

    adding this line to BuildConfig.groovy did not help either.

    one thing that i did note is that the plugin is being installed in an older version of the project (gsec instead of gsec2).

    i will start over with a new project.

    thanks


  13. For what it's worth, I hit a similar problem. With Intellij Idea 8.x I got something like:
    Information:Compilation completed with 100 errors and 5 warnings
    Information:100 errors
    Information:5 warnings
    /home/sean/.grails/1.3.3/projects/sdrprep/plugins/spring-security-core-1.0.1/src/java/org/codehaus/groovy/grails/plugins/springsecurity/InterceptUrlMapFilterInvocationDefinition.java
    Error:Error:line (22)package org.springframework.security.web does not exist
    Error:Error:line (32)cannot find symbol class FilterInvocation
    /home/sean/.grails/1.3.3/projects/sdrprep/plugins/spring-security-core-1.0.1/src/java/org/codehaus/groovy/grails/plugins/springsecurity/AbstractFilterInvocationDefinition.java
    Error:Error:line (28)package org.springframework.security.access does not exist
    Error:Error:line (29)package org.springframework.security.access does not exist

    I finally was able to add in the two jar files I found in my ivy2 cache (I'm an ivy/maven noob, btw). I had two versions in each folder: 3.0.2 and 3.0.3; I picked 3.0.3. The two relevant folders for me were:
    /home/sean/.ivy2/cache/org.springframework.security/org.springframework.security.core/jars
    and
    /home/sean/.ivy2/cache/org.springframework.security/org.springframework.security.web/jars
    hth,

    Sean


  14. Sean, my stuff compiled and ran without errors from the command line. the "errors" i was getting were lots of "red" in sts because of some classpath problems.


  15. explicitly adding the jars in ~\.ivy2\cache\org.springframework.security got rid of most of the "red" in sts, but i am not sure how sane it is to do this sort of thing.

    the only problem left is for org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils. can't seem to find out where that one lives.


  16. I have also had similar dependency problems when installing some plugins(e.g. spock) through sts. The problem mostly got away after manually adding jars to the classpath. So I guess the problem lies with the sts grails dependency manager because the command line works well.


  17. hi
    how to install this when having a maven grails project?
    I tried
    mvn grails:exec -Dcommand=s2-quickstart -Darg='org.example SecUser SecRole'

    but it fails with over 100 warngins and errors like

    [INFO] Scanning for projects…
    [INFO] ————————————————————————
    [INFO] Building A custom grails project
    [INFO] task-segment: [grails:exec] (aggregator-style)
    [INFO] ————————————————————————
    [INFO] [grails:exec {execution: default-cli}]
    [INFO] Using Grails 1.3.4
    Running script /home/devel/Desktop/projects/springSecu/plugins/spring-security-core-1.0.1/scripts/S2Quickstart.groovy
    Environment set to development
    [groovyc] Compiling 34 source files to /home/devel/Desktop/projects/springSecu/target/plugin-classes
    [groovyc] org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
    [groovyc] Compile error during compilation with javac.
    [groovyc] /home/devel/Desktop/projects/springSecu/plugins/spring-security-core-1.0.1/src/java/grails/plugins/springsecurity/DigestAuthPasswordEncoder.java:21: package org.springframework.security.authentication.encoding does not exist
    [groovyc] import org.springframework.security.authentication.encoding.PasswordEncoder;
    [groovyc] ^
    [groovyc] /home/devel/Desktop/projects/springSecu/plugins/spring-security-core-1.0.1/src/java/grails/plugins/springsecurity/DigestAuthPasswordEncoder.java:22: package org.springframework.security.core.codec does not exist
    …..


  18. @xavier I would raise that question on the Grails user mailing list. I'm not sure how Maven users get round the problem. A workaround for now is probably to add the Spring Security libraries as dependencies to your POMs. In the meantime, I'll discuss with the team whether we should deploy the plugin to Maven central.


  19. I am having the same issue as Ray.

    I got the org.springframework.security dependency issues (red in STS) to go away by downloading spring-security-3.0.3 and manually adding the JARs to my build path.

    Has anyone figured out where the org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils and grails.plugins.springsecurity.Secured are located?

    I am using STS 2.3.2 and grails 1.3.4 and all I did was:
    1) create a new project
    2) ran 'install-plugin spring-security-core'
    3) then ran 's2-quickstart User Role Requestmap'
    4) I then created a SecureController and gave it the @Secured annotation as specified in the tutorial
    5) finally I ran the Grails Update Dependencies tool

    All of the import statements in the login and logiout controllers created by s2-quickstart have a red mark next to them indicateing they are not resolved.


  20. i looked again and fount it in: ~\.grails\1.3.4\projects\gsec\plugins\spring-security-core-1.0.1\src\java\org\codehaus\groovy\grails\plugins\springsecurity\SpringSecurityUtils.java


  21. Thanks Ray,

    I don't have spring-security-core-1.0.1 anywhere on my machine though. Shouldn't it be in spring-security-core-3.0.3 unless its deprecated?

    I googled around and couldn't fine anywhere to go to download it.


  22. i just made a new project from the command line and intalled spring-security-core. that makes: ~\.grails\1.3.4\projects\gsec2\plugins\spring-security-core-1.0.1

    if you installed the plugin, you should have it there.


  23. @Ray I just tried with a fresh project in STS but didn't get any errors. I'm wondering whether this is something that's been fixed in recent updates. I have these update sites set up:

    @Brian Everything starting with org.codehaus.groovy.grails.plugins.springsecurity is provided by the plugin, not the Spring Security libraries themselves. spring-security-core-1.0.1 is the Grails plugin, spring-security-3.0.3 is the Spring Security library.

    The location of the plugins shouldn't matter, because STS uses Grails to determine the classpath. So I suspect this may have something to do with either the version of STS you are using or the version of Grails. If you continue to have the problem with even the latest versions of STS (2.5.0 M3 ), then raise an issue so that the developers can take a look at it.


  24. @Peter Thanks, that fixed the issue. If anyone else runs into this problem you can:

    1) download and install STS 2.5.0 M3
    2) install the Grails and Groovy Extensions via the Dashboard in STS
    3) Create a new Grails Project within STS
    4) Run the 'install-plugins spring-security-core' Grails command (through STS interface)
    5) Right click on your project and go to Grails Tools -> Refresh Dependencies


  25. Ran into another issue following this tutorial.

    I'm running on STS 2.5.0 M3 and Grails 1.3.4 as stated in my last comment.

    When I try to use the SpringSecurityService in my Bootstrap.groovy to create the my adminUser I get the following error:

    2010-09-03 09:31:11,013 [main] ERROR context.GrailsContextLoader – Error executing bootstraps: No such property: springSecurityService for class: BootStrap
    groovy.lang.MissingPropertyException: No such property: springSecurityService for class: BootStrap
    at BootStrap$_closure1.doCall(BootStrap.groovy:18)
    at grails.util.Environment.evaluateEnvironmentSpecificBlock(Environment.java:251)
    at grails.util.Environment.executeForEnvironment(Environment.java:244)
    at grails.util.Environment.executeForCurrentEnvironment(Environment.java:220)
    at org.grails.tomcat.TomcatServer.start(TomcatServer.groovy:164)
    at grails.web.container.EmbeddableServer$start.call(Unknown Source)
    at _GrailsRun_groovy$_run_closure5_closure12.doCall(_GrailsRun_groovy:158)
    at _GrailsRun_groovy$_run_closure5_closure12.doCall(_GrailsRun_groovy)
    at _GrailsSettings_groovy$_run_closure10.doCall(_GrailsSettings_groovy:280)
    at _GrailsSettings_groovy$_run_closure10.call(_GrailsSettings_groovy)
    at _GrailsRun_groovy$_run_closure5.doCall(_GrailsRun_groovy:149)
    at _GrailsRun_groovy$_run_closure5.call(_GrailsRun_groovy)
    at _GrailsRun_groovy.runInline(_GrailsRun_groovy:116)
    at _GrailsRun_groovy.this$4$runInline(_GrailsRun_groovy)
    at _GrailsRun_groovy$_run_closure1.doCall(_GrailsRun_groovy:59)
    at RunApp$_run_closure1.doCall(RunApp.groovy:33)
    at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
    at gant.Gant$_dispatch_closure7.doCall(Gant.groovy:415)
    at gant.Gant$_dispatch_closure7.doCall(Gant.groovy)
    at gant.Gant.withBuildListeners(Gant.groovy:427)
    at gant.Gant.this$2$withBuildListeners(Gant.groovy)
    at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
    at gant.Gant.dispatch(Gant.groovy:415)
    at gant.Gant.this$2$dispatch(Gant.groovy)
    at gant.Gant.invokeMethod(Gant.groovy)
    at gant.Gant.executeTargets(Gant.groovy:590)
    at gant.Gant.executeTargets(Gant.groovy:589)

    So I decided to add a 'import grails.plugins.springsecurity.SpringSecurityService;' on the Bootstrap.groovy but it results in the same error.

    Any ideas? If I leave it out and just put the string 'password' as the password the app runs but I cannot login (I assume because its expecting the value to be encrypted.


  26. update – I was missing the def SpringSecurityService line in my bootstrap file.


  27. Is there any plan to enhance the default authorization model for Spring Security?

    Having only a Role concept is very weak. Is there any plan or a JIRA RFE that i can vote for that would include first-class support for a Permission concept (similar to Shiro), and even nicer would be support for Groups and scoped Permissions concepts (similar to Nimble's Shiro extensions)?

    I know Spring Security has an optional Group-like concept, but it seems it's only for grouping users without support for managing the authorities of contained users.

    ie. it would be very nice if…
    - Permissions are the fine-grained authority that code tests against. It's crazy that an editProfile controler should be checking to see if the current Principal has an "AdminRole" or "SuperUserRole" or "PowserUserRole" or "FooBarRole"…, rather than just testing that the current Principal has the EditProfilePermission.
    - Roles are sets of Permissions.
    - User's can have any number of Permissions and Roles associated with them.
    - Users can be added to groups.
    - Groups can have any number of Permissions and Roles associated with them.
    - The User's set of Permissions are the union of the Permissions associated with themselves and the ones associated to the Groups they are members of, and the Permissions of the Roles associated with themselves and the Permissions of the Roles associated to the Groups they are members of.

    Of course Spring Security could be extended to support any auth model, but the default is what all tools are written against (including admin UI's and the Grails plugin).

    It's a shame that all these extensions are being built on top of an inadequate auth model.


  28. it must be an sts thing. i can compile and run from the command line using 1.3.4 on windoze xp.

    thanks


  29. I have a big problem with the springSecurityService.
    I implemented it just as said here, but I get a NullPointerException 'java.lang.NullPointerException: Cannot get property 'principal' on null object'

    My class:
    import grails.plugins.springsecurity.Secured

    @Secured(['ROLE_ADMIN','ROLE_USER'])
    class DocumentController {
    // Define springSecurityService
    def springSecurityService

    def scaffold = Document

    // Attach user
    def user = User.get(springSecurityService.principal.id)

    // Retreive documents for the logged in user
    def documents = {
    [ user: user ]
    }
    }


  30. It would be interesting to make an article showing how to implement the LDAP feature


  31. Hey Folks,

    i have the exact same problem as Ray. I have a basically naked STS installation (up-to-date version) and the groovy grails extensions in there.

    I'm having some very simple projects already and tried to install the plugin according to the provided instructions. On existing projects and on completely new one. He cannot resolve dependencies. And when i go to the project properties and add the external class path manually he is able to resolve them but then suddenly shows problems in "grails-app/conf -> spring -> resources.groovy" and somewhere in the grails-app tree. I really don't know what to do. downloading the hubbub-finished version shows the same problems and won't run in my STS after importing it.

    Any ideas?

    I'm pretty new to this, but i have some basic understanding, thats why i started searching for the jars and stuff but still couldn't fix even after adding the class path.

    Me and a friend are programming on different machines on different projects, and on both machines we have the same effect so i dont think it's an issue of my configuration or sth.

    My machine: Windows XP, Service Pack 2 (company restrictions) and STS Version: 2.3.2.RELEASE
    Build Id: 201003230009

    Cheers, Alex


  32. @Peter Ledbrook I finally succeed to install and use spring security. I installed a fresh grails app, without maven, then installed the plugin, on a classic grails way. when everything was installed and set up, I copied my former grails app content into the new one.

    thanks for your blog. It is quite my basis of work, except I did not persist authentication into a database – so I got rid of sec_user etc. – but instead I populate a home brewed CrowdUserDetails, with info retrieved from our internal crowd server.


  33. Update:

    works like a charme on my Mac it seems, must be an Issue of the Windows Version of STS somehow. Also found some inofficial workarounds, that didn't really work for me.

    Cheers, Alex


  34. OK, now i downloaded STS 2.5.0 M3 nd went thorugh the whole process. Is working fine now. Must have been an issue of 2.3.2

    Cheers, Alex


  35. Problem deploying to Tomcat 6.0.20
    Installed security Core and ACL plugins and all is great doing a run-app within STS. Using MS SQL Server 2005 for the DB and let Grails create all the tables – again good to go. Did a "war" and tried to deploy the war to Tomcat 6.0.20 and I get the following error:

    Caused by: org.hibernate.MappingException: Could not determine type for: org.codehaus.groovy.grails.plugins.springsecurity.acl.AclObjectIdentity, at table: acl_
    entry, for columns: [org.hibernate.mapping.Column(acl_object_identity)]

    Also tried deploying changing the DataSource to "jdbc:hsqldb:mem:devDB" and got the same error. Works fine against either DataSource setting doing a run-app. Thoughts??


  36. STS version springsource-tool-suite-2.3.2.RELEASE-e3.5.2-macosx-cocoa-x86_64-installer.dmg
    I have experience all the error above whit this plugin and Solr plugin. Trying to fix error, importing jar and classes and plugin directory, etc not only did not help but made it more confusing and more error prone. Finally, it seems to me not only STS has problem but also corrupts project.

    STS version springsource-tool-suite-2.5.0.M3-e3.6-macosx-cocoa-x86_64-installer.dmg
    I started completely new project and copied my files from old project. This time i do not have any problem with this plugin nor with Solr plugin. But still Annotation does not work.

    The old project directory still does not work with STS 2.5.0.M3 and it seems corrupted by the STS 2.3.2 version. In other hand some members of group that use windows-xp are ok with STS 2.3.2


  37. @Eric I don't understand why you would be getting different behaviour with a WAR. Are you able to create an application that reproduces the problem so we can try it out?


  38. Haven't been able to create an app to reproduce. The odd part I was trying to create a war based on the latest committed changes so I did a fresh checkout from SVN creating a new project in STS. This project gives me the error. I have another STS project based on the same SVN code base but with work in progress and when I war'ed it up and deployed it all was fine. So obviously there's something different between the two projects but they both run within STS and I don't see any obvious differences. Any thoughts on what I should look for? Thanks for the help.


  39. @Eric Burt, the creator of the plugin, thinks it may be related to this issue: http://jira.codehaus.org/browse/GRAILS-6662 – perhaps the information there will help.


  40. Burt's full comment:

    I'm not sure why it's different in a war than in run-app, but I think you're seeing http://jira.codehaus.org/browse/GRAILS-6662 which is fixed for 1.3.5. AclObjectIdentity extends an abstract base class to support different identifier types beyond just Long. Any chance you'll be able to upgrade to 1.3.5 when it's released? It's being tested now and will be released very soon.


  41. How do I add a custom error msg if I use the custom login panel?

    …………………

    Currently a failed login just re-loads the page with no error msg.

    Cheers!


  42. I keep getting this exception when running against MySQL

    Configuring Spring Security …
    2010-10-10 19:54:15,010 [main] ERROR util.JDBCExceptionReporter – Table not found in statement [select this_.id as id2_0_, this_.version as version2_0_, this_.authority as authority2_0_ from sec_role this_ where this_.authority=?]
    2010-10-10 19:54:15,027 [main] ERROR context.GrailsContextLoader – Error executing bootstraps: could not execute query; SQL [select this_.id as id2_0_, this_.version as version2_0_, this_.authority as authority2_0_ from sec_role this_ where this_.authority=?]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query
    org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; SQL [select this_.id as id2_0_, this_.version as version2_0_, this_.authority as authority2_0_ from sec_role this_ where this_.authority=?]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query
    at BootStrap$_closure1.doCall(BootStrap.groovy:7)
    at grails.util.Environment.evaluateEnvironmentSpecificBlock(Environment.java:251)
    at grails.util.Environment.executeForEnvironment(Environment.java:244)
    at grails.util.Environment.executeForCurrentEnvironment(Environment.java:220)
    at org.grails.tomcat.TomcatServer.start(TomcatServer.groovy:164)
    at grails.web.container.EmbeddableServer$start.call(Unknown Source)
    at _GrailsRun_groovy$_run_closure5_closure12.doCall(_GrailsRun_groovy:158)
    at _GrailsRun_groovy$_run_closure5_closure12.doCall(_GrailsRun_groovy)
    at _GrailsSettings_groovy$_run_closure10.doCall(_GrailsSettings_groovy:280)
    at _GrailsSettings_groovy$_run_closure10.call(_GrailsSettings_groovy)
    at _GrailsRun_groovy$_run_closure5.doCall(_GrailsRun_groovy:149)
    at _GrailsRun_groovy$_run_closure5.call(_GrailsRun_groovy)
    at _GrailsRun_groovy.runInline(_GrailsRun_groovy:116)
    at _GrailsRun_groovy.this$4$runInline(_GrailsRun_groovy)
    at _GrailsRun_groovy$_run_closure1.doCall(_GrailsRun_groovy:59)
    at RunApp$_run_closure1.doCall(RunApp.groovy:33)
    at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
    at gant.Gant$_dispatch_closure7.doCall(Gant.groovy:415)
    at gant.Gant$_dispatch_closure7.doCall(Gant.groovy)
    at gant.Gant.withBuildListeners(Gant.groovy:427)
    at gant.Gant.this$2$withBuildListeners(Gant.groovy)
    at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
    at gant.Gant.dispatch(Gant.groovy:415)
    at gant.Gant.this$2$dispatch(Gant.groovy)
    at gant.Gant.invokeMethod(Gant.groovy)
    at gant.Gant.executeTargets(Gant.groovy:590)
    at gant.Gant.executeTargets(Gant.groovy:589)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115)
    Caused by: org.hibernate.exception.SQLGrammarException: could not execute query
    … 28 more
    Caused by: java.sql.SQLException: Table not found in statement [select this_.id as id2_0_, this_.version as version2_0_, this_.authority as authority2_0_ from sec_role this_ where this_.authority=?]
    at org.hsqldb.jdbc.Util.throwError(Unknown Source)
    at org.hsqldb.jdbc.jdbcPreparedStatement.(Unknown Source)
    at org.hsqldb.jdbc.jdbcConnection.prepareStatement(Unknown Source)
    at org.apache.commons.dbcp.DelegatingConnection.prepareStatement(DelegatingConnection.java:248)
    at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.prepareStatement(PoolingDataSource.java:302)
    at $Proxy10.prepareStatement(Unknown Source)
    … 28 more

    DataSource

    development {
    pooled = true
    dbCreate = "update" // one of 'create', 'create-drop','update'
    url = "jdbc:mysql://localhost/test"
    driverClassName = "com.mysql.jdbc.Driver"
    username = "test"
    password = "test"
    dialect = "org.hibernate.dialect.MySQL5InnoDBDialect"
    loqSql = true
    }


  43. Interesting an upgrade to 1.3.5 fixed my problem, go figure.


  44. Very powerful but yet simple plugin to use, thanks!


  45. I would prefer to use the SHIRO security with the UI plug in here


  46. great post. i wanna share also a spoon-feed tutorial on Spring MVC

    http://www.adobocode.com/spring/a-spring-web-mvc-tutorial

    hope it will help people!


  47. The CAS plugin doesn't work.

    It appears to install fine but when you set the documented properties to the correct values the login will never redirect to CAS and just appears to go through normal Spring security.

    It's as if it isn't even installed.


  48. Alright, so the previous issue with CAS was a result of not having access control configured for that particular URL.

    Now I'm redirected to CAS and am able to authenticate however, the callback results in the following exception in the CAS logs. It looks as if the callback is trying to trigger another authentication that is failing.

    2010-11-26 20:22:05,758 INFO [org.jasig.cas.web.flow.InitialFlowSetupAction] –
    2010-11-26 20:22:14,628 INFO [org.jasig.cas.authentication.AuthenticationManagerImpl] –
    2010-11-26 20:22:14,653 INFO [org.jasig.cas.CentralAuthenticationServiceImpl] –
    2010-11-26 20:22:14,702 INFO [org.jasig.cas.authentication.AuthenticationManagerImpl] –
    2010-11-26 20:22:14,708 ERROR [org.jasig.cas.web.ServiceValidateController] –
    org.jasig.cas.ticket.TicketCreationException: error.authentication.credentials.bad
    at org.jasig.cas.CentralAuthenticationServiceImpl.delegateTicketGrantingTicket_aroundBody6(CentralAuthenticationServiceImpl.java:300)


  49. Adding URL to pastie since the stacktrace is stripped when posting here:

    http://www.pastie.org/1327466


  50. Sorry, I don't have any experience with CAS. Some people seem to be using it without trouble, while others run into problems. It's quite possibly a configuration issue. Or perhaps /secure/receptor is secured by SpringSecurity?


  51. Hi!

    I've installed the plugin version 1.0.1, but I have an issue, running my app. I get the following exception:

    SpringSecurityUtils.java:650: method does not override a method from its superclass

    There is an @Override annotation on this line. When commented out, everything compiles just fine. Java version doesn't matter – get the error with both JDK 1.5 and JDK 1.6.

    Am I doing something wrong here? Is there a fix for this?

    Thanks!


  52. The code snippet

    def adminUser = User.findByUsername('admin') ?: new User(
    username: 'admin',
    password: springSecurityService.encodePassword('admin'),
    enabled: true).save(failOnError: true)

    should be corrected to

    def adminUser = SecUser.findByUsername('admin') ?: new SecUser(
    username: 'admin',
    password: springSecurityService.encodePassword('admin'),
    enabled: true).save(failOnError: true)


  53. Thanks, you're quite correct. I'm surprised how long that mistake has remained there!


  54. Hi

    I'm suffering from the same problem as Ray here.
    This is my development platform:
    Macbook OS X 10.5
    Java 6
    Netbeans 6.9
    Grails 1.3.6
    spring-security-core plugin 1.0.1 (could not compile with newest version)

    In Netbeans I get unresolved issues in the login controller.
    example:
    import org.springframework.security.authentication.AccountExpiredException

    I'm not quite sure how Ray solved this problem.
    I still can start the app from console but it does not work in netbeans anymore.
    Do I have to edit the classpath in the netbeans project ? where can I do this ?
    (I'm not familiar with netbeans)

    Thanks for help


  55. Sorry, don't have any experience with NetBeans. Perhaps best to ask on some NetBeans forums?


  56. Great plugin – very easy to get started with.
    I am wondering if some stronger (or even meaningful) option for password encryption could be integrated, e.g. like bcrypt. All the options offered by the JDK do not seem to be really secure:
    http://codahale.com/how-to-safely-store-a-password/

    I looked into integrating something like jBCrypt:
    http://www.mindrot.org/projects/jBCrypt/

    Wrapping jBCrypt into a MessageDigestSPI seems doable but a bit too much cruft. Any chance to get jBCrypt build right into the plugin?


  57. @Jan You might be interested in the BCrypt plugin for Spring Security: http://grails.org/plugin/spring-security-bcrypt


  58. Peter,

    Thanks for this excellent blog. I'm a relative newb to Grails and this is my first foray into using a Grails plug-in. This blog, the screencasts, and your links to Bert Beckwith's User Guide and all of the examples have made this a very painless and pleasant experience. Can't thank you and the Grails team enough!

    Cheers!

    Rich


  59. Hi all,

    I am new to Grails, and I like it so far. I followed this tutorial and everything works just fine (except "the last pieces of the puzzle"). I am getting stuck with a small issue and would like some help.
    under views I have:
    login
    |_auth.gsp
    |_denied.gsp
    index.gsp

    and my UrlMappings.groovy looks like this:

    static mappings = {
    "/$controller/$action?/$id?"{
    constraints {
    // apply constraints here
    }
    }
    "/"(view:"/index")
    "500"(view:'/error')
    "/login/$action?"(controller: "login")
    "/logout/$action?"(controller: "logout")
    }

    I want to map "/" to "login/auth" so that users are automatically sent to "login/auth" first (unless remembered) and after authentication are redirected to "/index".

    I tried to change the url mapping to "/"(view:"/index") but it doesn't work. I think I need to change the defaultTargetUrl but I'm sure. Any help would be greatly appreciated.

    Thankx !


  60. I may have hit a bug with the Ajax Spring Security feature. I am using the SECURED annotation for protecting an action that is invoked via grails remoteLink. Grails allows users to call the same action with the .xml or .js extensions. I am specifically using .js and using the withFormat functionality to return JSON. The issue I am facing is – Spring Security does not intercept this remote request and authAjax in LoginController never gets called.

    Are there any known workarounds for this issue?


  61. I would ask in the Security sub-forum here: http://grails.org/plugins/forum


  62. Yassine: as long as your index page is protected, you will get the behaviour you want. How is your index/home page implemented? Controller action? As a simple index.gsp?

    As with Sathish, you would be better asking such questions in the plugin forum.


  63. Peter, I implemented the ajax auth method based on the documentation in the spring-security-core plugin. I ran into an issue, and then searching for a solution, I found this blog article. I can't see anything I've done differently than what you've shown. Could you please take a look at my post on SO and tell me if you see anything out of order?

    http://stackoverflow.com/questions/5628199/spring-security-core-authajax-how-do-i-ignore-the-referer

    Thanks.


  64. Hi Peter:

    Thus far your example is about authenticating UI login or forms.
    How does one goes about authenticating web services(soap in my case).
    Supposed that I have a service under /service/Myservice.groovy exposed by
    Xfire like so:
    class MyService {
    static expose = ["xfire"]
    String getName(){ ..}
    String getAddress(){…}

    ..}

    Q: How do I go about configuring for authentication?. I want user to be authenticated first even before I even allow them to invoke the methods.
    How do I do this?.

    Thanks,
    BK


  65. @BK: One approach is to enable Basic Authentication for the URLs that match the web services. That's my usual starting point for REST interfaces. This mailing list thread may help: http://grails.1312388.n4.nabble.com/Re-Spring-Security-Core-Plugin-Basic-auth-for-rest-url-td2283871.html

    But really I suggest you look into authentication and authorisation for web services. I think there is a specification for this…WS-Security. Here's some documentation on using it with Spring-WS: http://static.springsource.org/spring-ws/site/reference/html/security.html


  66. ow do I decode the password with the springSecurityService ?


  67. How do I decode the password with the springSecurityService ?


  68. @Roberto: you can't. Passwords are hashed, therefore you cannot go from hashed password to the original plain text. This is by design so that if an attacker gains access to the passwords in the database, he cannot reverse engineer them to get the actual passwords.


  69. Thanks for this compact though detailed explaining article. It saved me a whole lot of time to figure out the basics of the Grails SpringSecurity stuff.
    With this basic information consumed, I can now try to continue learning the ACL plugin.
    Did I miss it, or is there really not so many articles/tutorials available on that topic (including Grails, not plain SpringSecurity) ?


  70. Peter, do you know if this plugin will provide security when using the ZK framework? I'm currently using grails with the ZKGrails plugin and found that the security that comes with grails won't work because it can't block the .zul URLs.
    Thanks!


  71. Thomas: I don't think there are many articles on Spring Security ACLs at all. I'm certainly not aware of any for Grails and it's also not a topic that I'm familiar with either I'm afraid. If you were to write a blog post or equivalent about your experience, I'd be happy to promote it.

    Eduardo: I'm not familiar with ZK, so I can't really answer this. What handles the '.zul' URLs? A dedicated servlet? If so, you probably need to do a bit more work and add the Spring Security servlet filter to that servlet too. You can run 'grails install-templates' and then add the filter mapping to 'src/templates/war/web.xml'.


  72. Peter, I actually tried using the plugin in my app and it worked fine! Thanks for your reply.

    Regards,
    Eduardo


  73. After installing the spring-security-core 1.1.3 on top of Grails 1.3.7 in STS 2.6.1.RELEASE,
    I was still getting the unable to resolve class: org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
    error in STS.

    It seems that the plugin did not define its dependencies in a BuildConfig.groovy.
    The solution was to add the following to the project's BuildConfig.groovy:

    dependencies {

    compile('org.springframework.security:org.springframework.security.core:3.0.4.RELEASE') {
    excludes 'com.springsource.org.aopalliance',
    'com.springsource.org.apache.commons.logging',
    'org.springframework.beans',
    'org.springframework.context',
    'org.springframework.core'
    }

    compile('org.springframework.security:org.springframework.security.web:3.0.4.RELEASE') {
    excludes 'com.springsource.javax.servlet',
    'com.springsource.org.aopalliance',
    'com.springsource.org.apache.commons.logging',
    'org.springframework.aop',
    'org.springframework.beans',
    'org.springframework.context',
    'org.springframework.core',
    'org.springframework.web'
    }

    }


  74. Hi Peter,

    I've been trying to figure out how to implement multiple sources to authenticate a user. I am using the CAS plugin.

    I'm trying to have my regular spring security core plugin functionality (login into my sistem with users stored in my system), and a CAS server from one organization, and a CAS server from another organization to provide access.

    I don't even know where to start. I was reading through the documentation and couldn't figure it out either.

    Could you please help?

    Thanks!

    Daniel


  75. I just installed spring-security-core-1.1.3; and created the user/role models via the helpers.

    Everything seemed to work fine until i tried to auth, then i got the:

    "null does not have the clazz property"

    This is usually due to not having the right config in Config.groovy, where you need to have something like:

    grails.plugins.springsecurity.userLookup.userDomainClass=

    But the generator adds this to Config.groovy automatically, and they were there, so it should've worked.

    I then noticed (when editing Config.groovy with vi) that there were funny chars at the end of each line (shows up as a ^M in vi). I removed them, restarted, and voila, things were fine.

    This is on windows, so i'm guessing the auto-modification of Config.groovy is using some other o/s's EOL convention and messing up Config.groovy.


  76. I want to use the Spring Security plugin in an app that already has User, Role, and UserRole (Java) classes that I need to reuse, i.e. I cannot use the Grails domain classes that the s2-quickstart script generates.

    These classes are in a separate Java project that does not have a dependency on the Grails app, so there's no way I can make them extend the classes generated by s2-quickstart either. I have a rough idea of how I might be able to get this working, but a few open questions too. If anyone has any suggestions, I'd be grateful if they'd pass them on.

    More details here:
    http://stackoverflow.com/questions/6899566/use-existing-domain-classes-with-spring-security-plugin/6913928#6913928


  77. Thanks for a great article Peter. I want to use the Spring Security plugin in an app that already has User, Role, and UserRole (Java) classes that I need to reuse, i.e. I cannot use the Grails domain classes that the s2-quickstart script generates.

    These classes are in a separate Java project that does not have a dependency on the Grails app, so there's no way I can make them extend the classes generated by s2-quickstart either. I have a rough idea of how I might be able to get this working, but a few open questions too. If anyone has any suggestions, I'd be grateful if they'd pass them on.

    More details here:
    http://stackoverflow.com/questions/6899566/use-existing-domain-classes-with-spring-security-plugin/6913928#6913928


  78. In version 1.2 of the plugin, the password is encoded in the domain class, so the code above in Bootstrap.groovy would cause the password to be encoded twice.

    http://jira.grails.org/browse/GPSPRINGSECURITYCORE-104?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#issue-tabs


  79. ga: ^M usually indicates carriage returns. Config.groovy has Unix line endings by default I believe, so if extra lines get added with Windows EOLs you run into that issue. Good catch.

    Donal: Right. I'll add an update. Thanks for pointing it out.


  80. Hi,
    there is a mistake in your post because password from bootstrap is hashed two times.
    One time in bootstrap file and second time before saving User class.
    I think you should fix this for save people time.

    Best regards
    Tom


  81. @Tom: I have already added an 'Update' paragraph explaining the change with Spring Security Core 1.2, but thanks for pointing it out. If you have suggestions for making it clearer, let me know.


  82. Hi Peter,

    I am a Grails newbie, trying to use the spring-security-core plugin to secure my first Grails application. I can't seem to figure out how to the plugin where to redirect control once a successful login occurs. What if each type of user/role is supposed to see a different "home" page?

    This would seem to me to be a crucial piece of using the framework this plugin provides. Did I just miss it? How do you do this?

    Thanks for the great screen cast – very helpful!

    Michael


  83. @Michael: this can be handled within a controller. So Spring Security redirects to a "home" action which could then redirect to the appropriate page based on the user's principal and/or role(s). The plugin gives you access to the necessary information through the SpringSecurityService bean and the SecurityUtils utility class.


  84. @Michael: I also saw this article recently, which tackles that particular problem:

    http://omarello.com/2011/09/grails-custom-target-urls-after-login/


  85. I just created a new grails-app,
    everything was fine until I decided
    to install Spring Security Core.

    After installing Spring Security Core
    doing an s2-quickstart and hitting
    grails run-app, it produced the
    following error:
    URI
    /test1/
    Class
    java.lang.IllegalStateException
    Message
    No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

    Anybody know how to fix this?
    I would really appreciate it if
    you help. I have tried looking for
    answers in other websites, however
    I was unable to solve it. :)
    BTW, I am using:
    Spring Security Core 1.2.4
    Grails 2.0.0.RC1


  86. I've been following the examples in the screencast, but couldn't get it to work… until I red Tomasz comment and realized I was encrypting the password twice. Now everything maskes sense.
    BTW: I'm looking forward to see the next Manning Grails book :) .


  87. Hi Peter,

    I've written an article using your example application and added spring-security-ldap plugin to manage authentication and authorization.

    http://blog.alfonsorv.com/grails-ldap-authentication-and-authorization/

    Regards

    Alfonso


  88. Sorry for the much delayed reply.

    @Hyun Jung Soh: I can't tell from that error message, but it may be a conflict between Resources and Spring Security Core. I'll try to get an answer for you if you haven't managed to resolve it yet.

    @Alberto: right. I added a note to the article, but re-recording the screencast is a bit more work.

    @Alfonso: that's great! Thanks for publishing that.


  89. @Hyun Jung Soh: Peter's right, this is a conflict between the resources plugin which is installed by default in 2.0 and the Spring Security plugin. We are testing a fix and will have updated plugins soon – for now just uninstall the resources plugin by removing it from BuildConfig.groovy and running 'grails clean'


  90. I have some philosophical problems with the implementation of Spring Security… Perhaps I'm misunderstanding how to use it?

    First observation: annotations don't control access when template=true in the controller. I like to leave the controllers as generic as possible for as long as I can to keep my code as DRY as possible.

    Second, as has been observed elsewhere: the notion of role is very blunt compared to the Basic Security (GSEC) plugin. Basically I have to tightly integrate the code I write with each controller so my security logic becomes tightly integrated with both my business logic and with my views of the data.

    Third, I can't control edit/delete authorization solely through intercept URL's (that I can see, anyway). Odds are good that I'm missing something, but maybe not?

    I want to use tools that are going to be supported, but as near as I can tell the (GSEC) Basic Security plugin is superior in several ways.


  91. @Paul: do you mean 'scaffold = true' rather than 'template = true'? If that's the case, then yes you can't use annotations on the dynamically scaffolded actions. You would either have to use static scaffolding or specify URL rules instead.

    There is a Spring Security ACL plugin, but it's geared towards protecting domain classes.

    I'm not too sure what you mean with your third point. Why can you not use URL rules for this?


  92. @Peter Ledbrook: Thanks for responding. Yes, I meant scaffold– I'm very new to Grails/Groovy and am still learning the ropes!

    Re: URL rules, it may be my ignorance and the lack of an example demonstrating the idea.

    My core values:

    - Avoid generating controllers and views as long as possible
    - Don't show users options they can't select
    - Assignment of authorization to roles should be separated from business logic
    - I really don't want to have to rewrite fine grained authorizations for each new app

    For example, if you have two roles ROLE_USER and ROLE_MANAGER and you want USER to only see the data while allowing MANAGER to create, edit, and delete items. We want to use scaffolding for both the controller and the views as long as we can, to minimize having to deal with stovepipe bugs and to keep our code DRY.

    With GSEC you create basic authorizations for each operation and then assign them to a role; then each user is assigned to a role. The GSEC scaffolding for the controller already "understands" add, edit, view and delete authorizations– All you have to do is to assign them to the role. You don't touch any controller or view code /for security purposes/.

    With Spring Security you can control access via an intercept URL, but I don't see how to allow GET but refuse PUT/POST, DELETE and create requests (without customizing the controller?) Controlling the URL access still doesn't address not showing users options that aren't available to them…

    To do that you have to generate and modify each controller to behave as you want for each role and domain– If you don't want USER to have an EDIT option then you have to code each controller to understand the specific roles it must handle.

    That seems like a significant violation of the DRY principle, at least compared to GSEC! :-)

    I'm hoping there is something easy and obvious that I've missed!


  93. Great post. What is the recommended strategy for testing AJAX methods that require authentication using an automated approach. How could this be handled in integration tests? Alternatively, is there a way to use curl and if so, what credentials would be specified on the command line.


  94. Where can I download the sample code shown in the web cast ?


  95. I downloaded the app from the above link and upgraded it to run on grails 2.0M2.
    Also had to upgrade the spring-security plugin to get it working.

    Any help is appreciated.

    Now when I start the server, I get a bootstrap error :

    Configuring Spring Security UI …
    Creating user chuck_norris…

    | Error 2012-02-01 10:57:51,514 [Thread-5] ERROR context.GrailsContextLoader – Error executing bootstraps: object references an unsaved transient instance – save the transient instance before flushing: org.example.Profile; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance – save the transient instance before flushing: org.example.Profile
    Line | Method
    ->> 46 | onApplicationEvent in org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener
    - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - –
    | 47 | doCall in BootStrap$_closure1_closure3
    | 30 | doCall . . . . . . . . . . . . . in BootStrap$_closure1
    | 264 | evaluateEnvironmentSpecificBlock in grails.util.Environment
    | 257 | executeForEnvironment . . . . . in "
    | 233 | executeForCurrentEnvironment in "
    | 303 | innerRun . . . . . . . . . . . . in java.util.concurrent.FutureTask$Sync
    | 138 | run in java.util.concurrent.FutureTask
    | 886 | runTask . . . . . . . . . . . . in java.util.concurrent.ThreadPoolExecutor$Worker
    | 908 | run in "
    ^ 662 | run . . . . . . . . . . . . . . in java.lang.Thread

    Caused by TransientObjectException: object references an unsaved transient instance – save the transient instance before flushing: org.example.Profile


  96. @Smita It appears to be a bug in Grails 2.0 that will be fixed in 2.0.1 when that is released. For the time being, edit 'grails-app/conf/BootStrap.groovy' and insert this line:

    . user.profile.user = user

    immediately after this one (line 21):

    . user.profile = new Profile(profileAttrs)


  97. returns null CurrentUser me, anyone know why? want to help me please?


  98. @Ruben I recommend asking on the Grails mailing list for help: http://grails.org/Mailing Lists – please provide example code that demonstrates the problem what Grails version and Spring Security Core plugin version you are using.


  99. The two screencast links are currenlty broken, the mov's do not exits.

    However after much hunting in YouTube :) I have found Peter's hard work. Now if someone could fix the blog links that would be nice.

    http://www.youtube.com/watch?v=auwML_bsUEE

    http://www.youtube.com/watch?v=omhEVBrnJPU


  100. Has anyone gotten CAS to work with Grails 2.x. I have it working with 1.3.7 but can't get it working with 2.0.4. It would be nice if someone can confirm that they have it working and would offer advise. Thanks Keith


  101. Hi

    Can anyone suggest how should I inject the logged in user (SecUser instance) in my controllers and services?

    Thanks


  102. @Roger Thanks for the heads up. I have fixed the links.

    @Keith Spring Security CAS has recently been updated. It may be worth trying the latest version.

    @Kumar The first code sample under "The user interface" demonstrates how to do this. Does that not work for you?


  103. Hi Peter,

    That's correct. We can get SecUser instance using :-

    def user = SecUser.get(springSecurityService.principal.id)

    But I think that each time the method is invoked the instance will be fetched from database (or the hibernate session).

    In my scenario, I have made the controller with scope session using

    static scope = "session"

    I want the SecUser instance to be injected in my session scoped controller (using some annotation or in some external config.) so that it is available to all controller actions without explicitly getting it using the '.get' method every time.

    Please tell if I am missing anything or if it's right approach.

    Thanks

8 trackbacks

Leave a Reply