sso: Use POST method for logout

- This prevents CSRF attacks that allow adversarial websites from logging out
users from FreedomBox. Django itself has made this change in 4.x releases.

Tests:

- Logout works with the menu item in drop-down when Javascript is enabled. The
menu item appears similar to other drop-down menu items.

- Logout works with the menu item when JavaScript is disabled on the page. The
menu item appears similar to other menu items.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2023-08-12 12:01:16 -07:00 committed by James Valleroy
parent dc9e86d918
commit cf6c604cec
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
4 changed files with 28 additions and 12 deletions

View File

@ -14,6 +14,7 @@ from django.contrib.auth import logout as auth_logout
from django.contrib.auth.views import LoginView
from django.http import HttpResponseRedirect
from django.utils.translation import gettext as _
from django.views.decorators.http import require_POST
from plinth import translation, utils, web_framework
@ -92,6 +93,7 @@ class CaptchaLoginView(LoginView):
return set_ticket_cookie(request.user, response)
@require_POST
def logout(request):
"""Logout an authenticated user, remove SSO cookie and redirect to home."""
auth_logout(request)

View File

@ -184,10 +184,12 @@
<li class="dropdown-divider d-none d-md-block"></li>
{% endif %}
<li>
<a class="dropdown-item" href="{% url 'users:logout' %}"
title="{% trans "Log out" %}">
{% trans "Log out" %}
</a>
<form class="form form-logout" method="post"
action="{% url 'users:logout' %}">
{% csrf_token %}
<input type="submit" class="dropdown-item no-running-status"
value="{% trans "Log out" %}"/>
</form>
</li>
</ul>
</li>
@ -211,12 +213,12 @@
{% endif %}
{% if user.is_authenticated %}
<li id="logout-nojs" class="nav-item">
<a class="nav-link" href="{% url 'users:logout' %}"
title="{% trans "Log out" %}">
<i class="fa fa-times-circle nav-icon"></i>
{% trans "Log out" %}</a>
</li>
<form id="logout-nojs" class="form form-inline form-logout"
method="post" action="{% url 'users:logout' %}">
{% csrf_token %}
<input type="submit" class="nav-link no-running-status btn btn-link"
value="{% trans "Log out" %}"/>
</form>
{% endif %}
{% endblock %}
</ul>

View File

@ -277,7 +277,7 @@ def login_with_account(browser, url, username, password=None):
if user_menu.text == username:
return
visit(browser, '/plinth/accounts/logout/')
logout(browser)
login_button = browser.links.find_by_href('/plinth/accounts/login/')
if login_button:
@ -306,7 +306,14 @@ def login_with_account(browser, url, username, password=None):
def logout(browser):
"""Log out of the FreedomBox interface."""
visit(browser, '/plinth/accounts/logout/')
# Navigate to the home page if logout form is not found
if not browser.find_by_css('.form-logout'):
visit(browser, '/plinth/')
# We are not logged in if the home page does not contain logout form
if browser.find_by_css('.form-logout'):
browser.find_by_id('id_user_menu').click()
submit(browser, form_class='form-logout')
#################

View File

@ -457,6 +457,11 @@ footer {
height: 3.25rem;
}
.main-header .nav-link,
.main-header .nav-link:hover {
color: white;
}
.main-header .navbar-toggler {
border: 1px solid #ddd;
}