goauthentik / goauthentik/authentik

scim provider: allow syncing only users or only groups

Open
#13,441 2 comments 0 reactions 0 assignees View on GitHub
enhancement enhancement/under_consideration
Dominant language
Python
Stars
25.6k
Forks
2k
Avg merge
1d 2h
Merged PRs (30d)
651

Description

**Describe the bug**

I've set up SCIM for GitHub Organization. When I look at the SCIM provider I see a long Exception error. However, when I query the API or look in the GitHub console, SCIM has worked correctly!

**To Reproduce**

Steps to reproduce the behavior:

1. Setup GitHub Organization SAML as documented at https://docs.goauthentik.io/integrations/services/github-organization/
2. Create a fine-grained token with Write access to Organization Members
3. Setup a SCIM provider with URLs as documented by GitHub https://docs.github.com/en/enterprise-cloud@latest/rest/scim/scim?apiVersion=2022-11-28#scim-provisioning-for-organizations
4. Run a sync
5. View SCIM mappings for each user by querying https://api.github.com/scim/v2/organizations/ORGNAME/Users confirms that the users are synced
6. View invitations for users provisioned in Authentik but not active in GitHub in the console or https://api.github.com/scim/v2/organizations/ORGNAME/invitations

...

7. Be utterly confused why Authentik logs only a NotFound exception in Sync Status

**Logs**

Expand to see JSON logs...

