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

Franceconnect Laravel Package

socialiteproviders/franceconnect

FranceConnect OAuth/OpenID Connect provider for Laravel Socialite, letting applications offer secure login through the French government identity service (FranceConnect). Adds a franceconnect driver so users can authenticate with their existing certified identity provider and share verified data lik...

View on GitHub
Deep Wiki
Context7

Getting Started

socialiteproviders/franceconnect is a Socialite driver for FranceConnect, the French government's OIDC identity federation. You don't use it like a normal social login — it's an identity broker that authenticates citizens against impots.fr, AMELI, La Poste Identité Numérique, etc., and returns a certified identity (sub, name, birthdate, gender, birthplace). Treat it as "civil-identity verification", not "get an email address".

Minimum steps:

composer require socialiteproviders/franceconnect:^4.1

config/services.php (key name is the driver name):

'franceconnect' => [
    'client_id'     => env('FRANCECONNECT_CLIENT_ID'),
    'client_secret' => env('FRANCECONNECT_CLIENT_SECRET'),
    'redirect'      => env('FRANCECONNECT_REDIRECT_URI'),
],

Register the extend listener. Laravel ≤10, in EventServiceProvider:

protected $listen = [
    \SocialiteProviders\Manager\SocialiteWasCalled::class => [
        \SocialiteProviders\FranceConnect\FranceConnectExtendSocialite::class.'@handle',
    ],
];

Laravel 11+, in AppServiceProvider::boot():

Event::listen(function (\SocialiteProviders\Manager\SocialiteWasCalled $event) {
    $event->extendSocialite('franceconnect', \SocialiteProviders\FranceConnect\Provider::class);
});

Your first use case — a login route pair:

Route::get('/auth/franceconnect', fn () => Socialite::driver('franceconnect')->redirect());
Route::get('/auth/franceconnect/callback', function () {
    $fc = Socialite::driver('franceconnect')->user();
    // $fc->getId() === sub === the identifiant pivot
});

Where to look first: the package README (environment/endpoint switching), then your FranceConnect partner account on the DINUM portal, because nothing works until your exact redirect URI is declared there.

Implementation Patterns

Persist sub, not email. The FranceConnect sub is the stable "identifiant pivot" for a user. Store it in its own indexed column and map it to your local user:

$user = User::firstOrCreate(
    ['franceconnect_sub' => $fc->getId()],
    ['name' => $fc->getName()]
);

Raw claims are on $fc->user (birthdate, gender, birthplace, birthcountry) — useful for one-time identity proofing, not for profile sync.

Environment switching. Keep integration (fcp.integrate.api.fr) and production (app.franceconnect.gouv.fr) credentials as separate env blocks and select the base URL per environment; never let a staging deploy point at prod credentials or vice-versa. If the package reads endpoints from config, override there rather than patching the provider.

Scopes and eIDAS levels. FranceConnect v2 expects the identity scope set (openid given_name family_name birthdate gender birthplace birthcountry) and an acr_values level (eidas1 by default). Set them explicitly so a package default change doesn't silently alter what you receive:

Socialite::driver('franceconnect')
    ->scopes(['openid', 'given_name', 'family_name', 'birthdate', 'gender', 'birthplace', 'birthcountry'])
    ->with(['acr_values' => 'eidas1'])
    ->redirect();

Access the ID token. The token response body is exposed on the user object ($fc->accessTokenResponseBody['id_token']). You need it for RP-initiated logout, and it's the only way to get auth-time metadata Socialite doesn't surface.

Multiple user types. If both agents and citizens log in, register two drivers pointing at the same provider class with different scope/acr config, rather than branching inside one callback.

Testing. Don't hit FranceConnect in CI. Http::fake() the /token and /userinfo endpoints and drive the callback route with a canned code, or bind a fake driver into the container. Assert on your own persistence layer, not on Socialite's internals.

Gotchas and Tips

  • http://localhost will not work. FranceConnect only accepts declared HTTPS redirect URIs on reachable hosts. Use a tunnel (ngrok, expose, Cloudflare Tunnel) and register that URL in the partner portal, or you'll burn hours on redirect_uri_mismatch.
  • Do not use stateless(). FranceConnect requires state (and a nonce for OIDC). stateless() disables exactly the check you need; if the package doesn't send a nonce for you, add it via ->with(['nonce' => ...]) and verify it on callback.
  • Migrating a v1-era integration: FranceConnect v2 dropped email and preferred_username from the available scopes. If your code does $fc->getEmail() and expects a value, it will be null — this is the single most common breakage. Redesign around sub.
  • The sub differs by eIDAS level / scope set in some configurations; don't assume a user identified at eidas1 matches a record created under an eidas2 flow. Key your table on (sub, acr_level) if you ever offer both.
  • Logout is mandatory. FranceConnect requires RP-initiated logout against /api/v1/logout with id_token_hint and state. Socialite's logout() doesn't apply here — check whether the 4.x driver exposes a logout helper; if not, build the URL yourself from the stored id_token and redirect. Local Auth::logout() alone leaves the FranceConnect session alive.
  • Socialite gives you a user, not a token store. There's no refresh handling; persist tokens yourself if you need to call partner APIs afterwards.
  • 4.1.1 is a patch release with no changelog entries beyond the commit diff — a dependency/bugfix bump, no API change. Safe to take; pin ^4.1 and read the diff only if you were bitten by a specific bug in 4.1.0.
  • Habilitation is a prerequisite, not a detail. Using FranceConnect in production requires accreditation as a fournisseur de service; sandbox access is separate. Plan that lead time before promising a delivery date.
  • Config caching bites in the usual way: after changing credentials, php artisan config:clear, and remember SocialiteWasCalled registration is code, not config — it won't survive a stale event cache in older skeleton apps.
  • Debugging: log the authorize URL, the raw token response status, and the userinfo payload (redact id_token and access token). Almost every failure is a redirect-URI, state, or scope mismatch — all visible at the URL/HTTP layer, not in Socialite exceptions.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource