mubas/laravel-auth-api

Laravel package for MUBAS One API authentication

Maintainers

Package info

bitbucket.org/poly-mubas/laravel-auth-api

pkg:composer/mubas/laravel-auth-api

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

v2.1.6 2026-02-17 08:11 UTC

README

Overview

A Laravel package that provides seamless integration with the MUBAS One API for LDAP-based authentication. This package replaces custom LDAP implementations with a simple, secure, and standardized approach to authenticate users against an LDAP directory via a central API service.

Features

  • Simple integration with existing Laravel applications
  • Secure LDAP authentication via centralized API
  • Token-based session management with expiration support
  • Automatic user creation on first login
  • Support for multiple authentication modes (local_only, remote_first, fallback)
  • Support for multiple local authentication models in sequence (up to 3 models)
  • Dynamic field mapping (name, slug, expires_at)
  • Schema-aware user synchronization
  • Event-driven architecture for authentication lifecycle
  • Token verification and global logout capabilities
  • Domain restriction validation
  • Comprehensive error handling with specific exception types

Requirements

  • PHP >= 8.2
  • Laravel >=11.0
  • Access to MUBAS One API service

Installation

Install the package via Composer:

composer require mubas/laravel-auth-api

Publish the configuration file:

php artisan vendor:publish --provider="Mubas\AuthApi\AuthApiServiceProvider"--tag="config"

Configuration

After publishing, configure the package by updating config/auth_api.php:

<?php

return [
    // MUBAS One API base URL
    'api_base_url' => env('AUTH_API_BASE_URL', 'https://your-api-domain.com'),
    
    // Application token for API access (provided by MUBAS One API admin)
    'app_token' => env('AUTH_API_APP_TOKEN'),
    
    // Domain restriction (optional)
    // Limits authentication to specific email domains
    'allowed_domain' => env('AUTH_API_ALLOWED_DOMAIN', ''),
    
    // Authentication mode: 'local_only', 'remote_first', 'fallback'
    // 'local_only' - Use local authentication only
    // 'remote_first' - Try MUBAS One first, then fallback to local if remote fails
    // 'fallback' - Try local first, then fallback to MUBAS One if local fails
    'auth_mode' => env('AUTH_API_AUTH_MODE', 'local_only'),
    
    // User model for authentication
    'user_model' => env('AUTH_API_USER_MODEL', '\\App\\Models\\User'),
    
    // Local authentication configuration with multiple models support (max 3 models)
    'local_auth' => [
        'models' => [
            [
                'model' => env('AUTH_API_LOCAL_MODEL_1', '\\App\\Models\\User'),
                'username_field' => env('AUTH_API_USERNAME_FIELD_1', 'email'),
                'password_field' => env('AUTH_API_PASSWORD_FIELD_1', 'password'),
                'password_hashed' => env('AUTH_API_PASSWORD_HASHED_1', true),
            ],
            [
                'model' => env('AUTH_API_LOCAL_MODEL_2', ''),
                'username_field' => env('AUTH_API_USERNAME_FIELD_2', 'username'),
                'password_field' => env('AUTH_API_PASSWORD_FIELD_2', 'password'),
                'password_hashed' => env('AUTH_API_PASSWORD_HASHED_2', true),
            ],
            [
                'model' => env('AUTH_API_LOCAL_MODEL_3', ''),
                'username_field' => env('AUTH_API_USERNAME_FIELD_3', 'email'),
                'password_field' => env('AUTH_API_PASSWORD_FIELD_3', 'password'),
                'password_hashed' => env('AUTH_API_PASSWORD_HASHED_3', true),
            ],
        ],
    ],
];

Add these environment variables to your .env file:

AUTH_API_BASE_URL=https://your-mubas-api.com
AUTH_API_APP_TOKEN=your_application_token_here
AUTH_API_ALLOWED_DOMAIN=
AUTH_API_AUTH_MODE=local_only
AUTH_API_USER_MODEL=\App\Models\User

# Local authentication configuration
AUTH_API_LOCAL_MODEL_1=\App\Models\User
AUTH_API_USERNAME_FIELD_1=email
AUTH_API_PASSWORD_FIELD_1=password
AUTH_API_PASSWORD_HASHED_1=true

# For additional models:
# AUTH_API_LOCAL_MODEL_2=\App\Models\Admin
# AUTH_API_USERNAME_FIELD_2=username
# AUTH_API_PASSWORD_FIELD_2=password
# AUTH_API_PASSWORD_HASHED_2=true
# AUTH_API_LOCAL_MODEL_3=\App\Models\Staff
# AUTH_API_USERNAME_FIELD_3=staff_id
# AUTH_API_PASSWORD_FIELD_3=staff_password
# AUTH_API_PASSWORD_HASHED_3=true

Usage

Basic Authentication

Unified API Login

The package provides a single method for all authentication needs:

use Mubas\AuthApi\Facades\AuthApi;

