delight-im / PHP-Foundation

Writing modern PHP applications efficiently
MIT License
29 stars 7 forks source link

Best practice for Ajax request with the framework. #5

Closed daebak74 closed 5 years ago

daebak74 commented 5 years ago

For the Aiax Request I was thinking to create a customController in app and call a route in index.php

Example

$app->post('/admin/request', [ '\App\ReqAjaxController', 'exampleRequest' ]);

For security reason need to add an access token and compare it or there is some other way ?

Thanks.

ocram commented 5 years ago

Yes, that’s exactly how you would do it.

You can use any controller class, e.g. also a separate one just for this type of request, as you suggested, and implement a route as normal. You can use GET, POST, or anything else.

In the implementation of that route, you don’t have to return HTML (via Twig templates), and you can change the output MIME type from text/html to something else using

$app->setContentType('text');
// or
$app->setContentType('json');
// or
$app->setContentType('xml');
// or
// ...

For security reasons, yes, you would need some form of authentication if you only want certain users to access certain resources. Random tokens would work fine, and you can submit them as part of the POST data, or in the HTTP headers, etc. Just make sure to use TLS/HTTPS in production.

daebak74 commented 5 years ago

Thanks, there is an helper from template to get the token ? so send it and check from te class.

And I give this post for ask about route, first time that I work with it. For a form I have to declare 2 time ?

$app->get('/admin/login', [ '\App\Controllers\Login', 'getLogin' ]);
$app->post('/admin/login', [ '\App\Controllers\Login', 'postLogin' ]);

One for get the form and one for post and get the result. It's correct ?

ocram commented 5 years ago

You usually don’t need the token in the templates (views) but in the application code (app), right?

In your PHP code in app, you can just use $_POST[...] or $_SERVER[...] or $app->input()->post(...) to get the token.

As for your route definitions, they’re perfect.

You could write

$app->any([ 'GET', 'POST' ], '/admin/login', [ '\App\Controllers\Login', 'getPostLogin' ]);

but then you would have to check in your getPostLogin method whether it’s a GET or a POST request, so I don’t think that’s better.

daebak74 commented 5 years ago

You usually don’t need the token in the templates (views) but in the application code (app), right? Maybe is too late and the mind is out :) I need to send token request (hidden text or js var) and compare with the Session token before allo the action or I am in wrong ?

if(!isset($_SESSION['token']) || $_POST['form_token'] !== $_SESSION['token']) {

Form Token how I get ? :)

ocram commented 5 years ago

Are you trying to implement CSRF protection?

If you don’t really want to authenticate the user so that you know who they are and what resources they may access, you probably don’t need to implement anything. CSRF protection should be built-in via the SameSite cookie flag. That’s supported in Chrome and Firefox, at least.

And if you’re not building an API but want to know who your users are in AJAX requests as part of your normal web application, you may just want to use cookies as usual.

daebak74 commented 5 years ago

So I do not know if I understood the logic of the auth system! I don't wanna waste your time I study better the code. :)

If there is the certainty of the user identification then the token in the Ajax request is not necessary.

In any case, thanks and as usuall, you are always very kind and punctual.

ocram commented 5 years ago

Well, if both the frontend and the backend are on the same domain, which should be the case if you’re handling both with the same application, cookies should be sent with AJAX requests by default.

And that means that normal authentication should be possible with the authentication component. So if that’s what you want, just try to use

$app->auth()->isLoggedIn()
// or
$app->auth()->getUserId()

in your code handling the AJAX request and see if it works.