Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

RoffDaniel's avatar

How do I change the password verification algorithm?

Hi, everybody. In my project, I use a different method of password encryption, using salt. Please tell me how you can normally implement password verification with salt? Of course, the salt is stored in a separate column. I tried to enter some of my own options, but I'm more than sure that it will turn out to be a shit code... The logic is simple. When authorizing a user, the user's presence is checked first, and then, if there is one, we get the password and password from the database. We use salt to encrypt the password entered in the input form and check it against the database. If everything is OK, we will authorize it =) Or please tell me where this can be changed

Thank you in advance!

Here is a small piece of code when registering:

$salt = generateSalt($length);
        return User::create([
            'uLogin' => $data['uLogin'],
            'uEmail' => $data['uEmail'],
            'uPassword' => SHA256($salt, $data['uPassword']),
            'uSalt' => $salt,
            'uRegDate' => time(),
            'uLastDate' => time()
        ]);
0 likes
8 replies
rodrigo.pedra's avatar

You can replace the User Provider Laravel authentication system uses.

By default it will use the EloquentUserProvider and hash the password using the bcrypt algorithm (this is the default, you can set a different hash algorithm).

But in your case I would implement a custom user provider as you need to check more than one column for password validation.

Take a read on the docs to learn how custom user providers work and how you can use them:

https://laravel.com/docs/7.x/authentication#adding-custom-user-providers

And take a look in the code for EloquentUserProvider for implementation hints:

https://github.com/laravel/framework/blob/7.x/src/Illuminate/Auth/EloquentUserProvider.php

1 like
RoffDaniel's avatar

@rodrigo.pedra Thank you for the answer, but I am a very bad theorist, I remember well in practice... Besides, I'm new to Laravel, I only started about two weeks ago. Before that, I wrote my engine in MVC, but I was already confused about it myself. I decided to study Laravel. I would not refuse to help =). But if not, then what, I'll figure it out

Of course not for "Thank you"

martinbean's avatar

@roffdaniel You don’t need to salt passwords. Password hashing in Laravel (using Bcrypt) is quite strong already.

1 like
jlrdw's avatar

See the php manual https://www.php.net/manual/en/function.password-hash.php

It's done anyway.

Also read the warning on that page.

Quote

Warning

The salt option has been deprecated as of PHP 7.0.0. It is now preferred to simply use the salt that is generated by default.

unQuote

Just a tip: If custom coding, it doesn't hurt to consult the PHP manual on such matters.

1 like
rodrigo.pedra's avatar
Level 56

Hi @roffdaniel

I wasn't with enough time yesterday, so sorry for the late response.

Recently I had to connect a Laravel project to a legacy database and had some of the issues you describe (custom users table, custom hashing, etc.)

To outline a path for you I first created a new laravel project using a SQLite database, using these commands:

# create from composer
composer create-project --prefer-dist laravel/laravel test
cd test || exit

# tweak .env configuration
sed -i 's/mysql/sqlite/' .env
sed -i 's/DB_DATABASE/# DB_DATABASE/g' .env

# create sqlite database file
touch database/database.sqlite

# require auth scaffolding
composer require laravel/ui
php artisan ui bootstrap --auth

# install frontend dependencies
npm install
npm run dev

The sed commands above only replaces the .env config to use SQLite instead of MySQL. At the end my .env file had these lines regarding the database:

DB_CONNECTION=sqlite
DB_HOST=127.0.0.1
DB_PORT=3306
# DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=

With the project in place I took the following steps:

1. Tweaking the User Model

First I modified the users migration that comes with Laravel to mimic your scheme:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersTable extends Migration
{
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('uLogin')->unique();
            $table->string('uEmail')->unique();
            $table->string('uPassword');
            $table->string('uSalt');

            // timestamps seemed to be saved as integers in your example
            $table->unsignedInteger('uRegDate');
            $table->unsignedInteger('uLastDate');
        });
    }

    public function down()
    {
        Schema::dropIfExists('users');
    }
}

Then I tweaked the User model (located at ./app/User.php) to match the DB scheme:

<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use Notifiable;

    // if using custom table name change this
    protected $table = 'users';

    // tell laravel to use these as timestamps columns
    const CREATED_AT = 'uRegDate';
    const UPDATED_AT = 'uLastDate';

    // tell laravel to save dates unix timestamps
    protected $dateFormat = 'U';

    protected $fillable = [
        'uLogin',
        'uEmail',
        'uPassword',
        'uSalt',
    ];

    protected $hidden = ['uPassword', 'uSalt'];

    // Useful for default auth scaffolding
    public function getAuthPassword()
    {
        return $this->uPassword;
    }

    // Useful for avoiding tweaking default auth scaffolding
    public function getNameAttribute()
    {
        return $this->uLogin;
    }
}

I added some comments above to highlight some the changes.

2. Custom user provider

