https://github.com/tigusigalpa/vtb-id-php
PHP/Laravel пакет для интеграции OAuth2 авторизации через VTB ID. Поддерживает Laravel 8-12 и чистый PHP 8.0+. Включает полный OAuth2 flow (авторизация, обмен токенов, refresh, revoke), получение данных пользователя, встроенные маршруты, middleware, facade, события и helper-функции. Простая установка через Composer с подробной документацией.
https://github.com/tigusigalpa/vtb-id-php
api laravel oauth2 oauth2-client php vtb vtb-id vtbid
Last synced: 5 months ago
JSON representation
PHP/Laravel пакет для интеграции OAuth2 авторизации через VTB ID. Поддерживает Laravel 8-12 и чистый PHP 8.0+. Включает полный OAuth2 flow (авторизация, обмен токенов, refresh, revoke), получение данных пользователя, встроенные маршруты, middleware, facade, события и helper-функции. Простая установка через Composer с подробной документацией.
- Host: GitHub
- URL: https://github.com/tigusigalpa/vtb-id-php
- Owner: tigusigalpa
- License: mit
- Created: 2025-12-24T05:24:47.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2025-12-24T05:30:35.000Z (6 months ago)
- Last Synced: 2025-12-25T18:51:38.573Z (6 months ago)
- Topics: api, laravel, oauth2, oauth2-client, php, vtb, vtb-id, vtbid
- Language: PHP
- Homepage:
- Size: 21.5 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README-en.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.md
Awesome Lists containing this project
README
# VTB ID PHP/Laravel Package

