Laravel - Prevent non admin users from accessing the dashboard - laravel

I am preventing users who do not have a role of 'admin' from logging in to the dashboard in a Laravel 5.5 app like this in app/http/Controllers/auth/LoginController.php..
protected function credentials(\Illuminate\Http\Request $request)
{
$credentials = $request->only($this->username(), 'password');
return array_add($credentials, 'type', 'admin');
}
This works well, but if somebody resets their password using the forgotten password function then it bypasses this function and lets them in to the dashboard.
How can I lock the dashboard down to prevent this happening?
Should I disable auto login after password reset, will this be enough?

Use Middleware, you will have full control on all requests in your app.
Also, you might want to have a look at (spatie/laravel-permission) # github it will make your Role/Permission process really easier.

Overwrite the authenticated method in LoginController. Place the code below in the LoginController.
protected function authenticated(Request $request, $user)
{
if ( Use your Logic here ) {
return redirect()->route('admin.home');
}
return redirect('/home');
}

Related

Laravel Login and save user details

I want to save the user id,name etc when a successfull login happens.
This is my code,
public function Login(Request $request){
$result1=json_decode(DB::table('tbl_admin_details')
->where('Username',$request->input('username'))
->where('Password',base64_encode($request->input('password')))
->get(),true);
if(count($result1)>0){
return redirect('dashboard');
}else{
return redirect('/');
}
}
when a successfull login happens it will redirect to dashboard, I need to access the user data in that page. how its possible ???
if(count($result1)>0) {
$id= session(['id'=>$result1[0]->id]);
$name= session(['name'=>$result1[0]->name]);
return redirect('dashboard');
}
Then use session()->get('id') and session()->get('name').
in your loginController put method:
protected function authenticated( \Illuminate\Http\Request $request, $user) {
dd(\Auth::user());
}
this method fires up when user is successfully logged in
and gives you logged in user information.
feel free to use it as you want

restrict multiple login in different browser using a single account in laravel 5.5

For Example i want like -
If user login from google chrome and trying to login from Firefox then previous session should automatically destroy with a alert message.
So far i have done below which is actually not the correct way because it's working fine with manually logout but when user logged out automatically because of session timeout or browser close or shutdown the db not update as it should be -
protected function authenticated(Request $request, $user)
{
$previous_token = $user->token_id;
$token = $request->session()->token();
if ($previous_token == NULL) {
Auth::user()->token_id = $token;
Auth::user()->save();
}elseif ($previous_token == $token) { }
else
{
if ($previous_token != $token) {
Auth::logout();
}
}
}
public function logout(Request $request, User $user)
{
Auth::user()->token_id = NULL;
Auth::user()->save();
$this->guard()->logout();
$request->session()->invalidate();
return redirect('/');
}
Please assist me on this. Thanks in advance :)
One way to do what you want is to generate new a random string/hash (you can use the str_random helper function and optionally Hash::make to help you with that) as token whenever the user login, then store it in the DB and browser-side(cookie, so it is not affected by session timeout).
Then you can make a middle-ware or modify existing one to check if the two tokens are the same, and log the user out (and/or alert them) when they are not.
Since cookie is not shared by browsers, logging in with one will invalidate the token stored by the other, thus ending that session.

How to logout a user from API using laravel Passport

