In laravel documentation, for ajax based applications, there is CSRF protection via HTML meta tag and cheking header request.
Why this method needed and why not check ajax request as usual request? I mean, if for ajax whe use POST method, then send CSRF token as usual parameter (for example as csrf_token) and then check in server side (PHP) :
if ( !isset($_POST['csrf_token']) OR $_POST['csrf_token'] !== $_SESSION['csrf_token'] ) {
// incorrect csrf token, stop processing
}
Cheking header request have some advantage than this method ?
If you are doing POST request, CSRF doesn't go through the header it goes through the http message body, what Laravel has is some kind of default middleware for csrf protection, where is the issue in that?
If you go into assets/js folder you can see the CSRF token in bootstrap.js.
You can fetch a CSRF token from a global Javascript variable and send it through ajax post request body.
Related
Just started learning Slim3. Have been spending some time figuring out how to perform redirects with overriding original request type with no success.
I want the /origin route to perform the redirect to /dest route.
/origin route receives GET request performs validation and after success redirects with POST request to /dest uri route. Here is the screenshot. I think I am doing something dumb here:
$app->get('/origin', function($req,$res,$args)
{
$req= $req->withHeader('X-Http-Method-Override','POST');
return $res->withRedirect('/dest');
});
$app->post('/dest', function($req,$res,$args)
{
echo "this is destination page";
});
As noted in the comment, this is not possible as the request made by the browser is not in your control.
When you call ->withRedirect() you are sending a status code of 302 and a Location header to the HTTP client (web browser usually).
The web browser sees the 302 status code and then issues a new request to the URL in the Location header. The server has no control over this request and every web browser makes a GET request.
Now, if you want to redirect a POST request to another URL and keep the same POST method, then you can use the 307 status code with a Location header and the browser should do the right thing. Note that this code does not let you change a GET into a POST - it just keeps the same method as the original request for the followup redirection request.
Usually if I want to return some data from a server, I would make a POST request with some token inside the request body:
$token = filter_input(INPUT_POST, 'token');
$request = filter_input(INPUT_POST, 'request');
But what about securing GET rest api requests? I don't want to place tokens inside the URL. How should I send a security token inside a GET request?
Place the token in the request header (for all request types,not just for GET).This is the recommended way.
The quick question is: is there ane way to change http authorisation header with html / php / javascript?
The goal
I'd like to make an auth service used for user login as well as providing with whole site protection. I want user to be restricted from viewing any file except login page unless authorised. For php I can of course check at the beginning for example session token availability, and redirect if missing, but I can't do it directly for for example jpg images. I thought of creating htaccess file that will verify if user is logged.
The solution
1.
Using Apache I've created .htaccess file, that verifies, if HTTP authorisation is set. If not it redirects any request to login page. With that solution one can not open any file (no matter if it is php script or for example jpg image) except of the login page:
RewriteCond %{HTTP:Authorization} ^$
RewriteCond %{REQUEST_URI} !^/login.php
RewriteRule .* /login.php [L,R]
2.
The login page should display form and when login and password are correct set the http request auth header with proper token.
Unfortunately I can't find a way to create manually http request auth header. The only way I found was to use basic auth:
$auth = new Auth();
if (!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SESSION)) {
$auth->logout();
}
if (!empty($_SERVER['PHP_AUTH_USER']) && empty($_SESSION)) {
$login = $_SERVER['PHP_AUTH_USER'];
$haslo = (!empty($_SERVER['PHP_AUTH_PW']) ? Auth::hashPassword($_SERVER['PHP_AUTH_PW']) : null);
$auth->login($login, $haslo);
}
$auth->getLoginForm();
Where getLoginForm() displays Basic Auth standard form
public function getLoginForm()
{
header(self::HEADER_ERROR_ASK_CLIENT_DATA);
header(self::HEADER_RESPONSE_401);
exit;
}
This solution works, but http request auth header holds the original login data all the time, which is what I want to avoid. I want to inject there "Bearer + token" string, which will help in securing whole system.
What I've tried
I can easily do that with external frontend. For example with windows desktop app I can send one request with basic auth header and the next with bearer header.
The same I can do with JQuery and AJAX - I can retrieve token using url with basic auth, and then use token with custom header for next requests.
I can also make different requests with PHP CURL.
But I can't find a way to force regular browser to login with Basic auth header and after success keep new, custom bearer header for next requests.
There is no standard mechanism to get a User Agent (browser) to provide an Authorization: Bearer header by itself.
What you can do:
make sure all your requests are done via XHR (Ajax), and send the header there. But this will not allow "regular" file loads (new pages, images, scripts, CSS...).
what most people do: send a cookie with your authentication token, and check for that cookie. The browser will automatically send the cookie.
As an aside, note that your .htaccess only checks that there is an Authorization header present, not its value, so it's quite useless. You want to channel all reads via a script that will actually verify the header or cookie before delivering the file.
I'm securising my RESTful php API by autorizing only HTTP requests with a valid access token in the header.
I added to all my AJAX requests the header with the token:
$.ajaxSetup headers:
auth_token: auth_token
In order to secure the image access, I wanted to use the same logic and add the token in the request header.
Apparently, I can do that only with an AJAX request and Base64 image data:
$.get url, (imageData) =>
$image.attr src: "data:image/jpeg;base64," + imageData
I'm not sure about the performance?
Because my images size are between 12 bytes and 4mb and also, I want full mobile support.
The other way I found is with queries string:
$image.attr src: 'image/12.jpg?auth_token=' + token
It's working great, except the fact that my image won't be cached when the token changes.
What options are left?
You could use a cookie. The first request sets the cookie (like a session cookie) that you sign so it can't be faked. Then for image requests, or any other requests for that matter, check the browser sends that cookie with the right code that you can link to the original request. This way you only need the token on the first request.
The scenario: There's this voting form (vote.php) with 3 fields where one is a hidden field containing a hash. Once you submit the form, it requests using GET to a separate script (process.php) via XHR. I am trying to simulate this via cURL but only gotten so far to getting the hash and preserving the phpsessionid using a cookie jar.
The problem: The processing script (process.php) seems to be able to detect if a request didn't push thru using XHR and will return an error if I just submit its required parameters using regular cURL GET.
So how do I simulate XHR in cURL? Or I may be even wrong in saying there's XHR in cURL so can you please advice any methods on how to achieve this.
There is a good chance that process.php checks for an XHR request by looking at the HTTP_X_REQUESTED_WITH header, for example:
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']=="XMLHttpRequest") { /* Do stuff here */ }
So you could try setting that header in your cUrl request:
curl -H "HTTP_X_REQUESTED_WITH:XMLHttpRequest"
That has a good chance of working. Good luck!
Add the following header: X-Requested-Width: XMLHttpRequest. This is added by all major JS libraries to ease identifying such requests on the server.