Code going through laravel basic authentication - laravel

Ok so I'm half way trough my app and I notice that I can pass code into my database. For example I use standard laravel authentication and if I type e.g.<?php die(); ?> instead of first name it passes right trough and goes into database. I'm confused now , I tought that laravel takes care of those things and thats one of the reasons I chose this framework. This is my last resort, I have been searching something in laravel documentation and all over the web about this and I found nothing.
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, [
'role' => ['required', 'string', 'max:100'],
'gendre' => ['required', 'string', 'max:100'],
'firstname' => ['required', 'string', 'max:100'],
'lastname' => ['required', 'string', 'max:100'],
'country' => ['required', 'string', 'max:100'],
'company' => ['required', 'string', 'max:100'],
'phone' => ['required', 'string', 'max:15'],
'email' => ['required', 'string', 'email', 'max:100', '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([
'role' => $data['role'],
'gendre'=>$data['gendre'],
'firstname' => $data['firstname'],
'lastname' => $data['lastname'],
'country' => $data['country'],
'company' => $data['company'],
'phone' => $data['phone'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
}
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 implements MustVerifyEmail
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'firstname', 'lastname' , 'email','password', 'company', 'phone','country','role','gendre'
];
/**
* 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',
];
}
I only did some minor changes to what laravel already provides, nothing that special.
And Migration:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('role');
$table->string('gendre');
$table->string('firstname');
$table->string('lastname');
$table->string('country');
$table->string('company');
$table->string('phone');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}

I think there may be a little bit of confusion going on here!
SQL Injection Attacks
The Laravel framework uses things like prepared statements to prevent SQL Injection Attacks. The stops things like
"; DELETE FROM `users`"
being appended to a database query when inserting data provided by form requests.
Escaping Rendered Characters
Trying to render content into a blade template will also be escaped by default unless you explicitly tell it otherswise
# $php_code = "<?php die(); ?>"
{{ $php_code }}
This will render as a a string of "".
# $php_code = "<?php die(); ?>"
{!! $php_code !!}
This will render the php and stop the script from running
TLDR;
The fact the the input is "<?php die(); ?>" is fine provided it is treated as a string. At the end of the day, It's just a string of valid characters

Related

Jetstream unable to delete account after modifying the authentication logic. (Laravel 9,Jetstream, Inertia, VueJs3)

Recently I have decided to add another field when in log in page( Username ), it is unique.
When log in you can use either username or email to do so.
After the modification, "Login", "Registeration", "Changing Password", "Password Reset", "Email Verification" worked fine.
"Two Factor Authentication", "Browser Sessions", "Delete Account" does not working just wondering what has gone wrong
When i try to delete account or log out from all browser session, this pops out
for more detailed error https://flareapp.io/share/17DK4R9P#F73
config/fortify
'username' => 'auth',
'email' => 'email',
Models/User.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use JoelButcher\Socialstream\HasConnectedAccounts;
use JoelButcher\Socialstream\SetsProfilePhotoFromUrl;
use Laravel\Fortify\TwoFactorAuthenticatable;
use Laravel\Jetstream\HasProfilePhoto;
use Laravel\Jetstream\HasTeams;
use Laravel\Sanctum\HasApiTokens;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use App\Models\Post;
class User extends Authenticatable implements MustVerifyEmail
{
use HasApiTokens;
use HasFactory;
use HasProfilePhoto {
getProfilePhotoUrlAttribute as getPhotoUrl;
}
use HasTeams;
use HasConnectedAccounts;
use Notifiable;
use SetsProfilePhotoFromUrl;
use TwoFactorAuthenticatable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'username'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
'two_factor_recovery_codes',
'two_factor_secret',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* The accessors to append to the model's array form.
*
* #var array
*/
protected $appends = [
'profile_photo_url',
];
/**
* Get the URL to the user's profile photo.
*
* #return string
*/
public function getProfilePhotoUrlAttribute()
{
if (filter_var($this->profile_photo_path, FILTER_VALIDATE_URL)) {
return $this->profile_photo_path;
}
}
Users database
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('username')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password')->nullable();
$table->rememberToken();
$table->foreignId('current_team_id')->nullable();
$table->foreignId('current_connected_account_id')->nullable();
$table->foreignId('current_connected_post_id')->nullable();
$table->text('profile_photo_path')->nullable();
$table->timestamps();
});
}
}
}
action/fortify/UpdatesUserProfileInformation.php
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'username' => ['required', 'string', 'max:255', 'alpha_dash:users', Rule::unique('users')->ignore($user->id)],
'email' => ['required', 'email', 'max:255', Rule::unique('users')->ignore($user->id)],
'photo' => ['nullable', 'mimes:jpg,jpeg,png', 'max:10024'],
])->validateWithBag('updateProfileInformation');
action/fortify/CreatesNewUsers.php
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'username' => ['required', 'string', 'max:255', 'unique:users','alpha_dash:users'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => $this->passwordRules(),
'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['required', 'accepted'] : '',
])->validate();
return DB::transaction(function () use ($input) {
return tap(User::create([
'name' => $input['name'],
'email' => $input['email'],
'username' => $input['username'],
'password' => Hash::make($input['password']),
]), function (User $user) {
$this->createTeam($user);
});
});
provides/fortifyserviceprovider.php
Fortify::authenticateUsing(function (LoginRequest $request) {
$user = User::where('email', $request->auth)
->orWhere('username', $request->auth)->first();
if (
$user &&
Hash::check($request->password, $user->password)
) {
return $user;
}
});
provides/jetstreamserviceprovider.php
Fortify::authenticateUsing(function (LoginRequest $request) {
$user = User::where('email', $request->auth)
->orWhere('username', $request->auth)->first();
if (
$user &&
Hash::check($request->password, $user->password)
) {
return $user;
}
});
I have found the solution for all this,
Inside vendor/laravel/fortify/src/Actions/ConfirmPassword.php, there is a function __invoke which Confirm that the given password is valid for the given user.
In default, $username = config('fortify.username'); but my config('fortify.username') is set to auth that why it is not inside the database and return column not found
Is there a way to change this? cuz modifying the vendor is not a good solution.
You can do this in two ways and override the required items in Fortify
app()->singleton(ConfirmPassword::class, MyConfirmPassword::class);
or
// custom hook for confirming passwords
Fortify::confirmPasswordsUsing(function($user, $password) {
// your code!;
});