I'm currently using 2 projects. 1 front end (with laravel backend to communicate with API) and another laravel project (the API).
Now I use Laravel Passport to authenticate users and to make sure every API call is an authorized call.
Now when I want to log out my user, I send a post request to my API (with Bearer token) and try to log him out of the API (and clear session, cookies,...)
Then on the client I also refresh my session so the token is no longer known. Now when I go back to the login page, it automatically logs in my user. (Or my user is just still logged in).
Can someone explain me how to properly log out a user with Laravel passport?
Make sure that in User model, you have this imported
use Laravel\Passport\HasApiTokens;
and you're using the trait HasApiTokens in the User model class using
use HasApiTokens
inside the user class.
Now you create the log out route and in the controller,
do this
$user = Auth::user()->token();
$user->revoke();
return 'logged out'; // modify as per your need
This will log the user out from the current device where he requested to log out. If you want to log out from all the devices where he's logged in. Then do this instead
$tokens = $user->tokens->pluck('id');
Token::whereIn('id', $tokens)
->update(['revoked'=> true]);
RefreshToken::whereIn('access_token_id', $tokens)->update(['revoked' => true]);
Make sure to import these two at the top
use Laravel\Passport\RefreshToken;
use Laravel\Passport\Token;
This will revoke all the access and refresh tokens issued to that user. This will log the user out from everywhere. This really comes into help when the user changes his password using reset password or forget password option and you have to log the user out from everywhere.
You need to delete the token from the database table oauth_access_tokens
you can do that by creating a new model like OauthAccessToken
Run the command php artisan make:model OauthAccessToken to create the model.
Then create a relation between the User model and the new created OauthAccessToken Model , in User.php add :
public function AauthAcessToken(){
return $this->hasMany('\App\OauthAccessToken');
}
in UserController.php , create a new function for logout:
public function logoutApi()
{
if (Auth::check()) {
Auth::user()->AauthAcessToken()->delete();
}
}
In api.php router , create new route :
Route::post('logout','UserController#logoutApi');
Now you can logout by calling posting to URL /api/logout
This is sample code i'm used for log out
public function logout(Request $request)
{
$request->user()->token()->revoke();
return response()->json([
'message' => 'Successfully logged out'
]);
}
Create a route for logout:
$router->group(['middleware' => 'auth:api'], function () use ($router) {
Route::get('me/logout', 'UserController#logout');
});
Create a logout function in userController ( or as mentioned in your route)
public function logout() {
$accessToken = Auth::user()->token();
DB::table('oauth_refresh_tokens')
->where('access_token_id', $accessToken->id)
->update([
'revoked' => true
]);
$accessToken->revoke();
return response()->json(null, 204);
}
I am using Laravel 6.12.0, below function is working for me.
public function logout(Request $request){
$accessToken = Auth::user()->token();
$token= $request->user()->tokens->find($accessToken);
$token->revoke();
$response=array();
$response['status']=1;
$response['statuscode']=200;
$response['msg']="Successfully logout";
return response()->json($response)->header('Content-Type', 'application/json');
}
This is my first post.. and i find a clean solution (Laravel last Version)
/**
* Logout api
*
* #return \Illuminate\Http\Response
*/
public function logout(Request $request)
{
if (Auth::check()) {
$token = Auth::user()->token();
$token->revoke();
return $this->sendResponse(null, 'User is logout');
}
else{
return $this->sendError('Unauthorised.', ['error'=>'Unauthorised'] , Response::HTTP_UNAUTHORIZED);
}
}
Below is the simplest way I found to do it.
1. USE database SESSION INSTEAD OF file SESSION
Official documention
php artisan session:table
php artisan migrate
Replace SESSION_DRIVER=file by SESSION_DRIVER=database in your .env file.
2. DELETE USER SESSION RIGHT AFTER LOGIN
After a user is redirected to your frontend and logs in to finally get a token, you probably call a route in api/routes.php to get the user information, that's where I'm closing the user backend session before sending back user information to the frontend:
Route::middleware('auth:api')->get('/user', function (Request $request) {
// Close user session here
Illuminate\Support\Facades\DB::table('sessions')
->whereUserId($request->user()->id)
->delete();
return $request->user();
});
3. REVOKE TOKENS AT LOGOUT
Then, to "log out" (actually, revoke tokens) the user from the frontend, you just need to call another route to revoke the token and refresh_token:
Route::middleware('auth:api')->post('/logout', function (Request $request) {
// Revoke access token
// => Set oauth_access_tokens.revoked to TRUE (t)
$request->user()->token()->revoke();
// Revoke all of the token's refresh tokens
// => Set oauth_refresh_tokens.revoked to TRUE (t)
$refreshTokenRepository = app('Laravel\Passport\RefreshTokenRepository');
$refreshTokenRepository->revokeRefreshTokensByAccessTokenId($request->user()->token()->id);
return;
});
You may prefer to put these two closures in the UserController.
Hope help someone:
if (Auth::check()) {
$request->user()->tokens->each(function ($token, $key) {
$token->delete();
});
}
Good Luck.
I use this in my project to logout from multiple device.
public function logout(Request $request, $devices = FALSE)
{
$this->logoutMultiple(\Auth::user(), $devices);
return response()->json([], 204);
}
private function logoutMultiple(\App\Models\User $user, $devices = FALSE)
{
$accessTokens = $user->tokens();
if ($devices == 'all') {
} else if ($devices == 'other') {
$accessTokens->where('id', '!=', $user->token()->id);
} else {
$accessTokens->where('id', '=', $user->token()->id);
}
$accessTokens = $accessTokens->get();
foreach ($accessTokens as $accessToken) {
$refreshToken = \DB::table('oauth_refresh_tokens')
->where('access_token_id', $accessToken->id)
->update(['revoked' => TRUE]);
$accessToken->revoke();
}
}
Try this code to help you to logout from passport authentication.
Route::post('/logout', function(){
if (Auth::check()) {
Auth::user()->AauthAcessToken()->delete();
}
return response()->json([
'status' => 1,
'message' => 'User Logout',
], 200);
});
check whether your model contains OauthAccessToken which needs to connect with the database oauth_access_tokens. The access token is stored in the database table oauth_access_tokens. and makes a relation from users to oauth_access_tokens.
public function AauthAcessToken(){
return $this->hasMany(OauthAccessToken::class);
}
You can use following code to remove to token for logged in user.
$request->user()->token()->revoke();
If you want to learn about this in-depth then watch this tutorial:
https://www.youtube.com/watch?v=UKSQdg1uPbQ
public function logout(Request $request)
{
$request->user()->token()->revoke();
if ($request->everywhere) {
foreach ($request->user()->tokens()->whereRevoked(0)->get() as $token) {
$token->revoke();
}
}
return response()->json(['message' => 'success']);
}

