fix(scim): make POST /Users and /Groups idempotent on external_id#6
Merged
Conversation
When Authentik's SCIM provider is recreated, it loses its remote-id mappings and re-POSTs every user/group on the next sync. Without idempotency, every POST hits the `external_id` UNIQUE constraint and fails with 409, blocking re-provisioning. POST now looks up by `external_id` first; if a resource already exists, update it from the payload, return 200 + Location instead of 201. This lets Authentik adopt the existing struudel resource and store the current struudel id for future PUT/PATCH calls. Also log constraint name and Postgres detail (e.g. which key collided) on any remaining SCIM 409, so future unique-constraint violations are diagnosable from the app log without psql access.
Authentik's outgoing SCIM PATCH on a group sometimes omits the top-level `schemas: [PatchOp]` array (RFC 7644 §3.5.2 requires it) and puts the Group schema inside the operation's `value` instead. Additionally, the `value` dict carries SCIM-meta keys like `id`, `schemas` and `meta` that have no direct mapping to a column. Drop the top-level PatchOp schema requirement (Operations being a list is enough to identify the request), and silently skip the meta keys in group replace operations. Matches the existing Authentik-lenience pattern from fbcbe02 (members remove without value-eq filter).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
POST /scim/v2/Usersnow adopts an existing user when the incomingexternalIdalready exists in struudel: applies the payload as an update and returns200 OK+Locationinstead of409 uniqueness. Same logic forPOST /scim/v2/Groups.IntegrityErrorhandler now logs constraint name and Postgresmessage_detail(e.g.Key (preferred_username)=(mopolka) already exists.) plus the request body, so future SCIM 409s are diagnosable from the app log alone.Why
When the SCIM provider in Authentik is deleted and recreated, Authentik loses its
scim_idmapping for every user/group and POSTs them all on the next sync. Without idempotency onexternal_id, struudel rejects every POST with 409 (UNIQUE onusers.external_id/groups.external_id) and re-provisioning is impossible without dropping all SCIM-managed data first.With this fix Authentik re-discovers each resource on first POST, learns the correct current struudel
id, and switches toPUT-based updates from then on.Test plan
SCIM POST /Users adopted existing user id=...and the sync completesLocationheaders are stable across repeat syncs (i.e. Authentik is now mapped to the right ids)constraint=anddetail=🤖 Generated with Claude Code