Pete
Pete

Reputation: 10928

OAuth2 with spring-security - limit REST access by HTTP method

So we've implemented the OAuth2 - client credentials grant between our REST server and a client application server using spring-security . The client can access its resources with the token it gets using client credentials authentication.

What I don't get are the Scopes I can set up for a client and the resources.

I explicitly said, Client A has Role X with Scope READ and I said Resource U can be accessed with Role X and Scope READ. Now I expect the resource to reject any DELETE or POST request but apparently I am mistaken. If I send a HTTP DELETE to Resource U it will get through.

So it looks like the Scopes are meaningless in my setup. How can I make use of them?

Or do I still need to limit access at the resource itself as I suggested below?


Snippets from our setup:

<oauth:client-details-service id="clientDetails">
    <oauth:client client-id="the_client"
        authorized-grant-types="client_credentials" authorities="ROLE_CLIENT"
        scope="read" secret="secret" />
</oauth:client-details-service>


<http pattern="/rest/**" create-session="never"
    entry-point-ref="oauthAuthenticationEntryPoint"
    access-decision-manager-ref="accessDecisionManager"
    xmlns="http://www.springframework.org/schema/security">
    <anonymous enabled="false" />

    <intercept-url pattern="/rest/persons" access="ROLE_CLIENT,SCOPE_READ" />

    <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>

The REST resource:

@Path("/persons")
@Named
public class PersonRest {

    @GET
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @Produces({ MediaType.APPLICATION_JSON })
    public Response getAll(@Context UriInfo uriInfo) {
        // ...
    }

    @DELETE
    @Path("/{id}")
    @Consumes(MediaType.TEXT_PLAIN)
    @Produces(MediaType.APPLICATION_JSON)
    @Transactional
    public Response delete(@PathParam("id") String id) {
        // ...
    }

Is there any "simple" configuration to tell spring security on the server side, that ROLE_READ should allow only GET requests?

Or do I need some @PreAuthorize annotation or context setup for the specific resource?

So, would something like that work: ?

    @PreAuthorize("hasScope(read)")
    @DELETE
    @Path("/{id}")
    // ...
    public Response delete(@PathParam("id") String id) {

Though that would be horrible news if I had to do it this way as then I'd have to configure each resource individually...

Maybe I can make use of some filter?

Thanks for any help with this!

Upvotes: 4

Views: 4450

Answers (1)

TheWhiteRabbit
TheWhiteRabbit

Reputation: 15768

Why can't you use

@RolesAllowed({"customRole"})

to protect your HTTP Method , and convert Oauth scope to {customRole} using a Filter

or have you tried

<security:intercept-url pattern="/rest/persons" access="hasAnyRole('ROLE_USER_READ')" method="GET"/> 

or something similar

Upvotes: 3

Related Questions