How can I restrict API info to user? Laravel 5.7 - php

I already have authentication with api_token working correctly, but I want my consumer to make an API request and return the info respecting only to his user_id.
I know I can do this by passing info in the URL, as I have it right now in Route::get('/getOrder/{user_id}','OrderController#indexByUser'); but I'm afraid that any user could just enter another user_id and get the orders from another User.
api.php
<?php
use Illuminate\Http\Request;
Route::post('login', 'Auth\LoginController#login');
Route::post('logout', 'Auth\LoginController#logout');
Route::group(['middleware' => 'auth:api'], function() {
Route::get('/user', function (Request $request) {
return $request->user();
});
Route::get('/getOrder/{user_id}','OrderController#indexByUser');
});
Login and Logout gives/clears api_token respectively.
Thanks in advance.

You can create own midlleware, were set this logic.
public function handle($request, Closure $next, ...$guards)
{
if (Auth::user()->getId() !== $request->getPathInfo()) { // if userId contains in path
return redirect(back(413));
}
return parent::handle($request, $next, $guards);
}
(this is only example code )
Or you can use policies
https://laravel.com/docs/8.x/authorization#writing-policies

Related

Laravel - How to cancel redirecting to login when unauthorized

In my project, I using laravel as api
UserController > profile() need token to run
For example when I call it without token, laravel display error which "Route [login] not defined" and it's right because we don't have any template in laravel.
How can I return json response instead redirect to login page as html?
public function profile(): JsonResponse
{
//using protected method
return response()->json($this->guard()->user());
}
So basically what you can do is you can create a customized Auth middleware which returns a JSON response.
Or you can use a simple condition in your function:
if (Auth::check()){
//if logged in user exists
} else {
//if logged in user does not exist
}
You can make middleware manually and in the middleware you can check user if exists. For example, if you use JWT token, then you can write like that as app/Http/Middleware/Authenticate.php :
public function handle($request, Closure $next, $guard = null)
{
/* Check is token filled */
if (!Auth::check()) {
return response()->json([
'success' => false,
'status' => 401,
'message' => 'Bad authorization',
'data' => []
], 401);
}
return $next($request);
}
For route partion:
Route::group([
'middleware' => 'auth'
], function () {
Route::get('/profile', 'User#profile');
});
Open Authenticate file app/Http/Middleware/Authenticate.php
add reference
use Closure;
use Illuminate\Support\Facades\Auth;
put this code:
public function handle($request, Closure $next, ...$guards)
{
if (!Auth::guard('api')->check()) {
return response()->json(['message' => 'Error Message!']);
}
return $next($request);
}
The code that you want to edit is located in app/Http/Middleware/Authenticate.php in the function redirectTo

Laravel 6 - Auth::guard('user')->user return null

I create a multiple Authentication in Laravel. When I login with user, on debug in post login method, after Auth::guard('user')->attempLogin..... I see a user but after redirect to HomeController this return null.
How to resolve? I'm beginner in Laravel.
Thank's!!!
/routes/auth/user.php
Route::prefix('backoffice')->name('user.')->namespace('User')->middleware('user')->group(function () {
Auth::routes();
Route::get('home', 'HomeController#index')->name('home');
});
/routes/web.php
Route::group(['middleware' => 'web'], function() {
require 'auth/user.php';
Route::get('/', function () {
return view('welcome');
});
Route::get('/home', 'HomeController#index')->name('home');
Route::resource('cadastro', 'CadastroController');
});
/app/Controllers/User/Auth/LoginController - #post Login
public function login(Request $request) {
$credentials = [
'username' => $_POST['username'],
'password' => $_POST['password']
];
Auth::guard('user')->attempt($credentials, false);
//dd('auth', Auth::guard('user'));
return redirect()->intended('/backoffice/home');
}
/app/Controllers/User/HomeController
public function __construct()
{
$this->middleware('user');
dd('after middleware', Auth::guard('user'), Auth::guard('user')->user());
}
public function index()
{
return view('user.home');
}
By default, Laravel doesn't ship with auth guard user. Perhaps you meant to use web guard i.e Auth::guard('web'). Auth::guard()->user() should return the logged in user object if a user is logged in.
Also, the default middleware for checking logged in user is auth, not user. So, your route might look like this: Route::prefix('backoffice')->name('user.')->namespace('User')->middleware('auth')->group(function () {});, except you've defined a custom middleware in app/Http/Kernel.php $routeMiddleware array with alias user

Protecting Routes with Role Permissions using middleware Laravel

I have a multilevel members website and need to protect my routes in the web.php file in Laravel 5.5.
I have a column on my users table called role_id.
In role_id is the following values
NULL (For New Users)
1 (For Owner)
2 (For Admin)
3 (For Moderators)
4 (For Banned Users)
I was trying to do it with a simple IF statement
if (Auth::user()->role_id != '2'):
return view('home');
else:
//ADMIN ROUTES
Route::get('/admin','AdminController#index')->name('admin');
endif;
if (Auth::user()->role_id != '1'):
return view('home');
else:
//OWNER ROUTES
Route::get('/admin','OwnerController#index')->name('owner');
endif;
ETC....
But get Error Trying to get property of non-object. Also probably not the best way to do that.
So I read about doing it with MIDDLEWARE like this: (Looks much better)
Route::group(['middleware' => ['auth', 'admin']], function() {
// put all your admin routes here
});
Route::group(['middleware' => ['auth', 'owner']], function() {
// put all your owner user routes here
});
But it didn't explain how to add the Middleware.
Would I have to create 5 different Middleware files for each group similar to file I found:
use Illuminate\Contracts\Auth\Guard;
class Admin
{
protected $auth;
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
public function handle($request, Closure $next)
{
if($this->auth->user()->role_id != '2') {
return redirect()->view('home');
}
return $next($request);
}
}
Could someone lend a helping hand and explain how to write the correct middleware to achieve this?
web.php
Route::group(['middleware' => ['auth', 'admin']], function() {
Route::get('/admin/dashboard', function(){
return view('admin.dashboard');
});
});
into protected $routeMiddleware of Kernel.php
'admin' => \App\Http\Middleware\AdminMiddleware::class,
AdminMiddleware.php
$user = Auth::user();
if($user->role == 'admin'){
return $next($request);
} else
// abort(403, 'Wrong Accept Header');
return new Response(view('notauthorized')->with('role', 'admin'));
}
admin, moderators, owner, banned_user will be value of user_type/role column of user table.
or you can use user_type_id or role_id instead of user_type_name or role_type
Don't forget to add
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Response;
just under the
use Closure;
of your Middleware
You can also do it with other ways like Gate, let me know if you need it. :)
Like this example:
Route::get('/cart/payment', 'CartController#getcartpayment')->middleware('checkAuth');
$user = Sentinel::findById($user_id);
$role= $user->role();
Error Trying to get property of non-object. Can be found if user not logged in yet.
Before u check
if (Auth::user()->role_id != '2'):
u should make sure that user is logged in with
Auth::check()
first...

Laravel change main page after login

I would like show other main page after login to the user.
Route::get('/', 'PagesController#getIndex');
Route::group(['middleware' => 'auth'], function () {
Route::get('/', 'BlogController#getUserBlog');
});
When user is log in I would like to show BlogController#getUserBlog it's working but, when user is not authenticated laravel shows /login page not PagesController#getIndex. How to correct this for:
Auth user: BlogController#getUserBlog
Guest: PagesController#getIndex
Make changes in this Middleware RedirectIfAuthenticated
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
//Logged In
return redirect()->route('getUserBlog');
}
// Not Logged In
return redirect()->route('getIndex');
}
and make the necessary change in your routes file
Route::get('/', 'PagesController#getIndex')->name('getIndex');
Route::get('/', 'BlogController#getUserBlog')->name('getUserBlog');
Or you can do it without middleware :
Route::group(['prefix' => '/'], function()
{
if ( Auth::check() )
{
Route::get('/', 'BlogController#getUserBlog');
} else{
Route::get('/', 'PagesController#getIndex');
}
});

