Abhishek Patil
Abhishek Patil

Reputation: 1445

Spring security bypass CSRF verification for specific URL's

I have a spring security + MVC based project.

The web aspect of the project has already been developed by previous developers. I am tasked with exposing some API's on which an service provider is going to do callback.

To archive this I have done the following code.

@RestController
public class LeegalityController {

    private static final Logger logger = LoggerFactory.getLogger(LeegalityController.class);

    @RequestMapping(value = "webhook/{user}/{id}", method = RequestMethod.POST)
    public ResponseEntity<String> webhook(@PathVariable("user") int user, @PathVariable("id") String id,
            @RequestBody LeegalityReqResp reqResp, HttpServletRequest request) {
        try {
            logger.info("webhook()== user[" + user + "] == id[" + id + "]");
            logger.info("webhook()== LeegalityReqResp-->" + reqResp.toString());

        } catch (Exception e) {
            logger.error("webhook() Error==[" + e.getMessage() + "]", e);
        }

        return new ResponseEntity<String>("success", HttpStatus.OK);
    }

}

However while testing the API via postman I got the following error

enter image description here

I have tried some changes in security configuration xml as below

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
    xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security.xsd">


    <http pattern="*/webhook/**" security="none" create-session="stateless" />

    <http auto-config="true">
        <intercept-url pattern="/"
            access="hasAnyRole('ROLE_ADMIN','ROLE_ONE','ROLE_TWO')" />

        <!-- <intercept-url pattern="/webhook/**" method="POST" access="permitAll" /> -->


        <intercept-url pattern="/admin"
            access="hasRole('ROLE_ADMIN')" />

        <intercept-url pattern="/otp"
            access="hasAnyRole('ROLE_ONE','ROLE_TWO')" />


        <form-login login-page="/ProjectName-Home"
            default-target-url="/" authentication-failure-url="/login?error"
            username-parameter="username" password-parameter="password" />

        <logout logout-success-url="/login?logout" />
    </http>

    <authentication-manager
        alias="authenticationManager">
        <authentication-provider
            ref="userAuthenticationProvider">
        </authentication-provider>

    </authentication-manager>

    <beans:bean id="userAuthenticationProvider"
        class="com.java.ProjectName.service.user.UserAuthenticationProvider"></beans:bean>

    <beans:bean id="encoder"
        class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
        <beans:constructor-arg name="strength"
            value="11" />
    </beans:bean>
</beans:beans>

What should I do to make sure this /webhook/* is excluded from CSRF verification. Any help is appreciated and thank you in advance.

My spring version is 4.2.0.RELEASE and spring security version is 4.0.2.RELEASE.

Upvotes: 1

Views: 3429

Answers (2)

Sandip Jangra
Sandip Jangra

Reputation: 164

For anyone, If Answer from @ken Chan doesnt work due to pom definition errors. Please try below configurations.

I am using spring security 3.2 and below configurations worked for me.

<beans:bean id="csrfMatcher" class="org.springframework.security.web.util.matcher.AndRequestMatcher">
                <beans:constructor-arg name="requestMatchers">
                        <beans:list>
                                <beans:bean class="org.springframework.security.web.csrf.CsrfFilter$DefaultRequiresCsrfMatcher" />
                                <beans:bean class="org.springframework.security.web.util.matcher.NegatedRequestMatcher">
                                        <beans:constructor-arg>
                                                <beans:bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
                                                        <beans:constructor-arg value="/j_spring_security_check"/>
                                                </beans:bean>
                                        </beans:constructor-arg>
                                </beans:bean>
                        </beans:list>
                </beans:constructor-arg>
        </beans:bean>

Please add block of NegatedRequestMatcher in the list if you want to bypass multiple urls.

Upvotes: 1

Ken Chan
Ken Chan

Reputation: 90447

To exclude a particular URL from CSRF protection , you could use <csrf request-matcher-ref="csrfMatcher"> . The csrfMatcher is the RequestMatcher which defines which URL request will have CSRF protection.

Docs has an example to just excluding a particular URL while still keeping other default settings remain unchanged:

<http ...>
    <csrf request-matcher-ref="csrfMatcher"/>
    ...
</http>


<beans:bean id="csrfMatcher" class="org.springframework.security.web.util.matcher.AndRequestMatcher">
    <beans:constructor-arg value="#{T(org.springframework.security.web.csrf.CsrfFilter).DEFAULT_CSRF_MATCHER}"/>
    <beans:constructor-arg>
        <beans:bean class="org.springframework.security.web.util.matcher.NegatedRequestMatcher">
          <beans:bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
            <beans:constructor-arg value="/webhook/**"/>
          </beans:bean>
        </beans:bean>
    </beans:constructor-arg>
</beans:bean>

Upvotes: 4

Related Questions