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

Tiktok Laravel Package

socialiteproviders/tiktok

TikTok OAuth 2.0 provider for Laravel Socialite. Add TikTok login to your Laravel app using Socialite’s familiar redirect and callback flow. Install with Composer, configure your TikTok client ID and secret, and authenticate users via the socialiteproviders/tiktok driver.

Deep Wiki
Context7

Getting Started

Install the driver together with the manager package it depends on:

composer require socialiteproviders/manager socialiteproviders/tiktok

Register the driver's event listener. In Laravel ≤10 that lives in app/Providers/EventServiceProvider.php:

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

If you're on the Laravel 11+ skeleton (no EventServiceProvider by default), do the same thing in AppServiceProvider::boot():

Event::listen(
    \SocialiteProviders\Manager\SocialiteWasCalled::class,
    \SocialiteProviders\TikTok\TikTokExtendSocialite::class.'@handle',
);

Add credentials in config/services.php:

'tiktok' => [
    'client_id'     => env('TIKTOK_CLIENT_ID'),
    'client_secret' => env('TIKTOK_CLIENT_SECRET'),
    'redirect'      => env('TIKTOK_REDIRECT_URI'),
],

Wire two routes and you have your first use case — a login button that redirects out and a callback that returns a SocialiteProviders\Manager\OAuth2\User:

Route::get('/auth/tiktok/redirect', fn () =>
    Socialite::driver('tiktok')
        ->scopes(['user.info.basic'])   // TikTok needs explicit scopes
        ->redirect()
);

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

    $user = User::firstOrCreate(
        ['tiktok_id' => $tiktokUser->getId()],
        ['name' => $tiktokUser->getName(), 'avatar' => $tiktokUser->getAvatar()],
    );

    Auth::login($user, remember: true);
    return redirect()->intended('/dashboard');
});

The first place to look when something breaks is the provider class itself (vendor/socialiteproviders/tiktok/Provider.php) — it's small, and it tells you exactly which scopes, URLs, and response keys the driver expects.

Implementation Patterns

Standard web redirect flow. Redirect → TikTok consent → callback → ->user()->getId(). Keep the scopes() call explicit and identical between redirect and callback; TikTok ties the issued token to the scope set requested at authorize time.

Stateless / API-driven flow. For a SPA or mobile client that obtains the code itself, use stateless() so Socialite doesn't attempt session state validation, and pass the code back to your API:

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

If the client sends an access token instead of a code, call ->userFromToken($token) (present on most Socialite Providers drivers — verify against the vendor class before relying on it).

Account linking table. Store both identifiers, because TikTok exposes two IDs with different scopes:

Schema::create('social_accounts', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained()->cascadeOnDelete();
    $table->string('provider');
    $table->string('provider_user_id'); // tiktok open_id
    $table->string('union_id')->nullable();
    $table->text('access_token');
    $table->text('refresh_token')->nullable();
    $table->timestamp('expires_at')->nullable();
    $table->timestamps();
    $table->unique(['provider', 'provider_user_id']);
});

open_id is per-app per-user; union_id is stable across all apps under the same developer account. Use open_id for login, union_id if you ever add a second TikTok app.

Token lifecycle. Store $user->token, $user->refreshToken, and compute expires_at from $user->expiresIn. TikTok access tokens are short-lived (~24h), so schedule a refresh job well before expiry rather than refreshing on request. The driver exposes TikTok's refresh endpoint; typical usage is $provider->refreshToken($storedRefreshToken) — check the vendor signature, and always overwrite the stored refresh token with the one in the response, since it is re-issued.

Raw payload access. $user->getRaw() / $user->user gives the mapped user array; $user->accessTokenResponseBody gives the raw token exchange body (open_id, scope, token_type). Persist these if you need to debug or support multiple apps.

Testing. Mock the driver so tests never hit TikTok:

Socialite::shouldReceive('driver->user')->andReturn(
    (new \SocialiteProviders\Manager\OAuth2\User)->map(['id' => 'abc', 'name' => 'Test'])
);

Or use Http::fake() around the token/user endpoints if you want to exercise the provider's mapping logic.

Multi-provider abstraction. Since the driver is just a string, keep a SocialiteController with redirect($provider) / callback($provider) and an allowlist of providers — swapping in Google/GitHub later is a config change, not a new controller.

Gotchas and Tips

  • Driver [tiktok] is not supported is almost always the missing event listener, or a cached event map. Run php artisan event:clear and php artisan config:clear. In Laravel 11+, forgetting that EventServiceProvider no longer exists is the usual cause.
  • Config cache poisoning. Adding services.tiktok and then forgetting php artisan config:cache gives you null client IDs and a cryptic TikTok error page. Cache after editing.
  • No email scope. TikTok's user.info.basic returns open_id, union_id, display_name, and avatar_url — no email. $user->getEmail() will be null. Don't build a standard Laravel starter-kit auth flow expecting an email; either prompt for one after linking or generate a placeholder.
  • Empty scopes fail. Omitting ->scopes([...]) frequently produces an authorization error from TikTok. user.info.basic is the minimum for login; user.info.profile adds display_name/avatar_url, user.info.stats adds follower counts.
  • Redirect URI must match byte-for-byte, including scheme and trailing slash, and must be HTTPS and registered in the TikTok developer portal. http://localhost will be rejected outside sandbox configuration.
  • Sandbox mode is a common surprise. A newly created TikTok app can only authenticate test users you've explicitly added, which looks like "the login works for me but not my teammate."
  • Raw user response is nested. TikTok's user endpoint returns { "data": { "user": { ... } } }; the driver unwraps it for you, but if you inspect getRaw() and see no open_id, check whether you're looking at $user->user (unwrapped) versus $user->accessTokenResponseBody.
  • Refresh tokens rotate. Each refresh returns a new refresh_token; failing to persist it will break the next refresh and force re-consent.
  • State/session issues behind a load balancer. InvalidStateException on callback usually means session cookies aren't shared across instances, or the redirect was opened in a different browser tab than the callback. stateless() sidesteps this at the cost of CSRF protection — only use it when you have your own state handling.
  • Debugging a failed token exchange. The provider wraps Guzzle, so the useful detail is inside the exception. Wrap the callback in try/catch (Throwable $e) and report($e), then replay the token request manually with Http::asForm()->post('https://open.tiktokapis.com/v2/oauth/token/', [...]) to see TikTok's actual error/error_description.
  • Extension point: if you need to tweak the auth URL or mapping, don't fork — Socialite::extend('tiktok', fn ($app) => new YourSubclass($app['request'], $config)) and override getAuthUrl/mapUserToObject.
  • The package last shipped in April 2024, so pin the major version in composer.json and re-test the OAuth flow after any Socialite core upgrade — TikTok has revised its v2 endpoints before.
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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin