Authentication

Overview

Yabasi framework provides flexible authentication mechanisms that support both session-based and token-based authentication. The authentication system is designed to be secure, scalable, and easy to implement while following modern security practices.

Secure by Default

Built-in protection against common vulnerabilities including CSRF, XSS, and session hijacking.

Flexible Integration

Supports multiple authentication guards and custom authentication providers.

Performance Optimized

Efficient session handling and caching mechanisms for optimal performance.

Session vs Token Authentication

Session-based Authentication

  • Maintains user state on the server using PHP sessions
  • Ideal for traditional web applications
  • Built-in CSRF protection
  • Automatic session security features

Session-based authentication is enabled by default in web routes.

Token-based Authentication

  • Stateless authentication using JWT or API tokens
  • Perfect for APIs and mobile applications
  • Scalable across multiple servers
  • Support for token expiration and refresh

Token authentication is automatically enabled for API routes.

Authentication Flow

  1. User Credentials Submission

    Application receives login credentials via form submission or API request.

  2. Validation

    Credentials are validated against security rules and database records.

  3. Authentication Process

    Yabasi verifies credentials and creates appropriate authentication session or token.

  4. Session/Token Management

    Framework maintains authentication state and handles session/token lifecycle.

Security Considerations

Common Vulnerabilities

  • Session fixation
  • Cross-site scripting (XSS)
  • CSRF attacks
  • Man-in-the-middle attacks

Built-in Protections

  • Automatic CSRF token validation
  • Secure session handling
  • Password hashing
  • SSL/TLS support

Configuration

Yabasi's authentication system requires minimal configuration to get started. The main components include the auth configuration file, user model setup, and database structure.

Auth Config Structure

Authentication configuration is defined in your config/config.php file under the auth key:

config/config.php
return [
    'auth' => [
        'model' => Yabasi\Models\User::class,
        'table' => 'users',
        'username_field' => 'email',
        'password_field' => 'password',
        'session_lifetime' => 120, // minutes
        'token_lifetime' => 60, // minutes
        'password_timeout' => 10800 // seconds
    ],
];
Option Description Default
model The user model class Yabasi\Models\User::class
table Database table for users users
username_field Field used for authentication email

User Model Setup

Your User model should extend the base Model class and implement the AuthenticatableInterface:

app/Models/User.php
namespace App\Models;

use Yabasi\Database\Model;
use Yabasi\Auth\AuthenticatableInterface;

class User extends Model implements AuthenticatableInterface
{
    protected static string $table = 'users';

    protected array $fillable = [
        'name',
        'email',
        'password',
    ];

    protected array $hidden = [
        'password',
        'remember_token',
    ];
}

Required Methods

  • getAuthIdentifier() - Returns the unique identifier for authentication
  • getAuthPassword() - Returns the hashed password field
  • getRememberToken() - Returns the remember me token

Database Requirements

Your users table must include these minimum required fields:

database/migrations/create_users_table.php
public function up(): void
{
    Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('email')->unique();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
}

Make sure to always hash passwords before storing them in the database. Yabasi provides built-in methods for secure password hashing.

Basic Usage

Learn how to implement common authentication operations in Yabasi. This section covers all the basic functionality you'll need for a secure authentication system.

User Registration

To register a new user, you'll need to validate the input data and create a new user record:

app/Controllers/AuthController.php
use Yabasi\Http\Request;
use Yabasi\Models\User;
use Yabasi\Auth\Auth;

class AuthController extends Controller
{
    public function register(Request $request)
    {
        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users',
            'password' => 'required|min:8'
        ]);

        $user = User::create([
            'name' => $validated['name'],
            'email' => $validated['email'],
            'password' => Auth::hash($validated['password'])
        ]);

        Auth::login($user);
        
        return $this->response->redirect('/dashboard');
    }
}

Registration Form Example

<form method="POST" action="/register">
    {{ csrf_field() }}
    
    <div class="mb-4">
        <label for="name">Name</label>
        <input type="text" name="name" id="name" required>
    </div>
    
    <div class="mb-4">
        <label for="email">Email</label>
        <input type="email" name="email" id="email" required>
    </div>
    
    <div class="mb-4">
        <label for="password">Password</label>
        <input type="password" name="password" id="password" required>
    </div>
    
    <button type="submit">Register</button>
</form>

Login Implementation

Implement user login with email/password credentials:

