soeverse / laravel-cas
Native CAS Authentication package for Laravel.
Requires
- php: ^8.0
- illuminate/http: ^9.0|^10.0|^11.0|^12.0|^13.0
- illuminate/support: ^9.0|^10.0|^11.0|^12.0|^13.0
Requires (Dev)
- orchestra/testbench: ^7.0|^8.0|^9.0|^10.0|^11.0
- phpunit/phpunit: ^9.6|^10.5|^11.0|^12.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
A lightweight native CAS authentication package for Laravel with no dependency on outdated packages.
Supports Laravel 9 through 13 and PHP 8.0 or later.
Installation
Install this package in your Laravel application using Composer:
composer require soeverse/laravel-cas
Configuration
Publish the configuration file so you can customize the package settings:
php artisan vendor:publish --tag="cas-config"
The command above copies the configuration file to config/cas.php. Add the following environment variables to your .env file:
CAS_BASE_URL=https://sso.example.com/cas CAS_VERSION=2.0 CAS_LOGOUT_URL=https://sso.example.com/cas/logout CAS_SSL_VERIFY=true CAS_TIMEOUT=10 CAS_CONNECT_TIMEOUT=3
CAS_HOSTNAME remains supported for existing installations, but CAS_BASE_URL is recommended for new installations.
Usage
To use this package effectively, it helps to understand the CAS authentication flow:
CAS Authentication Flow
- Access the local login endpoint: The user visits your application login URL, such as
/sso/login. - Redirect to the CAS server:
CasServicechecks for the?ticket=query parameter. If it is missing,CasServiceredirects the user to the central CAS login page. - Authenticate with SSO: The user enters their username and password on the SSO page. After successful authentication, the CAS server redirects the user back to your application login URL with a Service Ticket, such as
/sso/login?ticket=ST-12345.... - Validate the ticket: Your application detects the
?ticket=parameter. The controller usesCasServiceto validate the ticket with a server-to-server HTTP request to the CAS server. - Create the local session: If the ticket is valid, the CAS server returns user data, such as an email address. Your application then matches the email against the local
usersdatabase table and creates a Laravel session usingAuth::login().
The following example implements this flow:
1. Register the Routes
In routes/web.php, define routes for login and logout:
use App\Http\Controllers\AuthController; use Illuminate\Support\Facades\Route; Route::get('/sso/login', [AuthController::class, 'ssoLogin'])->name('sso.login'); Route::post('/sso/logout', [AuthController::class, 'ssoLogout'])->name('sso.logout');
2. Implement the Controller
The following is a complete AuthController.php example using dependency injection:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Soeverse\Cas\CasServiceInterface; use App\Models\User; class AuthController extends Controller { /** * Handle the SSO login flow. */ public function ssoLogin(Request $request, CasServiceInterface $cas) { // 1. Determine the callback URL (this route's URL) $serviceUrl = route('sso.login'); // 2. If there is no ticket, redirect to the CAS server if (!$request->has('ticket')) { return redirect()->away($cas->getLoginUrl($serviceUrl)); } // 3. Validate the ticket with the CAS server $ticket = $request->query('ticket'); $authData = $cas->validateTicket($ticket, $serviceUrl); // 4. Handle ticket validation failure if (!$authData || empty($authData['user'])) { return redirect()->route('login')->with('error', 'Tiket SSO tidak valid atau sudah kedaluwarsa.'); } // 5. Normalize the email or username $email = strtolower(trim($authData['user'])); // 6. Find the user in the local database by email $user = User::where('email', $email)->first(); if (!$user) { return redirect()->route('login')->with('error', "Akun dengan email {$email} tidak ditemukan di sistem lokal."); } // 7. Log the user into the local Laravel session Auth::login($user); // Optional: Store a flag indicating that the user logged in through CAS $request->session()->put('is_native_cas', true); // 8. Redirect to the local dashboard return redirect()->intended('/dashboard'); } /** * Handle the SSO logout flow. */ public function ssoLogout(Request $request, CasServiceInterface $cas) { $isNativeCas = $request->session()->get('is_native_cas', false); // 1. Clear the local Laravel session Auth::logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); // 2. If the user logged in through CAS, redirect to CAS logout if ($isNativeCas) { // Return to the application homepage after CAS logout return redirect()->away($cas->getLogoutUrl(url('/'))); } // 3. For non-SSO users, return directly to the local homepage return redirect('/'); } }
3. Use the Facade (Optional)
If you prefer Laravel-style static calls, you can also use the Cas facade:
use Soeverse\Cas\Facades\Cas; // ... public function checkSsoUrl() { // Cukup panggil method secara statis $loginUrl = Cas::getLoginUrl(route('sso.login')); return $loginUrl; } // ...
API Reference
getLoginUrl(string $serviceUrl): string
Generates the complete URL for redirecting users to the SSO login page.
$serviceUrlis your application callback URL after authentication succeeds. The CAS server redirects to this URL with a?ticket=...parameter.
validateTicket(string $ticket, string $serviceUrl): ?array
Validates a ticket with the CAS server using a server-to-server HTTP request.
- Returns an array containing the
userandattributeskeys when validation succeeds. - Returns
nullwhen validation fails or the ticket format is not recognized.
getLogoutUrl(?string $serviceUrl = null): string
Generates the complete URL for redirecting users to the SSO logout page.
- If
$serviceUrlis provided, the CAS server redirects to that URL after logout (optional).
Testing
Install the development dependencies and run the test suite:
composer install
composer test
License
This package is released under the MIT License.