From cc71179a998b3aeb5830ddf681f67bf092b39b4a Mon Sep 17 00:00:00 2001 From: Etienne Stalmans Date: Wed, 3 Jun 2026 16:43:11 +0200 Subject: [PATCH] chore: consistent oauth param delete --- internal/api/custom_oauth_admin.go | 34 +++++++++++++++++------------- internal/api/external.go | 12 +++++++++-- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/internal/api/custom_oauth_admin.go b/internal/api/custom_oauth_admin.go index 82cef1702..1d614a449 100644 --- a/internal/api/custom_oauth_admin.go +++ b/internal/api/custom_oauth_admin.go @@ -643,28 +643,32 @@ func getBoolOrDefault(value *bool, defaultValue bool) bool { return *value } +// reservedOAuthParams lists OAuth2/OIDC parameters that the auth server +// controls. They must never be overridden by client-supplied input, since +// allowing override would be a security issue (e.g. swapping redirect_uri or +// state). nonce is reserved here so it can't be pinned to a static value in a +// provider's stored authorization_params; it is still allowed as a per-request +// passthrough on the external redirect (see external.go). +var reservedOAuthParams = []string{ + "client_id", + "client_secret", + "redirect_uri", + "response_type", + "state", + "code_challenge", + "code_challenge_method", + "code_verifier", + "nonce", +} + // validateAuthorizationParams ensures no reserved OAuth parameters are overridden func validateAuthorizationParams(params map[string]interface{}) error { if params == nil { return nil } - // Reserved OAuth2/OIDC parameters that should never be overridden - // These are set by the auth server and allowing override would be a security issue - reservedParams := []string{ - "client_id", - "client_secret", - "redirect_uri", - "response_type", - "state", - "code_challenge", - "code_challenge_method", - "code_verifier", - "nonce", // We control nonce generation for security - } - for key, value := range params { - if slices.Contains(reservedParams, key) { + if slices.Contains(reservedOAuthParams, key) { return apierrors.NewBadRequestError( apierrors.ErrorCodeValidationFailed, "Cannot override reserved OAuth parameter: %s", key, diff --git a/internal/api/external.go b/internal/api/external.go index 0f88a64b8..ae3989d38 100644 --- a/internal/api/external.go +++ b/internal/api/external.go @@ -70,8 +70,16 @@ func (a *API) GetExternalProviderRedirectURL(w http.ResponseWriter, r *http.Requ authUrlParams := make([]oauth2.AuthCodeOption, 0) query.Del("scopes") query.Del("provider") - query.Del("code_challenge") - query.Del("code_challenge_method") + // Strip OAuth params the auth server controls so a client cannot + // override redirect_uri, state, code_challenge, etc. by passing them + // through on the redirect URL. nonce is deliberately NOT stripped — some + // upstream OIDC providers expect the client to supply it. + for _, k := range reservedOAuthParams { + if k != "nonce" { + query.Del(k) + } + } + for key := range query { if key == "workos_provider" { // See https://workos.com/docs/reference/sso/authorize/get