Skip to content

Commit

Permalink
tighten login csrf protection by using a login timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
lilioid committed Dec 27, 2024
1 parent 43dfc57 commit 64c4eab
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 4 deletions.
3 changes: 3 additions & 0 deletions src/simple_openid_connect/integrations/django/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ class SettingsModel(BaseModel):
)
"A string specifying a class that inherits from :class:`simple_openid_connect.integrations.django.user_mapping.UserMapper`."

OPENID_LOGIN_TIMEOUT: int = 60 * 5
"Time in seconds which a login procedure is allowed to take at maximum. If a user takes more than this time between initiating a login and completing it, the login process fails and they have to redo it."


class OpenidAppConfig(AppConfig):
"""
Expand Down
17 changes: 13 additions & 4 deletions src/simple_openid_connect/integrations/django/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
import logging
import secrets
from datetime import datetime, timedelta, timezone
from http import HTTPStatus
from typing import Mapping

Expand Down Expand Up @@ -69,7 +70,9 @@ def get(self, request: HttpRequest) -> HttpResponse:

# save the login state into the session to prevent CSRF attacks (openid state parameter could be used instead)
# See https://www.rfc-editor.org/rfc/rfc6749#section-10.12
request.session["openid_auth_in_progress"] = True
request.session["openid_auth_start_time"] = datetime.now(
tz=timezone.utc
).timestamp()

# prevent replay attacks by generating and specifying a nonce
nonce = secrets.token_urlsafe(48)
Expand All @@ -93,13 +96,19 @@ class LoginCallbackView(View):
"""

def get(self, request: HttpRequest) -> HttpResponse:
app_settings = OpenidAppConfig.get_instance().safe_settings
client = OpenidAppConfig.get_instance().get_client(request)

# prevent CSRF attacks by verifying that the user agent is curently in the process of authenticating
if request.session.get("openid_auth_in_progress", False) is not True:
# prevent CSRF attacks by verifying that the user agent is curently in the process of authenticating and that the authentication was not started more than the configured amount of time ago
if request.session.get("openid_auth_start_time", None) is None or (
datetime.now(tz=timezone.utc)
- datetime.fromtimestamp(
request.session["openid_auth_start_time"], tz=timezone.utc
)
) > timedelta(seconds=app_settings.OPENID_LOGIN_TIMEOUT):
raise InvalidAuthStateError()
else:
del request.session["openid_auth_in_progress"]
del request.session["openid_auth_start_time"]

# exchange the passed code for tokens
token_response = client.authorization_code_flow.handle_authentication_result(
Expand Down

0 comments on commit 64c4eab

Please sign in to comment.