Repository: goauthentik/authentik

Issue:
Date field can't be serialized to JSON on user write stage
**Describe the bug**

`Date` fields can't be serialised to JSON and thus are not saved to the user.

**To Reproduce**

I've added a field of type `Date` to my user settings by adding it in the `default-user-settings` prompt stage.
When I go into my user settings, set a value and save it, my user's fields are no longer displayed, instead replaced by a `Open settings` button.

![image](https://github.com/goauthentik/authentik/assets/40198445/d6945e36-424d-4678-9bec-8b4b82c4614a)

When I click the button I get this error message:

```
builtins.TypeError: Object of type date is not JSON serializable
```

![image](https://github.com/goauthentik/authentik/assets/40198445/41867936-781a-44e2-a941-1a205320a9ef)

-   authentik version:  2023.6.1
-   Deployment: docker-compose

**Additional context**
https://discord.com/channels/809154715984199690/1129892642080161913



Discussion:
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
The error is still present in 2023.8.3

Resolving patch:
diff --git a/authentik/events/utils.py b/authentik/events/utils.py
--- a/authentik/events/utils.py
+++ b/authentik/events/utils.py
@@ -2,6 +2,7 @@
 import re
 from copy import copy
 from dataclasses import asdict, is_dataclass
+from datetime import date, datetime, time, timedelta
 from enum import Enum
 from pathlib import Path
 from types import GeneratorType
@@ -13,6 +14,7 @@
 from django.db import models
 from django.db.models.base import Model
 from django.http.request import HttpRequest
+from django.utils import timezone
 from django.views.debug import SafeExceptionReporterFilter
 from geoip2.models import City
 from guardian.utils import get_anonymous_user
@@ -84,7 +86,7 @@ def get_user(user: User, original_user: Optional[User] = None) -> dict[str, Any]
     return user_data
 
 
-# pylint: disable=too-many-return-statements
+# pylint: disable=too-many-return-statements,too-many-branches
 def sanitize_item(value: Any) -> Any:
     """Sanitize a single item, ensure it is JSON parsable"""
     if is_dataclass(value):
@@ -134,6 +136,23 @@ def sanitize_item(value: Any) -> Any:
             "type": value.__name__,
             "module": value.__module__,
         }
+    # See
+    # https://github.com/encode/django-rest-framework/blob/master/rest_framework/utils/encoders.py
+    # For Date Time string spec, see ECMA 262
+    # https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.15
+    if isinstance(value, datetime):
+        representation = value.isoformat()
+        if representation.endswith("+00:00"):
+            representation = representation[:-6] + "Z"
+        return representation
+    if isinstance(value, date):
+        return value.isoformat()
+    if isinstance(value, time):
+        if timezone and timezone.is_aware(value):
+            raise ValueError("JSON can't represent timezone-aware times.")
+        return value.isoformat()
+    if isinstance(value, timedelta):
+        return str(value.total_seconds())
     return value
 
 


Test patch: