Improve expired session and CSRF error handling

This commit is contained in:
Thomas Sileo 2022-09-16 18:14:50 +02:00
parent 949365d8ba
commit b99552384c
5 changed files with 32 additions and 8 deletions

View file

@ -40,13 +40,22 @@ from app.utils import pagination
from app.utils.emoji import EMOJIS_BY_NAME from app.utils.emoji import EMOJIS_BY_NAME
def user_session_or_redirect( async def user_session_or_redirect(
request: Request, request: Request,
session: str | None = Cookie(default=None), session: str | None = Cookie(default=None),
) -> None: ) -> None:
if request.method == "POST":
form_data = await request.form()
if "redirect_url" in form_data:
redirect_url = form_data["redirect_url"]
else:
redirect_url = request.url_for("admin_stream")
else:
redirect_url = str(request.url)
_RedirectToLoginPage = HTTPException( _RedirectToLoginPage = HTTPException(
status_code=302, status_code=302,
headers={"Location": request.url_for("login") + f"?redirect={request.url}"}, headers={"Location": request.url_for("login") + f"?redirect={redirect_url}"},
) )
if not session: if not session:

View file

@ -200,10 +200,19 @@ def generate_csrf_token() -> str:
return csrf_serializer.dumps(secrets.token_hex(16)) # type: ignore return csrf_serializer.dumps(secrets.token_hex(16)) # type: ignore
def verify_csrf_token(csrf_token: str = Form()) -> None: def verify_csrf_token(
csrf_token: str = Form(),
redirect_url: str | None = Form(None),
) -> None:
please_try_again = "please try again"
if redirect_url:
please_try_again = f'<a href="{redirect_url}">please try again</a>'
try: try:
csrf_serializer.loads(csrf_token, max_age=1800) csrf_serializer.loads(csrf_token, max_age=1800)
except (itsdangerous.BadData, itsdangerous.SignatureExpired): except (itsdangerous.BadData, itsdangerous.SignatureExpired):
logger.exception("Failed to verify CSRF token") logger.exception("Failed to verify CSRF token")
raise HTTPException(status_code=403, detail="CSRF error") raise HTTPException(
status_code=403,
detail=f"The security token expired, {please_try_again}",
)
return None return None

View file

@ -509,3 +509,9 @@ nav.flexbox {
} }
} }
} }
.error-title {
a {
text-decoration: underline;
}
}

View file

@ -6,7 +6,7 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="centered primary-color"> <div class="centered primary-color box">
<h1>{{ title }}</h1> <h1 class="error-title">{{ title | safe }}</h1>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -33,7 +33,7 @@ Whenever one of these config items is updated, an `Update` activity will be sent
The server will need to be restarted for taking changes into account. The server will need to be restarted for taking changes into account.
Before restarting, you can ensure you haven't made any mistakes by running the [configuration checking task](/user_guide.html#configuration-checking). Before restarting the server, you can ensure you haven't made any mistakes by running the [configuration checking task](/user_guide.html#configuration-checking).
### Profile metadata ### Profile metadata
@ -161,7 +161,7 @@ And only the last 20 interactions (likes/shares/webmentions) will be displayed,
## Admin section ## Admin section
You can login to the admin section by clicking on the `Admin` link in the footer or by visiting `https://yourdomain.tld/admin`. You can login to the admin section by clicking on the `Admin` link in the footer or by visiting `https://yourdomain.tld/admin/login`.
The password is the one set during the initial configuration. The password is the one set during the initial configuration.
### Lookup ### Lookup