Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 19 additions & 15 deletions internal/api/custom_oauth_admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
12 changes: 10 additions & 2 deletions internal/api/external.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading