spring 4 and CSRF - spring

I use spring boot, spring rest and spring security in a single page application.
With spring 4, CSRF is enable by default.
I wrote a class who extend WebSecurityConfigureAdapter
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/rest/**").authenticated();
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
http.formLogin().successHandler(authenticationSuccessHandler);
http.formLogin().failureHandler(authenticationFailureHandler);
http.logout().logoutSuccessUrl("/");
// tried with and without... same issue
http.addFilterAfter(new CsrfTokenResponseHeaderBindingFilter(), CsrfFilter.class);
}
CsrfTokenResponseHeaderBindingFilter come from
https://github.com/aditzel/spring-security-csrf-filter/blob/master/src/main/java/com/allanditzel/springframework/security/web/csrf/CsrfTokenResponseHeaderBindingFilter.java
I use only html (so no jsp, no xhmtl...) page only.
I do ajax call and feed my html.
Request header
POST /login HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 30
Pragma: no-cache
Cache-Control: no-cache
Accept: */*
Origin: http://localhost:8080
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost:8080/
Accept-Encoding: gzip, deflate
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: JSESSIONID=B05ED2676EC1637D74AC7622E018C9FD
In my form i have
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
When I try to log, i get
{"timestamp":1444179957867,"status":403,"error":"Forbidden","message":"Expected CSRF token not found. Has your session expired?","path":"/login"}
When the log fail, this command return null
jqXHR.getResponseHeader('X-CSRF-TOKEN')
ajax call
var data = 'username=' + $('#username').val() + '&password=' + $('#password').val();
$.ajax({
data: data,
timeout: 1000,
type: 'POST',
url: '/login'
}).done(function (data, textStatus, jqXHR) {
window.location = "main.html";
}).fail(function (jqXHR, textStatus, errorThrown) {
});
});
EDIT
In the browser when i connect to localhost:8080.
i see in the header answer
X-CSRF-HEADER:X-CSRF-TOKEN
X-CSRF-PARAM:_csrf
X-CSRF-TOKEN:0d5bf042-a30f-4f2e-a99c-51ed512f811a
How to get this information in JS? I need to put it in my post call.

There isn't enough information to debug this issue. You should post the following information:
Your XML/Java Spring Security Configuration.
Your Spring Web Configuration. Are you using JSPs or XHTML? Are you sure your view model is correct? Maybe your having issues with the web module not sending the token.
The actual http request headers/body. Is the request actually correct or is spring just not picking up the token?

Related

Web API CORS requests and browser cache

