How to protect edit user profile route? - laravel

I'm building an app where a logged in user can edit their own profile and of course unable to edit another user's profile.
I have this following route :
http://2mark.dev/profile/derp22/edit
The problem with that route is that the route is accessible by another users and and will finally allow the other users to the edit "derp22" profile data. My question is how to protect this route so that the other users can't access it ?
Thanks for the help!

You can check this in the method in your profile controller.
Here is the methodology:
1. Get the current user.
2. Get the user you want to edit.
3. Check against those Id's.
4. Throw/return error message or proceed in method.
Example:
$currentUser = \Auth::user();
$user = User::findOrFail($id);
if ($user->id != $currentUser->id) {
abort(403);
}
// Then have the save method.
https://github.com/jeremykenedy/laravel-auth/blob/master/app/Http/Controllers/ProfilesController.php

Check this https://laravel.com/docs/5.4/authorization#via-the-user-model
or
You can compare if the authenticated user id is equal the id

Related

Laravel Redirect and Change URL

I thought this would be an easy task and would be the default functionality ... I was wrong.
I am attempting to redirect the user to the dashboard once logged in, I have tried this several ways:
return redirect('/dashboard');
return redirect()->to('/dashboard');
return redirect()->route('dashboard');
All of these work to display the dashboard, but they do not change the URL, so you cannot tell the user location from the address. Could someone please tell me what is required to achieve this.
i had this problem & saw that my mistake was in the Route file.
i had twice a time [..., 'index'] action defined in the same controller
Route::post('/cart', [CheckoutController::class, 'index'])->name('checkout.cart');
Route::get('/checkout', [CheckoutController::class, 'index'])->name('checkout.index');

How to make custom authentication on Laravel?

I have a Laravel application, with a login form. I am using subdomains, for example: {{business_subdomain}}.laravel.test. The purpose of my application is create companies in my database, and make registered users login on their attached company and specific domain.
So in my web.php I declared the following:
Route::domain('{business_subdomain}.' . env('APP_URL'))->middleware(['business.subdomain'])->group(function ()
My database contains the following tables:
* Standard tables like users
* Businesses which contains id, name and subdomain
* Business_user which contains business_id and user_id
The business_id (business_user table) has a relationship with id (business table)
The user_id (business_user table) has a relationship with id (users table)
I created a middleware that checks the following:
$business = $request->user()->businesses->where('subdomain', $request->route('business_subdomain'))->first();
So the subdomain value (business table) must be the equal to the URL/route subdomain value, otherwise when you login, you will get an 403 page.
So what I want to achieve: When a user has an account, but is not attached to the right company/business, I want to display the standard authentication error: These credentials do not match our records.
I've tried to use the code in my middleware on the LoginController and override almost every function separately, but it didn't work.
Do I need to override Laravel authentication functions, do I need to create another middleware or use Guards?
The laravel authentication login order (the order the application uses for logging in a user) seems very confusing for me.
Maybe someone can provide me with more information or help me out!
I tried to use the code in my middleware on the LoginController and override almost every function separately, but it didn't work.
Sounds like you might be looking for multi-tenancy. There are a couple different packages available, both for single and multi-database setups.
Here are some very informative slides on the topic, specific to Laravel. And an excellent article for more detail.
We have a similar application with subdomain routing using torzer/awesome-landlord. The tenant package ensures that login will only search for users of the correct tenant.
To set the correct tenant we added a middleware (App is the tenant, in your case it would be Business):
public function handle($request, Closure $next)
{
$subdomain = $this->getSubdomain($request->server('HTTP_HOST'));
if ($subdomain) {
$app = App::getBySlug($subdomain);
abort_if(!$app, 404);
$this->tenantManager->addTenant($app);
} else {
// empty or generic subdomain
// this is OK as long as there is no user
if ($user = $request->user()) {
return $this->redirectToUserAppSubdomain($request, $user);
}
}
return $next($request);
}

Laravel 5.7 Auth::loginUsingId() not working after CSRF token generated

I am trying to auto-login user on step-2 of registration steps. After successful insert into db i am using Auth::loginUsingId($user_id) to auto-login user using ajax.
I am always submitting CSRF token on each steps.
Now the problem is after successful login CSRF token get generated and Auth::user() gets blank on step 3
Also before and after login CSRF is different.
First of all, csrf token is required when using non-GET request, so if in your case using GET request seems reasonable you can use it.
Otherwise, in step 2 you should return new CSRF token for example like this:
Auth::loginUsingId($user_id);
return response()->json(['csrf_token' => csrf_token()];
and then in step 3 use this new token you got from Step 2 response.
You may try this method Auth::User()->id;
You can try Auth::id() to get the current user's id.
If you want all the details about logged in user then you can use Auth::user().
By Auth::user() you can access all details about the user.
You can also log in from the controller by passing user id Auth::login($user_id)
And if you user Auth::loginUsingId() then you have to pass user id and true status for remember the details.
Like :Auth:loginUsingId(user_id, true)
For Example :
Get User's Id : Auth::id()
Get User's Name : Auth::user()->name
Get User's email : Auth::user()->email
etc....
Seems like its not an issue of CSRF at all.
When you create a new user, Like
$user = new App\User;
$user->username = $request->username;
...
...
$user->save();
Auth::loginUsingId($user->id);
Then place dd(Auth::user()->id); to check that user is logged in or not.
Let us know.

Laravel advanced middlewares

I'm using this line in some controller's __construct
$this->middleware('auth');
This results, that every not logged user will be redirected to login page. It's of course, ok, but there is a problem.
I have two groups of users. In database I have a column called "role", which is boolean. 0 means basic users and 1 means admins. How can I treat, that entrance to some of controllers will be allowed only for admins? I really don't know how to do that in pretty way.
You can pass things to the middleware, like
$this->middleware('auth:1');
Now in the middleware you can check to see if the authenticated user has a role that you passed (in the example, 1). If they don't have the role that you require, then you can redirect them to the login screen or however you want to handle it.
you can use the following code to get the authenticated user and then write custom logic.
if(Auth::user()->role==0)
{
//you are basic user
}
esle if(Auth->user()->role==1)
{
//you are admin
}
you can also Gates and Policies for this type of work.

Laravel "conditional routing"?

I have an interesting problem I need to solve and looking for best way to approach it.
Have a laravel 5.4 app that is fronted by a few public static pages. App is a golf performance tracking app. User enters data and the app does some analysis and shows graphs etc.
Problem is that if a new user signs up they have no data and they need to enter a score for the app to "work"
User signs up, verifies email, etc. so they now have authorized access to the app.
What I want to do is check if the user has any scores in the db (fine I can do that easily) then if they have at least one score entered send them to the app. Fine.
If they have no scores I want to send them to a view that explains that they need to have to enter a score and present the form to do so.
Question is:
where is the best place to check if the user has no scores and then send them to the view to enter the score and not allow them to access any of the app views.
Looking for the best way to do this? Is it create the condition and check the db in the routes/web.php? Is there a better way to accomplish it? and if so what do I do with the routes that sit in:
Route::group(['middleware' => ['web','auth']], function () {
Create a custom middleware and check if the user has score and redirect to any route or display any view you want. Something like this.
public function handle($request, Closure $next)
{
$user = $request->user();
if ($user && ($user->score == 0)) {
return redirect()->route('instruction');
}
return $next($request);
}
Apply this new middleware to all the routes which shouldn't be accessed by users with no scores. Also make sure you use this middleware after auth and not before.

Resources