Laravel Login Issue for multiple roles - laravel

I have added multiple roles authentication in laravel 8.6. Used common middleware for this but occurring issues for login.
i.e If i logged in as admin (role id 1) it will redirected successfully to dashboard. But if you logged out and login as user (role id 2) it will redirect to login page again and the on second time it will redirected to dashboard on second attempt.
I need solution for it.

In your login controllers authenticated method,
If you are using spatie/larave-permission package
$user = Auth::user();
if ($user->hasRole('super-admin')) {
return redirect()->route('dashboard');
}
if ($user->hasRole('admin')) {
return redirect()->route('login');
}
If using self role middleware
$user = Auth::user();
if ($user->role_id === 1) {
return redirect()->route('dashboard');
}
if ($user->role_id === 2) {
return redirect()->route('login');
}
But you can not force a logged-in user to log in again. What is your plan? I strongly advise you to try something else.

Related

Ask User's Password When Logging with Social Account - Laravel Socialite

I have fully functional Socialite social login with Google and Facebook but i want to add another step that is "ask a password before logging in".
This function logs the user immediately after successfully logging in with the provider:
public function callback(Request $request, $provider, SocialAccountsService $service)
{
if ($request->has("error")) {
return redirect()->route("website.index");
}
try {
$user = $service->createOrGetUser(
Socialite::driver($provider)->user(),
$provider
);
auth()->login($user);
} catch (InvalidStateException $e) {
Log::error($e->getMessage());
return redirect()->route("auth.register.index");
}
return redirect()->route("dashboard.profile.index");
}
What should i do so when they login with the provider they must insert a password before logging to my website?
Okey, you want to create user but do not want to log it. Than:
Delete auth()->login($user);
Add something like session()->put('created_social_user_id', $user->id);
Create PasswordCreation controller and view and redirect user from callback to it
In this controller - use session, get user_id, find before created model and ask user about password.
After password creation - add auth()->login($user); and redirect to dashboard

JWT laravel: check auth. Cannot check if user is authenticated even i have set the token

I'm trying make a mobile application with vue and i'm using jwt in laravel.
On first login, I can access the auth()->check() then I get false after the app is cancelled. I'm saving the token. I'm saving the token in local storage. How can I get the authenticated user.
controller:
public function JwtAuth(){
if($this->getAuthenticatedUser()){
return $this->JwtUser = $this->getAuthenticatedUser();
}
return [];
}
I want to acheive something like:
if(auth()->user()){
$user = "something";
}else{
$user = '';
}
return $user;
So sometime I will have token and sometime i dont .. how to check?

How to authorize user in laravel

We have auth microservice and an admin panel based on laravel. We login user by calling auth api and returning user id and token. How I could make user as authorized in laravel 5.3? I did not found any information googling.
$request = Request();
$authorize = new Authorize();
$response = $authorize->logIn($request->all());
if ($response->status == 'success') {
$user = new User();
$userResponse = $user->getUser($response->data->id);
Session::put('userId', $response->data->id);
Session::put('userToken', $response->data->token);
Session::put('userData', $userResponse);
if ($request->input('save_login')) {
Cookie::queue(Cookie::make('savedLogin', $request->input('login'), 129600, null, null, false, false));
} else {
Cookie::queue(Cookie::forget('savedLogin'));
}
return redirect('/');
}
You can manually log in the user with either the id or the User Instance.
From the docs:
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. Of course, the
App\User model included with Laravel already implements this
interface:
Auth::login($user);
// Login and "remember" the given user...
Auth::login($user, true);
Authenticate A User By ID
To log a user into the application by their ID, you may use the
loginUsingId method. This method accepts the primary key of the user
you wish to authenticate:
Auth::loginUsingId(1);
// Login and "remember" the given user...
Auth::loginUsingId(1, true);

Redirect user to homepage if he is not authorized to access page its not working properly

If a user creates a conference with id "2" he should be allowed to access "proj.test/conference/manage/2".
But a user that did not create the conference with id "2" should be redirected to the login page if he is not authenticated. If he is authenticated should be redirected to the homepage.
But its not working properly, if the user created the conference with id 2 he can access "proj.test/conference/manage/2" but other user that did not create this conference if accesses "proj.test/conference/manage/2" it appears an error:
This action is unauthorized.
So instead of redirecting the user to the homepage it shows this error. Do you know why is not working?
I have the store method, after storing the conference the user is redirected to the management area to manage that specific conference, for example, to manage the conference with id 2 the user is redirected to "proj.test/conference/manage/2".
Store method:
public function store(Request $request)
{
$this->validate($request, [
'conference_name' => 'required|max:255|string',
...
]);
$conference = Conference::create([
'name' => $request->conference_name,
...
]);
}
Then in the AuthServiceProvider I add:
public function boot(GateContract $gate)
{
$this->registerPolicies();
$gate->define('access-management-area', function($user, $conference)
{
return $user->id == $conference->conference_creator_id;
});
}
And in the manage method I have:
public function manage($id){
$conference = Conference::findOrFail($id);
if($this->authorize('access-management-area', $conference)){
return view('conferences.manage')->with('myconference',$conference);
}
else{
return redirect('/home');
}
}
Do not use $this->authorize as it does not work the same as Gate::allows()/denies().
The authorize method will throw an exception if it fails, it will not return false for the sake of conditional comparison.
From the docs:
If the action is not authorized, the authorize method will throw an Illuminate\Auth\Access\AuthorizationException, which the default Laravel exception handler will convert to an HTTP response with a 403 status code.
So, instead, use Gate::denies for comparisons.
if(Gate::allows('access-management-area', $conference)) {
return view('conferences.manage')->with('myconference',$conference);
} else {
return redirect('/home');
}

