Weave 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

Raven Bundle Laravel Package

misd/raven-bundle

Symfony bundle that integrates the Raven Sentry client, automatically capturing exceptions and errors and reporting them to Sentry. Provides configurable Symfony service wiring so PHP applications can add Sentry error tracking with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

Read this first: the package does not install into Laravel. misd/raven-bundle is a Symfony 2 bundle. It registers through AppKernel, hooks Symfony's DI container and security.firewall, and implements AuthenticationProviderInterface. There is no service provider, no config/auth.php hook, and Composer will refuse resolution on PHP 8 / Laravel 9+ without --ignore-platform-reqs (never do that for auth code). Also note the package description.md in this repo is stale/wrong — it describes a Sentry/Raven error-tracking integration. The actual bundle is Cambridge Ucam WebAuth (Raven) login. The word "Raven" is doing double duty; confirm which one you actually need before spending a day on it.

So "getting started" means: clone it, read it, port ~150 lines of protocol logic into a Laravel guard. Budget a 1–2 day spike.

Minimal steps for the spike:

  1. Clone the repo and read it in this order:
    • DependencyInjection/Configuration.php — the authoritative list of config keys (host, port, path, key, timeouts, logger).
    • Security/ — the listener and authentication provider that perform the redirect-out / redirect-in dance and validate the WLS-Response.
    • The Raven client wrapper — this is the part you actually want to copy: signature verification, issue freshness check, params replay check.
  2. Stand up against Raven's test WLS endpoint (https://raven.cam.ac.uk/auth/authenticate.html for prod, but use the test/demo host for the spike). Capture a real WLS-Response and keep it as a fixture.
  3. Build a tiny throwaway script that validates that fixture. Get the signature check green before writing any Laravel code.
  4. Only then build the Laravel guard.

First use case worth shipping: gate an internal admin/dashboard route behind Cambridge SSO and read the CRSID (principal) off the session, mapping it to a local users row on first login.

If you are in a genuinely legacy Symfony 2.x app, the native install looks like:

// app/AppKernel.php
$bundles = [ /* ... */ new Misd\RavenBundle\MisdRavenBundle() ];
# app/config/config.yml
misd_raven:
    host: raven.cam.ac.uk
    port: 443
    path: /auth/authenticate.html
    key: "<session key used to sign the request>"
# app/config/security.yml
security:
    firewalls:
        secured:
            pattern: ^/
            misd_raven: ~
    access_control:
        - { path: ^/, roles: ROLE_USER }

Implementation Patterns

The protocol flow (this is what you are porting). There are only three moving parts:

  1. Redirect out. Send the user to authenticate.html with ver=3, url (your callback — must be HTTPS, Raven rejects http and non-https callbacks), date (ISO 8601 UTC), desc, and skey. Optionally ptags if you want Raven to assert group membership.
  2. Validate the response. Raven redirects back to your url with a WLS-Response query parameter. Decode it and check, in this order:
    • ver is a version you support and status is 200.
    • sig — recompute the signature over the response fields (excluding sig) using Raven's published key for the kid in the response. Use a constant-time comparison (hash_equals).
    • issue — timestamp must be within a tolerance window (Raven specifies minutes; enforce a small skew tolerance and require NTP).
    • url — must match the callback URL you sent, exactly.
    • params — if you sent a nonce/state in params, it must match your stored value and must not have been seen before (replay protection). This requires a shared store if you run more than one app instance.
  3. Establish the session. Map principal (the CRSID) to a local user.

Laravel translation — custom guard + two routes. Do not try to bolt this onto Auth::attempt(); model it as a redirect-based provider:

// routes/web.php
Route::get('/auth/raven', [RavenController::class, 'redirect'])->name('raven.login');
Route::get('/auth/raven/callback', [RavenController::class, 'callback'])->name('raven.callback');
// app/Http/Controllers/RavenController.php
public function redirect()
{
    $state = Str::random(32);
    session(['raven.state' => $state]);

    $params = [
        'ver'  => 3,
        'url'  => route('raven.callback'), // must be https
        'date' => now()->utc()->toIso8601String(),
        'desc' => config('app.name'),
        'params' => $state,
    ];
    // sign/assemble per the bundle's client wrapper
    return redirect($this->raven->authenticateUrl($params));
}

