-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
now the validator will check for HTTP and APIKey authentication on operations. Signed-off-by: Dave Shanley <[email protected]>
- Loading branch information
1 parent
bde416a
commit fbd40b0
Showing
10 changed files
with
543 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
// Copyright 2023 Princess B33f Heavy Industries / Dave Shanley | ||
// SPDX-License-Identifier: MIT | ||
|
||
package parameters | ||
|
||
import ( | ||
"fmt" | ||
"github.com/pb33f/libopenapi-validator/errors" | ||
"github.com/pb33f/libopenapi-validator/helpers" | ||
"github.com/pb33f/libopenapi-validator/paths" | ||
v3 "github.com/pb33f/libopenapi/datamodel/high/v3" | ||
"net/http" | ||
"strings" | ||
) | ||
|
||
func (v *paramValidator) ValidateSecurity(request *http.Request) (bool, []*errors.ValidationError) { | ||
|
||
// find path | ||
var pathItem *v3.PathItem | ||
var errs []*errors.ValidationError | ||
if v.pathItem == nil { | ||
pathItem, errs, _ = paths.FindPath(request, v.document) | ||
if pathItem == nil || errs != nil { | ||
v.errors = errs | ||
return false, errs | ||
} | ||
} else { | ||
pathItem = v.pathItem | ||
} | ||
|
||
// extract security for the operation | ||
security := helpers.ExtractSecurityForOperation(request, pathItem) | ||
|
||
if security == nil { | ||
return true, nil | ||
} | ||
|
||
for _, sec := range security { | ||
for secName, _ := range sec.Requirements { | ||
|
||
// look up security from components | ||
secScheme := v.document.Components.SecuritySchemes[secName] | ||
if secScheme != nil { | ||
|
||
switch strings.ToLower(secScheme.Type) { | ||
case "http": | ||
switch strings.ToLower(secScheme.Scheme) { | ||
case "basic", "bearer", "digest": | ||
// check for an authorization header | ||
if request.Header.Get("Authorization") == "" { | ||
return false, []*errors.ValidationError{ | ||
{ | ||
Message: fmt.Sprintf("Authorization header for '%s' scheme", secScheme.Scheme), | ||
Reason: "Authorization header was not found", | ||
ValidationType: "security", | ||
ValidationSubType: secScheme.Scheme, | ||
SpecLine: sec.GoLow().Requirements.ValueNode.Line, | ||
SpecCol: sec.GoLow().Requirements.ValueNode.Column, | ||
HowToFix: "Add an 'Authorization' header to this request", | ||
}, | ||
} | ||
} | ||
} | ||
|
||
case "apikey": | ||
// check if the api key is in the request | ||
if secScheme.In == "header" { | ||
if request.Header.Get(secScheme.Name) == "" { | ||
return false, []*errors.ValidationError{ | ||
{ | ||
Message: fmt.Sprintf("API Key %s not found in header", secScheme.Name), | ||
Reason: "API Key not found in http header for security scheme 'apiKey' with type 'header'", | ||
ValidationType: "security", | ||
ValidationSubType: "apiKey", | ||
SpecLine: sec.GoLow().Requirements.ValueNode.Line, | ||
SpecCol: sec.GoLow().Requirements.ValueNode.Column, | ||
HowToFix: fmt.Sprintf("Add the API Key via '%s' as a header of the request", secScheme.Name), | ||
}, | ||
} | ||
} | ||
} | ||
if secScheme.In == "query" { | ||
if request.URL.Query().Get(secScheme.Name) == "" { | ||
copyUrl := *request.URL | ||
fixed := ©Url | ||
q := fixed.Query() | ||
q.Add(secScheme.Name, "your-api-key") | ||
fixed.RawQuery = q.Encode() | ||
|
||
return false, []*errors.ValidationError{ | ||
{ | ||
Message: fmt.Sprintf("API Key %s not found in query", secScheme.Name), | ||
Reason: "API Key not found in URL query for security scheme 'apiKey' with type 'query'", | ||
ValidationType: "security", | ||
ValidationSubType: "apiKey", | ||
SpecLine: sec.GoLow().Requirements.ValueNode.Line, | ||
SpecCol: sec.GoLow().Requirements.ValueNode.Column, | ||
HowToFix: fmt.Sprintf("Add an API Key via '%s' to the query string "+ | ||
"of the URL, for example '%s'", secScheme.Name, fixed.String()), | ||
}, | ||
} | ||
} | ||
} | ||
if secScheme.In == "cookie" { | ||
cookies := request.Cookies() | ||
cookieFound := false | ||
for _, cookie := range cookies { | ||
if cookie.Name == secScheme.Name { | ||
cookieFound = true | ||
break | ||
} | ||
} | ||
if !cookieFound { | ||
return false, []*errors.ValidationError{ | ||
{ | ||
Message: fmt.Sprintf("API Key %s not found in cookies", secScheme.Name), | ||
Reason: "API Key not found in http request cookies for security scheme 'apiKey' with type 'cookie'", | ||
ValidationType: "security", | ||
ValidationSubType: "apiKey", | ||
SpecLine: sec.GoLow().Requirements.ValueNode.Line, | ||
SpecCol: sec.GoLow().Requirements.ValueNode.Column, | ||
HowToFix: fmt.Sprintf("Submit an API Key '%s' as a cookie with the request", secScheme.Name), | ||
}, | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return true, nil | ||
} |
Oops, something went wrong.