SavvasM
SavvasM

Reputation: 49

403 Forbidden Invalid CSRF

I am building a web app using spring security and thymeleaf, I got it work with login and logout, but I have some issues when I try to register as an end user. I am getting an invalid csrf token error. I am new to this, and I could use some help. My question is how can I attach a token to that request?(Post /registration) By the way I haven't used any XML, I use annotations.

This is the request

    $scope.registerUser = function() {
      $http.post(BASE_URL + "/registration", $scope.registrationRequest).
          success(function (data, status, headers, config) {
            $log.info("Success: " + headers('Location'));
            $scope.hasRegistered = true;
          }).error(function(data, status, headers, config) {
             $scope.hasRegisterErrors = true;
             $log.info("Error: status =" + status + ", body =" + JSON.stringify(data));
          });
  }

And the error

    Error: status =403, body ={"timestamp":1430645356572,"status":403,"error":"Forbidden","message":"Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.","path":"/registration"}

Upvotes: 1

Views: 15687

Answers (2)

M2E67
M2E67

Reputation: 970

you should add csrf parameter as a parameter in your request. for example, use following code to define an input in your form to get csrf token and add as request parameter for sending post request by form:

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>

or use following code to send as ajax call:

<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>

Then construct the header:

var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");

$(document).ajaxSend(function(e, xhr, options) {
    xhr.setRequestHeader(header, token);
});

so, you need get srcf token to send as a parameter in your request. by spring security you can define csrf parameter name by following configuration:

<http>
    <!-- ... -->
    <csrf token-repository-ref="tokenRepository"/>
</http>
<bean id="tokenRepository"
    class="org.springframework.security.web.csrf.CookieCsrfTokenRepository"
    p:cookieHttpOnly="false">
    <property name="sessionAttributeName" value="_csrf"/>
    <property name="headerName" value="_csrf_header"/>
</bean>

for more, see following links: https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html https://spring.io/blog/2013/08/21/spring-security-3-2-0-rc1-highlights-csrf-protection/ http://www.baeldung.com/spring-security-csrf

Upvotes: 0

Stephen C
Stephen C

Reputation: 719561

The response message is telling you that the server expects your POST request to include either a "_csfr" parameter or an "X-CSRF-TOKEN" header. Presumably, your server has CSFR protection enabled. This is default behaviour with Spring Security though you can disable it. (I wouldn't recommend doing that.)

The Cross Site Request Forgery (CSRF) chapter of the Spring Security documentation explains what this is all about. This section explains how to implement CSRF tokens, including examples that how to embed the token in an HTML <form> or include it in an AJAX request.

Upvotes: 1

Related Questions