AuthController.php
public function login(Request $request)
{
    $credentials = $request->validate([
        'email' => 'required|email',
        'password' => 'required'
    ]);

    if (Auth::attempt($credentials)) {
        $request->session()->regenerate();
        return $this->response->redirect('/dashboard');
    }

    return $this->response->back()->with('error', 'Invalid credentials');
}

Available Login Methods

  • Auth::attempt($credentials) - Attempt to authenticate a user
  • Auth::login($user) - Log in a user instance
  • Auth::loginById($id) - Log in a user by ID

Logout Process

Implementing logout functionality:

AuthController.php
public function logout(Request $request)
{
    Auth::logout();
    
    $request->session()->invalidate();
    $request->session()->regenerateToken();
    
    return $this->response->redirect('/login');
}

Password Management

AuthController.php
    // Hash a password
    $hashedPassword = Auth::hash($password);
    
    // Verify a password
    if (Auth::verify($password, $user->password)) {
        // Password is correct
    }

Password Reset

AuthController.php
    // Generate password reset token
    $token = Auth::createPasswordResetToken($user);
    
    // Reset password
    Auth::resetPassword($token, $newPassword);

Session Handling

AuthController.php
    // Generate password reset token
    $token = Auth::createPasswordResetToken($user);
    
    // Reset password
    Auth::resetPassword($token, $newPassword);

Yabasi automatically handles session security including CSRF protection, session fixation prevention, and secure cookie settings.

Authentication Best Practices

  • Always validate user input before processing
  • Regenerate session ID after login and logout
  • Use HTTPS in production environments
  • Implement rate limiting for login attempts

Guards

Guards in Yabasi determine how users are authenticated for each request. Multiple guards can be used to provide different types of authentication for different parts of your application.

Available Guards

Session Guard

Default guard for web applications using PHP sessions.

 // Using session guard
 Auth::guard('web')->attempt($credentials);

Token Guard

For API authentication using tokens.

// Using token guard
Auth::guard('api')->authenticate($token);
config/config.php
'auth' => [
    'defaults' => [
        'guard' => 'web',
    ],
    
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        
        'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'lifetime' => 60, // minutes
        ],
    ],
]

Custom Guard Implementation

Create a custom guard by implementing the GuardInterface:

app/Auth/CustomGuard.php
namespace App\Auth;

use Yabasi\Auth\Guards\GuardInterface;

class CustomGuard implements GuardInterface
{
    protected $user;

    public function check(): bool
    {
        return $this->user !== null;
    }

    public function user()
    {
        return $this->user;
    }

    public function validate(array $credentials = []): bool
    {
        // Custom validation logic
    }

    public function setUser($user): void
    {
        $this->user = $user;
    }
}

Register Custom Guard

ServiceProvider.php
// In your service provider
use Yabasi\Auth\Auth;

public function boot()
{
    Auth::extend('custom', function ($app, $name, array $config) {
        return new CustomGuard($app['request']);
    });
}

Multiple Authentication

Using Multiple Guards

 // Check authentication with specific guard
 if (Auth::guard('api')->check()) {
    // User is authenticated with API guard
 }
 
 // Get user from specific guard
 $user = Auth::guard('web')->user();
 
 // Attempt authentication with specific guard
 Auth::guard('web')->attempt($credentials);

Note that each guard maintains its own authentication state. A user authenticated with one guard may not be authenticated with another.

routes/web.php
// Routes with different guards
$router->group(['guard' => 'web'], function ($router) {
    $router->get('/dashboard', 'DashboardController@index');
});

$router->group(['guard' => 'api'], function ($router) {
    $router->get('/api/user', 'ApiController@user');
});

Guard-Specific Middleware

 // Protect routes with specific guard
 $router->middleware(['auth:api'])->group(function ($router) {
    // Routes protected by API guard
 });
 
 $router->middleware(['auth:web'])->group(function ($router) {
    // Routes protected by web guard
 });

Guard Best Practices

  • Use the appropriate guard for your authentication context
  • Implement proper error handling for guard failures
  • Consider rate limiting for token-based authentication
  • Keep guard configurations secure and environment-specific

Middleware

Authentication middleware in Yabasi provides a secure way to protect your routes and ensure users are properly authenticated before accessing specific parts of your application.

Auth Middleware Usage

Basic Usage

routes/web.php
// Single Route Protection
$router->get('/dashboard', 'DashboardController@index')
    ->middleware('auth');

// Group Route Protection
$router->group(['middleware' => ['auth']], function($router) {
    $router->get('/profile', 'ProfileController@show');
    $router->post('/settings', 'SettingsController@update');
});

Guard Specific Middleware

