Middleware for 2 step authorization - php

I am beginner in Laravel. I make my application in Laravel 8 and spatie/laravel-permission.
Actually i have persimmons: individual|company
Route::group(['prefix' => '', 'middleware' => ['role:individual|company']], function () {
Route::get('/cms-historia-przesylek-nadanych', 'Account\SendPackageController#index')->name('cms-history-send-packages')->middleware('company');
Route::get('/cms-przesyleka-nadana/{id}', 'Account\SendPackageController#show')->name('cms-view-send-package')->middleware('company');
Route::get('/cms-przesyleka-nadana-zwrot/{id}', 'Account\SendPackageController#returnBackPackage')->name('cms-view-send-package-return')->middleware('company');
Route::post('/cms-przesyleka-nadana-zwrot/zamow-paczke/{id}', 'Account\SendPackageController#orderPackage')->name('cms-view-send-package-return-order')->middleware('company');
Route::get('/cms-pobierz-przesyleke-nadana/{id}', 'Account\SendPackageController#getPdf')->name('cms-get-send-package')->middleware('company');
Route::get('/cms-historia-przesylek-odebranych', 'Account\ReceivedPackageController#index')->name('cms-history-received-packages')->middleware('company');
Route::get('/cms-przesyleka-odebrana/{id}', 'Account\ReceivedPackageController#show')->name('cms-view-received-package')->middleware('company');
Route::get('/cms-pobierz-przesyleke-odebrana/{id}', 'Account\ReceivedPackageController#getPdf')->name('cms-get-received-package')->middleware('company');
Route::get('/cms-dwu-stopniowa-weryfikacja', 'Account\TwoStepVerificationController#index')->name('cms-two-step-verification');
});
And this is my USER.php:
<?php
namespace App\Models;
use App\Traits\ScopeActiveTrait;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Spatie\Permission\Traits\HasRoles;
use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;
class User extends Authenticatable
{
use Notifiable,
ScopeActiveTrait,
HasRoles,
SoftDeletes,
HasSlug;
/**
* Get the options for generating the slug.
*/
public function getSlugOptions() : SlugOptions
{
return SlugOptions::create()
->generateSlugsFrom(['company_name', 'id'])
->slugsShouldBeNoLongerThan(250)
->saveSlugsTo('slug');
}
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name',
'email',
'password',
'enable',
'company_id',
'surname',
'email_verified_at',
'description',
'is_company',
'package1',
'package2',
'package3',
'sms',
'phone',
'street',
'building_number',
'city',
'postal_code',
'revicer_default_inpost_parcel',
'shipping_default_inpost_parcel',
'file_name',
'nip',
'company_name',
'remember_token',
'subdomain',
'lng',
'lat',
'show_map',
'ofert_type',
'discount_value1',
'discount_value2',
'discount_value3',
'discount_value4',
'discount_value5',
'is_two_step_authorization',
'two_step_authorization_token',
];
protected $dates = [
'created_at',
'updated_at',
'deleted_at'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
'company_id' => 'integer',
'enable'=>'boolean',
'isCompany'=>'boolean',
'show_map'=>'boolean',
];
/* User Login history */
public function loginHistory()
{
return $this->hasMany('App\Models\UserLoginHistory');
}
/* User images */
public function images()
{
return $this->hasManyThrough('App\Models\UploadFile', 'App\Models\User', 'id', 'file_id');
}
public function mainImage()
{
return $this->images()->where('file_type', 'DZ_ADMIN');
}
/* Admin Avatar */
public function getAvatar()
{
return $this->images()->where('file_type', 'DZ_ADMIN')->orderBy('order', 'ASC')->first();
}
public function isCompany(): bool
{
return $this->is_company == 1;
}
}
When I have is_two_step_authorization = 1.- then I need run new middleware for 2 step authorization,.
How can I make it?
is_two_step_authorization = 0 - 2 factorial authorization is disabled. is_two_step_authorization = 1 - Two-factor authentication is enabled.
I think use this tutorial: https://www.itsolutionstuff.com/post/laravel-8-two-factor-authentication-with-smsexample.html but this middleware work always for route with middleware 2fa.
In my case, selected routs may require 2-step security (if the user has chosen so in the settings) or not (the user has disabled security).
How can I change the code from the tutorial to get it?

You need to update the middleware from the tutorial in order to only redirect to 2fa index if the logged user has is_two_step_authorization on. Of course you may need other checks, or to ensure that the user is logged in and so on, but just for this specific usecase, this line of code should do the trick.
app/Http/Middleware/Check2FA.php
public function handle(Request $request, Closure $next)
{
if ($request->user()->is_two_step_authorization && !Session::has('user_2fa')) {
return redirect()->route('2fa.index');
}
return $next($request);
}

Tweak the code from that example...
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Session;
class Check2FA
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
if ($request->user()->is_two_step_authorization == 1) {
return redirect()->route('2fa.index');
}
return $next($request);
}
If the requested user has the property of is_two_step_authorization with value one only then it will redirect to the 2fa page, otherwise not

