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

Gitlab Laravel Package

socialiteproviders/gitlab

GitLab OAuth provider for Laravel Socialite. Adds GitLab as an authentication driver for Socialite, letting users log in with their GitLab account and retrieve their profile. Install via Composer, add your GitLab client ID and secret, and configure the provider in your services config.

Deep Wiki
Context7

Getting Started

Minimum viable setup:

  1. Install the provider (it pulls in socialiteproviders/manager and expects laravel/socialite):

    composer require socialiteproviders/gitlab
    
  2. Register the extension listener. In older Laravel skeletons this lives in app/Providers/EventServiceProvider.php:

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

    On Laravel 11+ where EventServiceProvider is absent, either create one or add in AppServiceProvider::boot():

    Event::listen(
        \SocialiteProviders\Manager\SocialiteWasCalled::class,
        \SocialiteProviders\GitLab\GitLabExtendSocialite::class
    );
    
  3. Add credentials to config/services.php:

    'gitlab' => [
        'client_id'     => env('GITLAB_CLIENT_ID'),
        'client_secret' => env('GITLAB_CLIENT_SECRET'),
        'redirect'      => env('GITLAB_REDIRECT_URI'),
        // 'instance' => env('GITLAB_INSTANCE', 'https://gitlab.com'),
    ],
    
  4. Create an OAuth application in GitLab (User Settings → Applications for gitlab.com, or https://<host>/-/profile/applications for self-hosted) with the callback URL matching GITLAB_REDIRECT_URI exactly, and the read_user scope.

First use case: the classic redirect/callback login flow for an internal tool that authenticates against a self-hosted GitLab instance:

Route::get('/auth/gitlab', fn () => Socialite::driver('gitlab')->redirect());
Route::get('/auth/gitlab/callback', function () {
    $gl = Socialite::driver('gitlab')->user();
    // $gl->id, $gl->nickname, $gl->name, $gl->email, $gl->avatar
});

If you only need to read a GitLab user profile (not "log in"), you can still use the provider's userFromToken() with a personal access token and skip the redirect dance.

Implementation Patterns

Web login (session-based). The canonical controller above; store the GitLab numeric id on your users table (or a social_identities pivot) and key firstOrCreate on it. Never trust email alone — GitLab users can change their primary email.

Self-hosted GitLab. Set the instance key in services.gitlab (e.g. https://gitlab.example.com). The provider appends /oauth/authorize, /oauth/token, and /api/v4/user to this value, so it works for sub-path installations like https://example.com/gitlab too. This is the differentiator versus using Socialite's built-in providers.

Stateless / API clients. For SPAs or mobile where session state isn't practical:

$user = Socialite::driver('gitlab')->stateless()->userFromToken($accessToken);

Send the user to Socialite::driver('gitlab')->stateless()->redirect()->getTargetUrl() and have the client deliver the code back, or handle the token exchange yourself against <instance>/oauth/token.

Scopes. Default is read_user (enough for /api/v4/user). For repository or CI operations, add api, read_repository, read_api, openid, etc.:

Socialite::driver('gitlab')->scopes(['read_user', 'read_api'])->redirect();

GitLab scopes are space-delimited, which matches Socialite's default formatScopes — no override needed.

Mapping and extension. The provider maps id, username → nickname, name, email, avatar_url → avatar. If you need state, confirmed_at, or web_url, subclass Socialiteproviders\GitLab\Provider and override mapUserToObject(), or just call $user->getRaw() and read the extra keys yourself.

Testing. Socialite's user() uses Guzzle directly, so Http::fake() won't intercept it. Mock at the Socialite boundary instead:

Socialite::shouldReceive('driver->user')->andReturn($fakeUser);

For unit tests of your callback logic, that's usually enough. If you need to test the provider itself, inject a Guzzle MockHandler through the guzzle config key.

Config caching. After editing services.php or .env, run php artisan config:clear (and config:cache in production) — a very common source of "invalid_client" confusion.

Gotchas and Tips

  • Read-only subtree split. This repo is generated from SocialiteProviders/Providers; PRs here are rejected. File issues/fixes against the monorepo, then the split is re-tagged.
  • Stale release vs. modern Laravel. The last tag is from December 2020 and may pin socialiteproviders/manager: ^3.0, which conflicts with the manager 4.x line needed by Laravel 9/10/11. Check composer why-not socialiteproviders/gitlab before assuming a bug. Workarounds: require socialiteproviders/manager:^4.0 explicitly, use a maintained fork, or copy the ~80-line provider class into app/Socialite/ and register it with Socialite::extend().
  • instance with a trailing slash produces https://host//oauth/authorize and GitLab will reject or misroute it. Strip trailing slashes in your env (rtrim).
  • Manual Socialite::extend() drops extra config keys. Socialite::buildProvider() only forwards client_id, client_secret, redirect, and guzzle; instance is passed only via the manager's SocialiteWasCalled path (which consults additionalConfigKeys()). If you hand-roll the extend closure for a self-hosted instance, construct the provider yourself or instance will silently fall back to gitlab.com.
  • Redirect URI must match exactly. GitLab is strict about scheme/host/path; http vs https and trailing slashes count. Localhost is fine over HTTP; production should be HTTPS.
  • Email can be null. The /api/v4/user payload's email is the authenticated user's primary email, but it can be missing or unverified for some accounts. Make your users table's email nullable, or fall back to public_email and prompt for confirmation.
  • State mismatches. InvalidStateException usually means the session isn't shared between the redirect and callback (different subdomain, SESSION_DOMAIN misconfigured, or a load balancer stripping cookies). Use stateless() for API-style flows, but then validate the state yourself.
  • Self-signed or internal CA. Pass Guzzle options through config, e.g. 'guzzle' => ['verify' => '/path/to/ca.pem'] (avoid false in production). Without this, token exchange fails with a cURL error that looks unrelated to OAuth.
  • No token refresh. Socialite's base provider handles the authorization-code exchange only. If your GitLab instance issues expiring access tokens (configurable in newer GitLab versions), persist refresh_token and refresh manually — the package won't do it for you.
  • Scope changes require re-consent. GitLab won't silently upgrade scopes; users must re-authorize. Plan an "upgrade permissions" redirect if you later add api.
  • Token type. Personal access tokens work with userFromToken(); project/group access tokens generally do not have access to /api/v4/user. Make sure users generate a user-owned PAT.
  • Debugging. Socialite::driver('gitlab')->user() failures give little context; log the raw response by temporarily dumping $user->getRaw() or subclassing getUserByToken() to Log::debug() the body and status. The most common failures are: wrong instance, missing read_user scope, redirect URI mismatch, and expired/revoked token.
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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core