mirror of
https://github.com/netbox-community/netbox.git
synced 2026-01-11 21:10:29 +01:00
API POST requests fail when REMOTE_AUTH_HEADER is enabled #10896
Closed
opened 2025-12-29 21:37:24 +01:00 by adam
·
8 comments
No Branch/Tag Specified
main
update-changelog-comments-docs
feature-removal-issue-type
20911-dropdown
20239-plugin-menu-classes-mutable-state
21097-graphql-id-lookups
feature
fix_module_substitution
20923-dcim-templates
20044-elevation-stuck-lightmode
feature-ip-prefix-link
v4.5-beta1-release
20068-import-moduletype-attrs
20766-fix-german-translation-code-literals
20378-del-script
7604-filter-modifiers-v3
circuit-swap
12318-case-insensitive-uniqueness
20637-improve-device-q-filter
20660-script-load
19724-graphql
20614-update-ruff
14884-script
02496-max-page
19720-macaddress-interface-generic-relation
19408-circuit-terminations-export-templates
20203-openapi-check
fix-19669-api-image-download
7604-filter-modifiers
19275-fixes-interface-bulk-edit
fix-17794-get_field_value_return_list
11507-show-aggregate-and-rir-on-api
9583-add_column_specific_search_field_to_tables
v4.5.0
v4.4.10
v4.4.9
v4.5.0-beta1
v4.4.8
v4.4.7
v4.4.6
v4.4.5
v4.4.4
v4.4.3
v4.4.2
v4.4.1
v4.4.0
v4.3.7
v4.4.0-beta1
v4.3.6
v4.3.5
v4.3.4
v4.3.3
v4.3.2
v4.3.1
v4.3.0
v4.2.9
v4.3.0-beta2
v4.2.8
v4.3.0-beta1
v4.2.7
v4.2.6
v4.2.5
v4.2.4
v4.2.3
v4.2.2
v4.2.1
v4.2.0
v4.1.11
v4.1.10
v4.1.9
v4.1.8
v4.2-beta1
v4.1.7
v4.1.6
v4.1.5
v4.1.4
v4.1.3
v4.1.2
v4.1.1
v4.1.0
v4.0.11
v4.0.10
v4.0.9
v4.1-beta1
v4.0.8
v4.0.7
v4.0.6
v4.0.5
v4.0.3
v4.0.2
v4.0.1
v4.0.0
v3.7.8
v3.7.7
v4.0-beta2
v3.7.6
v3.7.5
v4.0-beta1
v3.7.4
v3.7.3
v3.7.2
v3.7.1
v3.7.0
v3.6.9
v3.6.8
v3.6.7
v3.7-beta1
v3.6.6
v3.6.5
v3.6.4
v3.6.3
v3.6.2
v3.6.1
v3.6.0
v3.5.9
v3.6-beta2
v3.5.8
v3.6-beta1
v3.5.7
v3.5.6
v3.5.5
v3.5.4
v3.5.3
v3.5.2
v3.5.1
v3.5.0
v3.4.10
v3.4.9
v3.5-beta2
v3.4.8
v3.5-beta1
v3.4.7
v3.4.6
v3.4.5
v3.4.4
v3.4.3
v3.4.2
v3.4.1
v3.4.0
v3.3.10
v3.3.9
v3.4-beta1
v3.3.8
v3.3.7
v3.3.6
v3.3.5
v3.3.4
v3.3.3
v3.3.2
v3.3.1
v3.3.0
v3.2.9
v3.2.8
v3.3-beta2
v3.2.7
v3.3-beta1
v3.2.6
v3.2.5
v3.2.4
v3.2.3
v3.2.2
v3.2.1
v3.2.0
v3.1.11
v3.1.10
v3.2-beta2
v3.1.9
v3.2-beta1
v3.1.8
v3.1.7
v3.1.6
v3.1.5
v3.1.4
v3.1.3
v3.1.2
v3.1.1
v3.1.0
v3.0.12
v3.0.11
v3.0.10
v3.1-beta1
v3.0.9
v3.0.8
v3.0.7
v3.0.6
v3.0.5
v3.0.4
v3.0.3
v3.0.2
v3.0.1
v3.0.0
v2.11.12
v3.0-beta2
v2.11.11
v2.11.10
v3.0-beta1
v2.11.9
v2.11.8
v2.11.7
v2.11.6
v2.11.5
v2.11.4
v2.11.3
v2.11.2
v2.11.1
v2.11.0
v2.10.10
v2.10.9
v2.11-beta1
v2.10.8
v2.10.7
v2.10.6
v2.10.5
v2.10.4
v2.10.3
v2.10.2
v2.10.1
v2.10.0
v2.9.11
v2.10-beta2
v2.9.10
v2.10-beta1
v2.9.9
v2.9.8
v2.9.7
v2.9.6
v2.9.5
v2.9.4
v2.9.3
v2.9.2
v2.9.1
v2.9.0
v2.9-beta2
v2.8.9
v2.9-beta1
v2.8.8
v2.8.7
v2.8.6
v2.8.5
v2.8.4
v2.8.3
v2.8.2
v2.8.1
v2.8.0
v2.7.12
v2.7.11
v2.7.10
v2.7.9
v2.7.8
v2.7.7
v2.7.6
v2.7.5
v2.7.4
v2.7.3
v2.7.2
v2.7.1
v2.7.0
v2.6.12
v2.6.11
v2.6.10
v2.6.9
v2.7-beta1
Solcon-2020-01-06
v2.6.8
v2.6.7
v2.6.6
v2.6.5
v2.6.4
v2.6.3
v2.6.2
v2.6.1
v2.6.0
v2.5.13
v2.5.12
v2.6-beta1
v2.5.11
v2.5.10
v2.5.9
v2.5.8
v2.5.7
v2.5.6
v2.5.5
v2.5.4
v2.5.3
v2.5.2
v2.5.1
v2.5.0
v2.4.9
v2.5-beta2
v2.4.8
v2.5-beta1
v2.4.7
v2.4.6
v2.4.5
v2.4.4
v2.4.3
v2.4.2
v2.4.1
v2.4.0
v2.3.7
v2.4-beta1
v2.3.6
v2.3.5
v2.3.4
v2.3.3
v2.3.2
v2.3.1
v2.3.0
v2.2.10
v2.3-beta2
v2.2.9
v2.3-beta1
v2.2.8
v2.2.7
v2.2.6
v2.2.5
v2.2.4
v2.2.3
v2.2.2
v2.2.1
v2.2.0
v2.1.6
v2.2-beta2
v2.1.5
v2.2-beta1
v2.1.4
v2.1.3
v2.1.2
v2.1.1
v2.1.0
v2.0.10
v2.1-beta1
v2.0.9
v2.0.8
v2.0.7
v2.0.6
v2.0.5
v2.0.4
v2.0.3
v2.0.2
v2.0.1
v2.0.0
v2.0-beta3
v1.9.6
v1.9.5
v2.0-beta2
v1.9.4-r1
v1.9.3
v2.0-beta1
v1.9.2
v1.9.1
v1.9.0-r1
v1.8.4
v1.8.3
v1.8.2
v1.8.1
v1.8.0
v1.7.3
v1.7.2-r1
v1.7.1
v1.7.0
v1.6.3
v1.6.2-r1
v1.6.1-r1
1.6.1
v1.6.0
v1.5.2
v1.5.1
v1.5.0
v1.4.2
v1.4.1
v1.4.0
v1.3.2
v1.3.1
v1.3.0
v1.2.2
v1.2.1
v1.2.0
v1.1.0
v1.0.7-r1
v1.0.7
v1.0.6
v1.0.5
v1.0.4
v1.0.3-r1
v1.0.3
1.0.0
Labels
Clear labels
beta
breaking change
complexity: high
complexity: low
complexity: medium
needs milestone
netbox
pending closure
plugin candidate
pull-request
severity: high
severity: low
severity: medium
status: accepted
status: backlog
status: blocked
status: duplicate
status: needs owner
status: needs triage
status: revisions needed
status: under review
topic: GraphQL
topic: Internationalization
topic: OpenAPI
topic: UI/UX
topic: cabling
topic: event rules
topic: htmx navigation
topic: industrialization
topic: migrations
topic: plugins
topic: scripts
topic: templating
topic: testing
type: bug
type: deprecation
type: documentation
type: feature
type: housekeeping
type: translation
Mirrored from GitHub Pull Request
No Label
type: bug
Milestone
No items
No Milestone
Projects
Clear projects
No project
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: starred/netbox#10896
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @llamafilm on GitHub (Mar 15, 2025).
Deployment Type
Self-hosted
NetBox Version
v4.2.4
Python Version
3.12
Steps to Reproduce
REMOTE_AUTH_ENABLEDandREMOTE_AUTH_HEADERin Netbox configcurl http://localhost:8000/api/dcim/sites/ -d '{"name": "site1", "slug": "site1"}'Expected Behavior
The request should succeed without "logging in". The same as how API requests work when you're not using
REMOTE_AUTH_HEADERand you provide an API token in the Authorization header.Observed Behavior
The request fails with HTTP 403:
The problem lies in Netbox customized version of
RemoteUserMiddleware. It runsauth.login()which causes Django to enforce CSRF. This of course fails, because a webhook cannot contain a CSRF token.I can workaround this by writing my own custom
REMOTE_AUTH_BACKENDclass, and using this logic to skip API requests:This avoids the
login()and the request succeeds, but this causes another minor problem: Every API request triggers auser_login_failedsignal which prints this message to the log:Furthermore, it should be possible to use
REMOTE_AUTH_HEADERwithout writing a custom class.@llamafilm commented on GitHub (Mar 15, 2025):
For a minimal, self-contained example to reproduce this situation, you can clone https://github.com/netbox-community/netbox-docker.git and add these files:
docker-compose.override.yml
Add to netbox.env:
httpd.conf
@llamafilm commented on GitHub (Mar 26, 2025):
Let me know if you'd like me to submit a patch for this. I think it's as simple as just adding those 2 lines I wrote above to the remote auth middleware.
@arthanson commented on GitHub (Apr 23, 2025):
@llamafilm I can assign to you if you want to work on a PR for this?
@llamafilm commented on GitHub (Apr 26, 2025):
Yes please assign to me
@jnovinger commented on GitHub (May 5, 2025):
Hey @llamafilm , I was assigned to review the PR for this and have been looking at the reported issue. I've come to the conclusion that I don't think it is a valid issue.
For the REST API, NetBox supports 2 kinds of authentication:
netbox.api.authentication.TokenAuthentication)rest_framework.authentication.SessionAuthentication).Note that Remote User Auth is not listed as a supported mechanism.
I've gathered from your
curlexample that this is not attempting to use token-based authentication, so if we expect Remote User Auth (as described above) to work for the example then we must assume that it's meant to use cookie-based authentication. In this case, the DRF docs indicate that session authentication (e.g. cookie-based) needs to include a valid CSRF token for any "unsafe" HTTP method call.Arthur did point out that you might be trying to use NetBox's ability to read-only from the REST API via the
EXEMPT_VIEW_PERMISSIONSsetting. However, yourcurlexample includes a-d '{"name": "site1", "slug": "site1"}'payload which implies an unsafe POST operation and must include a valid CSRF token as noted above.I think the take away here is that your example
curlrequest needs to be using an API token to make the specified POST call.Please let me know if I've misunderstood the situation.
@llamafilm commented on GitHub (May 5, 2025):
@jnovinger I just forgot to include the API token in my example curl command. I've updated the comment now, and the issue remains.
We do use API tokens to authenticate API requests. But Netbox is additionally trying to validate a CSRF token which doesn't make sense for webhooks.
I just updated the PR for compatibility with Django 5.2 (Netbox 4.3).
@jnovinger commented on GitHub (May 5, 2025):
Please, please make sure to include details like that in future reports as it makes a huge difference when trying to understand the issue.
I assume the remote user authentication is used for other reasons, since you are in fact using token auth for the REST API. In that case, your proxy needs to make sure that the header (
CUSTOMCUSTOMin this case) is not set for proxied requests coming from whatever is generating requests to the REST API.If the remote user header is sent with these requests, then--due to middleware running well before DRF has a chance to look at the API token--DRF will treat this as a session-based authenticated request and enforce CSRF validation as designed.
@llamafilm commented on GitHub (May 5, 2025):
Sorry about that. I'll try to add some more context here, since obviously this is a contrived example; in production, we run a customized version of Envoy which is tied into our SSO / identity system. The proxy validates the caller's identity (whether it be a user or an app) and passes that identity to Netbox as a header.
Envoy does have an option to disable authz for specific paths, but we would not want to do that because then anybody in possession of a Netbox token would be able to access the API. Those tokens are long-lived and possible to share accidentally. Enforcing authz in the proxy improves our security posture.
So in this scenario, the API token is sort of redundant because Netbox already knows the caller's identity and can map it to a Netbox user (and we trust the proxy does its job properly). But that's fine, I'm happy to include the token anyway.