How to use 'OR' middleware for route laravel 5

I've two types for user and I've created multiple middlewares.
Some routes need to allow for both type of user.
I've trying following code:
Route::group(['namespace' => 'Common', 'middleware' => ['Auth1', 'Auth2']], function() {
Route::get('viewdetail', array('as' => 'viewdetail', 'uses' => 'DashboardController#viewdetail'));
});
But its not working :(
Middleware is supposed to either return a response or pass the request down the pipeline. Middlewares are independent of each other and shouldn't be aware of other middlewares run.
You'll need to implement a separate middleware that allows 2 roles or single middleware that takes allowed roles as parameters.
Option 1: just create a middleware is a combined version of Auth1 and Auth2 that checks for 2 user types. This is the simplest option, although not really flexible.
Option 2: since version 5.1 middlewares can take parameters - see more details here: https://laravel.com/docs/5.1/middleware#middleware-parameters. You could implement a single middleware that would take list of user roles to check against and just define the allowed roles in your routes file. The following code should do the trick:
// define allowed roles in your routes.php
Route::group(['namespace' => 'Common', 'middleware' => 'checkUserRoles:role1,role2', function() {
//routes that should be allowed for users with role1 OR role2 go here
});
// PHP < 5.6
// create a parametrized middleware that takes allowed roles as parameters
public function handle($request, Closure $next) {
// will contain ['role1', 'role2']
$allowedRoles = array_slice(func_get_args(), 2);
// do whatever role check logic you need
}
// PHP >= 5.6
// create a parametrized middleware that takes allowed roles as parameters
public function handle($request, Closure $next, ...$roles) {
// $roles will contain ['role1', 'role2']
// do whatever role check logic you need
}
This example
How to pass multiple parameters to middleware with OR condition in Laravel 5.2
Instead of adding multiple arguments to your handle method and having to update it every time you add a new role to your application, you can make it dynamic.
Middleware
/**
* Handle an incoming request.
*
* #param $request
* #param Closure $next
* #return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function handle($request, Closure $next) {
$roles = array_slice(func_get_args(), 2); // [default, admin, manager]
foreach ($roles as $role) {
try {
Role::whereName($role)->firstOrFail(); // make sure we got a "real" role
if (Auth::user()->hasRole($role)) {
return $next($request);
}
} catch (ModelNotFoundException $exception) {
dd('Could not find role ' . $role);
}
}
Flash::warning('Access Denied', 'You are not authorized to view that content.'); // custom flash class
return redirect('/');
}
Route
Route::group(['middleware' => ['role_check:default,admin,manager']], function() {
Route::get('/user/{user_id}', array('uses' => 'UserController#showUserDashboard', 'as' => 'showUserDashboard'));
});
This will check if the authenticated user has at least one of the roles provided and if so, passes the request to the next middleware stack. Of course the hasRole() method and the roles themselves will need to be implemented by you.
You can use php 5.6
public function handle($request, Closure $next, ...$roles)
{
foreach ($roles as $role) {
try {
if ($request->user()->can($role)) {
return $next($request);
}
} catch (ModelNotFoundException $exception) {
abort(403);
}
}
}
Route::group(['middleware' => 'role:manager,admin'], function () {}
In middleware named 'role' you can destruct arguments into array
public function handle($request, Closure $next, ...$roles)
{
$userRole = $request->user()->role;
if (! $userRole || ! in_array($userRole->name, $roles)) {
abort(403);
}
return $next($request);
}
simply You can use like this syntax that means if has one of them
Route::group(['middleware' => ['role:first|second|third|....']], function () {});

Categories