Skip to content

Commit dac23cf

Browse files
committed
support validation for all http schemes
1 parent 26d43b7 commit dac23cf

2 files changed

Lines changed: 63 additions & 20 deletions

File tree

parameters/validate_security.go

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -124,24 +124,37 @@ func (v *paramValidator) validateHTTPSecurityScheme(
124124
request *http.Request,
125125
pathValue string,
126126
) (bool, []*errors.ValidationError) {
127-
switch strings.ToLower(secScheme.Scheme) {
128-
case "basic", "bearer", "digest":
129-
if request.Header.Get("Authorization") == "" {
130-
validationErrors := []*errors.ValidationError{
131-
{
132-
Message: fmt.Sprintf("Authorization header for '%s' scheme", secScheme.Scheme),
133-
Reason: "Authorization header was not found",
134-
ValidationType: helpers.SecurityValidation,
135-
ValidationSubType: secScheme.Scheme,
136-
SpecLine: sec.GoLow().Requirements.ValueNode.Line,
137-
SpecCol: sec.GoLow().Requirements.ValueNode.Column,
138-
HowToFix: "Add an 'Authorization' header to this request",
139-
},
140-
}
141-
errors.PopulateValidationErrors(validationErrors, request, pathValue)
142-
return false, validationErrors
127+
authorizationHeader := request.Header.Get("Authorization")
128+
if authorizationHeader == "" {
129+
validationErrors := []*errors.ValidationError{
130+
{
131+
Message: fmt.Sprintf("Authorization header for '%s' scheme", secScheme.Scheme),
132+
Reason: "Authorization header was not found",
133+
ValidationType: helpers.SecurityValidation,
134+
ValidationSubType: secScheme.Scheme,
135+
SpecLine: sec.GoLow().Requirements.ValueNode.Line,
136+
SpecCol: sec.GoLow().Requirements.ValueNode.Column,
137+
HowToFix: "Add an 'Authorization' header to this request",
138+
},
143139
}
144-
return true, nil
140+
errors.PopulateValidationErrors(validationErrors, request, pathValue)
141+
return false, validationErrors
142+
}
143+
if len(authorizationHeader) < len(secScheme.Scheme) || !strings.EqualFold(authorizationHeader[:len(secScheme.Scheme)], secScheme.Scheme) {
144+
validationErrors := []*errors.ValidationError{
145+
{
146+
Message: fmt.Sprintf("Authorization header scheme '%s' mismatch", secScheme.Scheme),
147+
Reason: "Authorization header had incorrect scheme",
148+
ValidationType: helpers.SecurityValidation,
149+
ValidationSubType: secScheme.Scheme,
150+
SpecLine: sec.GoLow().Requirements.ValueNode.Line,
151+
SpecCol: sec.GoLow().Requirements.ValueNode.Column,
152+
HowToFix: fmt.Sprintf("Use the scheme '%s' in the Authorization header "+
153+
"for this request", secScheme.Scheme),
154+
},
155+
}
156+
errors.PopulateValidationErrors(validationErrors, request, pathValue)
157+
return false, validationErrors
145158
}
146159
return true, nil
147160
}

parameters/validate_security_test.go

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -998,8 +998,8 @@ components:
998998
assert.Empty(t, errors)
999999
}
10001000

1001-
func TestParamValidator_ValidateSecurity_UnknownHTTPScheme(t *testing.T) {
1002-
// Test custom HTTP scheme - unknown to our validator, should pass through (not fail)
1001+
func TestParamValidator_ValidateSecurity_CustomHTTPScheme(t *testing.T) {
1002+
// Test custom HTTP scheme - should pass with correct scheme in header
10031003
spec := `openapi: 3.1.0
10041004
paths:
10051005
/products:
@@ -1017,8 +1017,9 @@ components:
10171017
m, _ := doc.BuildV3Model()
10181018
v := NewParameterValidator(&m.Model)
10191019

1020-
// Request with no auth - should pass because custom scheme is not validated
1020+
// Request with custom auth header - should pass
10211021
request, _ := http.NewRequest(http.MethodGet, "https://things.com/products", nil)
1022+
request.Header.Add("Authorization", "Custom dXNlcjpwYXNz")
10221023

10231024
valid, errors := v.ValidateSecurity(request)
10241025
assert.True(t, valid)
@@ -1053,3 +1054,32 @@ components:
10531054
assert.True(t, valid)
10541055
assert.Empty(t, errors)
10551056
}
1057+
1058+
func TestParamValidator_ValidateSecurity_HTTPScheme_Mismatch(t *testing.T) {
1059+
// Test http scheme with mismatch in header: should return errors
1060+
spec := `openapi: 3.1.0
1061+
paths:
1062+
/products:
1063+
get:
1064+
security:
1065+
- CustomAuth: []
1066+
components:
1067+
securitySchemes:
1068+
CustomAuth:
1069+
type: http
1070+
scheme: custom
1071+
`
1072+
1073+
doc, _ := libopenapi.NewDocument([]byte(spec))
1074+
m, _ := doc.BuildV3Model()
1075+
v := NewParameterValidator(&m.Model)
1076+
1077+
// Request with auth header - should fail as header scheme is incorrect
1078+
request, _ := http.NewRequest(http.MethodGet, "https://things.com/products", nil)
1079+
request.Header.Add("Authorization", "Basic dXNlcjpwYXNz")
1080+
1081+
valid, errors := v.ValidateSecurity(request)
1082+
assert.False(t, valid)
1083+
assert.Len(t, errors, 1)
1084+
assert.Contains(t, errors[0].Message, "Authorization header scheme 'custom' mismatch")
1085+
}

0 commit comments

Comments
 (0)