mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2026-04-25 08:45:58 +03:00
[GH-ISSUE #1563] OIDC callback endpoint should use GET and query parameters, not POST with JSON body #6637
Labels
No labels
Q/A
bug
casdoor
dependencies
docker
documentation
duplicate
enhancement
help wanted
invalid
lego
platform:openwrt
platform:windows
pull-request
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/nginx-ui#6637
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
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 @Tom60chat on GitHub (Feb 16, 2026).
Original GitHub issue: https://github.com/0xJacky/nginx-ui/issues/1563
Describe the bug
The OIDC callback handler (
OIDCCallbackat/oidc_callback) is currently registered as a POST endpoint and attempts to parse a JSON body for thecodeandstateparameters. This does not conform to the OAuth 2.0 (RFC 6749) and OpenID Connect specifications.Problem details
codeandstateincluded as URL query parameters (not a JSON body, and usually not POST).Relevant code (from
api/user/oidc.go):Specification references:
To Reproduce
Expected behavior
The callback endpoint should:
r.GET("/oidc_callback", OIDCCallback))codeandstatefrom query parameters (usingc.Query("code")andc.Query("state")in Gin)Additional context
If you want to support POST with form-encoded body (for providers using
response_mode=form_post), handle that as a special case—but standard OIDC and OAuth2 providers use GET + query parameters.Let me know if you'd like suggestions for updated code!
@Jraaay commented on GitHub (Feb 17, 2026):
Thank you for the report, but I believe this is actually working as designed. The implementation follows a Frontend-Mediated Callback pattern, which is a standard and well-established approach in Single Page Applications (SPAs).
How the flow actually works
The key point is: the redirect_uri registered with the OIDC provider points to the frontend SPA page, not the backend API endpoint. The OIDC provider does redirect via GET with query parameters — the frontend receives them correctly and then relays them to the backend through an API call.
Why this design is intentional
This is a widely used pattern — for example, libraries like oidc-client-js and Auth0 SPA SDK follow the same approach.
How to correctly configure OIDC
To use OIDC login with Nginx UI, add the following to your app.ini configuration file:
Or via environment variables:
Important notes:
RedirectUrimust point to the root URL of your Nginx UI instance (e.g.,https://your-domain.com). This is also the URL you should register as the "Redirect URI" / "Callback URL" in your OIDC provider's application settings. Since Nginx UI uses hash-based routing (#/login), the frontend will correctly pick upcodeandstatefrom the URL query parameters viawindow.location.searchafter the redirect.Endpointis the OIDC issuer URL. For example,https://accounts.google.comfor Google, orhttps://your-tenant.auth0.comfor Auth0.Scopesdefaults toopenid profile email username. Customize only if your provider requires specific scopes.Identifieris an optional claim name used to match the OIDC user to a local Nginx UI user. If left empty, the system will tryusername. The matched value must correspond to an existing username in Nginx UI — users are not auto-created.@Tom60chat commented on GitHub (Feb 23, 2026):
Sorry for the multiple edits in this issue, GitHub Copilot messed up and I have to manually reverse... that's what I get using AI
Apologies for my earlier misunderstanding!
I was not aware that the Frontend-Mediated Callback pattern existed. With the limited documentation, I did my best to figure out how the OIDC authentication flow worked, but now that I understand the SPA pattern, it all makes sense. I'm sorry for any confusion my earlier report may have caused—this approach is indeed correct and working well.
I've also changed my previous comments in #1488 reflect this clarification.
However, I did notice a possible issue while setting up OIDC:
When the
/oidc_callbackendpoint returns a 403 error (for example, because the mapped user does not exist), the error message ("User not exist") is not shown in the login screen. Instead, it always displays "State cookie not found," even though that's not the real problem.Expected:
If the OIDC login fails due to a missing user or another backend error, the frontend should show the actual error message returned by the backend (e.g., "User not exist"), so users know what went wrong.
Actual:
The frontend always reports "State cookie not found," which makes troubleshooting harder.
Thank you for the clarification and for your work on this project! 😸