Transitioning to bcrypt password while allowing legacy password hashing

Submitted by madshadow - 10 years ago

I have a legacy system that uses SHA1 for passwords as opposed to bcrypt, which is used by Laravel. For now, I need people to be able to access through both systems. I use the auth.attempt event to handle password conversion.

/*
create a migration to add a column to your user table for bcrypted password
*/

Schema::table('users', function(Blueprint $table)
    	{
			$table->string('bcryptpassword');
			
		});
        
/*
Alter User model to look for bcryptedpassword as the user password
*/

    /**
     * Get the password for the user.
	 *
	 * @return string
	 */
	public function getAuthPassword()
	{
		return $this->bcryptpassword;
	}
    
    
/*
create an event listener for auth.attempt event that will authenticate against
old password and add in brcypted password.  Because this event fires before the
actual login attempt, you don't need to mess with Laravel's hashing algorithym.
*/

Event::listen('auth.attempt', function($credentials)
    {
        //find the user. Should deal with situation where user
        //doesn't exist
		$user = User::where('username','=',$credentials['username'])->first();
		

        //if bycryptpassword is null, need to convert
		if (is_null($user->bcryptpassword));
		{
                
            //authenticate using sha1 on the legacy password
            if ($user->password == sha1($credentials['password']))
            {
                //save the bcryptpassword
			    $user->bcryptpassword = Hash::make($password);
				$user->save();
			}
			
	    }  
	});
    
/*
After the event fires and updates bcryptpassword, if necessary, Laravel's 
Auth::attempt() will work normally. The legacy system can continue sha1() 
against password field.  Once all the users have logged in 
(or most have and you reset the remaining users) and you no longer need the
legacy system, you can change the getAuthPassword() in the User model back to 
using the password field.
*/