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
47 changes: 30 additions & 17 deletions parameters/validate_security.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,24 +124,37 @@ func (v *paramValidator) validateHTTPSecurityScheme(
request *http.Request,
pathValue string,
) (bool, []*errors.ValidationError) {
switch strings.ToLower(secScheme.Scheme) {
case "basic", "bearer", "digest":
if request.Header.Get("Authorization") == "" {
validationErrors := []*errors.ValidationError{
{
Message: fmt.Sprintf("Authorization header for '%s' scheme", secScheme.Scheme),
Reason: "Authorization header was not found",
ValidationType: helpers.SecurityValidation,
ValidationSubType: secScheme.Scheme,
SpecLine: sec.GoLow().Requirements.ValueNode.Line,
SpecCol: sec.GoLow().Requirements.ValueNode.Column,
HowToFix: "Add an 'Authorization' header to this request",
},
}
errors.PopulateValidationErrors(validationErrors, request, pathValue)
return false, validationErrors
authorizationHeader := request.Header.Get("Authorization")
if authorizationHeader == "" {
validationErrors := []*errors.ValidationError{
{
Message: fmt.Sprintf("Authorization header for '%s' scheme", secScheme.Scheme),
Reason: "Authorization header was not found",
ValidationType: helpers.SecurityValidation,
ValidationSubType: secScheme.Scheme,
SpecLine: sec.GoLow().Requirements.ValueNode.Line,
SpecCol: sec.GoLow().Requirements.ValueNode.Column,
HowToFix: "Add an 'Authorization' header to this request",
},
}
return true, nil
errors.PopulateValidationErrors(validationErrors, request, pathValue)
return false, validationErrors
}
if len(authorizationHeader) < len(secScheme.Scheme) || !strings.EqualFold(authorizationHeader[:len(secScheme.Scheme)], secScheme.Scheme) {
validationErrors := []*errors.ValidationError{
{
Message: fmt.Sprintf("Authorization header scheme '%s' mismatch", secScheme.Scheme),
Reason: "Authorization header had incorrect scheme",
ValidationType: helpers.SecurityValidation,
ValidationSubType: secScheme.Scheme,
SpecLine: sec.GoLow().Requirements.ValueNode.Line,
SpecCol: sec.GoLow().Requirements.ValueNode.Column,
HowToFix: fmt.Sprintf("Use the scheme '%s' in the Authorization header "+
"for this request", secScheme.Scheme),
},
}
errors.PopulateValidationErrors(validationErrors, request, pathValue)
return false, validationErrors
}
return true, nil
}
Expand Down
36 changes: 33 additions & 3 deletions parameters/validate_security_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -998,8 +998,8 @@ components:
assert.Empty(t, errors)
}

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

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

valid, errors := v.ValidateSecurity(request)
assert.True(t, valid)
Expand Down Expand Up @@ -1053,3 +1054,32 @@ components:
assert.True(t, valid)
assert.Empty(t, errors)
}

func TestParamValidator_ValidateSecurity_HTTPScheme_Mismatch(t *testing.T) {
// Test http scheme with mismatch in header: should return errors
spec := `openapi: 3.1.0
paths:
/products:
get:
security:
- CustomAuth: []
components:
securitySchemes:
CustomAuth:
type: http
scheme: custom
`

doc, _ := libopenapi.NewDocument([]byte(spec))
m, _ := doc.BuildV3Model()
v := NewParameterValidator(&m.Model)

// Request with auth header - should fail as header scheme is incorrect
request, _ := http.NewRequest(http.MethodGet, "https://things.com/products", nil)
request.Header.Add("Authorization", "Basic dXNlcjpwYXNz")

valid, errors := v.ValidateSecurity(request)
assert.False(t, valid)
assert.Len(t, errors, 1)
assert.Contains(t, errors[0].Message, "Authorization header scheme 'custom' mismatch")
}