Awesome Open Source
Awesome Open Source

Twitter Follow

Authentication With Slim 4 (And much, much more)

Slim 4 Authentication Tutorial

Documentation Sections

Installation

Dependencies

  • Vagrant
  • VirtualBox or other available vagrant virtual machine provider
  1. Clone, enter, and determine the path the application
git clone https://github.com/zhorton34/authorize-slim-4.git

cd authorize-slim-4

pwd
  1. Copy output from pwd command (Full path to present working directory)

  2. Open authorize-slim-4/homestead.yaml and update folders map path (Has comment next to it below)

ip: 192.168.10.10
memory: 2048
cpus: 2
provider: virtualbox
authorize: ~/.ssh/id_rsa.pub
keys:
    - ~/.ssh/id_rsa
folders:
    -
       # Replace `map: /Users/zhorton/tutorials/authorize-slim-4`
       # With `map: {the_copied_output_from_pwd_in_step_2}
        map: /Users/zhorton/tutorials/authorize-slim-4
        ## map Update with path you cloned the repository on your machine
        to: /home/vagrant/code
sites:
    -
        map: slim.auth
        to: /home/vagrant/code/public
databases:
    - slim
features:
    -
        mariadb: false
    -
        ohmyzsh: false
    -
        webdriver: false
name: authorize-slim-4
hostname: authorize-slim-4
  1. Save and close homestead.yaml

  2. Run vagrant up --provision to boot up your virtual machine

  3. Once booted, open up your localmachine's host file (sudo vim /etc/hosts on linux or mac)

  4. Add slim.auth

  5. Boot up the vagrant virtual

  vagrant up --provision
  1. Open your localmachines host file (sudo vim /etc/hosts on linux and mac)

  2. Add slim.auth and the ip defined in the homestead.yaml (Example below, shouldn't need to change from example)

##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1	localhost
255.255.255.255	broadcasthost
::1             localhost

###########################
# Homestead Sites (Slim 4)
###########################
192.168.10.10   slim.auth
  1. Close and save hosts file

  2. Test out http://slim.auth/ in your browser (Make sure vagrant has properly finished booting from step 8)

  3. cd back into authorize-slim-4 within your terminal

  4. Run vagrant ssh

  5. Once ssh'd into your virtual machine, run

cd code && cp .env.example .env && composer install && npm install

===

List Slim Console Commands

  1. Run php slim from project root
sole Tool

Usage:
  command [options] [arguments]

Options:
  -h, --help            Display this help message
  -q, --quiet           Do not output any message
  -V, --version         Display this application version
      --ansi            Force ANSI output
      --no-ansi         Disable ANSI output
  -n, --no-interaction  Do not ask any interactive question
  -v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
  help              Displays help for a command
  list              Lists commands
  tinker            
 db
  db:fresh          Drop all database table and re-migrate, then re-seed all tables
  db:migrate        Migration migrations to database
  db:seed           Run Database Seeders
  db:show           Show all of your models/table records in a table for display
 error-logs
  error-logs:clear  Remove Errors Logs Rendered Templates
 make
  make:command      Generate Command Scaffold
  make:controller   description text for console command
  make:factory      Scaffold new factory command
  make:middleware   Generate or make Scaffold for new http middleware class
  make:migration    Make or scaffolded new migration for our database
  make:model        Generate The Scaffold For An Eloquent Model
  make:provider     Scaffold new Service Provider
  make:request      Generate Form Request Validation Scaffold
  make:seeder       Generate a database seeder scaffold
  make:event        Generate event scaffold
  make:listener     Generate listener scaffold
  make:trait        Create a new trait
  make:view         Generate view Scaffold
 migrate
  migrate:rollback  Rollback Previous Database Migration
 view
  view:clear        Remove Cache For View Templates

Migrate and Seed Database

  1. vagrant ssh
  2. cd code
  3. php slim db:migrate
  4. php slim db:seed

Show database table example

  1. vagrant ssh
  2. cd code
  3. php slim db:show users

Register Middleware

  1. Create Middleware Class (Example: \App\Http\Middleware\RouteGuardMiddleware::class)
  2. Open authorize-slim-4/app/Http/HttpKernel
  3. Add \App\Http\Middleware\RouteGuardMiddleware::class to a specific route group or globally
class HttpKernel extends Kernel
{
    /**
     * Global Middleware
     *
     * @var array
     */
    public array $middleware = [
//        Middleware\ExampleAfterMiddleware::class,
//        Middleware\ExampleBeforeMiddleware::class
    ];

    /**
     * Route Group Middleware
     */
    public array $middlewareGroups = [
        'api' => [],
        'web' => [
            Middleware\RouteContextMiddleware::class,
            'csrf'
        ]
    ];
}

Create and Register new php slim command

  1. Add new ExampleCommand.php File and class at app/console/commands/ExampleCommand.php
  2. Define Command name, description, arguments, and handler within class
class ExampleCommand extends Command
{
    protected $name = 'example:command';
    protected $help = 'Example Command For Readme';
    protected $description = 'Example Command For Readme';

    public function arguments()
    {
        return [
            'hello' => $this->required('Description for this required command argument'),
            'world' => $this-optional('Description for this optional command argument', 'default')
        ];
    }

    public function handler()
    {
        /** Collect Console Input **/
        $all_arguments = $this->input->getArguments();
        $optional_argument = $this-input->getArgument('world');
        $required_argument = $this->input->getArgument('hello');

        /** Write Console Output **/
        $this->warning("warning output format");
        $this->info("Success output format");
        $this->comment("Comment output format");
        $this->error("Uh oh output format");
    }
}
  1. Open app\console\ConsoleKernel.php
  2. Add ExampleCommand::class to Registered Commands
<?php

namespace App\Console;

use Boot\Foundation\ConsoleKernel as Kernel;

class ConsoleKernel extends Kernel
{
    public array $commands = [
        Commands\ExampleCommand::class, // Registered example command
        Commands\ViewClearCommand::class,
        Commands\MakeSeederCommand::class,
        Commands\DatabaseRunSeeders::class,
        Commands\DatabaseFreshCommand::class,
        Commands\MakeMigrationCommand::class,
        Commands\DatabaseMigrateCommand::class,
        Commands\DatabaseTableDisplayCommand::class,
        Commands\DatabaseRollbackMigrationCommand::class
    ];
}

php slim make:{command} Scaffold Stub Generators

  1. Available Generator Commands
  php slim make:command {ExampleConsoleCommand}      Generate Command Scaffold
  php slim make:controller {Example} description text for console command
  php slim make:factory {ExampleFactory}      Scaffold new factory command
  php slim make:middleware {ExampleMiddleware} Generate or make Scaffold for new http middleware class
  php slim make:migration {CreateExamplesTable   Make or scaffolded new migration for our database
  php slim make:model {Example}        Generate The Scaffold For An Eloquent Model
  php slim make:provider {ExampleServiceProvider}     Scaffold new Service Provider
  php slim make:request {ExampleFormRequest}     Generate Form Request Validation Scaffold
  php slim make:seeder {ExamplesTableSeeder}       Generate a database seeder scaffold
  1. Scaffold Generator Stubs (Dummy Files)

    • resources/stubs
  2. Scaffold Configuration

    • config/stubs.php

Global Helper Functions

/*

  • event
  • old
  • back
  • session
  • validator
  • asset
  • redirect
  • collect
  • factory
  • env
  • base_path
  • config_path
  • resources_path
  • public_path
  • routes_path
  • storage_path
  • app_path
  • dd (die and dump)
  • throw_when
  • class_basename
  • config
  • data_get
  • data_set */

old($input_name)

  • Used within blade to populate old input data when form validation fails

Example

<form>
  @csrf
  <input type='text' name='first_name' value='{{ old('first_name') }}' />
</form>

back()

  • Redirect user back to previous page

Example

ExampleController 
{
   index()
   {
      return back();
   }
}

event()

  • Set up events and event listeners
event()->listen('flash.success', fn ($message) => session()->flash()->add('success', $message);

event()->fire('flash.success', ['Way to go, it worked!']);

Alternatively, you can use the slim scaffold to set up event and listener classes php slim make:event ExampleEvent

  • creates App/Events/ExampleEvent php slim make:listener ExampleListener
  • create App/Listeners/ExampleListener

Register Class Event & Listeners in config/events.php

return [
   'events' => [
      ExampleEvent::class => [
          ExampleListener::class,
          ExampleListenerTwo::class,
          ExampleListenerThree::class
      ],
      ResetUserPasswordEvent::class => [
          GenerateResetPasswordKey::class,
          SendUserResetPasswordEmail::class,
      ]
   ]
];

Finally trigger the associated event

// Fire event using dependency injection
event()->fire(ExampleEvent::class);

// Fire event overriding default depency injections
event()->fire(ExampleEvent::class, [
   // parameterOne
   // parameterTwo
]);

session()

  • Session (Using Syfony Session Component)

Example

// Flash to session to only remember for the proceeding request
session()->flash()->set('success', ['Successful Form Submission!']);
session()->flash()->set('errors', ['Name field failed', 'Email field failed']);

// Set directly to session to remember for several requests
session()->set('remember_in_session_for_multiple_requests', ['remember me']);

validator($input, $rules = [], $messages = [])

  • Validator (Using Laravel Validators)

Example

$input = [
   'first_name' => 'John',
   'last_name' => 'Joe',
   'email' => '[email protected]'
];

$rules = [
   'first_name' => 'required|string',
   'last_name' => 'required|string|max:50',
   'email' => 'required|email|max:50|unique:users,email'
];

$messages = [
    'first_name.required' => 'First name is a required field',
    'first_name.string' => 'First name must be a string field',
    'last_name.required' => 'Last name must is a required field',
    'last_name.string' => 'Last name must be a string field',
    'email.email' => 'Email must be in the proper email format',
    'email.unique' => 'Email already taken, no duplicate emails allowed',
    'email.required' => 'Email is required',
];

$validation = validator($input, $rules, $messages);

if ($validation->fails()) {
   session()->flash()->set('errors', $validation->errors()->getMessages());
   
   return back();
}

if ($validation->passes() {
   session()->flash()->set('success', 'Successfully Submitted Form and Passed Validation');

   return redirect('/home');
}

Mailables (Send Emails)

  1. @see \Boot\Foundation\Mail\Mailable Example
class ExampleController
{
   public function send(\Boot\Foundation\Mail\Mailable $mail, $response)
   {
       $user = \App\User::first();
       
       $success = $mail->view('mail.auth.reset', ['url' => 'https://google.com'])
            ->to($user->email, $user->first_name)
            ->from('[email protected]', 'Slim Authentication Admin')
            ->subject('Reset Password')
            ->send();

       $response->getBody()->write("Successfully sent Email: {$success}");

       return $response;
   }
}

Events (Events & associated listeners with dependency injection)

Example One

  • Set up events and event listeners using the global event helper function NOTE: (This example show's an easy setup, but example two is considered better architecture)
// App\Providers\EventServiceProvider boot method()

event()->listen('flash.success', fn ($message) => session()->flash()->add('success', $message);

event()->fire('flash.success', [
   'Way to go, it worked!'
]);

Example Two: Event & Listener Classes

  1. php slim make:event UserLogin
  2. Open App/Events/UserLogin.php
  3. Use the UserLogin.php event __construct to build or "construct" the event payload
<?php

namespace App\Events;

use App\Support\Auth;
use Boot\Foundation\Http\Session;

class ExampleEvent
{
    public $user;
    public $session;

    public function __construct(Session $session)
    {
        $this->user = Auth::user();
        $this->session = $session;

        return $this;
    }
}
  1. php slim make:listener FlashWelcomeBackMessage
  2. Open App/Listeners/FlashWelcomeBackMessage
  3. Handle the event payload in the Listener __invoke method
<?php

namespace App\Listeners;

use App\Events\UserLogin;

class FlashWelcomeBackMessage
{
   public function __invoke(UserLogin $event)
   {
      $event->session->flash()->add('success', "Welcome Back {$event->user->first_name}!"); 
   }

}

Register Class Event & Listeners in config/events.php

return [
   'events' => [
      UserLogin::class => [
          FlashWelcomeBackMessage::class,
          // ExampleListenerTwo::class,
          // ExampleListenerThree::class
      ],
      // ResetUserPasswordEvent::class => [
           // GenerateResetPasswordKey::class,
           // SendUserResetPasswordEmail::class,
      // ]
   ]
];

Finally trigger event (Example: App\Http\Controllers\[email protected])

public function login(StoreLoginRequest $input)
{
  if ($input->failed()) return back(); 

  if (Auth::attempt($input->email, $input->password)) 
  {
      event()->fire(\App\Events\UserLogin::class); // Fire Event

      return redirect('/home');
   }

   return back();
}

Event Constructor and Listener Invoke Methods Support Dependency Injection // App\Http\[email protected]

// Example Using UserLogin Event:
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$session = app()->resolve('session');
$different_user = \App\User::find(5); 

event()->fire(UserLogin::class, [
   $session, $different_user
]);

// Example Using Random Event
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
event()->fire(ExampleEvent::class, [
   // parameterOne
   // parameterTwo
]);

// Dependency Injection With While Using event() to register listeners
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
event()->listen('welcome-view', fn (\Jessengers\Blade\Blade $blade) => $blade->make('welcome')->render());

// Fire's event. Listeners will work using the blade instance resolved from our service container
event()->fire('welcome-view');

// inject blade instance with different template path than the one binded to our container
event()->fire('welcome-view', [
    new \Jessengers\Blade\Blade(
        base_path('vendor/package/resources/views'), 
        storage_path('cache'),
    )
]);


Packages & Resources Glossary


Get A Weekly Email With Trending Projects For These Topics
No Spam. Unsubscribe easily at any time.
Javascript (1,541,393
Php (403,016
Vue (83,396
Vuejs (9,749
Authentication (3,858
Dotenv (449
Slim (356
Slim Framework (287
Laravel Mix (196
Related Projects