We're using web api cors requests in our application and many api calls are cacheable by the clients, i.e. browsers.
Chrome and Firefox honours the cache control headers and caches the responses as they are supposed to but Internet Explorer and Safari always performs new requests.
Controller:
[EnableCors("*", "*", "*")]
public HttpResponseMessage Get()
{
var response = Request.CreateResponse(HttpStatusCode.OK, "test");
response.Headers.CacheControl = new CacheControlHeaderValue
{
Public = true,
MaxAge = DateTime.UtcNow.AddDays(7) - DateTime.UtcNow
};
response.Headers.ETag = new EntityTagHeaderValue("\"" + Guid.NewGuid().ToString() + "\"");
return response;
}
JQuery ajax request (issued from another domain):
$.ajax({
type: 'GET',
url: 'http://next.b.se/api/tests'
}).done(function (data) {
$("#v").text("Done!");
}).error(function (jqXHR, textStatus, errorThrown) {
$("#v").text("Error");
});
Request (from fiddler):
GET http://next.b.se/api/tests HTTP/1.1
Referer: http://hitta.a.se/local.html
Accept: */*
Accept-Language: en,sv-SE;q=0.5
Origin: http://hitta.a.se
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: next.b.se
DNT: 1
Connection: Keep-Alive
Response (from fiddler):
HTTP/1.1 200 OK
Cache-Control: public, max-age=604800
Content-Type: application/json; charset=utf-8
Content-Encoding: gzip
ETag: "4bfa551b-61db-42cb-8877-25f20a0ec94d"
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
Access-Control-Allow-Origin: *
Date: Mon, 09 Jun 2014 10:58:12 GMT
Content-Length: 192
When loading the page hitta.a.se/local.html, from which the cross domain request is done, the first time after cleaning the browser cache all browsers (IE, CHrome, FF and Safari) makes a request to the api endpoint as expected.
When loading the page hitta.a.se/local.html the second time in a new tab and hitting return Chrome and FF gets the cached version, i.e. no request is issued to the api (as expected due to the cache-control headers) according to Fiddler and dev tools. The problem is that IE issues a new request, it does not use the cached version and it doesn't issue a conditional get using the etag and if-none-match header. I know that the api doesn't handle if-none-match requests but the problem is that the browser doesn't perform a conditional request at all.
Which is the appropriate approach if we would like IE and Safari to use the cached responses?
Notice! This question is posted on codeplex, https://aspnetwebstack.codeplex.com/discussions/548035, as well. I don't know where the web api gurus are most active!
UPDATE 2014-06-10
If we change the api call to use JSONP instead of Ajax Internet Explorer caches the response according to the cache headers.
JQuery JSONP request:
$.ajax({
type: 'GET',
url: 'http://next.b.se/api/tests',
dataType: 'jsonp',
contentType: 'text/javascript',
jsonpCallback: 'p',
cache: true
}).done(function (data) {
$("#v").text(data.v);
}).error(function (jqXHR, textStatus, errorThrown) {
$("#v").text("Error");
});
Safari still performs a new request. Any known workarounds for Safari? I.e. force Safari to honour the cache headers either on a cross domain XHR request or a JSONP request?
BR,
Max

Can't set a header using Cors and Ajax

Hello I am trying to do a http request with Basic Auth, but I can't set the header authorization and it is allowed in server.
Ajax :
$.ajax({
xhrFields: { withCredentials: true },
beforeSend: function(xhr){xhr.setRequestHeader('authorization', 'Basic cmFmmFuQHBoaWlubm92YXRpb25zLmNv=');},
url : 'http://www.vozi.dev.br/api/audio',
type: 'POST',
data: JSON.stringify(sender),
dataType: 'json',
contentType: 'application/json',
success : function(data, textStatus, jqXHR) {
//do something
}
});
Http Request Header:
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,pt;q=0.6
Access-Control-Request-Headers:accept, authorization, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:www.vozi.dev.br
Origin:http://localhost:8080
Referer:http://localhost:8080/act_text.jsp
User-Agent:Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36
Http Response Header:
Access-Control-Allow-Headers:accept, authorization, content-type
Access-Control-Allow-Methods:GET, POST, OPTIONS
Access-Control-Allow-Origin:*
cache-control:no-cache
Connection:Keep-Alive
Content-Type:text/html; charset=UTF-8
Date:Wed, 14 May 2014 20:15:53 GMT
Keep-Alive:timeout=5, max=100
Server:Apache/2.4.6 (Ubuntu)
Set-Cookie:PHPSESSID=k6gg748e47b2fv67; path=/
Transfer-Encoding:chunked
www-authenticate:Basic realm="Secured Area"
x-debug-token:5373cef9430fe
X-Powered-By:PHP/5.5.3-1ubuntu2
Error :
OPTIONS http://www.vozi.dev.br/api/audio 401 (A Token was not found in the SecurityContext.) jquery.js:8706
OPTIONS http://www.vozi.dev.br/api/audio Invalid HTTP status code 401 jquery.js:8706
XMLHttpRequest cannot load http://www.vozi.dev.br/api/audio. Invalid HTTP status code 401
I assume your having this issue with IE10 or IE11, This is not an issue with Chrome.
IE doesn't send authorization headers with OPTIONS request, so on server side if you enable Windows integrated authentication, it does reject the OPTIONS request.
I have this workaround posted on another stackoverflow question
I find out that i can't use
Access-Control-Allow-Origin:*
if I am using
withCredentials: true
Is necessary to set the origin.

JQuery-Ajax headers issue

I got a problem with the headers when i'm trying to do a POST Request with JSON
This is the code:
$.ajax({
type: "POST",
url: url,
data: jsonData,
dataType: 'json',
beforeSend: function(xhrObj){
xhrObj.setRequestHeader("Content-Type","application/json");
xhrObj.setRequestHeader("Accept","application/json");
},
error: function(){
alert("Fail");
},
success: function(){
alert("Success");
}
});
And this are the Request Headers displayed by Firebug.
OPTIONS /path HTTP/1.1
Host: 192.168.15.109:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20100101 Firefox/12.0 FirePHP/0.7.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Origin: http://localhost
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
x-insight: activate
Pragma: no-cache
Cache-Control: no-cache
And the Response Headers:
HTTP/1.1 204 No Content
Date: Thu, 24 May 2012 19:17:01 GMT
Allow: OPTIONS,POST
As you can see, the headers doesnt match with the ones im specifying, but when i use CURL the Headers are this ones instead:
POST /path HTTP/1.1
User-Agent: curl/7.25.0 (i386-pc-win32) libcurl/7.25.0 OpenSSL/0.9.8u zlib/1.2
Host: localhost:8080
Accept: */*
Content-Type: application/json
Content-Length: 5
Any idea or solution for this?
I also modified JQuery Source to set default values of the Headers sent by Ajax to JSON, but didnt work.
Seems like a same-origin policy issue. Using dataType='jsonp' should work, but this might require other changes.
See https://developer.mozilla.org/en/http_access_control for an in-depth explanation.
Actually, it was a cross Domain problem, I defined my URL as an IP, so the browser interpreted it like a Cross Domain request.
Thanks for everything!