auth attempt failing in Laravel 5.4

I have some post about auth attempt failure but my case seems to be different. Still in dev phase so my password is in plain text. I try to login but i keep getting false and so redirected back to login page.
The error message says username/password does not match but dd reveals that both email and password are correct.
What could be responsible for this failure? PS: it's my first time working with laravel
web.php
Route::post('/login', 'AuthController#authenticate');
Route::get('/', 'PostController#index');
AuthController
public function auth()
{
//dd($request);
// attempt to login the user
if (! auth()->attempt(request(['email', 'password']))) {
return back()->withErrors([
'message' => 'Username/Password does not macth'
]);
}
return redirect('/');
}
PostController
public function index()
{
$posts = Post::latest()->limit(3)->get();
return view('post.index', compact('posts'));
}
Use this code in your User model and the password will be hashed automatically only if it needs:
public function setPasswordAttribute($value)
{
if( \Hash::needsRehash($value) ) {
$value = \Hash::make($value);
}
$this->attributes['password'] = $value;
}
and change your password after, so you have the hashed password in the database
Not sure i understand... but if you are using the Laravel Authentication (php artisan make:auth) you will not be storing the password in plain text... so if you are setting the password directly in your db it will not work as it will check the password field in the db with the assumption that it is stored with a dbcrypt hash...
So if you are using the default auth that comes with laravel, use the registration form to create your user account
Since it's your first time working with laravel i would recommend taking a look at https://laracasts.com/series/laravel-from-scratch-2017/episodes/17 as it covers the auth concept and gives you a quick walkthrough on setting up user auth

Laravel Auth Register, Prevent automatic login

I was developing an app to manage users. I need to access auth/register from logged in users. The default auth redirecting to home page.
It seems after registration, Auth automatically doing ::attempt.
How can I prevent it?
Assuming you use the RegistersUsers (or AuthenticatesAndRegistersUsers) trait in your controller you can override the postRegister method and simply not log the user in. You can see the original method here
Without logging it that would be:
public function postRegister(Request $request)
{
$validator = $this->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
}
return redirect($this->redirectPath());
}

Resources