Related

Access restriction for users that are not admin and landlord

I am working on a laravel project. I want to restrict the api/property/create route so that only admins and landlord users can create property.However i am meeting a challenge in implementing this functionality.
Here is my route to create property
Route::group(['middleware' => ['auth:api', 'adminLandlord']], function() {
Route::post('/property/create', 'App\Http\Controllers\PropertyController#create')->name('createProperty');
});
Below is my AccountType Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class AccountType extends Model
{
use HasFactory;
protected $name = [
1 => 'Admin',
2 => 'Landlord',
3 => 'Guest',
4 => 'Tenant',
5 => 'Service Provider',
];
const ADMIN = 1;
const LANDLORD = 2;
const GUEST = 3;
const TENANT = 4;
const SERVICEPROVIDER = 5;
public static function getAccountName($id) {
$name = [
1 => 'Admin',
2 => 'Landlord',
3 => 'Guest',
4 => 'Tenant',
5 => 'Service Provider',
];
return $name[$id];
}
public function user()
{
return $this->hasMany(User::class);
}
}
This is the User model
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
use HasFactory, Notifiable, HasApiTokens;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'first_name',
'last_name',
'account_type',
'email',
'password',
'phone_number'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
const ADMIN = 'Admin';
const LANDLORD = 'Landlord';
const GUEST = 'Guest';
const TENANT = 'Tenant';
const SERVICEPROVIDER = 'Service Provider';
// Get property(s) under a user
public function properties()
{
return $this->hasMany(Property::class);
}
public function roles()
{
return $this->hasOne(AccountType::class);
}
public function isAdmin()
{
return $this->account_type == 1; // this looks for an account_type column in the users table
}
public function isLandlord()
{
return $this->account_type;
}
public function isGuest()
{
return $this->account_type;
}
public function isTenant()
{
return $this->account_type;
}
public function isServiceProvider()
{
return $this->account_type;
}
}
Here is my adminLandlord middleware
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Models\User;
use App\Models\AccountType;
class AdminLandlordMiddleware
{
/**
* The Guard implementation.
*
* #var Guard
*/
// protected $auth;
/**
* Create a new filter instance.
*
* #param Guard $auth
* #return void
*/
// public function __construct(Guard $auth)
// {
// $this->auth = $auth;
// }
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
if(Auth::check() && !Auth::user()->isLandlord($this->getAccountTypeId('Landlord')) || !Auth::user()->isAdmin($this->getAccountTypeId('Admin'))){
// return $next($request);
return response()->json(['error_message' => 'Unauthorized action'], 403);
}
return $next($request);
}
public function getAccountTypeId($name)
{
$accountType = AccountType::where('name', $name)->first();
return $accountType->id;
}
}
I need to be able to pass the getAccountTypeId() to the isAdmin and isLandlord methods so as to get the accountTypeId which i will then use in the condition in the middleware. I tried it the way shown above but its not working out.
Thank you for the help.

Call to undefined method App\User::admin() error in Session in Laravel

I'm trying to put some sessions in my project and it's working fine when I'm logged out. But when I'm logged in as an Admin I'm getting the following error:
Call to undefined method App\User::admin()
this is my routes
Route::resource('/create','PagesController#showCreate')->middleware(IsAdmin::class);
Route::get('/users','UserController#index')->middleware(IsAdmin::class);
Route::get('/verify','UserController#userVerify')->middleware(IsAdmin::class);
this is my User model
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
* protected $table = 'users';
*public $primaryKey ='id';
* #var array
*/
protected $fillable = [
'name', 'email', 'password','userType',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
'admin' => 'boolean',
];
public function posts(){
return $this->hasMany('App\Post');
}
public function isAdmin()
{
return $this->admin;
}
}
and this is my IsAdmin class
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class IsAdmin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
{
if ( Auth::check() && Auth::user()->admin() )
{
return $next($request);
}
return redirect('home');
}
}
}
And every time I try to redirect to other routes I get the same error except for the dashboard
Change if statement in your IsAdmin class:
if ( Auth::check() && Auth::user()->isAdmin() )

Relate a new user to a role from their registration Laravel

I have an app in laravel and I have 3 Admin, owner, user roles, I want that when a user registers he can choose between user and owner, for now I will use the registry of laravel / ui, I will leave them my relationships and my tables
Model Role
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
public function users(){
return $this->belongsToMany('App\User');
}
}
User Model
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
public function roles(){
return $this->belongsToMany('App\Role');
}
/* Validations */
// The roles are received in the authorizeRoles variable, and they are validated if my role is valid or not, when accessing a page, the helpers abort generates an http exception and the user receives an error
public function authorizeroles($roles){
if($this->hasAnyRole($roles)){
return true;
}
abort(401,'This action is unauthorized');
}
// Function, where we iterate (HasAnyRole) Enter the roles to check if you have any role
public function hasAnyRole($roles){
if(is_array($roles)){
foreach($roles as $role){
if($this->hasRole($role)){
return true;
}
}
}else{
if($this->hasRole($roles)){
return true;
}
}
return false;
}
// HasRole function - We validate if our user contains the role for which it is asked -->
public function hasRole($role){
if($this->roles()->where('name',$role)->first()){
return true;
}
return false;
}
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'provider', 'provider_id'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
Register Controller
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
}
I would like to know how to filter between only two roles in my controller and paint them in my view in a select, I would appreciate your support
In Controller
$roles = Role::whereIn('name', ['owner', 'user'])->get();
//And pass this roles in your view for example:
return view('user.create', compact('roles');
In view, in form:
<select name='role_id'>
#foreach($roles as $role)
<option value="{{$role->id}}">{{$role->name}}</option>
#endforeach
</select>

Laravel multi table authentication is not logging in

In my laravel project , am implementing another login for agencies, which i want to take from agencies table.Agencies table have email and password fields. But when i try to login it not get logged in and redirecting to same page and prducing validation error.But i provided exact email and password from agencie table
Following is my code in model
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Kyslik\ColumnSortable\Sortable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Agencie extends Authenticatable
{
use Notifiable;
use Sortable;
protected $guard = 'agencie';
protected $table = 'agencies';
protected $primaryKey = 'agency_id';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'agency_id', 'agency_name','agency_user_name' ,'agency_password', 'agency_city', 'agency_state', 'agency_zip', 'agency_email','status','created_at','updated_at'
];
}
Following i have addeed to config/auth.php
'guards' => [
'agencie' => [
'driver' => 'session',
'provider' => 'agencies',
],
],
'providers' => [
'agencies' => [
'driver' => 'eloquent',
'model' => App\Agencie::class,
],
],
Following is my code in LoginController
<?php
namespace App\Http\Controllers\Agency\AgencyAuth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Support\Facades\Auth;
use Hesto\MultiAuth\Traits\LogsoutGuard;
use JsValidator;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers, LogsoutGuard {
LogsoutGuard::logout insteadof AuthenticatesUsers;
}
protected $validationRules = [
'email' => 'required|email',
'password' => 'required'
];
/**
* Where to redirect users after login / registration.
*
* #var string
*/
// public $redirectTo = '/user/home';
public $redirectTo = '/user/dashboard-graph';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest:agencie', ['except' => 'logout']);
// $this->middleware('guest:agency')->except('logout');
}
public function username()
{
return 'agency_email';
}
/**
* Show the application's login form.
*
* #return \Illuminate\Http\Response
*/
public function showLoginForm()
{
$validator = JsValidator::make($this->validationRules,[],[],'#loginform');
return view('agency.auth.login')->with('validator', $validator);
}
/**
* Get the guard to be used during authentication.
*
* #return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard()
{
return Auth::guard('agencie');
}
/**
* Get the needed authorization credentials from the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
}
I have added following codes to app/Expecations/Handler.php
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated.'], 401);
}
$middleware = request()->route()->gatherMiddleware();
$guard = config('auth.defaults.guard');
foreach($middleware as $m) {
if(preg_match("/auth:/",$m)) {
list($mid, $guard) = explode(":",$m);
}
}
switch($guard) {
case 'agencie':
$login = 'agency/login';
break;
default:
$login = 'user/login';
break;
}
return redirect()->guest($login);
}
I have also added additonal 2 files in middleware named RedirectifAgency.php & Redirectifnotagency.php
Following is the code
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAgency
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = 'agencie')
{
if (Auth::guard($guard)->check()) {
return redirect('agency/home');
}
return $next($request);
}
}
What is the problem here.Please help

I want to select my balance "column" From user table laravel

I'm a beginner in laravel framework,I am in the course of developing an API,and I want to select from users table balance of user when I get her Id in api So I do what I found in documentations in my contoller and i use postman to test my work but always I get a error
this is my controller:
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
class MyBalanceController extends Controller
{
public function index(Request $request)
{
# code...
// $Ads = ads::all();
// return $this->sendResponse($Ads->toArray(), 'Ads read succesfully');
// This is the name of the column you wish to search
$input = $request->all();
$validator = Validator::make($input, [
'user_id'=> 'required'
] );
$Cards = User::where('user_id','=', $request->user_id)->pluck('balance')->toArray();
//$user = Auth::user();
// $Cards = DB::select('select balance from users where id = :id', ['id' => 1]);
return response()->json(['Cards'=>$Cards]);
}
}
this is my modal :
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements JWTSubject
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password','username','lastname','tel','adress','balance'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* #return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* #return array
*/
public function getJWTCustomClaims()
{
return [];
}
}
At first you can go to your .env file and set APP_DEBUG to true so you can see your exceptions when developing your app.
Regarding your problem try
$balance = User::findOrFail($request->user_id)->balance;
return response()->json($balance);
If no user was found with that id then a 404 HTTP error will be thrown

Categories