// Specify guard for routes
$router->middleware('auth:api')->group(function($router) {
    $router->get('/api/user', 'ApiController@user');
});

// Multiple guards
$router->middleware('auth:web,api')->group(function($router) {
    $router->get('/shared', 'SharedController@index');
});

Middleware Configuration

config/middleware.php
return [
    'global' => [
        \Yabasi\Middleware\StartSession::class,
    ],
    
    'route' => [
        'auth' => \Yabasi\Middleware\Authenticate::class,
        'guest' => \Yabasi\Middleware\RedirectIfAuthenticated::class,
    ],
];

Custom Middleware

Create custom authentication middleware by implementing the MiddlewareInterface:

app/Middleware/CustomAuthMiddleware.php
namespace App\Middleware;

use Yabasi\Middleware\MiddlewareInterface;
use Yabasi\Http\Request;
use Yabasi\Http\Response;

class CustomAuthMiddleware implements MiddlewareInterface
{
    public function handle(Request $request, Closure $next): Response
    {
        if (!Auth::check()) {
            // Custom authentication logic
            if ($this->hasCustomToken($request)) {
                // Validate custom token
                return $next($request);
            }
            
            return new Response('Unauthorized', 401);
        }

        return $next($request);
    }

    protected function hasCustomToken(Request $request): bool
    {
        // Implement custom token validation
        return false;
    }
}

Register Custom Middleware

 // In your service provider
 public function boot()
 {
    $this->app['middleware']->register('custom.auth', CustomAuthMiddleware::class);
 }
 
 // Usage in routes
 $router->middleware('custom.auth')->group(function($router) {
    // Protected routes
 });

Route Protection

Web Routes

 // Protect web routes
 $router->middleware(['web', 'auth'])->group(function($router) {
    $router->get('/account', 'AccountController@show');
    $router->post('/settings', 'SettingsController@update');
 });

API Routes

 // Protect API routes
 $router->middleware(['api', 'auth:api'])->group(function($router) {
    $router->get('/api/user', 'ApiController@user');
    $router->post('/api/logout', 'ApiController@logout');
 });

Advanced Protection

 // Combining multiple middleware
 $router->middleware(['auth', 'verified', 'throttle:60,1'])
    ->group(function($router) {
        $router->post('/sensitive-action', 'SensitiveController@handle');
    });
 
 // Role-based protection
 $router->middleware(['auth', 'role:admin'])
    ->group(function($router) {
        $router->get('/admin', 'AdminController@dashboard');
    });
Security Best Practices
  • • Always protect sensitive routes with appropriate middleware
  • • Combine authentication with rate limiting for enhanced security
  • • Use role-based middleware for granular access control
  • • Implement proper error handling for unauthorized access

Middleware Quick Reference

Built-in Middleware
  • 'auth' - Basic authentication
  • 'auth:api' - API authentication
  • 'guest' - Redirect if authenticated
Common Usage
  • Route protection
  • Group middleware
  • Guard-specific auth

Examples

Practical examples of implementing authentication features in Yabasi Framework. These examples demonstrate real-world usage scenarios using the framework's built-in capabilities.

Complete Registration Flow

Registration Controller

app/Middleware/CustomAuthMiddleware.php
namespace App\Middleware;

use Yabasi\Middleware\MiddlewareInterface;
use Yabasi\Http\Request;
use Yabasi\Http\Response;

class CustomAuthMiddleware implements MiddlewareInterface
{
    public function handle(Request $request, Closure $next): Response
    {
        if (!Auth::check()) {
            // Custom authentication logic
            if ($this->hasCustomToken($request)) {
                // Validate custom token
                return $next($request);
            }
            
            return new Response('Unauthorized', 401);
        }

        return $next($request);
    }

    protected function hasCustomToken(Request $request): bool
    {
        // Implement custom token validation
        return false;
    }
}

Registration Form Template

<!-- register.twig -->
{% raw %}
<form method="POST" action="{{ url('register') }}" class="space-y-4">
    {{ csrf_field() }}

    <div>
        <label for="name">Name</label>
        <input type="text" name="name" value="{{ old('name') }}"
                class="form-input" required>
        {% if errors.name %}
            <span class="text-red-500">{{ errors.name[0] }}</span>
        {% endif %}
    </div>

    <div>
        <label for="email">Email</label>
        <input type="email" name="email" value="{{ old('email') }}"
                class="form-input" required>
        {% if errors.email %}
            <span class="text-red-500">{{ errors.email[0] }}</span>
        {% endif %}
    </div>

    <button type="submit">Register</button>
