-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Describe the bug
When user_matching_mode = email_link is configured, and a user who already has a UserSourceConnection to a source logs in via the same source with a different identifier (same email), authentik attempts to INSERT a second UserSourceConnection record. This causes a database integrity error and crashes the login flow.
How to reproduce
- Configure an OAuth source (e.g., CILogon) with user_matching_mode: email_link.
- User logs in via the source for the first time through IdP A (e.g., campus SSO). → UserSourceConnection created with identifier = sub_A.
- Same user logs in through the same OAuth source via IdP B (e.g., Google) with the same email → different sub_B.
- authentik matches the user by email and then attempts to INSERT UserSourceConnection(user_id=X, source_id=Y, identifier=sub_B)
- Error below:
django.db.utils.IntegrityError: duplicate key value violates unique constraint
"authentik_core_usersourc_user_id_source_id_ad1f5aa7_uniq"
DETAIL: Key (user_id, source_id)=(56, 4eefecf7-b868-48f7-9f9d-e83a87d6b0fa) already exists.
at authentik/core/sources/stage.py line 25: connection.save()
Expected behavior
The behavior that I expect to see is:
When email_link matches an existing user who already has a connection to this source (different identifier, same user+source), authentik should authenticate the user rather than failing.
For example, at sources/stage.py, before calling connection.save() there should be a check:
existing = UserSourceConnection.objects.filter(
user=connection.user, source=connection.source
).first()
if existing:
# User already linked to this source — authenticate, don't re-insert
# Optionally update the identifier if policy allows it
return existing
Alternatively, changing the unique constraint from UNIQUE(user_id, source_id) to UNIQUE(user_id, source_id, identifier) would allow multiple connections per source and let users link multiple IdPs through the same broker source.
Screenshots
No response
Additional context
This affects CILogon, a widely-used OIDC federation broker for research/academic institutions. CILogon presents as a single OAuth source in authentik but fronts many backing IdPs (campus SSOs, Google, GitHub, ORCID, etc.). Each backing IdP produces a different sub for the same user. Users often forget which IdP they originally enrolled with and try a different one, triggering this error.
Deployment Method
Kubernetes
Version
2025.10.3
Relevant log output
django.db.utils.IntegrityError: duplicate key value violates unique constraint
"authentik_core_usersourc_user_id_source_id_ad1f5aa7_uniq"
DETAIL: Key (user_id, source_id)=(56, 4eefecf7-b868-48f7-9f9d-e83a87d6b0fa) already exists.
at authentik/core/sources/stage.py line 25: connection.save()