VK ID Authentication Implementation for Websites
VK ID is VKontakte's unified authorization system, replacing VK Connect. Relevant for Russian-speaking audiences—VK remains the largest social network in Russia and CIS. Supports OAuth2 and new VK ID SDK with improved UX.
Creating Application
- vk.com/dev → My apps → Create application
- Type: Website
- Specify site address and base domain
- Save Application ID and Secure key
- In settings → Authorization add allowed redirect URIs
Laravel Socialite
composer require laravel/socialite socialiteproviders/vkontakte
// config/services.php
'vkontakte' => [
'client_id' => env('VK_CLIENT_ID'),
'client_secret' => env('VK_CLIENT_SECRET'),
'redirect' => env('VK_REDIRECT_URI'),
],
class VkAuthController extends Controller
{
public function redirect(): RedirectResponse
{
return Socialite::driver('vkontakte')->scopes(['email'])->redirect();
}
public function callback(): RedirectResponse
{
try {
$vkUser = Socialite::driver('vkontakte')->user();
} catch (\Exception $e) {
return redirect('/login')->withErrors(['vk' => 'VK authorization error']);
}
$user = User::updateOrCreate(
['vk_id' => $vkUser->getId()],
[
'name' => $vkUser->getName(),
'email' => $vkUser->getEmail() ?: null,
'avatar' => $vkUser->getAvatar(),
]
);
if ($vkUser->getEmail() && !$user->email_verified_at) {
$user->update(['email_verified_at' => now()]);
}
Auth::login($user, remember: true);
return redirect()->intended('/dashboard');
}
}
VK OAuth Features
Email available only with explicit scope. Even with scope email, VK passes it not via standard OAuth but in callback parameters. Socialite provider handles this automatically.
Email may not arrive—if user hasn't confirmed email in VK or didn't grant permission.
Avatar: URL returns directly, stays current. No need to cache.
VK ID SDK (New Method)
VKontakte released official VK ID SDK for JavaScript with One Tap support:
<script src="https://unpkg.com/@vkid/sdk@latest/dist-cdn/index.js"></script>
<div id="vkid-container"></div>
<script>
const { VKID, OneTap, Auth } = window['@vkid/sdk'];
VKID.Config.init({
app: parseInt('{{ config("services.vkontakte.client_id") }}'),
redirectUrl: '{{ config("services.vkontakte.redirect") }}',
responseMode: VKID.ConfigResponseMode.Callback,
});
const oneTap = new OneTap();
oneTap.render({ container: document.getElementById('vkid-container') })
.on(Auth.AuthEventType.LOGIN_SUCCESS, (payload) => {
fetch('/auth/vk/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken },
body: JSON.stringify({ silent_token: payload.token, uuid: payload.uuid }),
});
});
</script>
// Exchange silent_token for access_token via VK API
public function handleToken(Request $request): JsonResponse
{
$response = Http::get('https://api.vk.com/method/auth.exchangeSilentAuthToken', [
'v' => '5.199',
'token' => $request->silent_token,
'access_token' => config('services.vkontakte.service_token'),
'uuid' => $request->uuid,
]);
$data = $response->json('response');
// $data contains access_token, user_id, email
}
Timeline
OAuth2 flow via Socialite—1–1.5 days. With VK ID SDK and missing email handling—2–3 days.







