diff --git a/authentik/events/models.py b/authentik/events/models.py index 4b245e49f..c43128419 100644 --- a/authentik/events/models.py +++ b/authentik/events/models.py @@ -217,6 +217,7 @@ def from_http(self, request: HttpRequest, user: Optional[User] = None) -> "Event "path": request.path, "method": request.method, "args": cleanse_dict(QueryDict(request.META.get("QUERY_STRING", ""))), + "user_agent": request.META.get("HTTP_USER_AGENT", ""), } # Special case for events created during flow execution # since they keep the http query within a wrapped query diff --git a/authentik/events/tests/test_event.py b/authentik/events/tests/test_event.py index 4d636e9b2..3019d5bae 100644 --- a/authentik/events/tests/test_event.py +++ b/authentik/events/tests/test_event.py @@ -53,7 +53,15 @@ def test_from_http_basic(self): """Test plain from_http""" event = Event.new("unittest").from_http(self.factory.get("/")) self.assertEqual( - event.context, {"http_request": {"args": {}, "method": "GET", "path": "/"}} + event.context, + { + "http_request": { + "args": {}, + "method": "GET", + "path": "/", + "user_agent": "", + } + }, ) def test_from_http_clean_querystring(self): @@ -67,6 +75,7 @@ def test_from_http_clean_querystring(self): "args": {"token": SafeExceptionReporterFilter.cleansed_substitute}, "method": "GET", "path": "/", + "user_agent": "", } }, ) @@ -83,6 +92,7 @@ def test_from_http_clean_querystring_flow(self): "args": {"token": SafeExceptionReporterFilter.cleansed_substitute}, "method": "GET", "path": "/", + "user_agent": "", } }, ) diff --git a/authentik/stages/authenticator_validate/tests/test_duo.py b/authentik/stages/authenticator_validate/tests/test_duo.py index 22d1fe746..1f3edb62e 100644 --- a/authentik/stages/authenticator_validate/tests/test_duo.py +++ b/authentik/stages/authenticator_validate/tests/test_duo.py @@ -184,6 +184,7 @@ def test_full(self): "args": {}, "method": "GET", "path": f"/api/v3/flows/executor/{flow.slug}/", + "user_agent": "", }, }, )