public function callback(Request $request)
{
    $response = $this->raven->validate($request->query('WLS-Response'), [
        'expected_url'    => route('raven.callback'),
        'expected_params' => session()->pull('raven.state'),
        'issue_tolerance' => 120, // seconds
    ]);

    $user = User::firstOrCreate(
        ['crsid' => $response->principal()],
        ['name' => $response->displayName()]
    );

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

Mapping CRSID → user. Do this in one place (a service, not the controller). Auto-provision on first login is the standard pattern. Keep authorization in your own database, keyed by CRSID — do not rely on ptags alone for roles, because ptags changes are not reflected in existing sessions. If you do consume ptags, re-evaluate them on each login and consider a version column on the user to force role refresh.

Testing. You cannot rely on the live IdP in CI. Build a fixture set from a captured real response and assert all the negative cases:

it('rejects a tampered signature', fn () => /* flip a byte in sig */);
it('rejects an expired issue timestamp', fn () => /* age the fixture */);
it('rejects a replayed params', fn () => /* use the fixture twice */);
it('rejects an unknown kid', fn () => /* swap the kid */);

Run these in CI. This is the whole point of using the bundle as a reference — you get the protocol logic and the test cases you must replicate.

Integration tips.

  • Keep Raven verification framework-agnostic (a plain PHP class) with a thin Laravel guard on top. That way the same class works if you later move to Symfony's authenticator system or a different app.
  • Prefer a maintained protocol layer (SimpleSAMLphp, onelogin/php-saml, Lightsaml) over the bundle's own crypto if it is available for your protocol generation. Only port the bundle if its validation is genuinely non-trivial relative to those libraries.
  • If the institution has migrated to Shibboleth-backed "University Login", the protocol is SAML, not Ucam WebAuth — stop and use a SAML library.

Gotchas and Tips

The description in this repo is misleading. description.md describes Sentry error tracking via the Raven PHP client. The bundle is Raven authentication. If your real need is Sentry, use sentry/sentry-symfony (or sentry/sentry-laravel). If your need is Cambridge login, keep reading. Confirm which one the request actually means before starting.

WLS-Response validation failures are silent and confusing. The common causes, in order of frequency:

  • Clock skew on issue. Enforce NTP on all app servers and a tolerance window (e.g. 120s). A skewed server produces "expired response" errors that look like IdP outages.
  • url mismatch. The callback URL you send and the one returned must match exactly — scheme, host, trailing slash included. Proxies and load balancers that terminate TLS can make the app see http where Raven saw https. Configure trusted proxies (TrustProxies in Laravel) or you will chase this for hours.
  • kid rotation. Raven rotates keys. If you cache keys, provide a refresh path and alert on validation failure spikes. A stale key is a total login outage.
  • Replay store not shared. If params replay protection is in-process memory, multi-instance deploys will intermittently reject valid logins. Use Redis or the DB.

Session key (skey) must be secret and stable per session. If you regenerate it between the redirect and the callback (e.g. session()->regenerate() before validation), the response will not verify. Validate first, then regenerate and log in.

params is your CSRF/state, but it is not enough on its own. Treat it as a nonce: generate server-side, store in session, compare with hash_equals, and delete after single use. Do not accept a params value the client supplied.

Case and normalization on principal. CRSIDs are typically lowercase; do not assume. Normalize on ingest (strtolower(trim())) or you will get duplicate user rows when one login path returns ABC123 and another abc123. Match CRSIDs case-insensitively in lookups.

ptags are authorization hints, not truth. They reflect group membership at the moment of the response. They go stale on the next click. If you need roles, either re-query at login or maintain them locally and reconcile.

Logout is not SSO logout. Authenticating via Raven does not propagate central logout. After a user logs out at Cambridge, they may still hold a valid local session. If your institution needs single logout, plan for it explicitly — the bundle does nothing here.

Do not install this as a dependency. 1 star, 0 dependents, single maintainer, Symfony 2 (EOL since 2018), no CI on modern PHP, no security review. In auth code, an unpatched validation library is a standing vulnerability. Copy the ~150 lines, own them, and test them against fixtures. If you need a maintained protocol layer, use a supported SAML/WebAuth library behind your own guard.

Extension points worth keeping when you port. (a) The signature/key-resolution step should be injectable so you can swap in a maintained verifier later. (b) The replay/state store should be an interface (session for single instance, Redis for multi). (c) The user-mapping step should be a service so tests can fake it. These three seams are where all the real failures and future changes will land.

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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin