Reputation: 10928
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
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