```
{"domain_url": null, "event": "Task started", "level": "info", "logger": "authentik.root.celery", "pid": 5521, "schema_name": "public", "task_id": "9c78603a-f0bb-4a99-a90b-6b75962ce2b1", "task_name": "scim_sync_objects", "timestamp": "2025-03-08T18:34:27.202935"}
{"domain_url": null, "event": "failed to get ServiceProviderConfig", "exc": "NotFoundSyncException()", "level": "warning", "logger": "authentik.lib.sync.outgoing.base", "pid": 5521, "provider": "GitHub SCIM", "schema_name": "public", "task_id": "task-9c78603af0bb4a99a90b6b75962ce2b1", "timestamp": "2025-03-08T18:34:27.417693"}
{"domain_url": null, "event": "Task finished", "level": "info", "logger": "authentik.root.celery", "pid": 5521, "schema_name": "public", "state": "SUCCESS", "task_id": "9c78603af0bb4a99a90b6b75962ce2b1", "task_name": "scim_sync_objects", "timestamp": "2025-03-08T18:34:31.940549"}
{"domain_url": null, "event": "Task published", "level": "info", "logger": "authentik.root.celery", "pid": 5523, "schema_name": "public", "task_id": "9b93b6344f974311bcab66c1ae7f7e6c", "task_name": "authentik.providers.scim.tasks.scim_sync_objects", "timestamp": "2025-03-08T18:34:31.950457"}
{"domain_url": null, "event": "Task started", "level": "info", "logger": "authentik.root.celery", "pid": 5521, "schema_name": "public", "task_id": "9b93b634-4f97-4311-bcab-66c1ae7f7e6c", "task_name": "scim_sync_objects", "timestamp": "2025-03-08T18:34:31.954312"}
{"domain_url": null, "event": "failed to get ServiceProviderConfig", "exc": "NotFoundSyncException()", "level": "warning", "logger": "authentik.lib.sync.outgoing.base", "pid": 5521, "provider": "GitHub SCIM", "schema_name": "public", "task_id": "task-9b93b6344f974311bcab66c1ae7f7e6c", "timestamp": "2025-03-08T18:34:32.123067"}
{"event": "Task authentik.providers.scim.tasks.scim_sync_objects[9b93b634-4f97-4311-bcab-66c1ae7f7e6c] raised unexpected: NotFoundSyncException()", "exception": [{"exc_type": "NotFoundSyncException", "exc_value": "", "frames": [{"filename": "/ak-root/venv/lib/python3.12/site-packages/celery/app/trace.py", "lineno": 453, "locals": {"I": "None", "IGNORE_STATES": "frozenset({'REJECTED', 'RETRY', 'IGNORED'})", "Info": "", "R": "None", "Rstr": "None", "T": "None", "_does_info": "False", "app": "", "args": "['authentik.core.models.Group', 1, 12]", "deduplicate_successful_tasks": "False", "eager": "False", "exc": "NotFoundSyncException()", "fun": "'<@task: authentik.providers.scim.tasks.scim_sync_objects of authentik at 0x7f656'+8", "hostname": "'celery@de9193d23122'", "inherit_parent_priority": "False", "kwargs": "{}", "loader_cleanup": "'", "name": "'authentik.providers.scim.tasks.scim_sync_objects'", "on_error": ".on_error at 0x7f655f9a4540>", "pid": "5521", "pop_request": "'", "state": "None", "success_receivers": "[]", "task": "'<@task: authentik.providers.scim.tasks.scim_sync_objects of authentik at 0x7f656'+8", "task_after_return": "None", "task_before_start": "None", "task_on_success": "None", "task_priority": "None", "task_request": "\"", "track_started": "False", "uuid": "'9b93b634-4f97-4311-bcab-66c1ae7f7e6c'"}, "name": "trace_task"}, {"filename": "/ak-root/venv/lib/python3.12/site-packages/sentry_sdk/utils.py", "lineno": 1783, "locals": {"args": "'(<@task: authentik.providers.scim.tasks.scim_sync_objects of authentik at 0x7f65'+48", "integration": "", "kwargs": "{}", "original_function": "'.__protected_call__ at 0x7f656e6ded4'+2", "sentry_patched_function": "._inner at 0x7f6560c032e0>"}, "name": "runner"}, {"filename": "/ak-root/venv/lib/python3.12/site-packages/sentry_sdk/integrations/celery/__init__.py", "lineno": 415, "locals": {"args": "'(<@task: authentik.providers.scim.tasks.scim_sync_objects of authentik at 0x7f65'+48", "exc_info": "\"(, NotFoun\"+71", "f": "'.__protected_call__ at 0x7f656e6ded4'+2", "kwargs": "{}", "latency": "0.010670185089111328", "span": "\"", "tp": "", "value": "NotFoundSyncException()"}, "name": "reraise"}, {"filename": "/ak-root/venv/lib/python3.12/site-packages/sentry_sdk/integrations/celery/__init__.py", "lineno": 410, "locals": {"args": "'(<@task: authentik.providers.scim.tasks.scim_sync_objects of authentik at 0x7f65'+48", "exc_info": "\"(, NotFoun\"+71", "f": "'.__protected_call__ at 0x7f656e6ded4'+2", "kwargs": "{}", "latency": "0.010670185089111328", "span": "\"", "req": "\""}, "name": "__protected_call__"}, {"filename": "/ak-root/venv/lib/python3.12/site-packages/celery/app/autoretry.py", "lineno": 38, "locals": {"args": "('authentik.core.models.Group', 1, 12)", "autoretry_for": "(,)", "dont_autoretry_for": "()", "kwargs": "{}", "retry_backoff": "1.0", "retry_backoff_max": "600", "retry_jitter": "True", "retry_kwargs": "{}", "task": "'<@task: authentik.providers.scim.tasks.scim_sync_objects of authentik at 0x7f656'+8"}, "name": "run"}, {"filename": "/authentik/providers/scim/tasks.py", "lineno": 14, "locals": {"args": "('authentik.core.models.Group', 1, 12)", "kwargs": "{}"}, "name": "scim_sync_objects"}, {"filename": "/authentik/lib/sync/outgoing/tasks.py", "lineno": 131, "locals": {"_object_type": "", "client": "'", "object_type": "'authentik.core.models.Group'", "page": "1", "paginator": "", "provider": "", "provider_pk": "12", "self": ""}, "name": "sync_objects"}, {"filename": "/authentik/lib/sync/outgoing/base.py", "lineno": 63, "locals": {"connection": "None", "obj": "", "self": "'", "scim_group": "\"Group(id=None, displayName='devx', members=[GroupMember(value='ed5d1222-fc47-11e\"+156", "self": "'", "self": "'"}, "domain_url": null, "event": "Created Event", "level": "info", "logger": "authentik.events.models", "pid": 5523, "schema_name": "public", "task_id": "task-6b6bba6efedd4c9b80ab666e120ca32f", "timestamp": "2025-03-08T18:34:33.796304", "user": {}}
{"event": "Task authentik.providers.scim.tasks.scim_sync[6b6bba6e-fedd-4c9b-80ab-666e120ca32f] raised unexpected: NotFoundSyncException('')", "exception": [{"exc_type": "NotFoundSyncException", "exc_value": "", "frames": [{"filename": "/ak-root/venv/lib/python3.12/site-packages/celery/app/trace.py", "lineno": 453, "locals": {"I": "None", "IGNORE_STATES": "frozenset({'REJECTED', 'RETRY', 'IGNORED'})", "Info": "", "R": "None", "Rstr": "None", "T": "None", "_does_info": "False", "app": "", "args": "[12]", "deduplicate_successful_tasks": "False", "eager": "False", "exc": "NotFoundSyncException('')", "fun": "<@task: authentik.providers.scim.tasks.scim_sync of authentik at 0x7f6569915c70>", "hostname": "'celery@de9193d23122'", "inherit_parent_priority": "False", "kwargs": "{}", "loader_cleanup": "'", "name": "'authentik.providers.scim.tasks.scim_sync'", "on_error": ".on_error at 0x7f6560c036a0>", "pid": "5523", "pop_request": "'", "state": "None", "success_receivers": "[]", "task": "<@task: authentik.providers.scim.tasks.scim_sync of authentik at 0x7f6569915c70>", "task_after_return": "'", "track_started": "False", "uuid": "'6b6bba6e-fedd-4c9b-80ab-666e120ca32f'"}, "name": "trace_task"}, {"filename": "/ak-root/venv/lib/python3.12/site-packages/sentry_sdk/utils.py", "lineno": 1783, "locals": {"args": "'(<@task: authentik.providers.scim.tasks.scim_sync of authentik at 0x7f6569915c70'+6", "integration": "", "kwargs": "{}", "original_function": "'.__protected_call__ at 0x7f656e6ded4'+2", "sentry_patched_function": "._inner at 0x7f6560c03920>"}, "name": "runner"}, {"filename": "/ak-root/venv/lib/python3.12/site-packages/sentry_sdk/integrations/celery/__init__.py", "lineno": 415, "locals": {"args": "'(<@task: authentik.providers.scim.tasks.scim_sync of authentik at 0x7f6569915c70'+6", "exc_info": "\"(, NotFoun\"+73", "f": "'.__protected_call__ at 0x7f656e6ded4'+2", "kwargs": "{}", "latency": "0.026908159255981445", "span": "\""}, "name": "_inner"}, {"filename": "/ak-root/venv/lib/python3.12/site-packages/sentry_sdk/utils.py", "lineno": 1718, "locals": {"tb": "", "tp": "", "value": "NotFoundSyncException('')"}, "name": "reraise"}, {"filename": "/ak-root/venv/lib/python3.12/site-packages/sentry_sdk/integrations/celery/__init__.py", "lineno": 410, "locals": {"args": "'(<@task: authentik.providers.scim.tasks.scim_sync of authentik at 0x7f6569915c70'+6", "exc_info": "\"(, NotFoun\"+73", "f": "'.__protected_call__ at 0x7f656e6ded4'+2", "kwargs": "{}", "latency": "0.026908159255981445", "span": "\""}, "name": "_inner"}, {"filename": "/ak-root/venv/lib/python3.12/site-packages/celery/app/trace.py", "lineno": 736, "locals": {"args": "(12,)", "kwargs": "{}", "orig": "", "req": "\"", "stack": ""}, "name": "__protected_call__"}, {"filename": "/ak-root/venv/lib/python3.12/site-packages/celery/app/autoretry.py", "lineno": 38, "locals": {"args": "(12,)", "autoretry_for": "(,)", "dont_autoretry_for": "()", "kwargs": "{}", "retry_backoff": "1.0", "retry_backoff_max": "600", "retry_jitter": "True", "retry_kwargs": "{}", "task": "<@task: authentik.providers.scim.tasks.scim_sync of authentik at 0x7f6569915c70>"}, "name": "run"}, {"filename": "/authentik/providers/scim/tasks.py", "lineno": 22, "locals": {"args": "()", "kwargs": "{}", "provider_pk": "12", "self": "<@task: authentik.providers.scim.tasks.scim_sync of authentik at 0x7f6569915c70>"}, "name": "scim_sync"}, {"filename": "/authentik/lib/sync/outgoing/tasks.py", "lineno": 98, "locals": {"groups_paginator": "", "lock_acquired": "True", "messages": "\"['Starting full provider sync', 'Syncing page 1 of users', 'Syncing page 1 of gr\"+6", "page": "1", "provider": "", "provider_pk": "12", "self": "", "sync_objects": "'<@task: authentik.providers.scim.tasks.scim_sync_objects of authentik at 0x7f656'+8", "task": "<@task: authentik.providers.scim.tasks.scim_sync of authentik at 0x7f6569915c70>", "users_paginator": ""}, "name": "sync_single"}, {"filename": "/ak-root/venv/lib/python3.12/site-packages/celery/result.py", "lineno": 251, "locals": {"EXCEPTION_STATES": "frozenset({'FAILURE', 'RETRY', 'REVOKED'})", "PROPAGATE_STATES": "frozenset({'FAILURE', 'REVOKED'})", "_on_interval": "", "callback": "None", "disable_sync_subtasks": "True", "follow_parents": "True", "interval": "0.5", "no_ack": "True", "on_interval": "None", "on_message": "None", "propagate": "True", "self": "", "timeout": "None"}, "name": "get"}, {"filename": "/ak-root/venv/lib/python3.12/site-packages/celery/backends/asynchronous.py", "lineno": 223, "locals": {"_": "None", "callback": "None", "kwargs": "\"{'timeout': None, 'interval': 0.5, 'on_interval': , 'no_\"+31", "propagate": "True", "result": "", "self": ""}, "name": "wait_for_pending"}, {"filename": "/ak-root/venv/lib/python3.12/site-packages/celery/result.py", "l
{"domain_url": null, "event": "Task finished", "level": "info", "logger": "authentik.root.celery", "pid": 5523, "schema_name": "public", "state": "FAILURE", "task_id": "6b6bba6efedd4c9b80ab666e120ca32f", "task_name": "scim_sync", "timestamp": "2025-03-08T18:34:33.825222"}
```

**Version and Deployment (please complete the following information):**

- authentik version: [e.g. 2025.2.0] 2025.2.1
- Deployment: [e.g. docker-compose, helm] podman quadlets (podman run by systemd)

**Additional context**

Add any other context about the problem here.

GitHub apparently doesn't provide the `/ServiceProviderConfig` which results in 404, is this perhaps being raised up as the sole error? Or is something else in the operation failing?

Contributor guide

Open the contributing guide

Research direction

Start with authentik/providers/scim/tasks.py and the sync flow in authentik/lib/sync/outgoing/tasks.py, then inspect the clients in authentik/providers/scim/clients/groups.py and base.py. Check how the GitHub SCIM URLs handle missing user or group endpoints; done means a provider can select only users or only groups and syncing the selected resource type completes without an unrelated 404 failure.

Written by the indexing model from the issue text.

Assessment

Tech stack
github, python
Domain
api, backend
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.