uxf / security
3.81.7
2026-07-03 17:04 UTC
Requires
- php: ^8.4
- ext-json: *
- firebase/php-jwt: ^6.0 || ^7.0
- twig/twig: ^3.0
- uxf/core: 3.81.5
This package is auto-updated.
Last update: 2026-07-04 17:24:35 UTC
README
Install
$ composer req uxf/security
// config/packages/uxf.php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->extension('uxf_security', [
'user_class' => User::class, // required
'base_url' => 'https://uxf.cz', // required
'public_key' => '%env(AUTH_PUBLIC_KEY)%', // required
'private_key' => '%env(AUTH_PRIVATE_KEY)%', // required
// optional
'access_token_lifetime' => 'P10Y', // default 1 day
'refresh_token_lifetime' => 'P20Y', // default 1 month
'refresh_token_cookie_path' => '/', // default null (suggestion: /api/auth/refresh-token)
'cookie_name' => 'Cookie-Name', // default Authorization - used for header + cookie
'cookie_secured' => false, // default true
'cookie_http_only' => false, // default true
// OpenID Connect - optional
'oidc' => [
'apple' => [
'client_id' => 'xxx',
],
'facebook' => [
'client_id' => 'xxx',
'client_secret' => 'xxx',
],
'gitlab' => [
'client_id' => 'xxx',
'client_secret' => 'xxx',
],
'google' => [
'client_id' => 'xxx',
],
'microsoft' => [
'client_id' => 'xxx',
],
'mojeid' => [
'client_id' => 'xxx',
],
'seznam' => [
'client_id' => 'xxx',
'client_secret' => 'xxx',
],
'uxf' => [
'client_id' => 'xxx',
'client_secret' => 'xxx',
'app_name' => 'xxx',
],
],
]);
};
Symfony security config - recommended
// config/packages/security.php
return static function (ContainerConfigurator $config): void {
$config->extension('security', [
'providers' => [
'provider' => [
'entity' => [
'class' => \UXF\CMS\Entity\User::class,
'property' => 'email', // BC break in 3.68 (id -> email)
],
],
],
...
]);
}
Events
LogoutUserEvent
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use UXF\Security\Event\LogoutUserEvent;
#[AsEventListener(LogoutUserEvent::class)]
final readonly class LogoutUserListener
{
public function __invoke(LogoutUserEvent $event): void
{
// edit response cookies/headers
...
}
}
OpenID Connect
Create new user
use Nette\Utils\Random;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use UXF\CMS\Entity\User;
use UXF\Security\Service\OIDC\NewUserEvent;
class NewUserEventSubscriber implements EventSubscriberInterface
{
public function process(NewUserEvent $event): void
{
$event->user = new User($event->oidcInfo->email, '', Random::generate());
}
/**
* @inheritDoc
*/
public static function getSubscribedEvents(): array
{
return [
NewUserEvent::class => 'process',
];
}
}
Providers & URLs
# login
https://domain.com/api/auth/oidc/<provider>/login
# login with redirect (default is /)
https://domain.com/api/auth/oidc/<provider>/login?redirect=/some-path
# login callback
https://domain.com/api/auth/oidc/<provider>/callback
Custom provider
use Symfony\Component\DependencyInjection\Attribute\AsTaggedItem;
use UXF\Security\Service\OIDC\Configuration;
use UXF\Security\Service\OIDC\OIDCConnector;
use UXF\Security\Service\OIDC\Provider\OIDCProvider;
use UXF\Security\Service\OIDC\Provider\OIDCProviderTrait;
#[AsTaggedItem(index: self::NAME)]
final readonly class FakeProvider implements OIDCProvider
{
use OIDCProviderTrait;
public const string NAME = 'fake';
public function __construct(
private OIDCConnector $connector,
private string $clientId,
) {
}
public function getConfiguration(): Configuration
{
return new Configuration(
providerName: self::NAME,
clientId: $this->clientId,
clientSecret: null,
responseType: 'id_token',
responseMode: 'form_post',
scope: 'openid email',
authorizationUrl: 'https://uxf.cz',
jwksUrl: 'https://uxf.cz',
tokenUrl: 'https://uxf.cz',
userInfoUrl: null,
oidcInfoCreator: fn (array $userInfo) => new OIDCInfo(
providerName: self::NAME,
sub: $userInfo['sub'],
email: Email::of($userInfo['custom_email']),
emailVerified: $userInfo['custom_verified'],
claims: $userInfo,
),
);
}
}