From ceb5e05329b9cb0fc1219cdb5c5658d9f8d4299a Mon Sep 17 00:00:00 2001 From: Stavros Date: Tue, 14 Jul 2026 15:54:27 +0300 Subject: [PATCH 1/3] feat: allow existing query params in oidc redirect uri --- internal/controller/oidc_controller.go | 50 ++++++++++++++------------ 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/internal/controller/oidc_controller.go b/internal/controller/oidc_controller.go index 0c5ac918..bf03995a 100644 --- a/internal/controller/oidc_controller.go +++ b/internal/controller/oidc_controller.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/http" + "net/url" "slices" "strconv" "strings" @@ -343,27 +344,30 @@ func (controller *OIDCController) authorizeComplete(c *gin.Context) { // Create the authorization code code := controller.oidc.CreateCode(*authorizeReq, *userContext) - queries, err := query.Values(AuthorizeCallback{ - Code: code, - State: authorizeReq.State, - }) + cu, err := url.Parse(authorizeReq.RedirectURI) if err != nil { controller.authorizeError(c, authorizeErrorParams{ err: err, - reason: "Failed to build query", - reasonPublic: "Failed to build query", + reason: "Failed to parse redirect URI", + reasonPublic: "Failed to parse redirect URI", callback: authorizeReq.RedirectURI, callbackError: "server_error", state: authorizeReq.State, json: true, }) - return } + q := cu.Query() + + q.Set("code", code) + q.Set("state", authorizeReq.State) + + cu.RawQuery = q.Encode() + c.JSON(200, gin.H{ "status": 200, - "redirect_uri": fmt.Sprintf("%s?%s", authorizeReq.RedirectURI, queries.Encode()), + "redirect_uri": cu.String(), }) } @@ -639,37 +643,37 @@ func (controller *OIDCController) authorizeError(c *gin.Context, params authoriz controller.log.App.Error().Err(params.err).Str("reason", params.reason).Msg("Authorization error") if params.callback != "" { - errorQueries := CallbackError{ - Error: params.callbackError, + cu, err := url.Parse(params.callback) + + if err != nil { + controller.log.App.Error().Err(err).Msg("Failed to parse callback URL") + c.AbortWithStatus(http.StatusInternalServerError) + return } + q := cu.Query() + + q.Set("error", params.callbackError) + if params.reasonPublic != "" { - errorQueries.ErrorDescription = params.reasonPublic + q.Set("error_description", params.reasonPublic) } if params.state != "" { - errorQueries.State = params.state - } - - queries, err := query.Values(errorQueries) - - if err != nil { - controller.log.App.Error().Err(err).Msg("Failed to build callback error query") - c.AbortWithStatus(http.StatusInternalServerError) - return + q.Set("state", params.state) } - redirectUrl := fmt.Sprintf("%s?%s", params.callback, queries.Encode()) + cu.RawQuery = q.Encode() if params.json { c.JSON(200, gin.H{ "status": 200, - "redirect_uri": redirectUrl, + "redirect_uri": cu.String(), }) return } - c.Redirect(http.StatusFound, redirectUrl) + c.Redirect(http.StatusFound, cu.String()) return } From afcfa7edd4a3a6f7fc0a970f078b948535d67e90 Mon Sep 17 00:00:00 2001 From: Stavros Date: Tue, 14 Jul 2026 16:08:03 +0300 Subject: [PATCH 2/3] fix: coderabbit review comments --- internal/controller/oidc_controller.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/controller/oidc_controller.go b/internal/controller/oidc_controller.go index bf03995a..c6b9900e 100644 --- a/internal/controller/oidc_controller.go +++ b/internal/controller/oidc_controller.go @@ -356,12 +356,16 @@ func (controller *OIDCController) authorizeComplete(c *gin.Context) { state: authorizeReq.State, json: true, }) + return } q := cu.Query() q.Set("code", code) - q.Set("state", authorizeReq.State) + + if authorizeReq.State != "" { + q.Set("state", authorizeReq.State) + } cu.RawQuery = q.Encode() From 9bb3a9d2afbfc568abbf703a48e425524274a5db Mon Sep 17 00:00:00 2001 From: Stavros Date: Tue, 14 Jul 2026 16:22:47 +0300 Subject: [PATCH 3/3] fix: do not pass unparseable redirect url to authorize error --- internal/controller/oidc_controller.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/internal/controller/oidc_controller.go b/internal/controller/oidc_controller.go index c6b9900e..59856244 100644 --- a/internal/controller/oidc_controller.go +++ b/internal/controller/oidc_controller.go @@ -348,13 +348,10 @@ func (controller *OIDCController) authorizeComplete(c *gin.Context) { if err != nil { controller.authorizeError(c, authorizeErrorParams{ - err: err, - reason: "Failed to parse redirect URI", - reasonPublic: "Failed to parse redirect URI", - callback: authorizeReq.RedirectURI, - callbackError: "server_error", - state: authorizeReq.State, - json: true, + err: err, + reason: "Failed to parse redirect URI", + reasonPublic: "Failed to parse redirect URI", + json: true, }) return }