View as Markdown
Logout Link
A link that logs the current user out through a secure POST form.
Loading...
<twig:LogoutLink class="">
Logout
</twig:LogoutLink>
Installation
php bin/console ux:install logout-link --kit common
Install the following Composer dependencies:
composer require symfony/security-bundle symfony/security-csrf
Copy the following file(s) into your app:
{# @prop firewall string|null The firewall name to log out from; when null, the current firewall is used. #}
{# @block content The link label. #}
{% props firewall = null %}
<twig:PostLink {{ ...attributes.defaults({
href: logout_path(firewall),
csrfTokenId: 'logout',
}) }}>
{{ block(outerBlocks.content)|default('Logout') }}
</twig:PostLink>
{# @prop href string The URL the form submits to. #}
{# @prop csrfTokenId string|null The CSRF token ID used to generate the hidden token field; when null, no token is added. #}
{# @prop method string The HTTP method used to submit the form; when not `POST`, a hidden `_method` field is added for method spoofing. #}
{# @prop confirm string|null A confirmation message shown before submitting; when null, no confirmation is required. #}
{# @block content The button label. #}
{% props href, csrfTokenId = null, method = 'POST', confirm = null %}
<form{{ attributes.nested('form').defaults({
action: href,
method: 'post',
class: 'inline',
onsubmit: confirm ? 'return confirm(' ~ confirm|json_encode ~ ')' : false,
}) }}>
{% if method|upper != 'POST' %}
<input type="hidden" name="_method" value="{{ method|upper }}">
{% endif %}
{% if csrfTokenId %}
<input{{ attributes.nested('csrf').defaults({
type: 'hidden',
name: '_csrf_token',
'data-controller': 'csrf-protection',
value: csrf_token(csrfTokenId),
}) }}>
{% endif %}
<button{{ attributes.defaults({type: 'submit'}) }}>
{% block content %}{% endblock %}
</button>
</form>
Usage
<twig:LogoutLink>
Logout
</twig:LogoutLink>
Warning
LogoutLink logs the user out through a POST request protected by a CSRF token (token id logout). For it to work, your firewall's logout must require POST and have CSRF protection enabled — otherwise logging out will be rejected.
Restrict the logout route to POST so it can't be triggered by a plain link or prefetch:
#[Route('/logout', name: 'app_logout', methods: ['POST'])]
public function logout(): never
{
throw new \LogicException('This method is intercepted by the logout key on your firewall.');
}
Point the firewall's logout at that route (app_logout) and enable CSRF protection (this validates the logout token the component sends):
# config/packages/security.yaml
security:
firewalls:
main:
logout:
path: app_logout
enable_csrf: true
Examples
Specific Firewall
Set the firewall prop to log out from a specific firewall instead of the current one.
Loading...
<twig:LogoutLink firewall="main" class="">
Logout from the main firewall
</twig:LogoutLink>
API Reference
<twig:LogoutLink>
| Prop | Type | Default |
|---|---|---|
firewall The firewall name to log out from; when null, the current firewall is used.
|
string|null |
null |
| Block | Description |
|---|---|
content |
The link label. |