As I told you in my first answer one approach is to use a Custom User Provider, for reference this is again the docs section about it:

https://laravel.com/docs/7.x/authentication#adding-custom-user-providers

So I created a new User Provider under the project ./app directory:

<?php

namespace App;

use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Support\Arr;

class CustomUserProvider implements UserProvider
{
    public function retrieveById($identifier)
    {
        return User::query()->find($identifier);
    }

    public function retrieveByToken($identifier, $token)
    {
        // not implementing remeber me
        return null;
    }

    public function updateRememberToken(Authenticatable $user, $token)
    {
        // not implementing remeber me
    }

    public function retrieveByCredentials(array $credentials)
    {
        if (Arr::has($credentials, 'email')) {
            return User::query()
                ->where('uEmail', $credentials['email'])
                ->first();
        }

        // allow login user either by email or name
        // default auth scaffolding will use email
        // but you can tweak the login view and LoginController
        // to login by "login" field
        if (Arr::has($credentials, 'login')) {
            return User::query()
                ->where('uLogin', $credentials['login'])
                ->first();
        }

        return null;
    }

    public function validateCredentials(Authenticatable $user, array $credentials)
    {
        $plain = $credentials['password'];

        // use custom hash mechanism
        $hash = \hash('sha256', $user->uSalt . $plain);

        // comparing with hash_equals prevents time-based attacks
        // see php docs about it
        return \hash_equals($user->getAuthPassword(), $hash);
    }
}

Then, per docs instructions, we need to register this User Provider. Let's follow the docs recommendation and change our app's AuthServiceProvider (located at ./app/Providers/AuthServiceProvider.php)

<?php

namespace App\Providers;

use App\CustomUserProvider;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;

class AuthServiceProvider extends ServiceProvider
{
    protected $policies = [
        // 'App\Model' => 'App\Policies\ModelPolicy',
    ];

    public function boot()
    {
        $this->registerPolicies();

        // ADD THIS. 
        // Don't forget to import the Auth Facade and CustomUserProvider
        Auth::provider('custom', function () {
            return new CustomUserProvider();
        });
    }
}

Note that for all changed classes I removed the default comments to minimize space here.

Lastly we need to tell Laravel to use this Custom User Provider for authentication. We can do so by modifying the ./config/auth.php file. I won't paste the whole file here, but should be easy to find the place to change looking at the snippet below:

    'providers' => [
        'users' => [
            'driver' => 'custom', // CHANGE HERE
            // 'model' => App\User::class, // not needed anymore
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

3. Default Auth scaffolding

To test it out I used Laravel default auth scaffolding (see composer require laravel/ui above).

When registering new users we need to tweak the RegisterController (located at ./app/Http/Controllers/Auth/RegisterController.php).

<?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\Validator;

class RegisterController extends Controller
{
    use RegistersUsers;

    protected $redirectTo = RouteServiceProvider::HOME;

    public function __construct()
    {
        $this->middleware('guest');
    }

    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],

            // might need to change the unique:users
            // if using custom users table name
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],

            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);
    }

    protected function create(array $data)
    {
        // added for reference. use your current salt function
        $salt = $this->createSalt(5);

        return User::query()->create([
            'uLogin' => $data['name'],
            'uEmail' => $data['email'],
            'uPassword' => \hash('sha256', $salt . $data['password']),
            'uSalt' => $salt,
        ]);
    }

    // added for reference. use your current salt function
    private function createSalt($length)
    {
        $text = md5(uniqid(rand(), true));
        return substr($text, 0, $length);
    }
}

Note this controller is made available after installing the laravel/ui package listed above and running the php artisan ui bootstrap --auth command (bootstrap can be swapped by vue and react).

If you already have some authentication code in place take a look at the laravel/ui repository to check out how they approach authentication.

https://github.com/laravel/ui

As we are using the Custom User Provider, after we have a user in our database, we won't need to customize the LoginController. Authentication will just work.

4. Migrating and running

Before testing out, we need first to migrate the database, this can be done with this command:

php artisan migrate

Then we can start a webserver to test in the browser, by using this command:

php artisan serve

To test it out, follow this steps:

  • Navigate to http://localhost:8000
  • Click Register on the top right
  • Fill the form and register a new user, the name field will be saved in the login column
  • Click the user's name (login) on the top right
  • Click logout
  • Click Login on the top right
  • Fill the user's credentials and login

You can check the user was created and saved to the Database with your custom scheme, custom timestamps and custom hashing.

Hope it helps!

1 like
RoffDaniel's avatar

@rodrigo.pedra omg... I am in shocked. Give me your paypal, if you have, and any social network please... for further communication, if you don't mind =)

rodrigo.pedra's avatar

You're welcome, glad to help =)

My twitter and github handles are linked on my Laracasts' profile close to my username.

Please or to participate in this conversation.