netbox-oidc-group-sync
A python-social-auth pipeline step that syncs NetBox
Django groups and is_superuser status from an OIDC groups claim.
Why this exists
NetBox Community ships two independent group-sync code paths under netbox.authentication:
RemoteUserBackend.configure_groups()implements dynamic, claim-based group sync (with optional auto-create) plus superuser evaluation fromREMOTE_AUTH_SUPERUSER_GROUPS-- but it's only ever invoked fromRemoteUserBackend.authenticate(), Django's HTTP-header remote-auth path (aREMOTE_USERheader set by an upstream reverse proxy). It is never reached by a social-auth/OIDC login.user_default_groups_handler, the step actually wired intoSOCIAL_AUTH_PIPELINEfor social-auth backends (including OIDC), only assigns a staticREMOTE_AUTH_DEFAULT_GROUPSlist. It never reads a claim and never touchesis_superuser.
So if you're using social_core.backends.open_id_connect.OpenIdConnectAuth (or another social-auth OIDC
backend) as your NetBox login method, setting REMOTE_AUTH_GROUP_SYNC_ENABLED / AUTO_CREATE_GROUPS /
SUPERUSER_GROUPS in your NetBox configuration has no effect whatsoever -- those settings are consumed
exclusively by the header-based backend. NetBox Labs' Enterprise product solves this with a proprietary
pipeline step (nbc_auth_extensions.azure_authentication.azuread_map_groups, Enterprise-only, Entra
ID-specific).
sync_groups closes that gap for Community: dropped into SOCIAL_AUTH_PIPELINE in place of
user_default_groups_handler, it re-implements configure_groups()'s logic against the OIDC response
instead of an HTTP header, reusing the exact same REMOTE_AUTH_* settings NetBox already defines -- no new
configuration surface.
Installation
pip install netbox-oidc-group-sync
Then, in your NetBox configuration.py (or an extraConfig block if you're deploying via the
netbox-chart Helm chart):
SOCIAL_AUTH_PIPELINE = (
"social_core.pipeline.social_auth.social_details",
"social_core.pipeline.social_auth.social_uid",
"social_core.pipeline.social_auth.social_user",
"social_core.pipeline.user.get_username",
"social_core.pipeline.user.create_user",
"social_core.pipeline.social_auth.associate_user",
"netbox_oidc_group_sync.sync_groups", # replaces netbox.authentication.user_default_groups_handler
"social_core.pipeline.social_auth.load_extra_data",
"social_core.pipeline.user.user_details",
)
The package itself needs to be on the NetBox pod's Python path -- if you're running the stock
netboxcommunity/netbox image, that means building a derivative image that pip installs it (see
docs/installation.md for a working Dockerfile example).
Configuration
Reuses NetBox's own settings -- nothing new to configure beyond what a RemoteUserBackend deployment would
already set:
| Setting | Effect |
|---|---|
REMOTE_AUTH_GROUP_SYNC_ENABLED |
Master on/off switch. sync_groups no-ops entirely when falsy. |
REMOTE_AUTH_GROUP_HEADER |
The key to look up in the OIDC claims/userinfo response dict for the user's group list. Named for its original HTTP-header use case; repurposed here as a claim key, which doesn't conflict with anything since it has no effect on social-auth logins upstream. |
REMOTE_AUTH_AUTO_CREATE_GROUPS |
Create a Django Group for a claimed group name that doesn't exist yet, instead of skipping it with a logged error. |
REMOTE_AUTH_SUPERUSER_GROUPS |
Group names that grant is_superuser when present in the user's synced claim groups. |
REMOTE_AUTH_SUPERUSERS |
Usernames that are always superusers, regardless of group membership. |
Group membership is a full sync, not additive: a user's Django groups are set to exactly what the claim
says on every login (matching configure_groups()'s own semantics), including clearing all groups -- and
revoking superuser status -- if the claim comes back empty or absent.
Development
uv sync
uv run pre-commit install
uv run pytest --cov=src --cov-report=term-missing
Docs are built with Zensical:
uvx zensical serve
Metadata
Release files for netbox-oidc-group-sync 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| netbox_oidc_group_sync-0.1.1.tar.gz | 79.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| netbox_oidc_group_sync-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 86.1 kB
Release files / netbox_oidc_group_sync-0.1.1.tar.gz
| Download URL | netbox_oidc_group_sync-0.1.1.tar.gz |
|---|---|
| Size | 79.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6079101673b3c3e96d283d069513fdf7ff962fc5f440a9c3ad06700bedb86ad7
|
|
BLAKE2b-256 checksum How to use checksums |
5a526c09b9e1cfea5f36dfe23f631d29cadfecc82c6e554c7edaff3dd70d5f02
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 25, 2026.
Transparency logRelease files / netbox_oidc_group_sync-0.1.1-py3-none-any.whl
| Download URL | netbox_oidc_group_sync-0.1.1-py3-none-any.whl |
|---|---|
| Size | 7.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d00fd39de1fab561029245cb88b7d10f018f7c171799c013bfa2c9b15a754ae5
|
|
BLAKE2b-256 checksum How to use checksums |
d6f3067436e4ce14bc8096e741d69942a6e45103d8c52c604a47b4f264671e01
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 25, 2026.
Transparency log