Adding a XSRF-TOKEN via a HTTP Interceptor causes a 400 Bad Request
Adding a XSRF-TOKEN via a HTTP Interceptor causes a 400 Bad Request
Using a XSRF-TOKEN to prevent against XSRF attacks as I'm passing a JWT threw a cookie for my Angular app. Here is what my HttpInterceptor
is looking like.
HttpInterceptor
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>
const headerName = "XSRF-TOKEN";
const respHeaderName = "X-XSRF-TOKEN";
let token = this.tokenExtractor.getToken() as string;
if (token !== null && !req.headers.has(headerName))
req = req.clone( headers: req.headers.set(respHeaderName, token) );
return next.handle(req);
This causes a 400 Bad Request error to pop up in my console with a message reading: Response for preflight does not have HTTP ok status. If I comment out the line of code where the request is cloned, the error goes away, and my HTTP request goes through perfectly.
My headers in my .htaccess
look like this.
.htaccess
Header set Access-Control-Allow-Origin "http://localhost:4200"
Header set Access-Control-Allow-Credentials "true"
Header set Access-Control-Allow-Headers "Content-Type"
Header set Access-Control-Allow-Headers "Authorization"
Header set Access-Control-Allow-Headers "X-XSRF-TOKEN"
Header set Access-Control-Expose-Headers: "Authorization"
Any help would be greatly appreciated, thanks.
EDIT 1: A MCVE of my PHP code
$return = array();
if (isset($_POST["email"]) && isset($_POST["password"]))
header("HTTP/1.0 200");
$return["msg"] = "random";
echo json_encode($return);
else
header("HTTP/1.0 400");
$return["error_message"] = "HTTP Post variables are not set!";
$return["friendly_error_message"] = "Client error!";
echo json_encode($return);
exit();
And my verify()
function in my Angular service.
verify()
verify(email: string, password: string): Observable<JSON>
let headers = new HttpHeaders()
headers = headers.set("Content-Type", "application/x-www-form-urlencoded");
let body = new HttpParams();
body = body.set("email", email);
body = body.set("password", password);
return this.http.post<JSON>("http://localhost:80/verify", body, headers: headers, withCredentials: true, observe: "response" ).pipe(
map(res =>
return res.body;
),
catchError(this.handleError)
);
I've been testing with a "XSRF-TOKEN" session cookie by commenting/un-commenting a line of PHP code. When the session cookie is active, this error happens.
When I delete the cookie, I obviously don't have this problem because the req.clone()
function never goes through as the conditional isn't met.
req.clone()
I'll edit my post and throw in my PHP code later today. Thanks for the help!
– Jacob
21 hours ago
@KoalaYeung check out my edit :)
– Jacob
13 hours ago
Your PHP conditional would only return a "200 OK" when (a) it is a POST request; and (b) the POST body has the correct email and password. As I said earlier, a preflight request is always an OPTION request. Therefore your logic here would always return "400 Bad Request".
– Koala Yeung
11 hours ago
That makes sense but I guess I just don't understand why this whole "XSRF-TOKEN" thing I'm doing is messing everything up.
– Jacob
11 hours ago
1 Answer
1
Your server side code is not correctly responding to the preflight request for XSRF / CSRF workflow. You have to return a "200 OK" response to an OPTIONS request so your Angular plugin works:
<?php
$return = array();
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS')
// instead of doing that in .htaccess
header("Access-Control-Allow-Origin: http://localhost:4200");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Headers: Content-Type");
header("Access-Control-Allow-Headers: Authorization");
header("Access-Control-Allow-Headers: X-XSRF-TOKEN");
header("Access-Control-Expose-Headers: Authorization");
// a 200 OK response to preflight with empty body
header("HTTP/1.0 200");
elseif (isset($_POST["email"]) && isset($_POST["password"]))
// presuming all request that are not a preflight
// must be a POST request.
header("HTTP/1.0 200");
$return["msg"] = "random";
echo json_encode($return);
else
header("HTTP/1.0 400");
$return["error_message"] = "HTTP Post variables are not set!";
$return["friendly_error_message"] = "Client error!";
echo json_encode($return);
exit();
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
You have not shown your PHP code. Browsers will use OPTION request to your endpoint for "preflight". And it should return an "200 OK" response with proper headers.
– Koala Yeung
yesterday