Run jQuery AJAX call when previous AJAX call fail due to connection was unexpactly closed

I know about error in application running on server and invoked operation disconnect all HTTP clients. I need to invoke this functionality on the server but I'm not able to fix the error.
Here is my server code:
<?php
// file: run_script.php
shell_exec('close_all_HTTP_connections_error '.$_REQUEST['params']);
?>
I'm trying to find workaround via AJAX call, I know that call fails, but user doesn't see error like ERR_EMPTY_RESPONSE. My problem is that I need to do another call to the server (which doesn't fail normaly). The second call is not send to server because previous call fail I guess.
Here is my jQuery AJAX call:
function sendData(url, step) {
$.ajax({
type: 'POST',
async: true,
url: url,
headers: { // I try it without this also
'Connection' : 'close'
},
data: {
'params' : 'bla bla'
},
complete: function(jqXHR, textStatus) {
console.log(jqXHR);
console.log(textStatus);
if (step < 2) {
sendData('another.php', step+1);
}
else {
console.log("done");
// go forward
}
},
dataType: 'html'
});
}
$(document).ready(function() {
sendData('run_script.php', 1);
});
Here is my screen shot from Chrome inspector:
And HTTP Requests:
run_script.php:
POST http://?????.com/test/run_script.php HTTP/1.1
Origin: http://?????.com
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.22 (KHTML, like Gecko)
Chrome/19.0.1049.3 Safari/535.22
Content-Type: application/x-www-form-urlencoded
Accept: text/html, */*; q=0.01
Referer: http://?????.com/test/result.php
params:bla bla
another.php:
POST http://?????.com/test/another.php HTTP/1.1
Origin: http://?????.com
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.22 (KHTML, like Gecko)
Chrome/19.0.1049.3 Safari/535.22
Content-Type: application/x-www-form-urlencoded
Accept: text/html, */*; q=0.01
Referer: http://?????.com/test/result.php
params:bla bla
There is no HTTP Response of course.
Problem was, that task previously invoked on server restarts server. Then I need to wait before next AJAX call is invoked.
I fact I have to solve problem with server restart first, this is work-around only and not the best solution.

Jquery AJAX call to pylons failing intermittently on identical requests

I am creating an ajax call like so:
var form = $("#form");
$.ajax({url: "/url/create_web_registration?invite_token=abc",
data: form.serialize(),
type: "POST",
dataType: "json",
success: $.web_registration.index.registerSubmitSuccess,
error: $.web_registration.index.registerSubmitError,
});
However when I repeat the request with identical parameters, I sometimes get the success callback and sometimes get the error callback. When the error callback is called, the jqXHR.status is always 0 on a failure, but there is nothing descriptive in statusText, responseText, textStatus or errorThrown.
I did a tcpdump on the HTTP requests and the request looks like:
POST /shopkick/v1/user/create_web_registration?invite_token=abc HTTP/1.1
Host: [redacted]:5000
Connection: keep-alive
Referer: http://[redacted]:5000/wr2/abc?invite_token=&zip_code=94123&phone_number=%2B16785556982&facebook-form=
Content-Length: 169
Origin: http://[redacted]:5000
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_7) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.215 Safari/535.1
Content-Type: application/x-www-form-urlencoded
Accept: application/json, text/javascript, */*; q=0.01
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
invite_token=&zip_code=94123&phone_number=%2B16785552982
The response looks like:
HTTP/1.0 200 OK
Server: PasteWSGIServer/0.5 Python/2.6.1
Date: Wed, 31 Aug 2011 05:34:10 GMT
Pragma: no-cache
Cache-Control: no-cache
Content-type: text/plain
Content-Length: 74
{"error_message": "Facebook account already registered", "success": false}
I am at a loss to why it is sometimes succeeding and sometimes failing.
The problem was I was using ajax to submit a form. When I clicked the submit button it would work fine, but when I hit enter in a text input field it would encounter the errors. Apparently hitting enter in a input field was causing the form to submit twice. The fix was to set onsubmit="return false;" for the form to prevent double submission.

Resources