oapi-codegen icon indicating copy to clipboard operation
oapi-codegen copied to clipboard

Can't pass security validation when using oapi validation middleware

Open bandirsen opened this issue 5 years ago • 7 comments

I use this library on sever side, while on client side do manually since the client is for mobile platform.

This is my openapi spec : I follow openapi documentation to define security scheme

paths:
  /admins:
    get:
      description: Get AdminList
      security:
        - bearerAuth: []
      operationId: getAdminList
    
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

And in my request I put Authorization header on request Authorization: Bearer ---random JWT token ----

But I always get 'Security requirements failed' from validation middleware (the JWT token was checked and valid) Am I missing something ?

PS: also it return http error 403, while above documentation recommending to return http 401 error for unauthorized request.

bandirsen avatar Aug 22 '20 19:08 bandirsen

Not sure this helps.. but you define auth globally in components, and you are applying it to the endpoint. You don't need to apply it to the endpoint since you are defining it globally as well. Try removing the security from the /admins endpoint.

kevinduffey avatar Aug 22 '20 19:08 kevinduffey

@kevinduffey

As fas as I understand from this documentation, global or per-operation(per-method) security, both require "securitySchemes" on components to define security schemes.

If we want to globaly security we put "security: " tag at same level as paths/component, for example:

paths:
  /admins:
    get:
    ...
components:
  securitySchemes:
    bearerAuth:
      type: http
     .....
security:
  bearerAuth: []

if we want per-operation (per-method) security we put 'security:' under method name like I do

bandirsen avatar Aug 22 '20 20:08 bandirsen

That sounds right.. but your first example you had it on the method.. though that should be valid too.

kevinduffey avatar Aug 22 '20 22:08 kevinduffey

I'm seeing this error as well, with the global security set (not at the path level):

paths:
  /models:
    post:
    ...
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
security:
  - bearerAuth: []

Removing the global security lets the validation pass:

curl -X POST "http://127.0.0.1:8090/models" -H "Authorization: Bearer a503faf9-45b5-4fec-8334-337284a66ea4" -H  "accept: application/json" -H  "Content-Type: application/json" -d "{\"name\":\"string\",\"type\":\"string\",\"options\":\"string\",\"parentId\":\"string\"}"

I'm looking into the issue now, just wanted to make a note of it here for reference

zaccari avatar Aug 26 '20 15:08 zaccari

@bandirsen I was able to resolve the issue by providing a custom validator function to the options, like so:

	validatorOptions := &oapimiddleware.Options{}

	validatorOptions.Options.AuthenticationFunc = func(c context.Context, input *oapifilter.AuthenticationInput) error {
		fmt.Println(">>>> INSIDE AuthenticationFunc")
		return nil
	}

	e.Use(oapimiddleware.OapiRequestValidatorWithOptions(swagger, validatorOptions))

If I don't pass a validator function, I get the Security requirements failed error

zaccari avatar Aug 26 '20 16:08 zaccari

@zaccari

In my case, I can't use global security, there are some my end-points that didn't requires authorization(jwt token), something like user registration etc, because of that, I solve my problem by creating custom oapi validation middleware based on current oapi validation middleware but I remove security validation part, and keeping the input validation part.

And then I create another custom middleware, based on echo jwtAuth middleware for token validation + user info extraction. and finally put that middleware to intercept request to oapi path that require authorization, so I do security validation and user info extraction from that jwt token in one step.

bandirsen avatar Aug 26 '20 21:08 bandirsen

@bandirsen

You can exclude your custom routes with the Skipper like this:

validatorOptions := &oapiMiddleware.Options{
    Skipper: func(c echo.Context) bool {
        return !strings.HasPrefix(c.Request().URL.Path, "/api/")
    },
}
e.Use(oapiMiddleware.OapiRequestValidatorWithOptions(swagger, validatorOptions))

This will skip validation for routes that don't start with /api/.

silenzium avatar Apr 05 '23 12:04 silenzium