Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Psrcas Laravel Package

drupol/psrcas

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to First Use

  1. Installation:

    composer require drupol/psrcas
    php artisan vendor:publish --provider="Drupol\Psrcas\PsrcasServiceProvider"
    

    This publishes the default config to config/psrcas.php.

  2. Configure CAS Server: Update config/psrcas.php with your CAS server details:

    'server_url' => 'https://your-cas-server.example.com/cas',
    'service_url' => 'https://your-app.example.com/cas/callback',
    'validation_endpoint' => '/validate',
    'login_endpoint' => '/login',
    
  3. Register Service Provider: Add the provider to config/app.php under providers:

    Drupol\Psrcas\PsrcasServiceProvider::class,
    
  4. First CAS Validation: Use the CASClient in a controller or command:

    use Drupol\Psrcas\CASClient;
    use Illuminate\Support\Facades\Http;
    
    public function validateTicket(Request $request, CASClient $casClient)
    {
        $ticket = $request->input('ticket');
        $response = $casClient->validateTicket($ticket);
    
        if ($response->isSuccess()) {
            $user = $this->createOrUpdateUser($response->getAttributes());
            auth()->login($user);
            return redirect()->intended('/dashboard');
        }
    
        return redirect()->route('cas.login')->with('error', 'Invalid ticket');
    }
    
  5. Create a Login Route: Add a route to initiate CAS login:

    Route::get('/cas/login', function () {
        return redirect()->away(config('psrcas.server_url') . config('psrcas.login_endpoint') .
            '?service=' . urlencode(config('psrcas.service_url')));
    })->name('cas.login');
    
  6. Handle Callback: Add a callback route to process the CAS response:

    Route::get('/cas/callback', [CasController::class, 'validateTicket']);
    

Implementation Patterns

Core Workflows

1. CAS Authentication Flow

  • Initiate Login: Redirect users to the CAS server using the login_endpoint.
    $casUrl = config('psrcas.server_url') . config('psrcas.login_endpoint') .
        '?service=' . urlencode(config('psrcas.service_url'));
    return redirect()->away($casUrl);
    
  • Validate Ticket: After CAS redirects back to your service_url, validate the ticket using CASClient::validateTicket().
    $response = $casClient->validateTicket($request->ticket);
    if ($response->isSuccess()) {
        $attributes = $response->getAttributes();
        // Map attributes to Laravel user and login
    }
    
  • User Mapping: Use CAS attributes (e.g., uid, email) to create/update a Laravel user.
    $user = User::firstOrCreate(
        ['email' => $attributes['email']],
        ['name' => $attributes['cn'] ?? $attributes['uid']]
    );
    auth()->login($user);
    

2. Middleware for Protected Routes

Create middleware to enforce CAS authentication:

namespace App\Http\Middleware;

use Closure;
use Drupol\Psrcas\CASClient;
use Illuminate\Http\Request;

class EnsureCASAuth
{
    public function __construct(protected CASClient $casClient) {}

    public function handle(Request $request, Closure $next)
    {
        if (!$request->has('ticket')) {
            return redirect()->route('cas.login');
        }

        $response = $this->casClient->validateTicket($request->ticket);
        if (!$response->isSuccess()) {
            return redirect()->route('cas.login')->with('error', 'Invalid ticket');
        }

        return $next($request);
    }
}

Register the middleware in app/Http/Kernel.php:

protected $routeMiddleware = [
    'cas.auth' => \App\Http\Middleware\EnsureCASAuth::class,
];

Use it on routes:

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

3. Attribute Handling

CAS servers return user attributes as key-value pairs. Map these to Laravel users:

public function handleCasAttributes(array $attributes)
{
    return [
        'email' => $attributes['email'] ?? $attributes['mail'] ?? null,
        'name' => $attributes['cn'] ?? $attributes['uid'] ?? null,
        'institution' => $attributes['institution'] ?? null,
    ];
}

Use this in your validation logic:

$userData = $this->handleCasAttributes($response->getAttributes());
$user = User::updateOrCreate(
    ['email' => $userData['email']],
    $userData
);

4. Session Integration

Store CAS-specific data in the session (e.g., ticket, attributes) for later use:

$request->session()->put('cas.attributes', $response->getAttributes());
$request->session()->put('cas.ticket', $request->ticket);

Retrieve later in middleware or controllers:

$attributes = $request->session()->get('cas.attributes');

5. Logging and Debugging

Use Laravel’s logging to track CAS events:

\Log::info('CAS validation started', [
    'ticket' => $ticket,
    'server' => config('psrcas.server_url'),
]);

try {
    $response = $casClient->validateTicket($ticket);
    \Log::debug('CAS response', ['success' => $response->isSuccess()]);
} catch (\Exception $e) {
    \Log::error('CAS validation failed', ['error' => $e->getMessage()]);
}

Integration Tips

Laravel-Specific Patterns

  1. Service Container Binding: Bind the CASClient to Laravel’s container for dependency injection:

    $this->app->singleton(CASClient::class, function ($app) {
        return new CASClient(
            $app['config']['psrcas.server_url'],
            $app['config']['psrcas.service_url']
        );
    });
    
  2. Custom Facade: Create a facade for cleaner syntax:

    namespace App\Facades;
    
    use Illuminate\Support\Facades\Facade;
    
    class Psrcas extends Facade
    {
        protected static function getFacadeAccessor()
        {
            return 'cas.client';
        }
    }
    

    Register the facade in config/app.php:

    'aliases' => [
        'Psrcas' => App\Facades\Psrcas::class,
    ],
    

    Bind the client in a service provider:

    $this->app->bind('cas.client', function ($app) {
        return new CASClient(
            $app['config']['psrcas.server_url'],
            $app['config']['psrcas.service_url']
        );
    });
    

    Now use Psrcas::validateTicket($ticket) in your code.

  3. Events for CAS Flow: Dispatch events for key CAS actions (e.g., login, validation failure):

    event(new \App\Events\CasLoginAttempt($ticket, $response->isSuccess()));
    

    Listen to events in EventServiceProvider:

    protected $listen = [
        \App\Events\CasLoginAttempt::class => [
            \App\Listeners\LogCasAttempt::class,
        ],
    ];
    
  4. Testing with Laravel Dusk/Pest: Test CAS flows using Laravel’s testing tools. Example with Pest:

    public function test_cas_login_flow()
    {
        $this->get('/cas/login')
             ->assertRedirect(config('psrcas.server_url') . config('psrcas.login_endpoint'));
    
        // Mock CAS response and test callback
        $this->actingAs(User::factory()->create())
             ->get('/cas/callback?ticket=ST-123-ABC')
             ->assertRedirect('/dashboard');
    }
    
  5. Caching Validated Tickets: Cache ticket validation results to reduce CAS server load:

    public function validateTicket(string $ticket)
    {
        $cacheKey = "cas.ticket.{$ticket}";
        if (Cache::has($cacheKey)) {
            return Cache::get($cacheKey);
        }
    
        $response = $this->casClient->validateTicket($ticket);
        Cache::put($cacheKey, $response, now()->addMinutes(10));
        return $response;
    }
    

Gotchas and Tips

Pitfalls

  1. Ticket Validation Timeouts:
    • CAS servers may timeout if validation takes too long. Ensure your validateTicket calls are efficient and avoid blocking operations (e.g., database queries during validation).
    • **Fix
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
andydefer/laravel-actions
aimeos/prisma
besmartand-pro/php-quality-config
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor