Laravel enable VerifyCsrfToken for specific routes - laravel

Running Laravel 5.3 I have certain API routes that my application calls for guests on the site.
I do not want these to be completely public and directly accessible so I'm think that I need to add "VerifyCsrfToken" middleware to these routes only.
I believe that would at least confirm that the request is coming from my application.
Any guidance on this? Thanks
UPDATE:
After adding the csrf middleware to the route as suggested by #motie and then also adding the "StartSession" middleware the route seemed to work - but it did not actually work according to what I had hoped - Was hoping for it to compare tokens and the fail if mismatch - but that was not the case.
The VerifyCsrfToken has the following in its checks:
if (
$this->isReading($request) ||
$this->runningUnitTests() ||
$this->shouldPassThrough($request) ||
$this->tokensMatch($request)
)
It requires any one of those conditions to pass - which is a bit strange as the "isReading" simply checks if the request uses "GET" method present so it always passes...
Also calling the StartSession middleware seems to refresh the csrf token for the API route which means the web token and api call token are not the same. I'm think it might just be easier to add this route to the "Web" routes or add the "web" middleware to it...

To enable csrf for some api routes, define an alias for it in ```app/Http/Kernel.php::
tected $routeMiddleware = [
...
'csrf' => \App\Http\Middleware\VerifyCsrfToken::class,
'session' => \Illuminate\Session\Middleware\StartSession::class,
...
]
then you will be able to add it to the routes you want in api.php.
Route::get('secured-api-route', ['middleware' => 'csrf']);
Edit:
Using the csrf middleware requires activating the session middleware. Hence, it will be better to create a new middleware group than registering separate middlewares.
'api.csrf' => [
\Illuminate\Session\Middleware\StartSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
]

Related

Calling the right guard in middleware for Multi-auth system

I am adding a custom authentication system via guards , models and providers.
After trying to read some documentation and articles, I am bit confused about the different way of invoking guards and middleware
Question 1:
So, if I want to invoke (default) authentication in a particular route (as defined in auth.php as "default => [ 'guard' => 'web' ... , is it
'middleware' => ['auth']]
Does this mean the default auth ? Or the middleware "auth" - which is included in the Kernel.php as below
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
if i want the default auth as defined in "web" of config/auth.php
should it be
'middleware' => ['auth']] or
'middleware' => ['web']] or
'middleware' => ['auth:web']]
Question 2:
Now there is a middleware group called "web" which has useful things like StartSession, EncryptCookies, CSRF Protection, - so if I have a custom guard "abcguard" - is session management, cookie encryption done through some mechanism or I should explicitly add that middleware "web" in my routes /route-group?
Question 3:
what if I have a custom guard called "abcguard" defined in auth.php as such
and I have a middleware group called abcguard (just for illustration purpose) -- how do I make sure that that a route dashboard is available after the abcguard authentication and passing though middleware abcguard
Is this the right way?
'middleware' => ['auth:abcguard', abcguard]]
How does Laravel know which one is authentication and which one is just a middleware? Or is "guard" just a name for another middleware - the only specific behaviour is that a guard determines how users are authenticated and a middleware might just check if an user is authenticated?
Q4 - In the statement below, how does laravel find out which abcguard is a guard and which is a middlewar group?
'middleware' => ['auth:abcguard', abcguard]]
First, you seem to confuse web middleware group (defined in Kernel) with web guard (authentication mechanism using session) for auth middleware, and they are even not related TBH. Guard is used to authenticate users, and middleware group just holds different middlewares for your web routes. If in your auth.php config, you have default guard web, the 'middleware' => 'auth' will end up using web guard. In case you want to use other guard, you will need to use 'middleware' => 'auth:other_guard'
Again, web middleware group only holds middlewares for ALL of your web routes. You should not add auth to all of them, for sure.
The right way will be 'middleware' => ['auth:abcguard', 'abcguard'], yea. In this case, you have auth middleware using abcguard guard and abcguard middleware group.
When you write auth:abcguard you are calling auth middleware and passing abcguard as argument to it's handle function. Same if it was web - default session guard, or api - default auth token, or sanctum - sanctum's session cookie. Middleware groups are defined in your App\Http\Kernel::class. In case you have abcguard middleware group there, you will be using all middlewares defined in that group.

How to access Sanctum package in custom laravel package

i want to access laravel sanctum auth which is working fine in project routes
I'm making a custom package of api's which needs to use same sanctum authentication with in the custom package routes
use auth sanctum middleware for your routes, See below example.
https://laravel.com/docs/9.x/sanctum#protecting-routes
I was having the same problem, but I found that the packet routes did not have a default guard and the session was not accessible through the packet.
The solution was to add the 'web' middleware to the routes.
Before:
Route::get('/dashboard', [HomeController::class, 'index'])->middleware(['auth:sanctum'])->name('dashboard');
After:
Route::get('/dashboard', [HomeController::class, 'index'])->middleware(['web', 'auth:sanctum'])->name('dashboard');
For those who don't understand why this happens, the question is simple, the 'web' guard is automatically added to the routes that are in the web.php file, but for some reason this doesn't happen with the routes of packages.
Why is the 'web' guard necessary?
Actually, the 'web' guard is not needed, the point is that it bundles various middlewares including: \Illuminate\Session\Middleware\StartSession, which is what handles the user session, so if you don't want to include the 'web' guard in the routes, you you can create a custom middleware group with everything needed for your routes to work in the app\Http\Kernel.php file and the problem will be solved.

Laravel - Protect API routes

I have Laravel application with VUEJS as front-end,
I am getting data by creating API Routes.
So for example the route for getting posts data will be http://localhost/api/posts
What is the best way to protect my routes?
I saw on laravel documentation that there is:
API athentication https://laravel.com/docs/5.8/api-authentication
also Passport https://laravel.com/docs/5.8/passport
For example now any user can reach to the route http://localhost/api/posts
and he will get json with all posts data.
I want protect that and allow only inner api request from my VUEJS commponent to get the data
I’m assuming you’re going to use the Laravel auth routes to do the authentication, and after the authentication, the next view you’re reaching is the one with all the Vue components.
The solution is simple, even that is on the documentation, the necessary steps should be clarified.
We need to:
Add passport composer require laravel/passport
Make the migrations php artisan migrate
Install passport php artisan passport:install
The fourth step is more complex. We need to open our User.php model file. And first we need to import the HasApiTokens and tell the model to use it.
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, Notifiable;
.......
}
Then on our config/auth.php we need to modify the api array and change the driver to passport
'api' => [
//for API authentication with Passport
'driver' => 'passport',
'provider' => 'users',
],
Then on our app/Http/Kernel.php we need to add a middleware to the $middlewareGroups array in the key web.
protected $middlewareGroups = [
'web' => [
................
//for API authentication with Passport
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
Now we can use the auth:api middleware on our api routes.
Route::middleware('auth:api')->group( function(){
...your routes here
});
This is what the CSRF TOKEN doing, it's not quite the same with the API Authorization doing
CSRF Token:
To protect (inner) API or access points from cross-site accessing, See Cross-site_request_forgery
CSRF Token is expired and generated within a randomly time, which will make the program access difficulty
API Authorization:
The API is design to be used from other programs, and you'd like to protect them from non-authorized access
Since API tokens expiration and generation is handle by admin manually, since you'll need to place this API token in your HTML to get your function working, it's not what you searching for here
More details of CSRF protection in Laravel see: Laravel CSRF production document
Generally, we'll protect all the routes POST and PUT routes by default

Lumen: add middleware to package defined routes

I have a problem with adding middleware to existing routes of a vendor package. I building an API on top of Lumen (micro-services framework created by Laravel). I am using Passport for oauth authentication and imported this package: https://github.com/dusterio/lumen-passport to use Passport in Lumen. I have implemented a custom route for requesting a token and want to block requests to the existing passport route: /oauth/token. But I also need the route myself in order to redirect token requests from my custom route.
I have tried to override the existing route like this:
$app->post('/oauth/token', [
'middleware' => 'reject',
'uses' => '\Dusterio\LumenPassport\Http\Controllers\AccessTokenController#issueToken'
]);
But this throws a 500 back at me without Exception tracing.
I am using a custom route for requesting a token in order to set the set the token scope based on the role of a user. I am using the scope to check the role of a user (or app with other grant types), the normal token route of Passport should be blocked to everyone except Lumen self. With this only Lumen should be able to set the scope.
TLDR: How can I add middleware to package defined routes in Lumen.
The latest merge of https://github.com/dusterio/lumen-passport supports prefixing the passport routes.
I added "dusterio/lumen-passport": "dev-master", to my composer.json and Dusterio\LumenPassport\LumenPassport::routes($app, [ 'prefix' => 'api/v1/protected', 'middleware' => 'reject', ]); at the end of my bootstrap/app.php.
See this issue for additional information: https://github.com/dusterio/lumen-passport/issues/31

How to use Postman for Laravel $_POST request

How can I try sending a post request to a Laravel app with Postman?
Normally Laravel has a csrf_token that we have to pass with a POST/PUT request. How can I get and send this value in Postman? Is it even possible without turning off the CSRF protection?
Edit:
Ah wait, I misread the question. You want to do it without turning off the CSRF protection? Like Bharat Geleda said: You can make a route that returns only the token and manually copy it in a _token field in postman.
But I would recommend excluding your api calls from the CSRF protection like below, and addin some sort of API authentication later.
Which version of laravel are you running?
Laravel 5.2 and up:
Since 5.2 the CSRF token is only required on routes with web middleware. So put your api routes outside the group with web middleware.
See the "The Default Routes File" heading in the documentation for more info.
Laravel 5.1 and 5.2:
You can exclude routes which should not have CSRF protection in the VerifyCsrfToken middleware like this:
class VerifyCsrfToken extends BaseVerifier
{
/**
* The URIs that should be excluded from CSRF verification.
*
* #var array
*/
protected $except = [
'api/*',
];
}
See the "Excluding URIs From CSRF Protection" heading documentation for more info.
If you store your sessions in Cookies, you can grab the Cookie from an auth request in Developer Tools.
Copy and paste that Cookie in the Header of your POSTMAN or Paw requests.
This approach allows you to limit your API testing to your current session.
1.You can create a new route to show the csrf token using your controller with help of the function below.
(Use a Get request on the route)
public function showToken {
echo csrf_token();
}
2.Select the Body tab on postman and then choose x-www-form-urlencoded.
3.Copy the token and paste in postman as the value of the key named _token.
4.Execute your post request on your URL/Endpoint
In the headers, add the cookies, before making request, the XSRF-TOKEN cookie and the app cookie. I.e yourappname_session
In laravel, 5.3. Go to app/Http/Kernel.php find middlewareGroups then comment VerifyCsrfToken. Because it executes all middleware before service your request.
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,
],
'api' => [
'throttle:60,1',
'bindings',
],
];

Resources