Laravel issue with loginUsingId (Manual Authentication)

I am trying to implement a single signon on multiple domains. The concept is pretty simple i.e to send unique user tokens and then verify these tokens to find the user and then log him in.
Now after verifying the token and then grabbing the user, i do something like this
$loggedInUser = Auth::loginUsingId($user->id, true);
Now i have a custom middleware where it first checks for a logged in user, i.e
Auth::Check()
The above works fine for the first time. But on refresh Auth::check() is not validated. I have also tried using all different session drivers but still doesn't work.
I used a similar code on laravel 5.2, and it did work. But on laravel 5.3 its not validating on persistent requests.
Edit: Let me show you my Code
I have not modified AuthServiceProvider or any other guard. I do have the user model inside a directory but i have modified the path in auth.php.
Here is the route that domain1 points to:
http://domain2.com/{{$role}}/{{$route}}/singlesignon/{{$token}}
This is then picked up by verifySingleSignOn method inside the loginController which takes in the role, route that the user came in from other domain and the token. The user is then redirected to the same routes, but on domain2. Here i can successfully recieve the user id before manually logging in.
public function verifySingleSignOn($role, $route, $token)
{
// Fetch Single Signon
$userRepository = new UserRepository();
$user = $userRepository->checkForSingleSignOnToken($token, ['id']);
// Check if Token Exists
if (isset($user->id) && is_int($user->id) && $user->id != 0) {
// Manually Logging a user (Here is successfully recieve the user id)
$loggedInUser = Auth::loginUsingId($user->id);
if (!$loggedInUser) {
// If User not logged in, then Throw exception
throw new Exception('Single SignOn: User Cannot be Signed In');
}
$redirectTo = $role . '/' . $route;
return redirect($redirectTo);
} else {
return Auth::logout();
}
}
Then i have this GlobalAdminAuth middleware
// Check if logged in
if( Auth::Check() ){
$user = Auth::User();
// Check if user is active and is a globaladmin
if( !$user->isGlobalAdmin() || !$user->isActive() ){
return redirect()->guest('login');
}
}else{
return redirect()->guest('login');
}
return $next($request);
Now the first time everything works fine and the user moves through the middleware successfully . but the second time the else statement is triggered.
Edit: Code for checkForSingleSignOnToken
public function checkForSingleSignOnToken($token, $columns = array('*'))
{
return User::where('single_signon', $token)->first($columns);
}
try
Auth::login($user);
instead of
Auth::loginUsingId($user->id, true);
Cookies are restricted domain-wise. Your application on domain1.com wont be able to grab cookies set by domain2.com.
You should be customizing the guard to use some other mechanism than cookies. Maybe use a token in the query parameters.
add this to your protected $middleware array in app\Http\Kernel.php
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class
I think it has to do with an update in the framework
no using auth:check in middleware
using request->user() or auth::user()
Please review bellow code structure, i had made manual authentication
in laravel 5.0.
routes.php
Route::get('login_user_by_id/{id?}', ['as' => 'login_user_by_id', 'uses' => 'UsersController#login_user_by_id']);
Route::post('user_login_post_for_admin',['as'=>'user_login_post_for_admin','uses'=>'LoginController#user_login_post_for_admin']);
Route::get('user_logout', ['as' => 'user_logout', 'uses' => 'UsersController#user_logout']);
LoginController.php
public function user_login_post_for_admin(){
$this->set_email($_POST['email']);
$this->set_password($_POST['password']);
$this->set_login_requested_role(['Admin','Moderator']);
return $this->user_login_post();
}
public function user_login_post(){
$User = new User();
if(isset($this->email) && !empty($this->email)){
$User->set_email(trim($this->email));
$User->set_password(Hash::make(trim($this->password)));
$user_login_data = $User->check_email_password_for_login();
if(isset($user_login_data) && !empty($user_login_data)){
if (Hash::check(trim($this->password), $user_login_data[0]->password)) {
$response['user_id']=$user_login_data[0]->id;
$response['name']=$user_login_data[0]->name;
$response['surname']=$user_login_data[0]->surname;
$response['profile_picture']=$user_login_data[0]->profile_picture;
$response['SUCCESS']='True';
$response['MESSAGE']='Login Success.';
return Redirect::route('login_user_by_id',[$user_login_data[0]->id]);
}else{
Session::put('SUCCESS','FALSE');
Session::put('MESSAGE', 'Invalid Credential.');
return redirect()->back();
}
}else{
Session::put('SUCCESS','FALSE');
Session::put('MESSAGE', 'Invalid Credential.');
return redirect()->back();
}
}else{
Session::put('SUCCESS','FALSE');
Session::put('MESSAGE', 'Invalid Credential.');
return redirect()->back();
}
}
UsersController.php
public function login_user_by_id($id=''){
if(isset($_GET['id'])&&!empty($_GET['id'])){
$id = $_GET['id'];
}
$User = new User();
$Log=new Log();
$user_for_auth = $User->find($id);
Auth::login($user_for_auth, true);
$User->id=AUTH::user()->id;
$auth_user_role=$User->auth_user_role();
$rl_title=$auth_user_role[0]->rl_title;
return Redirect::route('admin_home');
}
public function user_logout(User $user){
$User=new User();
$login_user_id = AUTH::user()->id;
$User->id=AUTH::user()->id;
$auth_user_role=$User->auth_user_role();
$login_user_role=$auth_user_role[0]->rl_title;
$response['user_id']=$login_user_id;
$response['SUCCESS']='TRUE';
$response['MESSAGE']='Successfully Logout.';
Auth::logout();
return Redirect::route('admin_login');
}

Resources