goauthentik / goauthentik/authentik

SCIM Source does not apply filtered group-member PATCH removals

Open
#24,173 3 comments 0 reactions 0 assignees View on GitHub
bug/confirmed
Dominant language
Python
Stars
25.6k
Forks
2k
Avg merge
1d 2h
Merged PRs (30d)
659

Description

### Describe the bug

For an incoming **SCIM Source**, group membership can become inconsistent when a client uses a filtered SCIM PATCH removal.

A request such as:

```json
{
"Operations": [
{
"op": "remove",
"path": "members[value eq \"\"]"
}
]
}
```

returns HTTP 200, but the corresponding Authentik group membership is not removed. A subsequent add can also be a no-op because Authentik still considers the user a member.

This was observed with Okta Push Groups, but the filtered member-removal syntax is standard SCIM 2.0 behavior and should not be vendor-specific.

### Environment

- authentik: 2026.5.4
- Deployment: Helm chart on Kubernetes
- Source type: SCIM Source
- SCIM client: Okta SCIM Client 1.0.0

### Steps to reproduce

1. Configure a SCIM Source with a group containing an existing Authentik user.
2. Send a SCIM PATCH request to the source's `/Groups/` endpoint with `op: "remove"` and `path: "members[value eq \"\"]"`.
3. Read the group again, or inspect its Authentik membership.
4. Optionally send a standard add PATCH for the same user.

### Actual behavior

- The PATCH returns HTTP 200.
- The SCIM source group's stored attributes may be updated.
- The actual Authentik group's user membership remains unchanged.
- A subsequent add therefore may not produce an effective membership change.

### Expected behavior

The actual Authentik group membership should reconcile with the group membership resulting from the SCIM PATCH. Filtered removal, add, remove-list, and replace operations should all produce consistent group membership, including removal of the final member.

### Relevant code

The affected logic is in `authentik/sources/scim/views/v2/groups.py`, `GroupsView.patch`. It manually handles some member PATCH shapes, then calls `SCIMPatchProcessor.apply_patches` and persists the source attributes with `apply_members=False`. A filtered removal that the patch processor does not materialize can therefore update neither the actual group membership nor a later add reliably.

A robust approach would be to derive the final member set from the applied patch (including filtered remove support), reconcile the actual group membership to that set, and add regression tests for the operation forms above.

### Notes

This is distinct from the outbound AWS SCIM-provider membership-cleanup issue (#23005).

Contributor guide

Open the contributing guide

Research direction

Start in authentik/sources/scim/views/v2/groups.py at GroupsView.patch, then trace how SCIMPatchProcessor.apply_patches handles filtered member removals and how apply_members=False persists attributes. Add regression coverage for filtered removal, add, remove-list, and replace operations, including removal of the final member. Done means the Authentik group membership matches the final SCIM member set and later adds work correctly.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, authentication, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.