Remove csrf token only for single method - Laravel - laravel

I am using paytabs payment gateway api. In that api, a redirect url have to given, so that once the transaction is completed, the page will redirect automatically to your given redirect url. The url was a GET url but since the response of the api comes as a POST type, I was unable to use get url. To resolve that issue, I made that route a POST url but by making it post method, I am not getting any CSRF token. In the end, I get this issue.
TokenMismatchException in VerifyCsrfToken.php line 68:
Is there any way by which I could disbale CSRF token functionality for only single POST url?
--SUGGESTION TRIED--
I did this as per your suggestion
class VerifyCsrfToken extends Middleware
{
protected $except = [
'signup/complete',
];
}
and now getting
Class 'Middleware' not found

From the docs:
Typically, you should place these kinds of routes outside of the web middleware group that the RouteServiceProvider applies to all routes in the routes/web.php file. However, you may also exclude the routes by adding their URIs to the $except property of the VerifyCsrfToken middleware:
class VerifyCsrfToken extends Middleware
{
protected $except = [
'stripe/*',
'http://example.com/foo/bar',
'http://example.com/foo/*',
];
}

You can exception in csrf middleware. go to app/http/Middleware/VirefyCsrfToken.php
class VerifyCsrfToken extends BaseVerifier{
protected $except = [
'route url1',
'route url2',
]
}

for how use localhost
in your project folder /app/http/middleware/VerifyCsrfToken.php edit
protected $except = [
//
'http://localhost/blog/return_url', // your url
];

Related

In Laravel, it seems the middleware is not applied immediately

I use Laravel 9.
I have this route, included in a group and middleware:
Route::middleware(['auth', 'ensureUserIsAdmin'])->group(function () {
.....
Route::resource('sports', SportController::class);
.....
});
The middleware is only to check if the user is or not an administrator.
When the connected user is not admin, and tries to go to this route for a known sport:
/sports/FOOT/edit
then he receives the response "FORBIDDEN". Perfect, the middleware made his job.
But when the same not admin user tries to go to a route for an unknown sport:
/sports/UNKNOWSPORT/edit
then he receives the response "NOT FOUND". Is it normal? It looks like the framework makes a database request and only after he applies the middleware.
What's wrong in my code?
Every route within web.php file is processed by web group middleware - you may find this in RouteServiceProvider class
Route::middleware('web')
->group(base_path('routes/web.php'));
This group defined within Kernel class and contains some app middleware. They're handled before any route specific middleware fires
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
So when you think your route has 'auth', 'ensureUserIsAdmin' as middleware only it is not quite true
In your case \Illuminate\Routing\Middleware\SubstituteBindings::class middleware is the one is failing and showing 404. And yes, it makes query to database if there are some route parameters in it
For simplicity, let say you have this route and only model with id=1 exists
Route::get('/sports/{sport}', function (Sport $sport) {
dump($sport);
});
/sports/1 is dumping model, sports/2 shows 404 as expected. Let's comment \Illuminate\Routing\Middleware\SubstituteBindings::class
Now both pages are actually dumping model, but sports/2 shows empty default model with no parameters
If you need to change this logic and show 403 for non-existing models, you may add middleware to a group BEFORE \Illuminate\Routing\Middleware\SubstituteBindings::class middleware
For example, lets' create simple middleware which always return 403 like
public function handle(Request $request, Closure $next)
{
abort(403);
}
And change web group to
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
AlwaysFalse::class, // HERE I AM
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
Now no matter what both pages will show 403
But this will be applied for EVERY route within routes/web.php file, so you may change the logic like
public function handle(Request $request, Closure $next)
{
// Applied only in any route named `sports.something` - resource routes including
// is_admin() function doesn't really exists, middleware logic is up to you
abort_if((Route::is('sports.*') && !is_admin()), 403);
return $next($request);
}
Now for admin user /sports/1 shows model, /sports/2 - 404 response.
For non-admin user both pages will return 403.
About is it normal or not - I think yes. Ask yourself - what can you do (what your access level) over a thing which is doesn't even exists? So it better define first does model really exists and after you're sure it is, make something with it. But it is just my opinion, someone may disagree
Hope it'll help

Send CSRF token with laravel header() method

Is it possible to protect post method with CSRF token with laravel header() method ?
just like
$obj->header('Content-Type', 'text/xml');
Every routes register within your app in the web.php file by default is already protect by the VerifyCsrfToken. In the App\Providers\RouteServiceProvider the method mapWebRoutes attach on every routes in the web.php file the web middleware which is a wrapper of many middleware like you can see in the App\Http\Kernel class
protected $middlewareGroups = [
'web' => [
// others middlewares goes here
\App\Http\Middleware\VerifyCsrfToken::class,
// others middlewares goes here
],

Laravel unknown status with Slack integration

I'm trying to implement Slack Actions in slack with Laravel as endpoint.
In Slack, I made the setup of the request URL as well as registering an action.
The button appear in Slack.
With laravel I made a simple route for testing the slack-payload like this
Route::post('slack-payload', function( $payload ){
dd( $payload );
})->name('slack-payload');
But when I press on my custom-action, on the laravel side I received a 419 unknown status.
I'm guessing it's because of the token missing from Slack that Laravel want. So I added my route in the $except of the VerifyCsrfToken middleware.
class VerifyCsrfToken extends BaseVerifier
{
protected $except = [
'slack-payload'
];
}
But now I'm having a 500 Internal Server Error ...

MethodNotAllowedHttpException path without CSRF

I pass a route in laravel which is called by a function in JS and I have no control of it because it is external, this route is a post method since I need it to be that way but it generates me a MethodNotAllowedHttpException as I do to exclude certain routes of this validation.
Note: I have already tried adding it in VerifyCsrfToken in its exception vector, modifying that class file VerifyCsrfToken extends Middleware to a new file called class VerifyCsrfToken extends BaseVerifier with all its dependencies and I have also disabled the validations in the Middleware but none of them works for me
From the docs:
You should place these kinds of routes outside of the web middleware group that the RouteServiceProvider applies to all routes in the routes/web.php file. However, you may also exclude the routes by adding their URIs to the $except property of the VerifyCsrfToken middleware:
protected $except = [
'your/route/*',
];
For this you have to add the URI of the route inside protected $except.
For example if you URL is www.example.com/full/route/
you have to add
protected $except = [
'/full/route/*',
];
Seems like you're adding route name but not the URI.

how to submit in postman without csrf token in laravel

I am working on a laravel project and want to use the front-end tool postman to post data to a particular controller function. But I get the error
TokenMismatchException in VerifyCsrfToken.php
How do I bypass this error or how do a submit the values with a csrf token?
You can bypass this error by adding '*' on $except variable in your App\Http\Middleware\VerifyCsrfToken class as:
protected $except = [
'*',
];
OR
You can remove \App\Http\Middleware\VerifyCsrfToken::class, from array $middlewareGroups in App\Http\Kernel class.

Resources