Nette DI Extension pro integraci BankID OAuth2/OpenID Connect autentizace.
Podporované země: 🇨🇿 Česká republika
PHP verze: 8.1, 8.2, 8.3, 8.4
ℹ️ Poznámka: Extension je připraven na budoucí podporu slovenského BankID, pokud bude systém spuštěn. Zatím však Slovensko nemá vlastní BankID implementaci. Kód umožňuje konfiguraci
country: 'sk's vlastními endpoints pro případné budoucí použití.
BankID je jednotné přihlašovací řešení poskytované bankami v České republice. Umožňuje uživatelům ověřit svou identitu pomocí internetového bankovnictví s nejvyšší úrovní bezpečnosti (LOA3).
composer require nks-hub/nette-bankidextensions:
bankid: NksHub\NetteBankId\DI\BankIdExtensionbankid:
clientId: 'your-client-id'
clientSecret: 'your-client-secret'
redirectUri: 'https://your-domain.com/bankid/callback'
sandbox: false # true pro testování, false pro production
country: 'cz' # pouze 'cz' (SK zatím není implementováno)
debug: false # true = Tracy debug panel + loggingExtension poskytuje OAuth2 provider pro BankID autentizaci. Ukládání dat do databáze je na vaší aplikaci.
- Navštivte BankID Developer Portal
- Zaregistrujte se jako vývojář
- Vytvořte novou aplikaci v Sandbox
- Získejte
client_idaclient_secret - Nastavte
redirect_uri(callback URL vaší aplikace)
- Projděte certifikačním procesem na BankID portálu
- Podepište smlouvu s poskytovatelem BankID
- Získejte produkční credentials
- Přepněte
sandbox: falsev konfiguraci
<?php
namespace App\Presenters;
use Nette\Application\UI\Presenter;
use NksHub\NetteBankId\OAuth2\BankIdProvider;
use NksHub\NetteBankId\Exceptions\VerificationFailedException;
class AuthPresenter extends Presenter
{
public function __construct(
private BankIdProvider $bankIdProvider,
) {
parent::__construct();
}
/**
* Krok 1: Redirect na BankID login
*/
public function actionLogin(): void
{
// Získej authorization URL
$authUrl = $this->bankIdProvider->getAuthorizationUrl();
// Ulož state do session pro CSRF ochranu
$this->getSession('bankid')->state = $this->bankIdProvider->getState();
// Redirect na BankID
$this->redirectUrl($authUrl);
}
/**
* Krok 2: Callback z BankID
*/
public function actionCallback(?string $code = null, ?string $state = null): void
{
if (!$code || !$state) {
$this->flashMessage('Autentizace selhala - chybí parametry', 'error');
$this->redirect('Homepage:');
}
try {
// Ověř, že se uživatel vrátil z BankID
$result = $this->bankIdProvider->authenticate($code, $state);
$userData = $result['user'];
$accessToken = $result['token'];
// Zde si můžete uložit user data do databáze nebo session
$this->getSession('user')->userData = $userData;
$this->flashMessage('Úspěšně přihlášeno přes BankID', 'success');
$this->redirect('Homepage:');
} catch (VerificationFailedException $e) {
$this->flashMessage('Autentizace selhala: ' . $e->getMessage(), 'error');
$this->redirect('Homepage:');
}
}
}Po úspěšné autentizaci získáte user data z BankID:
$result = $this->bankIdProvider->authenticate($code, $state);
$userData = $result['user'];
$accessToken = $result['token'];
// Dostupné user data:
$userData['sub']; // BankID user ID (unique identifier)
$userData['email']; // Email
$userData['given_name']; // Křestní jméno
$userData['family_name']; // Příjmení
$userData['name']; // Celé jméno
$userData['birthdate']; // Datum narození
$userData['phone_number']; // Telefon
$userData['acr']; // Level of Assurance (loa1, loa2, loa3)
$userData['address']; // Adresa (object)
// Access token info:
$accessToken->getToken(); // Access token string
$accessToken->getExpires(); // Expiration timestamp
$accessToken->getRefreshToken(); // Refresh token (if available)Extension poskytuje pouze OAuth2 autentizaci. Ukládání dat je na vaší aplikaci.
Příklad Doctrine entity:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
#[ORM\Table(name: 'bankid_verifications')]
class BankIdVerification
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private ?int $id = null;
#[ORM\Column(type: 'string', unique: true)]
private string $userId; // BankID sub
#[ORM\Column(type: 'string', nullable: true)]
private ?string $email = null;
#[ORM\Column(type: 'string', nullable: true)]
private ?string $fullName = null;
#[ORM\Column(type: 'datetime_immutable')]
private \DateTimeImmutable $verifiedAt;
// ... další properties podle potřeby
}Příklad service pro uložení:
<?php
namespace App\Service;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\BankIdVerification;
class BankIdService
{
public function __construct(
private EntityManagerInterface $em,
) {
}
public function saveVerification(array $userData): BankIdVerification
{
$verification = new BankIdVerification();
$verification->setUserId($userData['sub']);
$verification->setEmail($userData['email'] ?? null);
$verification->setFullName($userData['name'] ?? null);
$verification->setVerifiedAt(new \DateTimeImmutable());
$this->em->persist($verification);
$this->em->flush();
return $verification;
}
}Extension podporuje Tracy debug panel pro živé sledování BankID autentizace.
bankid:
debug: true # Aktivuje Tracy panel a loggingKdyž je debug: true, uvidíte v Tracy baru panel BankID s následujícími informacemi:
-
Základní info:
- Mode: Sandbox / Production
- Redirect URI
- Počet events
-
Authenticated User Data (po úspěšné autentizaci):
- sub (BankID user ID)
- name, given_name, family_name
- birthdate
- phone_number
- acr (Level of Assurance)
- další dostupná pole
-
Authentication Flow (živý log):
- Timing každého kroku (ms)
- Event popis (authenticate started, token retrieved, user info retrieved)
- Context data pro každý event
Kromě Tracy panelu se všechny debug info logují do souboru:
log/bankid.log
Formát logu:
[timestamp] Message
{
"context": {...}
}
BankID (3)
├─ Mode: Sandbox
├─ Redirect URI: https://prekupnici.loc/bankid/callback
└─ Logs: 3 events
Authenticated User Data:
├─ sub: 1234567890
├─ email: user@example.com
├─ name: Jan Novák
├─ given_name: Jan
├─ family_name: Novák
├─ birthdate: 1990-01-01
└─ acr: loa3
Authentication Flow:
├─ +0.00ms BankID authenticate started
│ code_length: 24, state: abc123...
├─ +125.50ms Access token retrieved
│ expires: 1234567890, has_refresh_token: false
└─ +234.12ms User info retrieved
sub: 1234567890, email: user@example.com, acr: loa3
# Production config
bankid:
debug: false # ← Vypnuto pro production
sandbox: falsebankid:
# Povinné parametry
clientId: 'your-client-id'
clientSecret: 'your-client-secret'
redirectUri: 'https://your-domain.com/bankid/callback'
# Volitelné parametry
sandbox: false # true = sandbox, false = production
country: 'cz' # pouze 'cz' podporováno (SK v budoucnu)
debug: false # true = Tracy panel + file logging
# Custom endpoints (pokud nechcete použít defaultní CZ endpoints)
# Pro budoucí SK BankID můžete použít custom URLs, až budou dostupné
authorizeUrl: null # null = použije se CZ default podle sandbox režimu
tokenUrl: null
userinfoUrl: nullbankid:
sandbox: true
clientId: 'sandbox-client-id'
clientSecret: 'sandbox-secret'
redirectUri: 'http://localhost:8080/bankid/callback'Testovací uživatelé: BankID poskytuje testovací účty v sandbox režimu - viz dokumentace na developer.bankid.cz
bankid:
sandbox: false
clientId: 'production-client-id'
clientSecret: 'production-secret'
redirectUri: 'https://your-domain.com/bankid/callback'Extension automaticky používá state token pro CSRF ochranu:
// Extension generuje a validuje state automaticky
$result = $this->bankIdProvider->authenticate($code, $state);Pro maximální bezpečnost doporučujeme šifrovat access_token a refresh_token v databázi:
// Použijte Doctrine encrypted column type nebo vlastní listener
use Doctrine\ORM\Mapping as ORM;
#[ORM\Column(type: 'encrypted_text')]
private string $accessToken;BankID VYŽADUJE HTTPS pro callback URL v production režimu.
bankid:
redirectUri: 'https://your-domain.com/bankid/callback' # HTTPS!Access tokeny mají omezenou platnost. Zkontrolujte platnost:
if (!$verification->isTokenValid()) {
// Token vypršel, vyžádejte novou autentizaci
}Pravidelně odstraňujte staré verifikace:
// Například v cron jobu
$repository->deleteExpired(new \DateTimeImmutable('-90 days'));BankID podporuje různé úrovně ověření:
- LOA1 - Nízká (základní identifikace)
- LOA2 - Střední (ověření dokumentem)
- LOA3 - Vysoká (bankovní identita) ← DEFAULT
Extension defaultně požaduje LOA3 (nejvyšší úroveň).
// Získej LOA z user dat
$loa = $verification->getAssuranceLevel(); // 'loa3'Příčina: Redirect URI v konfiguraci neodpovídá URI registrované v BankID portálu.
Řešení: Zkontrolujte, že redirectUri v config.neon přesně odpovídá URI v BankID developer portálu (včetně http/https, portu, path).
Příčina: CSRF token neodpovídá (možný útok nebo problém se session).
Řešení:
- Zkontrolujte, že máte správně nakonfigurované sessions v Nette
- Ujistěte se, že cookies fungují (session se ukládá do cookie)
- Zkontrolujte, že uživatel nebyl přesměrován přes jiný proxy/load balancer
Příčina: Sandbox má jiné endpoints než production.
Řešení: Ujistěte se, že máte sandbox: true v konfiguraci:
bankid:
sandbox: true # ← DŮLEŽITÉPříčina: Extension automaticky registruje mapping pouze pokud je Doctrine ORM dostupná.
Řešení: Ujistěte se, že máte nainstalovanou a nakonfigurovanou nettrine/orm:
composer require nettrine/orm
composer require nettrine/dbalPříčina: Access tokeny mají omezenou platnost (typicky 1 hodina).
Řešení: Použijte refresh token nebo vyžádejte novou autentizaci:
if (!$verification->isTokenValid()) {
// Vyžádejte nové přihlášení
$this->redirect('Auth:login');
}Pull requesty jsou vítány! Pro větší změny prosím nejprve otevřete issue.
- Fork repozitáře
- Vytvořte feature branch (
git checkout -b feature/nova-funkce) - Commit změn (
git commit -m 'feat: popis') - Push branch (
git push origin feature/nova-funkce) - Otevřete Pull Request
- 📧 Email: dev@nks-hub.cz
- 🐛 Bug reports: GitHub Issues
- 📖 BankID docs: developer.bankid.cz
MIT License — viz LICENSE
Made with ❤️ by NKS Hub