Laravel REST structuring - php

I am making a website which will have user login. Login form now leads to admin panel if your role is admin (route is behind admin middleware), and it leads back to home page if your role is user. Back on the home page you have the ability to see your profile page and add a product (which is behind auth middleware).
My question is what is the best approach to form my routes?
If I make site.com/user/{id} route, user ID's will be exposed to each user which logs in, as well as for example editing a product with site.com/user/{id}/product/{product_id}.
I see some security issues here and am wondering if a better solution is making site.com/profile route which will in turn in controller take Auth::user() not exposing ID's in the process?

Add your route without the ID and use Auth::user() It's best practice and makes your routes simpler
Public function profile(){
$user = Auth::user();
return view('profile', compact('user');
}
The above code is more straight forward than this:
Public function profile($id){
$user = User::find($id);
//prevent authenticated from viewing other users
if($user == Auth::user()){
return view('profile', compact('user');
}else{
//return something else
}
}

If you are worried about exposing user ID you can try use something like hashids, where ID will be encoded.

Here you go:
encode the id and product_id with base64_encode()
Example pass the id and product_id in url by encoding with base64_encode()
and when you want to use it use like this:
Route::get('user/{id}/product/{product_id}', function($code){
$id = base64_decode($id);
$product_id = base64_decode($product_id);
});

Related

making a log in as user in laravel

i want to know if there is any way to simulate the login as user and make the session for that user .i want my help-desk to see the site from users vision so they need to log in as user as long as i cant show the user s password to the admin (its not possible as far as i know if its not that would be a good solution too ). i want to place a button with some text for example :
LoginAsThisUser
and when my help desk clicks on the button he logs in as the user is there any way to do that ??
It's possible, and it's fairly simple to do. All you need to do is to create a route, something like this:
Route::get('admin/login-as-user/{id}', 'Admin\UserController#loginAsUser')->name('login.as.user');
After that, pass the route to your LoginAsThisUser button with desired user id :
LoginAsThisUser
And create a function in your controller:
public function loginAsUser($id)
{
$user = User::findOrFail($id);
Auth::login($user);
return redirect('/');
}
Note: this is not tested, let me know if you encounter any errors.
use Illuminate\Support\Facades\Auth;
//use user_id
Auth::loginUsingId(1);
// Login and "remember" the given user...
Auth::loginUsingId(1, true);
$user=User::find($userId);
//use Authenticatable user
Auth::login($user);
// Login and "remember" the given user...
Auth::login($user, true);
also use
Auth::guard('notDeafault')->login($user);
if you want switch default guard
With the Auth facade, you can use the loginUsingId method
Auth::loginUsingId($user_id);
This method allows you to force login without a password. But it does not allow you to retrieve cookies or cache from your user's browser that may impact their viewing.

Laravel loginUsingId doesn't seem to work

I need to manually login a user in Laravel 5.7 via Auth. Once I run Auth::loginUsingId($userId, true) I then relocate the user to his Account page.
The point of this is for a user coming through a token can be logged in into the website, without adding his credentials again.
I've tried anything I could find online, including moving the Session from MiddlewareGroup to Middleware, checking the Cookie name and some other things that didn't work.
My Controller looks something like this:
public function loginExternal(Request $request) {
$userId = $request->uid;
Auth::loginUsingId($userId, true);
redirect()->to('/account')->send();
}
and the route for it is pretty simple:
Route::get('/oneclick/{token}', 'Auth\AccountController#loginExternal')->middleware('signed')->name('oneclick');
I would expect the user to be logged in and taken to his account automatically. Now it just sends me to the login page.
What I noticed is that the loginUsingId() method generates a new session id only in this controller, but in other pages of the website, the website is using a different session, the same one (which should happen).
I need to mention that the user does get loggedin in the LoginExternal method. It just doesn't persist to the account page.
Any ideas?
In controller:
public function loginExternal($id) {
$user = User::find($id);
if($user){
\Auth::loginUsingId($id, true);
return redirect('/account');
} else {
return redirect('/')->with('error_message', 'No user found!');
}
}
In route file (web.php)
Route::get('/oneclick/{id}', 'Auth\AccountController#loginExternal')->name('oneclick');

How can restrict a user to access some section of my application in laravel 5.4

I have different type of users in my application. Ex: Super Admin, Client, Staff and HR.
Now I want to give all access to Super Admin and some for Client and some for Staff and some for HR also.
Lets say I have 3 section
a) Manage Staff
b) Manage Clients
c) Manage Projects
d) Manage Designation
Now I want to give access super admin a,b,c & d And for Client only C And For Staff Only c & d And for HR only a.
I have done it by checking the User type form my user table. (Not Right Way)
Lets Say I have a URL localhost/myApp/staff [ this can be access by Super Admin]
But when I logged in as Client and I hit the above URL then He/She is able to get the list of staffs, Which I want to restrict and redirect back him with some message.
How can I achive this in Laravel 5.4. Thanks in advance.
You need to use middleware for that.
See in the doc:
https://laravel.com/docs/5.4/middleware
A little example
public function handle($request, Closure $next)
{
$user = $request->user();
if ($user && $user->isAdmin())
{
return $next($request);
}
return new RedirectResponse(url('/home'));
}
}
With a middleware like that , if the user is Admin he can go on the page if not it will be redirect on the homepage.
The isAdmin is a function , you gonna need to create in your user Model like that.
public function isAdmin()
{
return $this->groups->name =='Admin';
}
In the function for the staff url check the type of user:
function staff(){
if(Auth::user ! = 'super-admin')
return redirect('/')
}
else{
//show the staff
}
You need check this page out Authenticate A User Instance.
Authenticate A User Instance
If you need to log an existing user instance into your application, you may call the login method with the user instance. The given object must be an implementation of the Illuminate\Contracts\Auth\Authenticatable contract.
Auth::login($user);
// Login and "remember" the given user...
Auth::login($user, true);`
Of course, you may specify the guard instance you would like to use:
Auth::guard('admin')->login($user);
You can follow the Laravel documentation or add a new field called 'role' or what ever to authenticate.

Pass current user to route in Laravel?

I'm trying to make a "Profile settings" section in an application.
The thing is, I learned how to do this the "Admin" way, the route would be /users/{user}/edit, the would call the edit method on the controller and it would return the edit view. There I would have a form which the user would patch to the route users/{user} and it would call the update method on the controller.
But I don't want anyone editing other users, so I'd like to know if there's a way to limit this route to the current user only.
Thanks in advance.
Since version 5.1 Laravel has Policies which are exactly what you need.
You can create a new policy by typing in command:
php artisan make:policy UserPolicy
In your UserPolicy class you can include the following method:
public function updateProfile(User $user, User $updatedUser) {
return $user->id === $updatedUser->id;
}
Please note: The first parameter $user is resolved automatically behind the scenes and is the currently logged in user. When checking the policy through the Gate facade in your application you need to pass only the second parameter $updatedUser.
Then you need to register your policy in the AuthServiceProvider:
use Acme\User;
use Acme\Policies\UserPolicy;
...
class AuthServiceProvider extends ServiceProvider {
protected $policies = [
User::class => UserPolicy::class
]
Now when you have your policy registered you can check it across your app using the Gate facade like so:
if(Gate::allows('updateProfile', $user)) {
// Your logic goes here
}
Or the other approach with I like more using the denies method and include it at the beginning of my controller methods and return http error:
public function edit($id) {
if(Gate::denies('updateProfile', $user)) {
abort(403, 'You do not have permissions to access this page!');
}
// The check is passed and your can include your logic
}
You can also check for permissions in your blade files using can and cannot like so:
#can('updateProfile', $user)
// Show something only to the user that can edit the $user's profile
#endcan
For more info check the docs.
you should not need to pass in the user id as there user is already logged in and there for should be able to edit themselves, thus only targetting the logged in user.
So you can use the routes /user/editand /user/updateetc
Just get the current user details like
Auth::user()->id
or something else like
$user = Auth::user();
Thus only the logged in user (themselves) can be edited.
In the view there should be a button or link, on click pass the ID to the desired route that's it.
Example:
For Grabbing the current logged in User id you should do like
$user = Auth::user()->id;
And directly in the route you can get it like
Edit
Now when someone clicks on the Edit Button/Link, the route will look like route/currentuserid.

Laravel 4 Prevent Authenticated users from viewing other user profiles

I am wondering how in laravel 4 the following is possible. I have a filter to check if a user is authenticate on all routes that have user/*. My filter works as it is suppose to but lets say that a user is logged in their url will look something like this user/id. How do I prevent an authenticated user from viewing another user?
another approach is to change your urls..
why have url like user/{id} ?
just change it to for example
user/profile
and inside the controller do something like:
$user = Auth::user();
that way the user just cant fake is id..
i only use urls with the id in the admin area where i need to edit some user:
/admin/{id}/edit
In your Auth filter you can access the route parameter ('user/{id}') and can check logged in user's id with the id passed in the url like
Route::filter('auth', function($route)
{
// get the id from rouqe
$id = $route->getParameter('id');
if( Auth::check() && Auth::user()->id != $id) {
// not authenticated user, so access is denied
return Redirect::to('/');
}
});
If it is a blanket policy that a user can only view their own profile then could you just check that the id from user/{id} route matches the current user id from the login session, eg. in the profile controller something like:
public function getProfile($profile_id) {
if (Auth::user()->id != $profile_id) {
//this is not your profile - don't be nosey!
} else {
//have you got nothing better to do than look at yourself all day!
}
}
Glen

Categories