Skip to content

providers/scim: modify user- and group syncing behavior#13947

Merged
BeryJu merged 8 commits intogoauthentik:mainfrom
ImmanuelVonNeumann:scim-user-and-group-filter
Jan 29, 2026
Merged

providers/scim: modify user- and group syncing behavior#13947
BeryJu merged 8 commits intogoauthentik:mainfrom
ImmanuelVonNeumann:scim-user-and-group-filter

Conversation

@ImmanuelVonNeumann
Copy link
Contributor

Details

This is the successor to #13550 with two main changes:

  • filter_groups have been renamed to group_filters (reasoning further below)
  • users are filtered by the scim-provider's application policies as suggested here

Full Details:

This PR aims to change user and group filtering of the SCIMProvider by incorporating the following changes:

  • Group syncing
    • Rename and modify filter_group to group_filters (including django migrations to keep a previously selected filter_group present)
    • Multiple groups can be selected as group_filters
    • Only groups within group_filters are synced to the SCIM Server
  • User syncing
    • Only users which are able to view the SCIMProvider's Application are being synced

Reasoning:

Most SCIM Clients allow groups to be filtered, however authentik currently does not.
This issue has been mentioned in #6065 which has been given the enhancement/confirmed-label.

Among the many use-cases one would be a multi-tenant setup where groups of one tenant should not be visible to another tenant.

I have chosen to rename the attribute to "group_filters" as I believe it to be more explanatory.
My understanding of a "filter_group" is a group that has filtering logic (not limited to groups but rather defined by groups).
Whereas a "group_filter" filters groups.
If this change is not welcome, I am happy to undo it.

Note

Since this does change user- and group-syncing behavior (f.e. not syncing previously synced groups anymore) as well as the schema, I suggest this change to be implemented in a major release.

Fixes #6065


Checklist

  • Local tests pass (ak test authentik/)
  • The code has been formatted (make lint-fix)

If an API change has been made

  • The API schema has been updated (make gen-build)

If changes to the frontend have been made

  • The code has been formatted (make web)

If applicable

  • The documentation has been updated
  • The documentation has been formatted (make website)

@ImmanuelVonNeumann ImmanuelVonNeumann requested review from a team as code owners April 9, 2025 15:37
@netlify
Copy link

netlify bot commented Apr 9, 2025

Deploy Preview for authentik-storybook ready!

Name Link
🔨 Latest commit 9ada3fe
🔍 Latest deploy log https://app.netlify.com/projects/authentik-storybook/deploys/697b6d64000b1a00087357c3
😎 Deploy Preview https://deploy-preview-13947--authentik-storybook.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link

netlify bot commented Apr 9, 2025

Deploy Preview for authentik-docs ready!

Name Link
🔨 Latest commit 4f2310b
🔍 Latest deploy log https://app.netlify.com/projects/authentik-docs/deploys/697b6aaa6d7d1f000872d00c
😎 Deploy Preview https://deploy-preview-13947--authentik-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@ImmanuelVonNeumann ImmanuelVonNeumann force-pushed the scim-user-and-group-filter branch from 15e241c to 54e4e2c Compare April 9, 2025 16:30
Comment on lines +133 to +137
pk__in=[
user.pk
for user in base
if PolicyEngine(self.backchannel_application, user, None).build().passing
]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be helpful to extend Application with the function get_users_allowed_to_view which generates a queryset of Users, subsequently centralizing this logic.

@codecov
Copy link

codecov bot commented Apr 10, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.23%. Comparing base (fd209ee) to head (b3236f6).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #13947      +/-   ##
==========================================
- Coverage   93.24%   93.23%   -0.02%     
==========================================
  Files         965      967       +2     
  Lines       53196    53269      +73     
