A way to make Laravel API private or restricted - laravel

I am now working on a development using Laravel and Vue.js. Vue files are included in Laravel, not separated. The problem is that I set up to send data to frontend(vue) by answering API calls.
I've recently deployed my app to VPS, and now anybody can send GET/POST request to the API using curl command...
Would you please let me know how I can make the API private/restricted? I would like it to be accessed only by Vue. FYI, I used JWT-auth for the login system.

You need to pass the token in every request and in the api.php file you can protect routes by api middleware. i recommend you this serie of tutorials: https://blog.peterplucinski.com/setting-up-jwt-authentication-with-laravel-and-vue-part-1/
How to protect routes
Route::group([
'middleware' => 'api',
'prefix' => 'posts'
],
function ($router) {
Route::post('/', 'PostController#index');
});
Another option:
Route::middleware('auth:api')->get('/posts','PostController#index');
How to pass token in request the request
axios.get('/api/posts', {
headers: {
Authorization: 'Bearer ' + localStorage.getItem('token')
}
})
.then(response => {
this.data = response.data
}).catch(error => {
})

Related

Passport auth:api middleware not working anymore after Laravel 5.8 upgrade

I recently upgraded my Laravel app from 5.6 to 5.8 and my Passport api does not work anymore.
The 'oauth/token' call works perfectly and I get my access_token as before. Then after, when using the usual call:
$response = $http_client->request('GET', 'api/test', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ' . $access_token,
],
]);
to a very basic protected route:
Route::middleware('auth:api')->get('test', function () {
return ['test' => 'test'];
});
I never get the expected response. Whatever I put inside the route function, I always get an empty 200 response.
This same route without the auth:api middleware works fine by the way:
Route::get('test', function () {
return ['test' => 'test'];
});
It seems that the api:auth middleware does not work anymore and I really don't know why.
My API used to work perfectly before the upgrade. I really don't know what happened.
You have mentioned in header that response should be in json format and you are returning a response with non-json format.
You should use
return response()->json(['test' => 'test']);
rather then
return ['test' => 'test'];

Laravel passport public api routes

I am trying to code a login function for my api that takes a username and password then give you a password grant token to make api requests. The login route when called gives you
{
"message": "Unauthenticated."
}
I am using passport on laravel to do secure the api. Why am I getting a 401 when the route does not have the auth:api middleware? I tried using a clousure to see if I get could get a response and the closure did not give me an error.
Route::group(['prefix' => '/v1', 'middleware' => ['auth:api'], 'namespace' => 'Api\V1', 'as' => 'api.'], function () {
Route::post('/post/like','PostLikeController#store');
});
Route::group(['prefix' => '/v1', 'namespace' => 'Api\V1', 'as' => 'api.'], function () {
Route::post('login', 'Auth\LoginController#login');
});
Does your login controller have a constructor? sometimes middleware is set in there?
Otherwise I've also had issues with having the middleware routes above the public ones.
Try putting the public routes in the file first and also checking the LoginController.php for a constructor which might be setting a middleware
It possibly due to the same prefixes, as it does not overriding but instead stacking on top of each other.
I suggest for your login route, possibly, you can use this
Route::post('login', 'Auth\LoginController#login')->withoutMiddleware([FooMiddleware::class]);
If it's still does not help try putting your login route above the middlewared route.

Token-based Authentication Laravel 5.5

Out of the gate, the auth config for Laravel specifies a token-based authentication approach for users:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
],
I have a few ajax endpoints I want to secure so no one outside of my application can interact with them. I've looked at Passport but it seems I may not actually need it given this auth configuration. How can I utilize this token to secure my ajax endpoints and if possible, identify the user the request belongs to?
Currently my api.php route file looks like:
//Route::middleware('auth:api')->group(function () {
Route::post('subscribe', 'SubscriptionController#create');
Route::post('unsubscribe', 'SubscriptionController#delete');
//});
I thought Laravel might've handled auth or something out of the gate for VueJS implementation but it doesn't look like it. My ajax request looks like:
this.$http.post('/api/subscribe', {
subscribed_by: currentUser,
game_id: this.gameId,
guild_discord_id: this.guildDiscordId,
channel_id: newChannelId,
interests: this.interests.split(',')
}).then(response => {
// success
}, response => {
console.error('Failed to subscribe');
});
As Maraboc already said, you should start by creating a column api_token: $table->string('api_token', 60)->unique(); in your users table.
Make sure each newly created user gets a token assigned, and encrypt it: $user->api_token = encrypt(str_random(60));
Next, you could define a Javascript variable in the footer of your app:
window.Laravel = <?php echo json_encode([
'apiToken' => !empty(Auth::user()) ? decrypt(Auth::user()->api_token) : ''
]); ?>;
Later, when you want to make a request to an endpoint, you should add a header, authorizing the user:
let url = '/path/to/your-endpoint.json';
let data = {
headers: {
'Authorization': 'Bearer ' + Laravel.apiToken
}
};
axios.get(url, data)
.then(response => console.dir(response));
Finally, in your controller, you can get your User instance by using Laravel's guard:
$user = !empty(Auth::guard('api')->user()) ? Auth::guard('api')->user() : null;
Hope this helps! BTW: these articles helped me on my way:
https://gistlog.co/JacobBennett/090369fbab0b31130b51
https://pineco.de/laravel-api-auth-with-tokens/
The solution I took was to not put ajax endpoints in the api namespace. By putting them as web routes instead of api it'll use CSRF (cross-site request forgery) protection to validate the route. So only if it comes from my domain will it be authenticated. This is ONLY useful when the site is served in https.

