diff --git a/aleksis/core/preferences.py b/aleksis/core/preferences.py
index a8cbe1ef56deee73e82c5d0a77983078de186dac..6594e3b1ddf8c48e038de228c0b9e22c13a70ec0 100644
--- a/aleksis/core/preferences.py
+++ b/aleksis/core/preferences.py
@@ -172,6 +172,24 @@ class PrimaryGroupField(ChoicePreference):
         return Person.syncable_fields_choices()
 
 
+@site_preferences_registry.register
+class AutoCreatePerson(BooleanPreference):
+    section = account
+    name = "auto_create_person"
+    default = False
+    required = False
+    verbose_name = _("Automatically create new persons for new users")
+
+
+@site_preferences_registry.register
+class AutoLinkPerson(BooleanPreference):
+    section = account
+    name = "auto_link_person"
+    default = False
+    required = False
+    verbose_name = _("Automatically link existing persons to new users by their e-mail address")
+
+
 @site_preferences_registry.register
 class SchoolName(StringPreference):
     section = school
diff --git a/aleksis/core/util/middlewares.py b/aleksis/core/util/middlewares.py
index 7ac5e5f2cbb710d3c6bb8c1bdda83ca170c96165..46067bb15bbfdbeb50d511efcfa9ff77521901c2 100644
--- a/aleksis/core/util/middlewares.py
+++ b/aleksis/core/util/middlewares.py
@@ -2,8 +2,8 @@ from typing import Callable
 
 from django.http import HttpRequest, HttpResponse
 
-from ..models import DummyPerson
-from .core_helpers import has_person
+from ..models import DummyPerson, Person
+from .core_helpers import get_site_preferences, has_person
 
 
 class EnsurePersonMiddleware:
@@ -12,6 +12,9 @@ class EnsurePersonMiddleware:
     It is needed to inject a dummy person to a superuser that would otherwise
     not have an associated person, in order they can get their account set up
     without external help.
+
+    In addition, if configured in preferences, it auto-creates or links persons
+    to regular users if they match.
     """
 
     def __init__(self, get_response: Callable):
@@ -19,12 +22,33 @@ class EnsurePersonMiddleware:
 
     def __call__(self, request: HttpRequest) -> HttpResponse:
         if not has_person(request):
-            if request.user.is_superuser:
-                # Super-users get a dummy person linked
-                dummy_person = DummyPerson(
-                    first_name=request.user.first_name, last_name=request.user.last_name
-                )
-                request.user.person = dummy_person
+            prefs = get_site_preferences()
+            if (
+                prefs.get("account__auto_link_person", False)
+                and request.user.first_name
+                and request.user.last_name
+            ):
+                if prefs.get("account__auto_create_person"):
+                    person, created = Person.objects.get_or_create(
+                        email=request.user.email,
+                        defaults={
+                            "first_name": request.user.first_name,
+                            "last_name": request.user.last_name,
+                        },
+                    )
+                    person.user = request.user
+                else:
+                    person = Person.objects.filter(email=request.user.email).first()
+                    if person:
+                        person.user = request.user
+                        person.save()
+
+        if request.user.is_superuser and not has_person(request):
+            # Super-users get a dummy person linked
+            dummy_person = DummyPerson(
+                first_name=request.user.first_name, last_name=request.user.last_name
+            )
+            request.user.person = dummy_person
 
         response = self.get_response(request)
         return response