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

Reddit Laravel Package

socialiteproviders/reddit

Reddit OAuth provider for Laravel Socialite. Adds Reddit login to your Laravel app using Socialite, supporting OAuth2 authentication with minimal setup. Install via Composer and configure your Reddit client ID and secret.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is an OAuth 2.0 driver for Reddit that plugs into Laravel Socialite. It contains no Reddit API client — it only handles the authorization-code exchange and returns a Laravel\Socialite\Two\User object. Anything beyond "who is this Redditor" is your job via Guzzle/Http.

Minimal setup:

composer require socialiteproviders/reddit
  1. Create a web app at https://www.reddit.com/prefs/apps. Copy the client ID (under the app name) and secret.
  2. Add credentials to config/services.php:
'reddit' => [
    'client_id'     => env('REDDIT_CLIENT_ID'),
    'client_secret' => env('REDDIT_CLIENT_SECRET'),
    'redirect'      => env('REDDIT_REDIRECT_URI'), // e.g. https://myapp.test/auth/reddit/callback
],
  1. Wire the provider into Socialite. The driver is registered via the SocialiteProviders\Manager event, not auto-discovery:
// Laravel 11+ — AppServiceProvider::boot()
use Illuminate\Support\Facades\Event;
use SocialiteProviders\Manager\SocialiteWasCalled;
use SocialiteProviders\Reddit\RedditExtendSocialite;

Event::listen(SocialiteWasCalled::class, RedditExtendSocialite::class.'@handle');

On Laravel 10 and below, add the same mapping to EventServiceProvider::$listen instead.

  1. Two routes:
Route::get('/auth/reddit', fn () => Socialite::driver('reddit')
    ->scopes(['identity'])
    ->redirect());

Route::get('/auth/reddit/callback', function () {
    $redditUser = Socialite::driver('reddit')->user();

    // getId() => t2_xxxxx without the prefix, getName() => username
    // getNickname() => username, getAvatar() => avatar URL, getEmail() => null
});

First use case: "Log in with Reddit" on a Laravel app, typically followed by reading the user's subscribed subreddits or posting on their behalf.

Implementation Patterns

Scope-first authorization. Reddit grants exactly what you ask for at redirect time and there is no incremental-consent prompt. Decide up front:

Socialite::driver('reddit')
    ->scopes(['identity', 'read', 'submit']) // add 'flair', 'edit', 'privatemessages' as needed
    ->redirect();

Stateless flow for APIs / SPAs. If your callback is hit by a mobile client or a separate front-end, use ->stateless() on both the redirect and the callback, and pass your own signed state through with(['state' => ...]).

Persisting the token set. $user->accessTokenResponseBody holds the raw payload, including refresh_token, expires_in, and scope. Store these on the user record — the driver will not refresh anything for you.

$user = Socialite::driver('reddit')->user();

SocialiteUser::updateOrCreate(
    ['reddit_id' => $user->getId()],
    [
        'username'      => $user->getName(),
        'avatar'        => $user->getAvatar(),
        'access_token'  => $user->token,
        'refresh_token' => $user->refreshToken,
        'expires_at'    => now()->addSeconds($user->expiresIn ?? 3600),
        'scopes'        => $user->accessTokenResponseBody['scope'] ?? null,
    ]
);

Token refresh job. Reddit's access tokens are short-lived (~1 hour). Refresh with basic auth against the same endpoint the provider uses internally:

Http::asForm()
    ->withBasicAuth(config('services.reddit.client_id'), config('services.reddit.client_secret'))
    ->withHeaders(['User-Agent' => config('services.reddit.user_agent')])
    ->post('https://www.reddit.com/api/v1/access_token', [
        'grant_type'    => 'refresh_token',
        'refresh_token' => $user->refresh_token,
    ]);

Always send a descriptive User-Agent on every Reddit API call (including oauth.reddit.com). Reddit throttles or blocks generic/empty agents aggressively. Put it in config/services.php and a shared Http::withHeaders() macro or a small RedditClient service.

Multi-provider apps. Keep the Event::listen registration alongside your other SocialiteProviders entries; the single SocialiteWasCalled listener pattern scales to Google, GitHub, Discord, etc. with no per-provider service provider sprawl.

Testing. Socialite's Guzzle client is not intercepted by Http::fake(). Mock the driver instead:

Socialite::shouldReceive('driver->user')->andReturn(
    (new \Laravel\Socialite\Two\User)->map([
        'id' => 'abc123', 'nickname' => 'spez', 'name' => 'spez',
        'email' => null, 'avatar' => 'https://...',
    ])
);

Then Http::fake(['oauth.reddit.com/*' => Http::response([...])]) for whatever your own Reddit API layer does.

Gotchas and Tips

  • Driver [reddit] is not supported is almost always a missing SocialiteWasCalled listener or a stale php artisan config:cache/event:cache. Clear both before debugging anything else.
  • Redirect URI must match byte-for-byte, including scheme, port, and trailing slash. Reddit app types matter too: choose web app for server-side code flows; an installed app has no secret and behaves differently.
  • No email is ever returned. $user->getEmail() is null; the Reddit API does not expose it. Design your users table so email is nullable or gate registration behind an email prompt.
  • IDs are strings like t2_abc123. getId() returns the id with the t2_ prefix stripped. Don't mix both forms as keys across tables — pick one and normalize.
  • Refresh tokens expire too. A default authorization yields a ~24-hour refresh token; adding duration=permanent to the authorize URL yields a long-lived one. The provider does not add this for you — extend RedditExtendSocialite or override the redirect URL if you need it.
  • Scopes are case-sensitive and easy to typo. An invalid scope causes Reddit to silently drop it (or redirect with error=invalid_scope), so assert the returned scope string matches what you requested before assuming a permission exists.
  • Rate limits are per OAuth client, not per user, at roughly 100 QPM. Queue any bulk moderation/reading work and back off on 429 rather than retrying immediately.
  • Extension points: subclass SocialiteProviders\Reddit\Provider and override getUserByToken() / mapUserToObject() when you need the raw /api/v1/me payload (e.g. is_gold, link_karma, created_utc), then register your subclass under the same reddit key in the SocialiteWasCalled listener.
  • Version pinning: the 4.x line tracks Socialite 5 / Laravel 11+ conventions. The 4.2.0 release notes are only a compare link, so read the diff or pin ^4.1 if you need a hard guarantee before upgrading — nothing in the changelog announces breaking changes, but a changelog-only release note means no feature to plan around either. Run your auth flow against a test Reddit app after any minor bump.
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