==========================================
+ Hits        49603    49664      +61     
- Misses       3593     3605      +12     
Flag Coverage Δ
conformance 38.09% <7.52%> (-0.05%) ⬇️
e2e 44.09% <7.52%> (-0.07%) ⬇️
integration 22.88% <6.45%> (-0.08%) ⬇️
unit 91.42% <100.00%> (+0.03%) ⬆️
unit-migrate 91.46% <100.00%> (+0.06%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@ImmanuelVonNeumann ImmanuelVonNeumann force-pushed the scim-user-and-group-filter branch from 3eb9b17 to 74ca7d3 Compare April 23, 2025 08:42
@ImmanuelVonNeumann
Copy link
Contributor Author

ImmanuelVonNeumann commented Apr 24, 2025

Another design decision to be had is:
Should you be able to sync no groups?
If so, how?

My initial thought is to change the syncing behavior when no groups are selected from syncing all groups to none.
This would however, also change the default behavior of the SCIM provider.
Nonetheless, in my opinion this would be more intuitive.

related to: #13441

@ImmanuelVonNeumann ImmanuelVonNeumann force-pushed the scim-user-and-group-filter branch from 74ca7d3 to c013f0a Compare May 12, 2025 14:06
Copy link
Member

@BeryJu BeryJu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good, we're discussing internally how to best deal with the migration path and to not break any existing setups.

I think if during the migration we detect the SCIM provider has one filter group selected, we enabled dry-run in the migration to effectively disable the provider until the user has reviewed the config. (Also I can't think of a scenario where you'd have a different set of users provisioned in SCIM than users who can access the application but it might exist somewhere).

The other thing that we want to do before shipping this is optimize the PolicyEngine more, especially when using user or group bindings as without optimizations this would have quite a performance impact especially with a lot of providers setup.

@ImmanuelVonNeumann
Copy link
Contributor Author

I think if during the migration we detect the SCIM provider has one filter group selected, we enabled dry-run in the migration to effectively disable the provider until the user has reviewed the config.

Sounds like a good idea.
It might be even better to reset the selection (filter_group) as the behavior has changed.

Especially in regards to how an empty selection for group_filters is handled (syncs all groups vs syncs no groups).
I believe that "sync no groups" would enable more use-cases and be more intuitive.
However, this would mean that if all groups are selected, new groups would not automatically be synced.
To solve this, we could have a button "sync all" which disables the selection and syncs all groups to the scim server.

@netlify
Copy link

netlify bot commented Jul 24, 2025

Deploy Preview for authentik-integrations ready!

Name Link
🔨 Latest commit 4f2310b
🔍 Latest deploy log https://app.netlify.com/projects/authentik-integrations/deploys/697b6aaa9eba9c00082024cb
😎 Deploy Preview https://deploy-preview-13947--authentik-integrations.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@BeryJu
Copy link
Member

BeryJu commented Jul 24, 2025

I think if during the migration we detect the SCIM provider has one filter group selected, we enabled dry-run in the migration to effectively disable the provider until the user has reviewed the config.

Sounds like a good idea. It might be even better to reset the selection (filter_group) as the behavior has changed.

Especially in regards to how an empty selection for group_filters is handled (syncs all groups vs syncs no groups). I believe that "sync no groups" would enable more use-cases and be more intuitive. However, this would mean that if all groups are selected, new groups would not automatically be synced. To solve this, we could have a button "sync all" which disables the selection and syncs all groups to the scim server.

Sorry for the once again delayed response, we've since merged a big improvement to the PolicyEngine that uses a lot less queries and time for static user/group bindings so from that aspect we can go ahead with this one.

I've merged the migrations and set the dry_run to true in the migration if a filter group has been set and merged main into that.

for the group_filters behaviour I would be tempted to say to add a 3-state enum (sync no groups, sync filtered groups, sync all groups) instead of trying to be smart about it? Making it an imperative action isn't really the best way to go about that imo

cc @goauthentik/backend for thoughts

@BeryJu
Copy link
Member

BeryJu commented Jul 25, 2025

One thing we should also do for this is post-sync review to compare the SCIM users in our database with the users that have access and deactivate/remove any users that were synced but no longer have access

@ImmanuelVonNeumann
Copy link
Contributor Author

ImmanuelVonNeumann commented Jul 28, 2025

I have gone ahead and fixed the linting issues.


for the group_filters behaviour I would be tempted to say to add a 3-state enum (sync no groups, sync filtered groups, sync all groups) instead of trying to be smart about it? Making it an imperative action isn't really the best way to go about that imo

This solution definitely makes sense in the current authentik "eco-system", however I believe that this might be a symptom of an underlying issue. I have created Issue 15816 where I explain this further since it doesn't affect this PR directly.

If the backend-team agrees with the 3-state enum approach I can go ahead and see if it is feasible for me to implement this feature.


One thing we should also do for this is post-sync review to compare the SCIM users in our database with the users that have access and deactivate/remove any users that were synced but no longer have access

I agree that this feature should be introduced.
However, I am currently uncertain whether I can take this on.

@BeryJu
Copy link
Member

BeryJu commented Dec 2, 2025

@ImmanuelVonNeumann sorry for keeping this waiting for so long, I still want to get this merged but I haven't gotten around to re-reviewing this and figuring out solutions for the issues in this thread

ImmanuelVonNeumann and others added 4 commits January 14, 2026 10:26
rename filtergroup to groupfilters and allow multiple values
only sync groups which are in the scimprovider's attribute \"group_filters\"
only sync users which are entitled to view the scimprovider's application
Signed-off-by: Immanuel von Neumann <45020096+ImmanuelVonNeumann@users.noreply.github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
@ImmanuelVonNeumann ImmanuelVonNeumann force-pushed the scim-user-and-group-filter branch from 2a9252f to 9a5cc79 Compare January 14, 2026 14:35
@ImmanuelVonNeumann
Copy link
Contributor Author

@BeryJu I have gone ahead and rebased the PR.

In my opinion, the current implementation is the most simplistic and implicit usage:

  • If you want to sync all groups you leave it as is (empty). This is the default state
  • If you want to sync specific groups you select those

If you would want to sync no groups you would have to make an empty "placeholder group" you select.
In the case that this has to be implemented the easiest solution would be a checkbox "disable group synchronization". This should be more implicitly understandable and easy to implement than a radio-selection (enum approach).

@ImmanuelVonNeumann ImmanuelVonNeumann force-pushed the scim-user-and-group-filter branch from 9a5cc79 to abb160e Compare January 21, 2026 12:38
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
@BeryJu BeryJu merged commit 6ca26b5 into goauthentik:main Jan 29, 2026
100 checks passed
kensternberg-authentik added a commit that referenced this pull request Jan 31, 2026
* main: (52 commits)
  website: QL Search keyboard interactions docs, examples. (#16259)
  website/integrations: immich: add signing algorithm (#19187)
  website/docs: endpoint devices: add version command (#19767)
  common: introduce common (#19852)
  web: bump @sentry/browser from 10.37.0 to 10.38.0 in /web in the sentry group across 1 directory (#19871)
  core: bump debugpy from 1.8.19 to 1.8.20 (#19872)
  ci: bump actions/cache from 5.0.2 to 5.0.3 (#19873)
  web: bump chromedriver from 144.0.1 to 145.0.0 in /web (#19874)
  web: Captcha Refinements, Part 2  (#19757)
  root: assign cherry-pick PRs to original author (#19858)
  web: Lit Development Mode, performance fixes. (#19825)
  web: Fix development theme overrides (#19826)
  website/docs: add tip for recovering from accidental main branch work (#19865)
  web: bump API Client version (#19857)
  rbac: clean up roles and permissions (#19588)
  web: bump API Client version (#19851)
  website/docs: add more info to entra id scim doc (#19849)
  sources/oauth: Fix an issue where wechat may crash duing login. (#18973)
  providers/scim: fix email validation mismatch (#19848)
  providers/scim: modify user- and group syncing behavior (#13947)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SCIM Group Filtering

2 participants