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

Laravel Swiss Eid Laravel Package

schaefersoft/laravel-swiss-eid

Laravel package for integrating Swiss E-ID (Swiss electronic identity) authentication into PHP applications. It simplifies identity flows, user login, and verification so you can add Swiss digital identity support quickly and securely.

View on GitHub
Deep Wiki
Context7

Getting Started

Requirements & install

  • v0.7.1 pins the floor at PHP 8.2+; the constraint is enforced in composer.json, so a project on 8.1 will hard-fail on composer require rather than degrade gracefully. Verify your CI matrix (and any platform.php override in config.platform) before bumping.
  • composer require schaefersoft/laravel-swiss-eid, then publish the config: php artisan vendor:publish --tag=swiss-eid-config (confirm the exact tag in the README — it's the first thing to check, since the package is pre-1.0 and tags have moved between releases).

Where to look first, in order

  1. config/swiss-eid.php — this is the contract. Client ID/secret, redirect URI, discovery/issuer URL, scopes, and any route/guard toggles all live here. Read it before writing a single line of integration code.
  2. src/Http/Controllers (or equivalent) — the package almost certainly ships a redirect + callback controller pair. Knowing whether it registers routes for you or expects you to wire them determines your whole integration shape.
  3. The service provider's boot() — reveals the registered routes, facade/singleton bindings, and any published migrations.
  4. The README's "Configuration" section for the IdP-side values (client registration, allowed redirect URIs).

First use case: add a "Login with Swiss EID" button

The minimal happy path is a redirect out, a callback in, and a local user:

Route::get('/auth/swiss-eid', [SwissEidController::class, 'redirect'])->name('swiss-eid.redirect');
Route::get('/auth/swiss-eid/callback', [SwissEidController::class, 'callback'])->name('swiss-eid.callback');

Register those two URIs at the identity provider, put the callback URL in the config, and you have a working login. Everything else (account linking, guard selection, step-up auth) is layered on top of this.

Implementation Patterns

Provisioning users on first login

Treat the sub claim as the primary key for the identity and store it on your users table:

// migration
$table->string('swiss_eid_sub')->nullable()->unique();
public function callback(Request $request)
{
    $identity = SwissEid::handleCallback($request); // per README naming

    $user = User::firstOrCreate(
        ['swiss_eid_sub' => $identity->sub()],
        [
            'name'  => $identity->name(),
            'email' => $identity->email(),
        ]
    );

    Auth::login($user, remember: true);

    return redirect()->intended(route('dashboard'));
}

Do not key on email — it can change upstream, and keying on it silently merges two people if the IdP ever recycles an address.

Account linking for existing users

If you already have password-based accounts, an explicit "link your Swiss EID" flow inside an authenticated session is safer than auto-merging by email on callback. Pattern: authenticated user hits a link route → redirect out with a marker in the session/state → callback attaches swiss_eid_sub to Auth::user() instead of logging in a different account. Verify the email matches before attaching, and log the link event.

Guard separation

If you want eID login to be an additional guard rather than the default, configure a dedicated guard in config/auth.php pointing at the package's user provider (if it exposes one) or wrap it in your own. Avoid swapping the default guard globally — it tends to break existing session-based auth in subtle ways.

Requiring a verified identity on sensitive routes

Wrap the routes that need it in a middleware that checks the swiss_eid_sub column is present, rather than relying on "logged in at all." This gives you a clean step-up story: ordinary browsing on a normal session, high-assurance actions behind eID.

Sensitive-action re-authentication

For signatures or data disclosure, re-run the redirect flow with prompt=login (or the IdP's equivalent) instead of trusting an hours-old session. Keep the flow short-lived: stash the intended action in the session, complete the round trip, then resume.

Testing

The callback is an HTTP boundary — fake the token endpoint rather than faking the package:

Http::fake([
    '*/token' => Http::response(['access_token' => 'x', 'id_token' => $jwt]),
]);

Build a helper that mints a signed id_token with your test claims so you can exercise claim-mapping, missing-email, and malformed-token branches. Keep at least one test that asserts the redirect URI in the outgoing request matches config exactly.

Logout

Standard session logout only clears your side. If the package supports RP-initiated logout, also hit the IdP's end-session endpoint with id_token_hint and post_logout_redirect_uri; otherwise users stay signed in upstream and get silently re-authenticated on the next login attempt, which looks like a bug.

Gotchas and Tips

Version and platform pitfalls

  • v0.7.1 is the release that guarantees PHP 8.2+. If you were running v0.7.0 on 8.1 by accident, this is a breaking install-time constraint even though it's tagged as a "fix." Pin ^0.7 and read changelogs — pre-1.0 releases here carry no backwards-compatibility promise.
  • Check composer why-not php 8.2 if the update refuses to resolve; a transitive dev dependency is the usual culprit.

Redirect URI mismatches

The single most common failure. The URI must match byte-for-byte what's registered at the IdP — scheme, host, port, trailing slash, and www.. http vs https and localhost vs 127.0.0.1 both count as mismatches.

Session state across the round trip

The callback is a fresh request that depends on values stashed before the redirect (state, nonce, PKCE verifier). Symptoms and causes:

  • New tab / different browser → no session, callback fails validation. Expected; show a friendly error, not a 500.
  • Session expired mid-flow → same. Set a sensible SESSION_LIFETIME and keep the flow snappy.
  • SESSION_DOMAIN misconfigured → the cookie set on the redirect request isn't sent back on the callback. In local dev with a tunnel (ngrok/Expose), make sure you're using one consistent hostname throughout.

Config caching

php artisan config:cache will freeze the config file's values. Changing credentials and seeing no effect is almost always a stale cache — php artisan config:clear after any .env or config edit in a cached environment.

HTTPS and local development

Assume HTTPS is required in production and strongly preferred by the IdP. For local work you either need a tunnel, or the IdP's sandbox/test environment with its own client credentials. Keep those credentials in a separate SWISS_EID_* env block rather than toggling a sandbox boolean, so you can't accidentally point staging at production.

Don't log tokens or raw claims

Debugging by Log::info($response->json()) is the fastest way to leak an id_token and full PII into your log storage. Log the sub and error codes; use debug level and strip the payload if you must.

Clock skew and token validation

JWT exp/nbf/iat checks are unforgiving. Container clocks drift; if you see intermittent "token expired" failures that vanish on retry, sync ntp or give the validator a small leeway in config if the package exposes one.

Extending rather than editing vendor code

If the claim mapping isn't right for you (unusual name formats, missing email_verified, extra AGOV attributes), look for a configurable claim map or a bindable interface in the container before reaching for a fork. Since this is a 0.x package, an override published into your own app is safer than vendor/ edits that vanish on the next composer update.

Upgrade hygiene

Keep a test that exercises the callback end-to-end. With a package moving through 0.x, that test is what tells you a patch bump quietly changed a claim name or a config key.

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.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator