After watching laracast video relating to passport,i understood that passport is used to authenticate our own api.Still i have confusion regarding passport
1.How to validate authentication request for get ,post ,put and delete.Suppose if i pass token in my get url user can easily see and use that token.
2.Can i restrict the number of request to particular user to use my api ?
3.if any one decode the android app then they use that api token.In this case how we can protect ?
if any think wrong in my question please forgive.I am not much comfortable about passport and api routing in laravel 5.3
Thank you
Yes you pass your token to each request. Like explained here: https://laravel.com/docs/master/passport#passing-the-access-token
Yes, you would do that using Middleware. I suggest you inspire yourself with the Illuminate\Routing\Middleware\ThrottleRequests class.
You can refresh a specific token if you notice it's been stolen or something... But it's clearly not safe to store the client_id and client_secret in a mobile app.
Passport is built on top of League OAuth2 server, you should get familiar with it if you want to go in depth and read on security regarding Oauth2, it's a bit out of the scope for a question here. To keep it simple, use the built-in functionality in Laravel 5.3, SSL/TLS on the server to secure the communication between the app and the server and you'll most probably be fine unless you do some really strange stuff. OAuth2 is really robust and is used by many major players in the field so don't worry to much about the security.
It might be a bit strange to get a grip of having to pass a token to each request if you're used to traditional ways of authentication, there is a really good article about it which explains how it works on Scotch: The Ins and Outs of Token Based Authentication
You can protect routes using middleware. Passport includes an authentication guard that validates the access tokens upon the incoming requests, Example:
Route::get('/api/user', function () {
//
})->middleware('auth:api');
There is a rate limiting built in Larael that limits the rate at which any API requester can make requests. As you might have guessed, you should also use a middleware for this, for laravel it's the throttle middleware that you can use, example code (with /api as prefix):
Route::group(['prefix' => 'api', 'middleware' => 'throttle'], function () {
Route::get('user', function () {
return Person::all();
});
});
The default throttle is to 60 attempts per minute and disables access for a minute if the user hits the limit.
If you make a request to this route, you will now see the following lines in the response header:
HTTP/1.1 200 OK
... other headers here ...
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
You can of course customize the throttle middleware, if you want to limit it to 10 attempts per minute, this is how you would do it:
Route::group(['prefix' => 'api', 'middleware' => 'throttle:10'], function () {
Route::get('user', function () {
return User::all();
});
});
You can also add a second parameter which decides the number of minutes until they can try again, you would do 'throtttle:10,10' instead.
Related
Does Laravel Passport support having permissions on routes, methods, and a number of requests? e.g., the user can only send GET request, or the user can only send 50 requests for the special route, or the user only has access to special routes.
If not, do you know any package in laravel or other PHP frameworks that provide such facilities for API authentication and authorization?
For this you need to make use of the middleware throttle.
for example:
Route::middleware('auth:api', 'throttle:60,1')->group(function () {
...
}
So, I intend to completely separate my back-end from my front-end. I am learning about Laravel/Lumen API and I intend to return my database data in JSON format to be used by my front-end developers.
I have read several similar threads on Stack Overflow and watched some YouTube videos. Most of them suggested that I should generate a token for "authorized" users. However, the problem is that my project does not have a login system. All of my users are guest users. So, I can't first authorize a person and then generate a token for them.
From what I have understood (which could be flawed), Laravel API follows a RESTful system. So, it is stateless and I can't use CSRF token to check if a request comes from a submitted form and it is not automated. So, what other options do I have?
The reason that I want to separate automated requests from requests coming from forms is that sometimes I have to do heavy processing on some requests and I don't want an automated script to send mass requests and causes a DOS attack.
Any help is appreciated.
Rate limiting can help prevent automated scripts. Laravel has this implemented by default via the Throttle middleware. Default throttle is 60:1, throttle:60,1, translating to throttle if 60 attempts are registered within 1 minute.
This middleware is applied to all routes, however, you can override this for individual routes and define custom values for number of attempts and time. Following example adapted from documentation configures the route to throttle if there's 30 attempts within 1 minute:
Route::middleware('auth:api', 'throttle:30,1')->group(function () {
Route::get('/user', function () {
//
});
});
There are other configuration options, please do refer to the documentation for more information on that.
https://laravel.com/docs/7.x/routing#rate-limiting
How does Laravel check that a guest user has sent too many requests?
In very basic terms, Laravel keeps track of hits on a particular endpoint/domain by a particular IP in the application cache. The request domain and the IP are used as the cache key. Every time an endpoint is hit, no of attempts, stored in the cache, is incremented. If the no of attempts reaches the maximum number of allowed attempts within the time window specified in the throttle config applied on the route, that IP will be locked out for a while.
Attempts are automatically cleared if there's no new hit in the time window.
How do I authenticate an user to a channel with a custom auth method?
For example, in my app I use a token auth (stored in the db for each user) for my API, passed via header and read by a custom middleware.
How do I control the access with these custom auth methods for channels? How would be the client and server side? I am using socket.io and the Laravel docs are quite unclear of how auth methods works for sockets.
USE CASE:
I have users stored in DB with default Laravel migration. However, how my app is just the API, it is stateless, then, rather than using remember_token to store session tokens, I use it to store an unique authentication token, generated in the login endpoint.
Every endpoint of the API, the request pass through a middleware, where the user is retrieved by the token present in the headers
$token = Request::header('X-token');
$request->user = User::findByToken($token);
return $next($request);
Now the question comes in. Laravel docs isn't much clear on how private channels works.
How would a broadcast client pass the mentioned token and get authorized to join a given channel?
The Laravel documentation on broadcasting is pretty comprehensive about this, although it doesn't go into minute detail on client libraries that it doesn't support out of the box.
In this case, you're wanting the section on authorizing channels. From the docs:
In the BroadcastServiceProvider included with your Laravel application, you will see a call to the Broadcast::routes method. This method will register the /broadcasting/auth route to handle authorization requests
When defining broadcast routes, the currently authenticated user is passed automatically as a parameter. Since you're wanting to change the authentication mechanism ahead of the broadcast route definition so that the correct user is passed along, your broadcast client would pass along the token (however you like - HTTP header, URL parameter, POST data, etc.) and then you would customise the /broadcasting/auth route to parse that data and use it to authenticate the user. From there you would use the standard Broadcast::channel() definitions to ensure that the authenticated user is also an authorized user on that channel.
As per the documentation, Broadcast::routes() takes an optional array of $attributes for it to use the web middleware. From the source:
$attributes = $attributes ?: ['middleware' => ['web']];
So if you wish, you may change the middleware authentication to 'api' by passing it to the Broadcast::routes() call (or any other standard route parameters).
Since the route is already created for you, if you want to customise it at a lower level that route functions/middleware then you would need to change the auth() method on whichever BroadcastProvider you're using. More specifically, when the route is set up, it calls the authenticate() method on the BroadcastController, which in turn simply calls the auth() method on the Broadcast facade. The facade would then call whichever provider you're using - there are a few providers defined out of the box which should give you a good starting point if you want to write your own. That being said, as long as you don't have a problem with the provider itself, it's probably easier to just write your own middleware and pass that to Broadcast::routes() as an attribute if you need something particular with your authentication (if it differs from the api authentication middleware).
As an extra, since you've tagged this with socket.io, you may also want to read up on Laravel Echo. There's also a section on talking to socket.io specifically in the broadcasting introduction.
On top of Leith's answer, those scratching head and wondering why creating a custom middleware and using it in BroadcastServiceProvider.php would throw back an error.
public function boot()
{
Broadcast::routes(['middleware' => ['custom.middleware']]);
require base_path('routes/channels.php');
}
Inside Broadcaster.php there is a method called retrieveUser() which should return $request->user() as a result of successful authentication from within your custom middleware.
In my case, I was trying to pass access token to API's custom middleware; and once authenticating the user, I simply passed on my original request return $next($request)
For the above code to work, I had to fetch the user model by access token and then merge it to the original request like so
$request->merge(['user' => $user ]);
$request->setUserResolver(function () use ($user) {
return $user;
});
return $next($request);
So now retrieveUser() method from Broadcaster.php is able to retrieve the authenticated user with return $request->user() command, and it gets passed to Broadcast::channel method as a first parameter
Broadcast::channel('private-channel-name', function ($user) {
// if you get here, you've been authenticated (within a custom middleware)
return true;
});
How can i make post request from another server to my laravel server?
I have a website from another provider (lets say domainA.com) , they have CMS system, so I can make my custom pages - the question is, I want to make a form in domainA.com, and post it to domainB.com (my original Server), how can I make it in laravel? As far as I understand I should use api route file for this, is it secure to make such a POST request? because as far as I understand there is no token protection on api requests right?
sorry for my english - i am most interested in security side of such a action - if you show me an example, it would be appreciated.
Laravel 5.4 has 2 route groups: web and api
the web group is used for all requests that come from the current laravel application. Laravel uses a csrf token with every request to make sure every request is coming from the own page to prevent cross site scripting.
the api group is for requests that a fired from an external server. For this group the csrf protection is disabled.
Remember: csrf protection ONLY checks if the requests is from your site, it does not handle the authentication or authorization.
To secure your API you can use json web tokens (jwt). There is a package that will handle the authentication parts for APIs.
If you want to keep it really simple you can write a middleware for all api calls, that is checking if the requests has a special value (your personal token) to give access to the api.
It's possible to accept post request to a Laravel Route and you can define route any of web.php or api.php route file but below are the differences.
web.php
Routes in Web.php will prevent the form without CSRF Token.
to avoid that you can add the route in VerifyCsrfToken.php file in except Array.
api.php
Routes will work directly but the api URL will be Example.com/api/<route>.
But for security you can share an Access Token for the routes and in the controller you can verify the requests with the access token and allow post.
You are right is not sure about this communication.
What you can do is a chain token code
Start with a code and every time you contact the server b it will give you a new code that you will need to use for the next message.
I know it's not as beautiful as a solution but I do not think of anything else.
You could implement your api framework but you would spend a lot of time
I am a bit confused, I have a web application having a login, Register, Logout. Some dashboard views etc(CRUD), I want to make an api for this application too.
Like an api which third party will use, Can update records, Can delete records etc.
Actually there should be some way which can be use by mobile app for CRUD.
I know we have that routes/api.php, But i am pretty confused that when to use it. Please explain the scenario, I am blank.
Update:
Scenario
Application having views, authentication system etc, How an android app will be able to perform CRUD operations on the same application ?
1.web routing uses session state, CSRF protection. does it mean api routing not using session state, CSRF protection?
All it possible but not required. You still can using sessions etc, but this is a REST principles violation.
2.laravel 5.3 uses seperate web and api routing, is there any advantages ?
It's just for your convenience. In Laravel 5.2 you need specify middleware for routes like ['web'] or ['api'] but it doesn't required anymore. In 5.3 routes stored in separated files and specify routes middleware not required.
If you are specifying routes in api.php, you will need to use the auth:api middleware. For example:
Route::group(['middleware' => ['auth:api']], function () {
Route::get('/test', function (Request $request) {
return response()->json(['name' => 'test']);
});
});
Notes about Token auth and Laravel 5.3:
If you've setup laravel's default auth system, you will also need to add a column for api_token to the user table. If you are using DB seeders, you might want to add something like:
$table->char('api_token', 60)->nullable();
to your users table seeder. Alternatively just add the column manually and fill that column with a random 60-char key.
When making the request, you can add the api_token as a URL/Querystring parameter like so:
domain.com/api/test?api_token=[your 60 char key].
You can also send the key as a header (if using Postman or similar), i.e: Header: Authorization, Value: Bearer [your 60 char key].
I order to get a useful error if the token is incorrect, also send the following header with all requests:
Header: Accept, Value: application/json. This allows the expectsJson() check in the unauthenticated() function inside App/Exceptions/Handler.php to work correctly.