@@ -12,6 +12,7 @@ import (
1212 v3 "github.com/pb33f/libopenapi/datamodel/high/v3"
1313 "github.com/pb33f/libopenapi/orderedmap"
1414
15+ "github.com/pb33f/libopenapi-validator/config"
1516 "github.com/pb33f/libopenapi-validator/errors"
1617 "github.com/pb33f/libopenapi-validator/helpers"
1718 "github.com/pb33f/libopenapi-validator/paths"
@@ -84,7 +85,7 @@ func (v *paramValidator) ValidateSecurityWithPathItem(request *http.Request, pat
8485 }
8586
8687 secScheme := v .document .Components .SecuritySchemes .GetOrZero (secName )
87- schemeValid , schemeErrors := v .validateSecurityScheme (secScheme , sec , request , pathValue )
88+ schemeValid , schemeErrors := v .validateSecurityScheme (secName , secScheme , pair . Value () , sec , request , pathValue )
8889 if ! schemeValid {
8990 requirementSatisfied = false
9091 requirementErrors = append (requirementErrors , schemeErrors ... )
@@ -103,11 +104,17 @@ func (v *paramValidator) ValidateSecurityWithPathItem(request *http.Request, pat
103104
104105// validateSecurityScheme checks if a single security scheme is satisfied by the request.
105106func (v * paramValidator ) validateSecurityScheme (
107+ secName string ,
106108 secScheme * v3.SecurityScheme ,
109+ scopes []string ,
107110 sec * base.SecurityRequirement ,
108111 request * http.Request ,
109112 pathValue string ,
110113) (bool , []* errors.ValidationError ) {
114+ if v .options .AuthenticationFunc != nil {
115+ return v .validateAuthenticationFunc (secName , secScheme , scopes , sec , request , pathValue )
116+ }
117+
111118 switch strings .ToLower (secScheme .Type ) {
112119 case "http" :
113120 return v .validateHTTPSecurityScheme (secScheme , sec , request , pathValue )
@@ -118,6 +125,39 @@ func (v *paramValidator) validateSecurityScheme(
118125 return true , nil
119126}
120127
128+ func (v * paramValidator ) validateAuthenticationFunc (
129+ secName string ,
130+ secScheme * v3.SecurityScheme ,
131+ scopes []string ,
132+ sec * base.SecurityRequirement ,
133+ request * http.Request ,
134+ pathValue string ,
135+ ) (bool , []* errors.ValidationError ) {
136+ authErr := v .options .AuthenticationFunc (request .Context (), & config.AuthenticationInput {
137+ Request : request ,
138+ SecuritySchemeName : secName ,
139+ SecurityScheme : secScheme ,
140+ Scopes : scopes ,
141+ })
142+ if authErr == nil {
143+ return true , nil
144+ }
145+
146+ validationErrors := []* errors.ValidationError {
147+ {
148+ Message : fmt .Sprintf ("Authentication failed for security scheme '%s'" , secName ),
149+ Reason : authErr .Error (),
150+ ValidationType : helpers .SecurityValidation ,
151+ ValidationSubType : secScheme .Type ,
152+ SpecLine : sec .GoLow ().Requirements .ValueNode .Line ,
153+ SpecCol : sec .GoLow ().Requirements .ValueNode .Column ,
154+ HowToFix : fmt .Sprintf ("Provide valid credentials for security scheme '%s'" , secName ),
155+ },
156+ }
157+ errors .PopulateValidationErrors (validationErrors , request , pathValue )
158+ return false , validationErrors
159+ }
160+
121161func (v * paramValidator ) validateHTTPSecurityScheme (
122162 secScheme * v3.SecurityScheme ,
123163 sec * base.SecurityRequirement ,
0 commit comments