Reputation: 461
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.
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.
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(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.
Upvotes: 0
Views: 1215
Reputation: 7863
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();
Upvotes: 1