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

Odnoklassniki Laravel Package

socialiteproviders/odnoklassniki

Odnoklassniki (OK.ru) OAuth2 provider for Laravel Socialite. Adds a ready-made driver so you can authenticate users via Odnoklassniki with one line: Socialite::driver('odnoklassniki')->redirect(). Install with Composer, set your client ID and secret, and receive standard Socialite user objects.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install the split package. The provider lives in the socialiteproviders/providers monorepo but is published separately, so Composer pulls in the manager package and Socialite automatically:

composer require socialiteproviders/odnoklassniki

Two transitive dependencies matter: socialiteproviders/manager (the wiring layer) and laravel/socialite (the driver contract). If either is held back by your app's constraints, this install will fail — check composer why-not before going further.

2. Register the provider listener. This is the step people skip, and it produces the least helpful error message in the whole flow.

// Laravel <= 10: app/Providers/EventServiceProvider.php
protected $listen = [
    \SocialiteProviders\Manager\SocialiteWasCalled::class => [
        \SocialiteProviders\Odnoklassniki\OdnoklassnikiExtendSocialite::class.'@handle',
    ],
];

// Laravel 11+: AppServiceProvider::boot()
Event::listen(
    \SocialiteProviders\Manager\SocialiteWasCalled::class,
    [\SocialiteProviders\Odnoklassniki\OdnoklassnikiExtendSocialite::class, 'handle']
);

3. Create the OK.ru application at ok.ru → Мои приложения. You get three credentials, not two: an Application ID (client_id), a Public key (application_key), and a Secret key (client_secret). Odnoklassniki's API signs requests with the public key alongside the secret, so the provider needs all three. Register the callback URL in the same screen.

4. Configure config/services.php — the array key must be lowercase and match the driver name exactly:

'odnoklassniki' => [
    'client_id'       => env('ODNOKLASSNIKI_CLIENT_ID'),
    'client_secret'   => env('ODNOKLASSNIKI_CLIENT_SECRET'),
    'application_key' => env('ODNOKLASSNIKI_APPLICATION_KEY'),
    'redirect'        => env('ODNOKLASSNIKI_REDIRECT_URI'),
],

5. First use case — "Sign in with OK.ru" on the login page. Two routes and one controller action get you to a user object:

Route::get('/auth/ok/redirect', fn () => Socialite::driver('odnoklassniki')->redirect());

Route::get('/auth/ok/callback', function (Request $request) {
    $okUser = Socialite::driver('odnoklassniki')->user();

    // $okUser->getId(), ->getName(), ->getNickname(), ->getEmail(), ->getAvatar()
    // $okUser->token, ->refreshToken, ->expiresIn, ->getRaw()
});

Where to look first when something breaks: the provider source (vendor/socialiteproviders/odnoklassniki/Provider.php) and $okUser->getRaw(). The provider does almost nothing beyond token exchange, a signed fb.do call, and a field mapping — reading those ~80 lines will answer most questions faster than the README.

Implementation Patterns

Persist by (provider, provider_id), never by email. OK.ru does not reliably return an email, and when it does the user must have granted GET_EMAIL. A social_accounts table keyed on (provider, provider_id) with a nullable user_id is the pattern that survives every other provider you add later.

$account = SocialAccount::firstOrNew([
    'provider'    => 'odnoklassniki',
    'provider_id' => $okUser->getId(),   // string — see Gotchas
]);

$account->fill([
    'nickname'    => $okUser->getNickname(),
    'name'        => $okUser->getName(),
    'avatar'      => $okUser->getAvatar(),
    'token'       => $okUser->token,
    'refresh_token' => $okUser->refreshToken,
    'expires_at'  => now()->addSeconds($okUser->expiresIn ?? 0),
])->save();

$user = $account->user ?? tap(User::create([
    'name'  => $okUser->getName() ?: $okUser->getNickname(),
    'email' => $okUser->getEmail(),   // may be null
]), fn ($u) => $account->user()->associate($u)->save());

Auth::login($user);

Account linking from an authenticated session. Reuse the same redirect route but stash intent in the session and pass a signed state through, so the callback knows whether it is creating a user or attaching one:

Route::get('/settings/link/ok', function () {
    session(['social.link' => true]);
    return Socialite::driver('odnoklassniki')->redirect();
});

In the callback, branch on session()->pull('social.link') and attach to auth()->id() instead of logging in. Reject the attach if that (provider, provider_id) row already belongs to a different user — otherwise you have an account-takeover vector.

Scope requests deliberately. The provider's default scope is narrow (typically VALUABLE_ACCESS). Ask for more only when you need it, and remember OK.ru joins scopes with ;:

Socialite::driver('odnoklassniki')->scopes(['VALUABLE_ACCESS', 'GET_EMAIL'])->redirect();

Adding GET_EMAIL changes the consent screen and may reduce conversion — request it on a profile-completion step rather than at first login if email is optional for your product.

One controller, many providers. If OK.ru is one of several buttons, keep the driver name in a validated allowlist and avoid branching per provider in the controller:

$driver = Socialite::driver($provider);   // $provider validated against config('services') keys

Stateless for API/mobile flows. ->stateless() skips session state validation; only use it when you are supplying your own CSRF protection, because otherwise the callback is replayable.

Testing. Do not hit ok.ru in tests. Fake the driver at the facade level:

Socialite::shouldReceive('driver->user')->andReturn(
    (new \Laravel\Socialite\Two\User)->map([
        'id' => '1234567890', 'nickname' => 'test', 'name' => 'Test User',
        'email' => '[email protected]', 'avatar' => 'https://…',
    ])
);

Assert the resulting social_accounts row and the authenticated session rather than the Socialite call itself.

Gotchas and Tips

Driver [odnoklassniki] is not supported means the listener is not registered — in Laravel 11 this is almost always because EventServiceProvider no longer exists and the listener was never moved into AppServiceProvider::boot(). The config block existing is not enough.

Missing application_key surfaces as a signature error, not a config error. The provider computes sig as an MD5 over alphabetically sorted params with md5(access_token . client_secret) appended; without the public key the signature is wrong and OK.ru returns PARAM_SIGNATURE / error code 104. It reads like an expired token and sends people down the wrong path. If you ever call fb.do yourself, replicate the sort-then-concat-then-double-MD5 exactly, and remember the access_token parameter is not included in the signed string.

OK.ru returns errors with HTTP 200. Check the decoded body for error_code / error_msg, not just the status. Messages are frequently in Russian and truncated — log $okUser->getRaw() (minus the token) on failure. The provider throws a Laravel\Socialite\Two\InvalidStateException for CSRF mismatch and a Guzzle RequestException for transport failures, but an API-level rejection may come back as a user object with missing fields rather than an exception.

getId() returns a string. Do not type-hint int on the column or compare with === against an integer. If you store it in a Postgres bigint, cast explicitly and reject non-numeric values — a forged callback with a junk id should not blow up the insert.

Email is absent more often than you expect. Even with GET_EMAIL, users can decline, and OK.ru is stricter than Google about which accounts have one. Make users.email nullable or run a "confirm your email" interstitial; do not let firstOrCreate(['email' => null]) silently merge unrelated accounts.

Redirect URI must match byte-for-byte. http vs https, www vs apex, and trailing slashes all break the token exchange. Store it in env() once and reuse the same value in the OK.ru dashboard. Behind a proxy, Socialite may generate an http:// URL from the request — add TrustProxies or the redirect will not match what you registered.

Avatar URLs (pic_1 … pic_*) are hotlink-protected and can 403 when embedded from a different origin. Either proxy them through your app or download to your own storage at registration time. The provider maps one of these fields to avatar, so do not assume the URL is stable long-term.

The monorepo version is not the package version. socialiteproviders/providers tags releases that may not correspond to the split package's tag, and a release can bump dozens of providers at once. Pin socialiteproviders/odnoklassniki:^4.1 and treat laravel/socialite and socialiteproviders/manager as the axes that actually matter when upgrading. PHP 8 support arrived in 4.1.0; on PHP 8.1+ watch the deprecation log after upgrading, since a constraint-widening release is not the same as a runtime-tested one.

Extension point: subclass the provider for custom mapping. If OK.ru's field names do not match your schema (they will not, exactly), subclass and override mapUserToObject, then register your own driver via Socialite::extend('odnoklassniki', fn ($app) => $app->make(YourProvider::class)) instead of patching the vendor file. This is also the clean seam for swapping in a mocked HTTP client in integration tests.

Rate limits and token lifetime. Refresh tokens are long-lived but the access token is short; if you call fb.do after login, persist expires_at and refresh proactively rather than catching the 102 error. Cache the profile fetch — there is no reason to call OK.ru on every page load.

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