Repository: swaggest/openapi-go (go)

Issue:
Security schemes validation error
Consider something like:

```go
var s openapi3.Spec

	spec := `openapi: 3.0.3
info:
  description: description
  license:
    name: Apache-2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html
  title: title
  version: 2.0.0
servers:
  - url: /v2
paths:
  /user:
    put:
      summary: updates the user by id
      operationId: UpdateUser
      requestBody:
        content:
          application/json:
            schema:
              type: string
        description: Updated user object
        required: true
      responses:
        "404":
          description: User not found
components:
  securitySchemes:
    api_key:
      in: header
      name: x-api-key
      type: apiKey
    bearer_auth:
      type: http
      scheme: bearer
      bearerFormat: JWT`

	if err := s.UnmarshalYAML([]byte(spec)); err != nil {
		log.Fatal(err)
	}
```

this results in: 

```
oneOf constraint failed for SecuritySchemeOrRef with 0 valid results: map[SecurityScheme:oneOf constraint failed for SecurityScheme with 0 valid results: map[APIKeySecurityScheme:required key missing: name HTTPSecurityScheme:oneOf constraint failed for HTTPSecurityScheme with 2 valid results: map[] OAuth2SecurityScheme:required key missing: flows OpenIDConnectSecurityScheme:required key missing: openIdConnectUrl] SecuritySchemeReference:required key missing: $ref]
```

when there really shouldn't be any error. It's coming from the generated `openapi3/entities.go` but when I use the source json schema directly it gives no errors as it should, so I there must be something wrong with the generated validation code

Version: v0.2.24

Pull request:
Fix validation of http bearer scheme
Fixes #51.

Patch:
diff --git a/go.mod b/go.mod
index a74fd8a..65e8260 100644
--- a/go.mod
+++ b/go.mod
@@ -6,7 +6,7 @@ require (
 	github.com/bool64/dev v0.2.22
 	github.com/stretchr/testify v1.8.1
 	github.com/swaggest/assertjson v1.7.0
-	github.com/swaggest/jsonschema-go v0.3.40
+	github.com/swaggest/jsonschema-go v0.3.41
 	github.com/swaggest/refl v1.1.0
 	gopkg.in/yaml.v2 v2.4.0
 )
diff --git a/go.sum b/go.sum
index 072c670..142431a 100644
--- a/go.sum
+++ b/go.sum
@@ -2,7 +2,7 @@ github.com/bool64/dev v0.2.5/go.mod h1:cTHiTDNc8EewrQPy3p1obNilpMpdmlUesDkFTF2zR
 github.com/bool64/dev v0.2.10/go.mod h1:/csLrm+4oDSsKJRIVS0mrywAonLnYKFG8RvGT7Jh9b8=
 github.com/bool64/dev v0.2.16/go.mod h1:/csLrm+4oDSsKJRIVS0mrywAonLnYKFG8RvGT7Jh9b8=
 github.com/bool64/dev v0.2.17/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg=
-github.com/bool64/dev v0.2.19/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg=
+github.com/bool64/dev v0.2.21/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg=
 github.com/bool64/dev v0.2.22 h1:YJFKBRKplkt+0Emq/5Xk1Z5QRmMNzc1UOJkR3rxJksA=
 github.com/bool64/dev v0.2.22/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg=
 github.com/bool64/shared v0.1.4/go.mod h1:ryGjsnQFh6BnEXClfVlEJrzjwzat7CmA8PNS5E+jPp0=
@@ -64,8 +64,8 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 github.com/swaggest/assertjson v1.7.0 h1:SKw5Rn0LQs6UvmGrIdaKQbMR1R3ncXm5KNon+QJ7jtw=
 github.com/swaggest/assertjson v1.7.0/go.mod h1:vxMJMehbSVJd+dDWFCKv3QRZKNTpy/ktZKTz9LOEDng=
-github.com/swaggest/jsonschema-go v0.3.40 h1:9EqQ9RvtdW69xfYODmyEKWOSZ12x5eiK+wGD2EVh/L4=
-github.com/swaggest/jsonschema-go v0.3.40/go.mod h1:ipIOmoFP64QyRUgyPyU/P9tayq2m2TlvUhyZHrhe3S4=
+github.com/swaggest/jsonschema-go v0.3.41 h1:YsrBk5TW+S7/jTudvo1jWUJTECAIBdfk4iM7O9kzbnU=
+github.com/swaggest/jsonschema-go v0.3.41/go.mod h1:yt5lcjdqywYtNnzkFgYnyfvMwlH2XHEDitKw749AV1w=
 github.com/swaggest/refl v1.1.0 h1:a+9a75Kv6ciMozPjVbOfcVTEQe81t2R3emvaD9oGQGc=
 github.com/swaggest/refl v1.1.0/go.mod h1:g3Qa6ki0A/L2yxiuUpT+cuBURuRaltF5SDQpg1kMZSY=
 github.com/yosuke-furukawa/json5 v0.1.2-0.20201207051438-cf7bb3f354ff/go.mod h1:sw49aWDqNdRJ6DYUtIQiaA3xyj2IL9tjeNYmX2ixwcU=
diff --git a/openapi3/entities.go b/openapi3/entities.go
index 74a725f..7142a4f 100644
--- a/openapi3/entities.go
+++ b/openapi3/entities.go
@@ -6792,6 +6792,30 @@ type NonBearer struct {
 	Scheme *interface{} `json:"scheme,omitempty"`
 }
 
+// UnmarshalJSON decodes JSON.
+func (b *NonBearer) UnmarshalJSON(data []byte) error {
+	var err error
+
+	var rawMap map[string]json.RawMessage
+
+	err = json.Unmarshal(data, &rawMap)
+	if err != nil {
+		rawMap = nil
+	}
+
+	if v, exists := rawMap["scheme"]; exists && string(v) == `"bearer"` {
+		return fmt.Errorf(`bad const value for "scheme" (not "bearer" expected, %s received)`, v)
+	}
+
+	if _, exists := rawMap["bearerFormat"]; exists {
+		return errors.New(`property "bearerFormat" should not exist`)
+	}
+
+	delete(rawMap, "scheme")
+
+	return nil
+}
+
 // WithScheme sets Scheme value.
 func (n *NonBearer) WithScheme(val interface{}) *NonBearer {
 	n.Scheme = &val


Test patch:
diff --git a/openapi3/entities_extra_test.go b/openapi3/entities_extra_test.go
new file mode 100644
index 0000000..75234a4
--- /dev/null
+++ b/openapi3/entities_extra_test.go
@@ -0,0 +1,50 @@
+package openapi3_test
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/swaggest/openapi-go/openapi3"
+)
+
+func TestSpec_MarshalYAML(t *testing.T) {
+	var s openapi3.Spec
+
+	spec := `openapi: 3.0.3
+info:
+  description: description
+  license:
+    name: Apache-2.0
+    url: https://www.apache.org/licenses/LICENSE-2.0.html
+  title: title
+  version: 2.0.0
+servers:
+  - url: /v2
+paths:
+  /user:
+    put:
+      summary: updates the user by id
+      operationId: UpdateUser
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+        description: Updated user object
+        required: true
+      responses:
+        "404":
+          description: User not found
+components:
+  securitySchemes:
+    api_key:
+      in: header
+      name: x-api-key
+      type: apiKey
+    bearer_auth:
+      type: http
+      scheme: bearer
+      bearerFormat: JWT`
+
+	assert.NoError(t, s.UnmarshalYAML([]byte(spec)))
+}
diff --git a/openapi3/entities_test.go b/openapi3/entities_test.go
index 77cf92e..023e911 100644
--- a/openapi3/entities_test.go
+++ b/openapi3/entities_test.go
@@ -852,7 +852,7 @@ func TestAPIKeySecurityScheme_MarshalJSON_roundtrip(t *testing.T) {
 
 func TestHTTPSecurityScheme_MarshalJSON_roundtrip(t *testing.T) {
 	var (
-		jsonValue = []byte(`{"scheme":"bee","bearerFormat":"cffaee","description":"dcddce","type":"http"}`)
+		jsonValue = []byte(`{"scheme":"bearer","bearerFormat":"cffaee","description":"dcddce","type":"http"}`)
 		v         HTTPSecurityScheme
 	)