API login from android app using laravel 5.3 passport

For two days I am digging google but could not find the starting thread for my problem, now I am out of option. Please help me with some direction/howTo
I have a web application running built with laravel 5.3, I have installed passport as described here . if I go /home its showing perfectly.
Now I have to make an android app from which
An already existing user of web app can login
get all the task list of that user TaskModel (ons_tasks(id, title, description))
routes related only
in web.php
Auth::routes();
in api.php
Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:api');
Route::group(['middleware' => ['auth:api']], function () {
Route::get('/test', function (Request $request) {
return response()->json(['name' => 'test']);
});
Route::get('/task/list', function (Request $request) {
$list = \App\Model\TaskModel::all();
return response()->json($list);
});
});
To login : if I send post request /login with email & password get the TokenMismatchException error but Where do I obtain a token for
android app in mobile? Do I need the Auth::routes() in the api too?
if then what else Do I need to just login and get a token so later I
can send it for getting the task lists.
Secondly,
If I go to /api/test it redirects me to /home page without
showing any error !!!
Thanks in advance.
To authenticate with your Passport-enabled API
You'll need to use the Password Grant Client in this situation, see this section of Passport's documentation.
Once you've generated a Password Grant Client, using:
php artisan passport:client --password
You will need to request an access token from your application, and send it with your subsequent requests, in order to access the protected auth:api middleware routes.
To get an access token, send a request to your app's /oauth/token route (this is a PHP implementation obviously, ensure you are correctly formatting below request in your Java implementation):
$http = new GuzzleHttp\Client;
$response = $http->post('http://your-app.com/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => '<client id returned from the artisan command above>',
' client_secret' => '<secret returned from artisan command above>',
'username' => 'taylor#laravel.com',
'password' => 'my-password',
'scope' => '',
],
]);
return json_decode((string) $response->getBody(), true);
Ensure you add the client_secret and client_id that was returned from the artisan call above, and ensure username and password references a valid user in your database.
If everything is fine here, you should receive an access_token and refresh_token in the response. The access_token is what you need to authenticate using the auth:api guard. To correctly pass this back to your api, you will need to send your subsequent requests with the headers Authorization: Bearer <your accessToken> and Accept: application/json
For example, to access your "test" route:
$response = $client->request('GET', '/api/test', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '. <accessToken from /oauth/token call>,
],
]);
If you've set these correctly, you should see a JSON response with the array you have specified.
Why is /api/test redirecting me with no error?
You are requesting a route with the auth:api middleware. This will redirect you as you have not specified the correct headers as described above, this is expected behavior.
Hope this helps.

TokenGuard class always need api_token

I am using AngularJs and Laravel 5.4
In the default guard, I changed the web guard to api. Finally it looks like below.
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
when i send the request using username and password from Angular Js....I always get invalid credentials because..
TokenGuard class has a method called validate which expects api_token value but I am on the login page.
I am assuming that in order to get the token, I need $this->guard(web) in login method?
Is it correct approach or Am I missing something?
By default all routes defined in routes/api.php have the api middleware as defined in app/Providers/RouteServiceProvider::mapApiRoutes(). Therefore, you always need to pass api_token.
What you can do is, in your api routes, define the login route like this
Route::post('login', 'api\AuthController#login'); //out of the group
And post from AngularJS
$http.post({
url: 'http://localhost/api/login',
data: $scope.userda,
headers: {
Authorization: ''
}
}).then(...)
Then define all your other routes in a group with auth:api
Route::group(['middleware' => 'auth:api'], function(){
//Other routes here
});
In angular, set the Authorization headers with the value of api_token. So before login, it will be empty and after login it will have the value of the user api_token.

Resources