[](https://github.com/tigusigalpa/vtb-id-php/releases)
[](LICENSE.md)
PHP/Laravel package for VTB ID integration (OAuth2 authorization via VTB Bank account).
**🌐 Language:** English | [Русский](README.md)
## Table of Contents
- [Requirements](#requirements)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Configuration](#configuration)
- [Usage](#usage)
- [API Reference](#api-reference)
- [Usage Examples](#usage-examples)
- [Security](#security)
- [Testing](#testing)
## Requirements
- PHP 8.0 or higher
- Guzzle HTTP Client 7.x
- Laravel 8.x, 9.x, 10.x, 11.x or 12.x (optional, for Laravel integration)
## Installation
### Via Composer (Recommended)
```bash
composer require tigusigalpa/vtb-id-php
```
### Publish Configuration
```bash
php artisan vendor:publish --tag=vtbid-config
```
### Local Installation (for development)
Add repository to `composer.json`:
```json
{
"repositories": [
{
"type": "path",
"url": "./packages/vtb-id-php"
}
],
"require": {
"tigusigalpa/vtb-id-php": "@dev"
}
}
```
Then install:
```bash
composer require tigusigalpa/vtb-id-php:@dev
```
## Quick Start
### For Laravel
#### 1. Installation (1 minute)
```bash
composer require tigusigalpa/vtb-id-php
php artisan vendor:publish --tag=vtbid-config
```
#### 2. Configuration (2 minutes)
Add to `.env`:
```env
VTBID_CLIENT_ID=your_client_id_from_vtb
VTBID_CLIENT_SECRET=your_client_secret_from_vtb
VTBID_REDIRECT_URI=https://your-domain.com/auth/vtb/callback
```
#### 3. Create Routes (2 minutes)
In `routes/web.php`:
```php
// Success route
Route::get('/auth/vtb/success', function () {
$user = session('vtbid_user');
// Create/update user in database
// and authenticate them in the system
dd($user); // For testing
})->name('vtbid.success');
// Error route
Route::get('/auth/vtb/error', function () {
$error = session('error');
return redirect('/login')->with('error', $error);
})->name('vtbid.error');
```
#### 4. Add Login Button
In any blade template:
```blade
Login with VTB ID
```
### For Plain PHP
#### 1. Installation
```bash
composer require tigusigalpa/vtb-id-php
```
#### 2. Create Configuration File
```php
// config.php
return [
'client_id' => 'your_client_id',
'client_secret' => 'your_client_secret',
'redirect_uri' => 'https://your-domain.com/callback.php',
];
```
#### 3. Login Page (login.php)
```php
generateState();
$_SESSION['vtbid_state'] = $state;
$authUrl = $client->getAuthorizationUrl($state);
header('Location: ' . $authUrl);
exit;
```
#### 4. Callback Handler (callback.php)
```php
getAccessToken($code);
// Get user data
$userData = $client->getUserData($tokenData['access_token']);
// Save to session
$_SESSION['vtbid_access_token'] = $tokenData['access_token'];
$_SESSION['vtbid_refresh_token'] = $tokenData['refresh_token'] ?? null;
$_SESSION['vtbid_user'] = $userData->toArray();
// Redirect to dashboard
header('Location: /dashboard.php');
exit;
} catch (VTBIDException $e) {
die('Authentication error: ' . $e->getMessage());
}
```
#### 5. User Dashboard (dashboard.php)
```php
Dashboard
Welcome, = htmlspecialchars($user['name']) ?>!
Email: = htmlspecialchars($user['email']) ?>
Phone: = htmlspecialchars($user['mainMobilePhone']) ?>
Logout
```
### Done! 🎉
Users can now authenticate via VTB ID.
## Configuration
### Environment Variables
Add to `.env`:
```env
VTBID_CLIENT_ID=your_client_id
VTBID_CLIENT_SECRET=your_client_secret
VTBID_REDIRECT_URI=https://your-domain.com/auth/vtb/callback
# Optional parameters
VTBID_BASE_URL=https://id.vtb.ru
VTBID_USER_DATA_URL=https://gost-id.vtb.ru
VTBID_SCOPE="openid name surname patronymic gender mainMobilePhone email"
VTBID_RESPONSE_TYPE=code
# Route settings
VTBID_ROUTES_ENABLED=true
VTBID_ROUTES_PREFIX=auth/vtb
```
### Getting VTB ID Credentials
1. Register on VTB ID developer portal
2. Create new application
3. Set Redirect URI: `https://your-domain.com/auth/vtb/callback`
4. Select required scopes
5. Get `client_id` and `client_secret`
### Available Scopes
```
openid - Required, basic authorization
name - First name
surname - Last name
patronymic - Middle name (patronymic)
gender - Gender
birthdate - Date of birth
mainMobilePhone - Primary phone
email - Email
inn - Tax identification number
snils - Insurance number
```
## Usage
### Basic Usage with Built-in Routes
The package automatically registers the following routes:
- `GET /auth/vtb/redirect` - Redirect to VTB ID authorization page
- `GET /auth/vtb/callback` - Handle callback from VTB ID
To start authorization, simply redirect the user to:
```php
return redirect()->route('vtbid.redirect');
```
### Using VTBIDClient Directly
```php
use Tigusigalpa\VTBID\VTBIDClient;
use Tigusigalpa\VTBID\Exceptions\VTBIDException;
// Via Dependency Injection
public function __construct(protected VTBIDClient $vtbid)
{
}
// Or via Facade
use Tigusigalpa\VTBID\Facades\VTBID;
// Get authorization URL
$state = VTBID::generateState();
session(['vtbid_state' => $state]);
$authUrl = VTBID::getAuthorizationUrl($state);
return redirect($authUrl);
// Handle callback
try {
$tokenData = VTBID::getAccessToken($code);
// $tokenData contains: access_token, refresh_token, expires_in, token_type
$userData = VTBID::getUserData($tokenData['access_token']);
// Access user data
echo $userData->name;
echo $userData->surname;
echo $userData->email;
echo $userData->getFullName(); // Surname Name Patronymic
} catch (VTBIDException $e) {
Log::error('VTB ID Error: ' . $e->getMessage());
}
```
### Refresh Token
```php
try {
$refreshToken = session('vtbid_refresh_token');
$newTokenData = VTBID::refreshAccessToken($refreshToken);
session([
'vtbid_access_token' => $newTokenData['access_token'],
'vtbid_refresh_token' => $newTokenData['refresh_token'] ?? null,
]);
} catch (VTBIDException $e) {
// Token expired or invalid
}
```
### Revoke Token
```php
try {
$accessToken = session('vtbid_access_token');
VTBID::revokeToken($accessToken, 'access_token');
session()->forget(['vtbid_access_token', 'vtbid_refresh_token', 'vtbid_user']);
} catch (VTBIDException $e) {
Log::error('Failed to revoke token: ' . $e->getMessage());
}
```
### Helper Functions
```php
// Check authentication
if (vtbid_authenticated()) {
$user = vtbid_user();
$token = vtbid_access_token();
}
```
## User Data
The `VTBIDUser` object contains the following fields:
- `sub` - Unique user identifier
- `name` - First name
- `surname` - Last name
- `patronymic` - Middle name (patronymic)
- `gender` - Gender (male/female)
- `birthdate` - Date of birth
- `mainMobilePhone` - Primary mobile phone
- `email` - Email address
- `emailVerified` - Email verified (boolean)
- `phoneNumberVerified` - Phone verified (boolean)
- `inn` - Tax identification number
- `snils` - Insurance number
### VTBIDUser Methods
```php
$userData->getFullName(); // Returns "Surname Name Patronymic"
$userData->toArray(); // Convert to array
$userData->getRawData(); // Returns raw data from API
```
## Integration with Laravel Auth
### Update User Migration
```bash
php artisan make:migration add_vtb_id_fields_to_users_table
```
```php
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('vtb_id')->nullable()->unique()->after('id');
$table->string('surname')->nullable()->after('name');
$table->string('patronymic')->nullable()->after('surname');
$table->string('phone')->nullable()->after('email');
});
}
```
```bash
php artisan migrate
```
### Update User Model
```php
protected $fillable = [
'name',
'surname',
'patronymic',
'email',
'phone',
'vtb_id',
'password',
];
```
### Example Controller
```php
use App\Models\User;
use Illuminate\Support\Facades\Auth;
Route::get('/auth/vtb/success', function () {
$vtbUser = session('vtbid_user');
$user = User::updateOrCreate(
['vtb_id' => $vtbUser['sub']],
[
'name' => $vtbUser['name'],
'surname' => $vtbUser['surname'],
'patronymic' => $vtbUser['patronymic'],
'email' => $vtbUser['email'],
'phone' => $vtbUser['mainMobilePhone'],
]
);
Auth::login($user, true);
return redirect('/dashboard');
})->name('vtbid.success');
```
## API Reference
### VTBIDClient
#### Constructor
```php
public function __construct(array $config = [])
```
**Parameters:**
- `client_id` (string) - VTB ID application ID
- `client_secret` (string) - Application secret key
- `redirect_uri` (string) - Callback URL
- `base_url` (string, optional) - Base API URL
- `user_data_url` (string, optional) - User data URL
- `scope` (string, optional) - Requested permissions
- `response_type` (string, optional) - Response type
#### getAuthorizationUrl()
```php
public function getAuthorizationUrl(?string $state = null): string
```
Generates URL for redirecting user to VTB ID authorization page.
#### generateState()
```php
public function generateState(): string
```
Generates random string for state parameter (CSRF protection).
#### getAccessToken()
```php
public function getAccessToken(string $code): array
```
Exchanges authorization code for access token.
**Returns:**
```php
[
'access_token' => '...',
'refresh_token' => '...',
'expires_in' => 3600,
'token_type' => 'Bearer'
]
```
#### refreshAccessToken()
```php
public function refreshAccessToken(string $refreshToken): array
```
Refreshes access token using refresh token.
#### getUserData()
```php
public function getUserData(string $accessToken): VTBIDUser
```
Gets user data using access token.
#### revokeToken()
```php
public function revokeToken(string $token, string $tokenTypeHint = 'access_token'): bool
```
Revokes (invalidates) token.
### Facade: VTBID
```php
use Tigusigalpa\VTBID\Facades\VTBID;
$authUrl = VTBID::getAuthorizationUrl();
$state = VTBID::generateState();
$tokenData = VTBID::getAccessToken($code);
$userData = VTBID::getUserData($accessToken);
$newTokenData = VTBID::refreshAccessToken($refreshToken);
VTBID::revokeToken($token);
```
### Middleware
#### VTBIDAuthenticated
Register in `app/Http/Kernel.php`:
```php
protected $routeMiddleware = [
'vtbid.auth' => \Tigusigalpa\VTBID\Middleware\VTBIDAuthenticated::class,
];
```
Usage:
```php
Route::middleware(['vtbid.auth'])->group(function () {
Route::get('/profile', function () {
return view('profile', ['user' => vtbid_user()]);
});
});
```
## Usage Examples
### Plain PHP Usage
#### Complete Application Example
**Project Structure:**
```
/
├── vendor/
├── config.php
├── login.php
├── callback.php
├── dashboard.php
├── logout.php
└── composer.json
```
**logout.php:**
```php
revokeToken($_SESSION['vtbid_access_token']);
} catch (VTBIDException $e) {
error_log('Failed to revoke token: ' . $e->getMessage());
}
}
// Clear session
session_destroy();
header('Location: /login.php');
exit;
```
**Token Refresh:**
```php
refreshAccessToken($_SESSION['vtbid_refresh_token']);
$_SESSION['vtbid_access_token'] = $newTokenData['access_token'];
$_SESSION['vtbid_refresh_token'] = $newTokenData['refresh_token'] ?? $_SESSION['vtbid_refresh_token'];
echo "Token refreshed successfully!";
} catch (VTBIDException $e) {
echo "Token refresh error: " . $e->getMessage();
header('Location: /login.php');
exit;
}
}
```
**Database Integration:**
```php
getAccessToken($code);
$userData = $client->getUserData($tokenData['access_token']);
// Database connection
$pdo = new PDO('mysql:host=localhost;dbname=myapp', 'username', 'password');
// Find or create user
$stmt = $pdo->prepare("
INSERT INTO users (vtb_id, name, surname, patronymic, email, phone, created_at, updated_at)
VALUES (:vtb_id, :name, :surname, :patronymic, :email, :phone, NOW(), NOW())
ON DUPLICATE KEY UPDATE
name = :name,
surname = :surname,
patronymic = :patronymic,
email = :email,
phone = :phone,
updated_at = NOW()
");
$stmt->execute([
'vtb_id' => $userData->sub,
'name' => $userData->name,
'surname' => $userData->surname,
'patronymic' => $userData->patronymic,
'email' => $userData->email,
'phone' => $userData->mainMobilePhone,
]);
$userId = $pdo->lastInsertId() ?: $pdo->query("SELECT id FROM users WHERE vtb_id = '{$userData->sub}'")->fetchColumn();
// Save to session
$_SESSION['user_id'] = $userId;
$_SESSION['vtbid_access_token'] = $tokenData['access_token'];
$_SESSION['vtbid_user'] = $userData->toArray();
header('Location: /dashboard.php');
exit;
} catch (VTBIDException $e) {
die('Authentication error: ' . $e->getMessage());
} catch (PDOException $e) {
die('Database error: ' . $e->getMessage());
}
```
### Custom Routes (Laravel)
Disable built-in routes in `.env`:
```env
VTBID_ROUTES_ENABLED=false
```
Create your own routes:
```php
use Tigusigalpa\VTBID\VTBIDClient;
use Tigusigalpa\VTBID\Exceptions\VTBIDException;
Route::get('/custom/vtb/login', function (VTBIDClient $vtbid) {
$state = $vtbid->generateState();
session(['vtbid_state' => $state]);
return redirect($vtbid->getAuthorizationUrl($state));
});
Route::get('/custom/vtb/callback', function (Request $request, VTBIDClient $vtbid) {
$code = $request->input('code');
$state = $request->input('state');
if (!$code || session('vtbid_state') !== $state) {
return redirect()->route('login')->with('error', 'Invalid request');
}
try {
$tokenData = $vtbid->getAccessToken($code);
$userData = $vtbid->getUserData($tokenData['access_token']);
// Your logic
return redirect()->route('dashboard');
} catch (VTBIDException $e) {
return redirect()->route('login')->with('error', $e->getMessage());
}
});
```
### Error Handling
Global handler in `app/Exceptions/Handler.php`:
```php
use Tigusigalpa\VTBID\Exceptions\VTBIDException;
public function register()
{
$this->renderable(function (VTBIDException $e, $request) {
\Log::error('VTB ID Exception', [
'message' => $e->getMessage(),
'code' => $e->getCode(),
]);
if ($request->expectsJson()) {
return response()->json([
'error' => 'vtb_id_error',
'message' => $e->getMessage(),
], 400);
}
return redirect()->route('login')
->with('error', 'VTB ID Error: ' . $e->getMessage());
});
}
```
### Auto-refresh Token
Middleware for automatic token refresh:
```php
namespace App\Http\Middleware;
use Closure;
use Tigusigalpa\VTBID\Facades\VTBID;
use Tigusigalpa\VTBID\Exceptions\VTBIDException;
class RefreshVTBIDToken
{
public function handle(Request $request, Closure $next)
{
if (!session()->has('vtbid_access_token')) {
return redirect()->route('vtbid.redirect');
}
$expiresAt = session('vtbid_token_expires_at');
if ($expiresAt && now()->addMinutes(5)->greaterThan($expiresAt)) {
$refreshToken = session('vtbid_refresh_token');
if ($refreshToken) {
try {
$newTokenData = VTBID::refreshAccessToken($refreshToken);
session([
'vtbid_access_token' => $newTokenData['access_token'],
'vtbid_refresh_token' => $newTokenData['refresh_token'] ?? $refreshToken,
'vtbid_token_expires_at' => now()->addSeconds($newTokenData['expires_in'] ?? 3600),
]);
} catch (VTBIDException $e) {
session()->forget(['vtbid_access_token', 'vtbid_refresh_token']);
return redirect()->route('vtbid.redirect');
}
}
}
return $next($request);
}
}
```
## Security
### Required Measures
1. **HTTPS is mandatory** - VTB ID doesn't work with HTTP
2. **Protect client_secret** - never commit to Git
3. **Verify state** - CSRF protection (already implemented in package)
4. **Validate redirect_uri** - must exactly match registered URI
### Recommendations
```php
// Verify email_verified
if (!$vtbUser['email_verified']) {
return redirect()->back()
->with('warning', 'Email not verified');
}
// Log authentication attempts
\Log::info('VTB ID login attempt', [
'vtb_id' => $vtbUser['sub'],
'email' => $vtbUser['email'],
]);
```
### Production Setup
#### HTTPS Required
```env
APP_URL=https://your-domain.com
VTBID_REDIRECT_URI=https://your-domain.com/auth/vtb/callback
```
#### Session Security
In `config/session.php`:
```php
'secure' => env('SESSION_SECURE_COOKIE', true),
'http_only' => true,
'same_site' => 'lax',
```
#### Cache Configuration
```bash
php artisan config:cache
php artisan route:cache
```
## Testing
```bash
composer test
```
### Verify Installation
```bash
php artisan tinker
```
```php
>>> config('vtbid.client_id')
=> "your_client_id"
>>> app(Tigusigalpa\VTBID\VTBIDClient::class)
=> Tigusigalpa\VTBID\VTBIDClient {#...}
>>> route('vtbid.redirect')
=> "http://your-domain.test/auth/vtb/redirect"
```
### Check Routes
```bash
php artisan route:list | grep vtb
```
## Troubleshooting
### "Class VTBIDServiceProvider not found"
```bash
composer dump-autoload
php artisan config:clear
php artisan cache:clear
```
### "Route [vtbid.success] not defined"
Create `vtbid.success` route in `routes/web.php`
### "invalid_client"
Check `VTBID_CLIENT_ID` and `VTBID_CLIENT_SECRET` in `.env`
### "redirect_uri_mismatch"
Ensure `VTBID_REDIRECT_URI` exactly matches registered URI in VTB ID
## VTB ID Documentation
- [Official Documentation](https://www.vtb.ru/malyj-biznes/vtb-id/integraciya/)
- [User Data (PDF)](https://www.vtb.ru/media-files/vtb.ru/sitepages/malyj-biznes/vtb-id/integraciya/Dannye_polzovatelya.pdf)
- [Error List (PDF)](https://www.vtb.ru/media-files/vtb.ru/sitepages/malyj-biznes/vtb-id/integraciya/Perechen_oshibok.pdf)
## Endpoints
- **Authorization URL**: `https://id.vtb.ru/`
- **Token URL**: `https://id.vtb.ru/oauth2/token`
- **User Data URL**: `https://gost-id.vtb.ru/oauth2/me`
- **Revoke Token URL**: `https://id.vtb.ru/oauth2/revoke`
## License
MIT License. See [LICENSE.md](LICENSE.md) for details.
## Author
**Igor Sazonov**
- Email: sovletig@gmail.com
- GitHub: [@tigusigalpa](https://github.com/tigusigalpa)
## Support
If you have any issues or questions, please create an [issue on GitHub](https://github.com/tigusigalpa/vtb-id-php/issues).
---
Made with ❤️ for Laravel community