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

Connect Laravel Package

symfonycorp/connect

PHP SDK and Symfony bundle for integrating Symfony Connect, the OAuth2 service for Symfony users. It handles authentication, lets users sign in with their Symfony Connect account, and provides API access for retrieving profile and account data.

View on GitHub
Deep Wiki
Context7

Getting Started

symfonycorp/connect is a thin, framework-agnostic SDK for the SymfonyConnect API. It does two things: drive the OAuth2-style authorization-code flow against connect.symfony.com, and give you an authenticated client for the Connect REST API (users, badges, projects). It is not a Symfony bundle — there is no recipe, no Extension, no auto-wiring. Expect to spend most of your time in your own security.yaml / services.yaml, not in this library.

Minimal steps:

composer require symfonycorp/connect
  1. Register an application at https://connect.symfony.com (My Apps) to obtain a client id, client secret, and to set an exact callback URL.
  2. Put the credentials in .env.local:
SYMFONY_CONNECT_CLIENT_ID=abc123
SYMFONY_CONNECT_CLIENT_SECRET=shhh
SYMFONY_CONNECT_REDIRECT_URI=https://example.com/connect/callback
  1. Wire the two service objects you will actually use:
# config/services.yaml
services:
    SymfonyCorp\Connect\OAuth\OAuth:
        arguments:
            $clientId: '%env(SYMFONY_CONNECT_CLIENT_ID)%'
            $clientSecret: '%env(SYMFONY_CONNECT_CLIENT_SECRET)%'
        calls:
            - [setRedirectUrl, ['%env(SYMFONY_CONNECT_REDIRECT_URI)%']]

Where to look first, in this order:

  • README.md — the only end-to-end example, and it is short.
  • src/OAuth/OAuth.php — getAuthorizationUrl() and getAccessToken($code). This is the whole login flow.
  • src/Api/Api.php and src/Api/Entity/ — the authenticated client and its read-only DTOs (User, Badge, …).
  • src/Security/ — legacy Symfony Security glue. Read it to understand the mapping, do not use it on Symfony 5.4+ (see Gotchas).

First use case — a "Log in with SymfonyConnect" button, controller-only, no Security bundle integration:

use SymfonyCorp\Connect\OAuth\OAuth;
use SymfonyCorp\Connect\Api\Api;

#[Route('/connect')]
final class ConnectController extends AbstractController
{
    #[Route('/start', name: 'connect_start')]
    public function start(OAuth $oauth): Response
    {
        return $this->redirect($oauth->getAuthorizationUrl());
    }

    #[Route('/callback', name: 'connect_callback')]
    public function callback(Request $request, OAuth $oauth): Response
    {
        $token = $oauth->getAccessToken($request->query->get('code'));
        $api   = new Api($token);
        $me    = $api->getRoot()->getCurrentUser();

        // $me->getUsername(), $me->getEmail() -> persist to YOUR User entity
        return $this->redirectToRoute('dashboard');
    }
}

Method names drift between minor versions — if a call above does not exist in your pinned tag, grep the class; the surface area is small enough to read in one sitting.

Implementation Patterns

Map the Connect user to a local user on first login. Never treat the SDK's User DTO as your application user — it is a detached value object, not a Doctrine entity. Store connect_id (and optionally the access token) on your own User row:

$user = $this->userRepository->findOneByConnectId($me->getId())
    ?? (new User())->setConnectId($me->getId());

$user->setUsername($me->getUsername())
     ->setEmail($me->getEmail())
     ->setConnectToken($token);   // encrypt at rest if you store it

$this->em->persist($user);
$this->em->flush();

Integrate with Symfony Security via a custom authenticator, not via the bundled ConnectUserProvider / ConnectAuthenticationProvider. On Symfony 5.4+/6/7 subclass AbstractAuthenticator and treat the whole OAuth round-trip as the authenticate() step, or (cleaner) keep the controller above and just call $security->login($user, 'form_login') after the mapping. The latter keeps the OAuth controller testable and avoids fighting the authenticator lifecycle.

Store the token only if you need the API later. If you only log users in, discard it. If you want to display a user's badges or projects, persist it and build a scoped service:

final class ConnectApiFactory
{
    public function forUser(User $user): Api
    {
        return new Api($user->getConnectToken());
    }
}

Cache aggressively. API responses are public-ish and change slowly; wrap calls in a cache.app pool keyed by Connect ID with a 15–60 minute TTL, and refresh on demand rather than on every page render.

Test against a mocked HTTP layer. The SDK funnels requests through its HTTP client dependency, so MockHttpClient (or your PSR-18 mock) lets you assert the token exchange and the /me call without touching the network. Assert on the authorization URL separately — it is pure string building.

Wrap it. Given the low release cadence, put the SDK behind a one-method interface (ConnectAuthenticator::authenticate(string $code): ConnectIdentity) so an upstream breakage or a switch to plain league/oauth2-client is a single-file change.

Gotchas and Tips

  • Not a bundle. No Flex recipe, no config tree, no autoconfiguration. Everything in services.yaml, by hand. Budget an hour for the first wiring.
  • The SymfonyCorp\ namespace is not Symfony\. It is a separate vendor namespace; do not assume it ships with the framework or that the classes are covered by Symfony's BC promise.
  • Legacy src/Security/ classes are version-locked. The ConnectUserProvider/ConnectToken code was written for the old Guard era. On modern Symfony they at best work by accident; use AbstractAuthenticator or post-controller login instead.
  • The redirect URI must match byte-for-byte, including trailing slash and scheme. A mismatch returns an error before your code ever runs, and the message from Connect is terse.
  • Authorization codes are single-use and short-lived. A refresh of the callback URL, or a user double-clicking, produces a failed getAccessToken() — catch it and redirect back to /connect/start rather than 500-ing.
  • CSRF/state is your job. The authorization URL is a plain string; if your version does not accept a state parameter, append one and verify it in the callback against the session. Without it the callback endpoint is a login-CSRF vector.
  • Scopes determine which fields are populated. Request too few and getEmail() returns null, which will blow up a non-nullable setEmail(). Guard every DTO getter, or validate before mapping.
  • Tokens are long-lived credentials. Treat a stored Connect token like a password: encrypt at rest, never log it, and remember that logging out of your app does not revoke it on Connect's side.
  • Debugging: the SDK swallows little, but its exceptions are generic. Catch around getAccessToken() and getRoot(), log the exception message plus the HTTP status, and — in dev only — dump the raw token-endpoint response; that is where invalid_client / invalid_grant hides.
  • Extension point: the HTTP client is injected, so this is where you add retries, a proxy, or a request logger. Subclassing the SDK classes is a last resort — they are small and mostly final-ish in spirit.
  • Pin the version ("symfonycorp/connect": "^2.0") and watch the repo; 90-odd stars and a small dependent count mean upstream fixes are infrequent, so you own the risk.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console