Laravel Eloquent Many to Many to One relationship

I'm creating a laravel application where the user logins in and can create clients and fill out an applicant form that is linked to the client.
I'm trying to make a relationship with many users that each have many clients, which have one applicant. But I get the following error:
Error
I'm confused with whats wrong and with naming the functions.
ClientContoller:
public function createApplicant(){
$data = request()->validate([
'name' => 'required',
'dob' => 'required',
'age' => 'required',
'gender' => 'required',
'ethnicity' => 'required',
'country' => 'required',
'interpreter' => '',
'language' => 'required',
'homeAddress' => 'required',
'job' => 'required',
'workAddress' => 'required',
'email' => 'required',
'phone' => 'required',
'contact' => 'required',
'extra' => 'required',
]);
auth()->user()->clients()->applicant()->create([
'name'=>$data['name'],
'dob'=>$data['dob'],
'age'=>$data['age'],
'gender'=>$data['gender'],
'ethnicity'=>$data['ethnicity'],
'country'=>$data['country'],
'interpreter'=>$data['interpreter'],
'language'=>$data['language'],
'homeAddress'=>$data['homeAddress'],
'job'=>$data['job'],
'workAddress'=>$data['workAddress'],
'email'=>$data['email'],
'phone'=>$data['phone'],
'contact'=>$data['contact'],
'extra'=>$data['extra'],
]);
dd($data);
}
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;
class User extends Authenticatable
{
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* 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',
];
public function clients(){
return $this->hasMany(Client::class);
}
}
Client Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Client extends Model
{
use HasFactory;
public $timestamps = false;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name',
'email'
];
public function applicant(){
return $this->hasOne(Applicant::class);
}
}
Applicant Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Applicant extends Model
{
use HasFactory;
protected $fillable = [
'fullName',
'date_of_birth',
'age',
'gender',
'ethnicity',
'country',
'interpreter',
'language',
'homeAddress',
'job',
'workAddress',
'email',
'phone',
'contact',
'extra'
];
}
applicants table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class Applicants extends Migration
{
public function up()
{
Schema::create('applicants', function (Blueprint $table) {
$table->id();
$table->string('fullName');
$table->date('date_of_birth');
$table->string('age');
$table->string('gender');
$table->string('ethnicity');
$table->string('country');
$table->boolean('interpreter');
$table->string('language');
$table->string('homeAddress');
$table->string('job');
$table->string('workAddress');
$table->string('email')->unique();
$table->string('phone');
$table->string('contact');
$table->string('extra');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('applicants');
}
}
clients table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class Clients extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('clients', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('clients');
}
}
Any help would be greatly appreciated.
Thank you!
As Maksim mentioned, Laravel is confused which client it should create an applicant for. So, you need to specify it somehow. My suggestion is:
public function createApplicant(Request $request){
$data = request()->validate([
'name' => 'required',
'dob' => 'required',
'age' => 'required',
'gender' => 'required',
'ethnicity' => 'required',
'country' => 'required',
'interpreter' => '',
'language' => 'required',
'homeAddress' => 'required',
'job' => 'required',
'workAddress' => 'required',
'email' => 'required',
'phone' => 'required',
'contact' => 'required',
'extra' => 'required',
]);
$client = Client::find($request->id);
$client->applicant()->create([
'name'=>$data['name'],
'dob'=>$data['dob'],
'age'=>$data['age'],
'gender'=>$data['gender'],
'ethnicity'=>$data['ethnicity'],
'country'=>$data['country'],
'interpreter'=>$data['interpreter'],
'language'=>$data['language'],
'homeAddress'=>$data['homeAddress'],
'job'=>$data['job'],
'workAddress'=>$data['workAddress'],
'email'=>$data['email'],
'phone'=>$data['phone'],
'contact'=>$data['contact'],
'extra'=>$data['extra'],
]);
dd($data);
}
So, you need to form a request before sending data to controller, with an id field, where you specify, which exact client you want to create applicant for.
Alternatively, if you call it like
Route::post('/add_applicant/{id}', 'ClientController#createApplicant');
you could replace Request $request and $request->id with just $id. The main idea is just to pass an id parameter somehow.
However, you still can find a more elegant approach.

Redirecting to previous page after registration in laravel 7

i want to redirect to a previously accessed page right before accessing the registration page after a user has successfully registered themselves. I edited the registration controller as below although i get the following exception View [http:..127.0.0.1:8000.prices] not found. I cross checked my routes and everything is fine. Here is my 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, [
'fname' => ['required', 'string', 'max:255'],
'lname' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'phonenumber' => ['required', 'string', 'min:10', 'max:10'],
'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([
'fname' => $data['fname'],
'lname' => $data['lname'],
'email' => $data['email'],
'phonenumber' => $data['phonenumber'],
'password' => Hash::make($data['password']),
]);
}
/**
* Show the application's registration form.
*
* #return \Illuminate\Http\Response
*/
public function showRegistrationForm()
{
if(session('link')) {
$myPath = session('link');
$registerPath = url('/register');
$previous = url()->previous();
if($previous = $registerPath) {
session(['link' => $myPath]);
}else{
session(['link' => $previous]);
}
}else{
session(['link' => url()->previous()]);
}
return view('auth.register');
}
protected function redirectTo()
{
if(session('link')){
return view(session('link'));
}
return view('/');
}
}
I think the issue is most likely to be with the function:
protected function redirectTo()
{
if(session('link')){
return view(session('link'));
}
return view('/');
}
I tried replacing return view(session('link')); with return url()->previous(); but there was no luck. I am using laravel 7.
The issue was actually with adding view. Instead of return view(session('link')); use return (session('link')); Same applies to the return outside the if statement.
try to use redirect back
return Redirect::back();
do not forget to import redirect in controller
use Redirect;

Auto Login After successful registration in laravel 6 getting an error

I am getting an error while trying to Auto Login After successful registration in laravel 6 getting the following error.
Argument 1 passed to Illuminate\Auth\SessionGuard::login() must implement interface Illuminate\Contracts\Auth\Authenticatable, null given, called in
My Registercontroller is
class RegisterController extends Controller
{
use RegistersUsers;
protected $redirectTo = RouteServiceProvider::HOME;
public function __construct()
{
$this->middleware('guest');
// $this->middleware(['auth','verified']);
}
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'min:3'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
protected function create(array $data)
{
$username = slugify($data['name'])."-".mt_rand(10000, 99999);
$user = User::create([
'name' => $data['name'],
'username' => $username,
'email' => $data['email'],
'password' => Hash::make($data['password']),
'email_token' => base64_encode($data['email']),
]);
Auth::loginUsingId($user->id);
}
}
User Model
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use App\Jobs\SendEmailJob;
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'email','name','password','username','picture',
'ip_address','email_verified_at','email_token','verified'
];
/**
* 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',
];
function socialProviders(){
return $this->hasMany(socialProvider::class);
}
// This is the code define in the sendEmailVerificationNotification
public function sendEmailVerificationNotification()
{
SendEmailJob::dispatch($this);
}
}
You have overwritten the registration logic, but you have ignored the fact that create method needs to return an instance of App\User - or at least a class that implements Authenticatable.
Take a look at the original logic; you will see that the docblock shows that an instance of App\User is being returned and that the original implementation returns the result of the User::create() call.
To get your custom method working, update it like so:
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'username' => slugify($data['name'])."-".mt_rand(10000, 99999);,
'email' => $data['email'],
'password' => Hash::make($data['password']),
'email_token' => base64_encode($data['email']),
]);
}
Laravel will take care of logging the user in by default anyway.

Laravel RegisterController route not found

I'm learning Laravel and I'm trying to use Laravel Passport.
When I try to create a new user I'm getting error 404 not found.
RegisterController.php
app/Http/Controllers/Auth
I also have this path for my api controllers
app/Http/Controllers/Api
Route in api.php
Route::post('/create', 'Auth\RegisterController#create');
RegisterController
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
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 = '/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, [
'username' => ['required', 'string', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:6', 'confirmed'],
]);
// return Validator::make($data, [
// 'name' => ['required', 'string', 'max:255'],
// 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
// 'password' => ['required', 'string', 'min:6', 'confirmed'],
// ]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
return User::create([
'username' => $data['username'],
'password' => Hash::make($data['password']),
]);
}
}
Testing registration with Insomnia
I know I'm not passing any values for registration.
I've tested 127.0.0.1:8000/create¹
I've tested 127.0.0.1:8000/auth/create²
I've tested 127.0.0.1:8000/Auth/create³
I can't see a way to register the user and get the token back. What is wrong? Manual is not clear for begginers.
EDIT 1
Other routes (GET) that you can see in the image are working.
you need to run following artisan command to create auth routes
php artisan make:auth
here is documentation link
https://laravel.com/docs/5.7/authentication#included-routing
Update
for laravel Passport you need to add passport routes like this in AppServiceProvider boot method
Passport::routes();
Read API Authentication documentation carefully everything is there
https://laravel.com/docs/5.7/passport

Resources