try {
    $result = AuthApi::apiLogin($identifier, $password);
    
    $user = $result['user'];  // Authenticated user model instance
    $token = $result['token']; // Plain text API token
    $expiresAt = $result['expires_at'] ?? null; // Token expiration timestamp (if supported)
    
    // Additional data from remote API (if authenticated via MUBAS One)
    $userFields = $result['user_fields_from_api'] ?? [];
    
} catch (\Illuminate\Validation\ValidationException $e) {
    // Handle credential validation errors
    $errors = $e->errors();
} catch (\Mubas\AuthApi\Exceptions\DomainRestrictionException $e) {
    // Handle domain restriction errors
} catch (\Mubas\AuthApi\Exceptions\ApiConnectionException $e) {
    // Handle API connection errors
}

Based on the auth_mode configuration, this method will:

  • local_only: Authenticate against local user database (trying models in sequence)
  • remote_first: Try MUBAS One first, fallback to local if remote fails
  • fallback: Try local first (trying models in sequence), fallback to MUBAS One if local fails

Advanced Usage

Multiple Local Authentication Models

Configure multiple models to try in sequence for local authentication:

// In config/auth_api.php
'local_auth' => [
    'models' => [
        [
            'model' => '\App\Models\User',        // Firstmodel to try
            'username_field' => 'email',         // Field to use for username
            'password_field' => 'password',      // Field to use for password
            'password_hashed' => true,           // Whether password is hashed
        ],
        [
            'model' => '\App\Models\Admin',      // Second model to try
            'username_field' => 'username',      // Field to use for username
            'password_field' => 'admin_password', // Different password field
            'password_hashed' => true,           // Whether password is hashed
        ],
    ],
],

The system will attempt authentication with each model in sequence until one succeeds or all fail.

Custom User ModelMapping

By default, the package creates standard Laravel users. You can customize this by implementing a custom user resolver:

// In a service provider
AuthApi::resolveUserUsing(function(array $userData) {
return User::updateOrCreate(
        ['email' => $userData['email']],
        [
            'name' => $userData['name'],
            'last_login' => now(),
            // ... other attributes
        ]
    );
});

Direct API Calls

For direct access to the API endpoints:

// Verify a token
$isValid = AuthApi::verifyToken($userToken);

// Logout from all sessions
$logoutCount = AuthApi::globalLogout($email);

// Set custom user resolver for testing or custom logic
AuthApi::resolveUserUsing(function(array $userData) {
    return User::updateOrCreate(
        ['email' => $userData['email']],
        ['name' => $userData['name']]
    );
});

Middleware

The package provides middleware for protecting routes that require authentication against the API:

// In app/Http/Kernel.php
protected $routeMiddleware = [
    // ... other middleware
    'auth.api' => \Mubas\AuthApi\Http\Middleware\ApiAuthMiddleware::class,
];

Then use it in your routes:

Route::middleware(['auth.api'])->group(function () {
    // Protected routes
});

Events

The package dispatches events during authentication flow:

  • Mubas\AuthApi\Events\UserLoggedIn - When a user successfully logs in
  • Mubas\AuthApi\Events\UserFailedLogin - When a login attempt fails
  • Mubas\AuthApi\Events\UserLoggedOut - Whena user logs out

Listen to these events by registering listeners in your EventServiceProvider:

protected $listen = [
    \Mubas\AuthApi\Events\UserLoggedIn::class => [
        \App\Listeners\LogSuccessfulLogin::class,
    ],
    \Mubas\AuthApi\Events\UserFailedLogin::class => [
        \App\Listeners\LogFailedLogin::class,
    ],
];

Error Handling

The package throws specific exceptions for different error conditions:

  • \Illuminate\Validation\ValidationException: For credential validation errors
  • \Illuminate\Auth\Access\AuthorizationException: For authorization failures
  • \Mubas\AuthApi\Exceptions\ApiConnectionException: For API connectivity issues
  • \Mubas\AuthApi\Exceptions\DomainRestrictionException: When email domain is not allowed

Handle these exceptions appropriately in your application:

try {
    $result = AuthApi::apiLogin($email, $password);
} catch (\Illuminate\Validation\ValidationException $e) {
   // Handle validation errors
    return response()->json(['errors' => $e->errors()], 422);
} catch (\Mubas\AuthApi\Exceptions\ApiConnectionException $e) {
    // Handle API connectionissues
    Log::error('Authentication API connection failed: ' . $e->getMessage());
   return response()->json(['error' => 'Authentication service unavailable'], 503);
}

Testing

The package provides helpers for testing your authentication functionality:

// In your tests
use Mubas\AuthApi\Tests\MocksAuthApi;

class LoginTest extends TestCase
{
    use MocksAuthApi;
    
    public function test_user_can_login_via_api()
    {
        $this->mockAuthApiLogin(['email' => 'test@mubas.ac.mw', 'name' => 'Test User']);
        $response = $this->post('/login', [
            'email' => 'test@mubas.ac.mw',
            'password' => 'password'
        ]);
        
        $response->assertStatus(200);
    }
}