1

By using Keycloack springboot adapter (with spring security), when defining the typical SecurityConfig (which extends from KeycloakWebSecurityConfigurerAdapter), and overriding the "configure" method, I run into a problem when defining access roles for an endpoint, like follows:

// typically access is defined something like this:
http
.authorizeRequests()
.antMatchers(GET, "/SOME_ENDPOINT").hasRole("SOME_ROLE")
....

This works for me, but when I change GET for POST, suddenly my API responds with - 403 Forbidden - for the intended endpoint (yes, I also updated the HTTP method on the controller's @RequestMapping annotation method itself).

What is even weirder is that I have already created many "bearer only" API's, also secured via Keycloak + springboot adapter + spring security, which have no problem whatsoever differentiating this type of endpoint access by HTTP method (I have used POST, PATCH, PUT, etc), and they work fine.

Is there some kind of restriction with "non bearer only" clients, or may I be overlooking something?

EDIT: The problem seem to stem from the fact that spring security only allows per default GET methods, and a way to go around this as suggested on the link I shared in the comments, would be disabling csrf as follows:

.csrf().disable() 

As also explained there, this deactivates the security for all endpoints which is not what I intend to do. What I'd expect would be that all http POSTs method calls (or any HTTP method) would be treated and secured by the same schema as their "GET" counterpart.

Cœur
  • 37,241
  • 25
  • 195
  • 267
tony _008
  • 647
  • 6
  • 19
  • Probably the solution is related to this(https://stackoverflow.com/questions/38108357/how-to-enable-post-put-and-delete-methods-in-spring-security?rq=1) , I'll check out. – tony _008 Sep 30 '19 at 09:39
  • You are not really describing what you think is problematic. Do you believe that the POST request should not need authorisation? – Gimby Sep 30 '19 at 09:46
  • Hi Gimby, thanks for your input, I added an edit to address your point. – tony _008 Sep 30 '19 at 09:56
  • You did not write what I asked though, you just spend more words on explaining that there is a problem and that you have found random hints on what may work around it, not what that problem exactly is. Please, start at the beginning. What happens, what do you expect to happen, why do you expect it to happen. – Gimby Sep 30 '19 at 11:10
  • I told you: 1- Spring security activates per default "cross site request forgery " checks for "Non Get Requests". 2 - Deactivating crsf, deactivates it for all the application which is inconvenient. 3 - I'd like to know if there is a common solution for allowing Non-Get requests get arround this standard behaviour. This is very succint, and any more than this would be answering my own question. Thank anyway for your help. – tony _008 Sep 30 '19 at 11:21
  • If you see a similar topic here, you'll see an even more general question (https://stackoverflow.com/questions/38108357/how-to-enable-post-put-and-delete-methods-in-spring-security?noredirect=1&lq=1) I'm quoting "How do I solve this, I'm new to Spring Security things" ..... and that received much more helpfull and constructive comments from which I'm deriving a solution now. – tony _008 Sep 30 '19 at 11:25
  • how you tested? by browser or postman? – PraveenKumar Lalasangi Sep 30 '19 at 18:11
  • 1
    [From Spring Doc](https://docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/reference/htmlsingle/#csrf-configure) If you don't have valid csrf token, by default Spring Security’s CSRF protection will produce an HTTP 403 access denied. This can be customized by configuring the AccessDeniedHandler to process InvalidCsrfTokenException differently. I think your post request does not have _csrf.token. [so include csrf token](https://docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/reference/htmlsingle/#csrf-include-csrf-token) – PraveenKumar Lalasangi Sep 30 '19 at 18:28
  • Hi PraveenKumar Lalasangi, I do indeed not have one crsf token. My app is connecting to a keycloack server which generates a typical Oauth2 access-token. I did test both (postman & browser). In my current solution I do deactivate csrf for some specific endpoints (but that is probably not the best solution). I'll check into your suggestions, thanks. – tony _008 Oct 01 '19 at 04:59
  • PraveenKumar Lalasangi, with your help (documentation you provided) I solved the problem in a satisfactory manner, namely by providing csrf tokens (json + ajax strategy described on the link), without the need to deactivate csrf checks - thanks for your input! – tony _008 Oct 01 '19 at 08:11

1 Answers1

2

Long story short, for anybody running into a similar problem; Spring security by its default CSRF (cross site request forgery) protection policy, will produce an HTTP 403 access denied for all non safe http verbs (POST, PUT, PATCH, DELETE) type of request.

One approach often seen here on stack overflow forums to go around this, is simply to disable csrf checks for a subset of the endpoints like this:

//@configure method of your Spring Security config

// disable some endpoints
http.csrf().ignoringAntMatchers("/URL_PREFIX_WHERE_CRSF_IS_IGNORED/*")....

// or disable all endpoints
http.csrf().disable()....

A better approach would be to explicitly include csrf tokens for any request (and thus avoiding the need to deactivate csrf checks).

Insight into the problem was provided by PraveenKumar Lalasangi as seen on the comments, and here is a detailed documentation related to the inclusion/use of csrf tokens:

https://docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/reference/htmlsingle/#csrf-include-csrf-token

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
tony _008
  • 647
  • 6
  • 19