</form>
{% endraw %}
    

Password Reset Flow

PasswordResetController.php
class PasswordResetController extends Controller
{
    public function request(Request $request): Response
    {
        $validated = $request->validate([
            'email' => 'required|email'
        ]);

        $user = User::where('email', $validated['email'])->first();
        
        if ($user) {
            $token = Auth::createPasswordResetToken($user);
            // Send password reset email with token
        }

        return $this->response->back()
            ->with('message', 'Password reset instructions sent');
    }

    public function reset(Request $request): Response
    {
        $validated = $request->validate([
            'token' => 'required',
            'password' => 'required|min:8|confirmed'
        ]);

        if (Auth::resetPassword($validated['token'], $validated['password'])) {
            return $this->response->redirect('/login')
                ->with('message', 'Password reset successful');
        }

        return $this->response->back()
            ->with('error', 'Invalid token');
    }
}

Remember Me Implementation

AuthController.php
public function login(Request $request): Response
{
    $credentials = $request->validate([
        'email' => 'required|email',
        'password' => 'required',
        'remember' => 'boolean'
    ]);

    if (Auth::attempt($credentials, $credentials['remember'] ?? false)) {
        $request->session()->regenerate();
        return $this->response->redirect('/dashboard');
    }

    return $this->response->back()
        ->with('error', 'Invalid credentials');
}

Login Form with Remember Me

<!-- login.twig -->
{% raw %}
<form method="POST" action="{{ url('login') }}">
    {{ csrf_field() }}

    <div class="mb-4">
        <label for="email">Email</label>
        <input type="email" name="email" required>
    </div>

    <div class="mb-4">
        <label for="password">Password</label>
        <input type="password" name="password" required>
    </div>

    <div class="mb-4">
        <label>
            <input type="checkbox" name="remember">
            Remember me
        </label>
    </div>

    <button type="submit">Login</button>
</form>
{% endraw %}
Important Notes
  • • Always validate user input
  • • Use CSRF protection for forms
  • • Implement proper error handling
  • • Consider rate limiting for authentication attempts

Best Practices

Follow these recommended practices to ensure secure, efficient, and maintainable authentication implementation in your Yabasi application.

Security Guidelines

Password Security

  • Always use Auth::hash() for password hashing
  • Enforce minimum password length (8+ characters)
  • Never store plain-text passwords

Session Security

  • Regenerate session IDs after login
  • Use secure session settings
  • Implement session timeout
Secure Authentication Example
// Good Practice
public function login(Request $request): Response
{
    $credentials = $request->validate([
        'email' => 'required|email',
        'password' => 'required'
    ]);

    if (Auth::attempt($credentials)) {
        $request->session()->regenerate();
        return $this->response->redirect('/dashboard');
    }

    // Rate limiting after failed attempts
    Auth::incrementLoginAttempts($request);
    
    return $this->response->back()
        ->with('error', 'Invalid credentials');
}

Performance Tips

Database Optimization

  • Index authentication columns
  • Use efficient queries

Caching Strategy

  • Cache user permissions
  • Use session storage efficiently
Optimized Database and Caching Example
// Efficient database query
public function findByEmail(string $email): ?User
{
    return User::where('email', $email)
        ->select(['id', 'email', 'password'])
        ->first();
}

// Caching user data
public function getUserPermissions(User $user): array
{
    return Cache::remember("user.{$user->id}.permissions", 3600, function() use ($user) {
        return $user->getPermissions();
    });
}

Common Pitfalls

What to Avoid

  • Storing sensitive data in sessions
  • Skipping input validation
  • Hardcoding credentials

Best Solutions

  • Use environment variables for sensitive data
  • Implement proper validation middleware
  • Follow secure coding practices
Common Anti-Patterns to Avoid
Below are examples of code practices to avoid. Proper methods for handling sensitive operations are also provided.
// Bad Practice - Don't do this
if ($_POST['password'] === 'admin123') {
    $_SESSION['is_admin'] = true;
}

// Instead, use proper authentication
if (Auth::attempt($credentials)) {
    $request->session()->regenerate();
}

Quick Reference Checklist

Security
  • Use HTTPS
  • Implement CSRF protection
  • Hash passwords
Performance
  • Cache when possible
  • Optimize queries
  • Use proper indexes
Maintenance
  • Follow naming conventions
  • Document implementations
  • Use configuration files

Find the documentation helpful?

Show your support by starring our project on GitHub

Star on GitHub