mehandih / grails-jaxrs

Automatically exported from code.google.com/p/grails-jaxrs
0 stars 0 forks source link

securing resources #30

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
What is the best way to secure grails-jaxrs resources? I have tried to get the 
grails-jaxrs plugin working with spring-security-core, but unfortunately 
haven't been successful (trying both basic and digest authentication modes).  I 
can post some code to show what I'm doing if needed, but thought I would just 
ask the question first.

Has anybody else tried using spring-security-core with grails-jaxrs and 
successfully secured a service?  If not, what are you using to secure your 
services? Please let me know.

Thanks,
Bobby

Original issue reported on code.google.com by bobbywar...@gmail.com on 2 Feb 2011 at 3:23

GoogleCodeExporter commented 8 years ago
Hi Bobby,

You should be able to protect JAX-RS resources like any other Grails web 
application because all requests targeted at JAX-RS resources are dispatched by 
the JaxrsController, a Grails controller which is part of the grails-jaxrs 
plugin. So you should be able to use a security framework or plugin of your 
choice. 

If that security plugin makes use of Grails filters, an integration with 
grails-jaxrs applications is possible too as described in 
http://code.google.com/p/grails-jaxrs/wiki/AdvancedFeatures#Applying_filters.

I personally didn't use spring-security with grails-jaxrs yet so I don't know 
if there are any issues with a combined usage. Do you see grails-jaxrs specific 
exceptions when using spring-security? Just post a stacktrace if you want. 

Original comment by krass...@googlemail.com on 2 Feb 2011 at 3:58

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
Yup, I figured I could use a filter, but was just trying to use the config 
options provided by spring-security.

$ grails create-plugin sampleplugin
$ cd sampleplugin
$ grails create-domain-class com.example.sampleplugin.Book
$ vi grails-app/domain/com/example/sampleplugin/Book.groovy

package com.example.sampleplugin
class Book {
    String title
    String author    

    static constraints = {
        title(blank: false)
        author(blank: false)
    }
}

$ grails package-plugin
$ cd ..
$ grails create-app sampleapp
$ cd sampleapp
$ grails install-plugin ../sampleplugin/grails-sampleplugin-0.1.zip
$ grails install-plugin spring-security-core
$ grails s2-quickstart com.example.sampleapp User Role
$ vi grails-app/conf/BootStrap.groovy

import com.example.sampleapp.User
import com.example.sampleapp.Role
import com.example.sampleapp.UserRole
import com.example.sampleplugin.Book
class BootStrap {
    def springSecurityService
    def init = { servletContext ->
        if (!Book.count()) {
            new Book(author: "Stephen King", title: "The Shining").save(failOnError: true)
            new Book(author: "James Patterson", title: "Along Came a Spider").save(failOnError: true)
        }
        def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush: true)
        def userRole = new Role(authority: 'ROLE_USER').save(flush: true)      
        String password = springSecurityService.encodePassword('password')
        def testUser = new User(username: 'me', enabled: true, password: password)
        testUser.save(flush: true)      
        UserRole.create testUser, userRole, true      
        assert User.count() == 1
        assert Role.count() == 2
        assert UserRole.count() == 1
    }
    def destroy = {
    }
}

$ grails install-plugin jaxrs
$ grails generate-resources com.example.sampleplugin.Book
$ vi grails-app/conf/Config.groovy

Add these two lines to the bottom.

grails.plugins.springsecurity.useBasicAuth = true
grails.plugins.springsecurity.basic.realmName = "Sample App"

Then I tried both of these techniques.

Technique #1, static rules in grails-app/conf/Config.groovy
grails.plugins.springsecurity.controllerAnnotations.staticRules = [
   '/api/**': ['ROLE_USER']
]

Technique #2, url map in grails-app/conf/Config.groovy
grails.plugins.springsecurity.interceptUrlMap = [
   '/api/**': ['ROLE_USER']
]

$ grails run-app
$ open http://localhost:8080/sampleapp/api/book

There's no security, our sample data shows up in XML response with no Basic 
Authentication needed.

Original comment by bobbywar...@gmail.com on 2 Feb 2011 at 5:12

GoogleCodeExporter commented 8 years ago
Does it work with other Grails artifacts that are not JAX-RS resources e.g. a 
simple Grails controller?

Original comment by krass...@googlemail.com on 2 Feb 2011 at 6:07

GoogleCodeExporter commented 8 years ago
After a little more RTFM'ing, determined I just missed a step.  You need these 
two lines in Config.groovy too:

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

Works great now! Please close this issue. Thanks! Bobby

Original comment by bobbywar...@gmail.com on 2 Feb 2011 at 6:32

GoogleCodeExporter commented 8 years ago
Ah, ok. Glad that it's working now.

Original comment by krass...@googlemail.com on 2 Feb 2011 at 6:34

GoogleCodeExporter commented 8 years ago
Hi all,
using jaxrs with spring-security-core I noticed the jaxrsFilter comes before 
the springSecurityFilterChain. This lead to rest service calls miss security 
checks. This is probably due to the fact that both plugins add their servlet 
filters to the web.xml through a call to .doWithWebDescriptor(). This approach 
doesn't guarantee any relative insertion order.
But I've seen that adding 'spring-security-core' to the loadAfter array into 
JaxrsGrailsPlugin.groovy (i.e. def loadAfter = 
['controllers','services','spring-security-core'])
solves the problem (as per 
http://grails.org/doc/latest/guide/12.%20Plug-ins.html#12.10%20Understanding%20P
lug-in%20Load%20Order ).

Could it be considered a patch for the mainstream plugin version?

Cheers
Davide

Original comment by davide.cavestro on 9 Jun 2011 at 12:22

GoogleCodeExporter commented 8 years ago
@davide

the downside of this approach is that it doesn't scale when other/further 
plugins are used that add further filters to web.xml: with every other plugin 
that needs some special consideration, we'd need to modify the loadAfter array. 
Also, the plugin makes then assumptions about the application configuration.

On the other hand, I currently don't know an alternative how to solve this 
problem, so let's (temporarily) fix it as you've proposed. However, the ideal 
solution would be that the application defines the plugin load order, but I'm 
not sure if this is possible with Grails.

Original comment by krass...@googlemail.com on 9 Jun 2011 at 6:26

GoogleCodeExporter commented 8 years ago
Fixed and pushed to master. Can you please verify that it works?

Original comment by krass...@googlemail.com on 9 Jun 2011 at 6:40

GoogleCodeExporter commented 8 years ago
Hi Martin,
I can confirm your fix works like a charm.

About cleaner approaches, maybe you could search a way to modify the order of 
listeners instead of simply adding it (maybe it's not so easy, as per 
http://jira.grails.org/browse/GRAILS-3107 ) but I'm afraid since you're tied to 
filter chains you always ends up with a way to say that your filter should be 
first or after other ones (though it's surely less invasive that forcing the 
entire plugins load order).
A working example could be taken from spring-security docs, that shows some 
ways to register filters with relative positions 
(http://burtbeckwith.github.com/grails-spring-security-core/docs/manual/guide/16
%20Filters.html)

Cheers
Davide

Original comment by davide.cavestro on 10 Jun 2011 at 2:28

GoogleCodeExporter commented 8 years ago

Original comment by krass...@googlemail.com on 30 Aug 2011 at 9:25

GoogleCodeExporter commented 8 years ago
Hello guys,

i am facing the same issue. i am using grails 2.0.4 spring-security-core plugin 
and jax-rs 0.6.

i found "spring-security-core" in loadAfter(JaxrsGrailsPlugin.groovy)  
def loadAfter = ['controllers','services','spring-security-core']

But my resource are not secured yet.

I am using @secured i.e annotation based spring-security

Code Snippet to avail spring-security:

Config.grovvy:
grails.plugins.springsecurity.securityConfigType = "Annotation"

import static org.grails.jaxrs.response.Responses.*

import javax.ws.rs.Consumes
import javax.ws.rs.GET
import javax.ws.rs.Produces
import javax.ws.rs.Path
import javax.ws.rs.PathParam
import javax.ws.rs.POST
import javax.ws.rs.core.Response
import grails.plugins.springsecurity.Secured

CategoryCollectionResource.groovy:

@Path('/api/category')
@Consumes(['application/json'])
@Produces(['application/json'])
@Secured(['ROLE_ADMIN','ROLE_USER'])
class CategoryCollectionResource {

    @POST
    Response create(Category dto) {
        created dto.save()
    }

    @GET
    Response readAll() {
        ok Category.findAll()
    }

    @Path('/{id}')
    CategoryResource getResource(@PathParam('id') String id) {
        new CategoryResource(id:id)
    }

}

CategoryResource.groovy:
import static org.grails.jaxrs.response.Responses.*

import javax.ws.rs.Consumes
import javax.ws.rs.DELETE
import javax.ws.rs.GET
import javax.ws.rs.Produces
import javax.ws.rs.PUT
import javax.ws.rs.core.Response

import org.grails.jaxrs.provider.DomainObjectNotFoundException
import grails.plugins.springsecurity.Secured

@Secured(['ROLE_ADMIN','ROLE_USER'])
@Consumes(['application/xml','application/json'])
@Produces(['application/xml','application/json'])
class CategoryResource {

    def id

    @GET
    Response read() {
        def obj = Category.get(id)
        if (!obj) {
            throw new DomainObjectNotFoundException(Category.class, id)
        }
        ok obj
    }

    @PUT
    Response update(Category dto) {
        def obj = Category.get(id)
        if (!obj) {
            throw new DomainObjectNotFoundException(Category.class, id)
        }
        obj.properties = dto.properties 
        ok obj
    }

    @DELETE
    void delete() {
        def obj = Category.get(id)
        if (obj) { 
            obj.delete()
        }
    }

}

Controller are secured but Jax-rs resources are not.

Can anybody help me on this?

Thanks
Utsav

Original comment by jimuliau...@gmail.com on 20 Jun 2012 at 9:36

GoogleCodeExporter commented 8 years ago
Morning Utsav,

I'm seeing the same behavior as you described when using Annotation based 
security.  If you use the interceptUrlMap, it should work.  

With that, I think that the right place to ask this question would be on the 
forum or to open a new issue with the problem.  This specific issue was 
addressed in that it is possible to secure the resource using the 
interceptUrlMap.  

patrick

Original comment by psg9...@gmail.com on 24 Jul 2012 at 3:21

GoogleCodeExporter commented 8 years ago
Should have search before my first 
post...http://code.google.com/p/grails-jaxrs/issues/detail?id=65

Original comment by psg9...@gmail.com on 24 Jul 2012 at 3:23

GoogleCodeExporter commented 8 years ago
import grails.plugins.springsecurity.SecurityConfigType
grails.plugins.springsecurity.securityConfigType = 
SecurityConfigType.InterceptUrlMap

worked like a champ, thx.

Original comment by jmhed...@gmail.com on 9 Nov 2012 at 7:17