Skip to content

reproduce #267 #720

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
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
156 changes: 156 additions & 0 deletions openapi3filter/issue267_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package openapi3filter

import (
"net/http"
"strings"
"testing"

"github.com/stretchr/testify/require"

"github.com/getkin/kin-openapi/openapi3"
"github.com/getkin/kin-openapi/routers/gorillamux"
)

func TestIssue267(t *testing.T) {
spec := `
openapi: 3.0.0
info:
description: This is a sample of the API
version: 1.0.0
title: sample API
tags:
- name: authorization
description: Create and validate authorization tokens using oauth
paths:
/oauth2/token:
post:
tags:
- authorization
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/AccessTokenRequest'
examples:
ClientCredentialsTokenRequest:
$ref: '#/components/examples/ClientCredentialsTokenRequest'
RefreshTokenRequest:
$ref: '#/components/examples/RefreshTokenRequest'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/AccessTokenRequest'
examples:
ClientCredentialsTokenRequest:
$ref: '#/components/examples/ClientCredentialsTokenRequest'
RefreshTokenRequest:
$ref: '#/components/examples/RefreshTokenRequest'
responses:
'200':
description: 'The request was successful and a token was issued.'

components:
examples:
ClientCredentialsTokenRequest:
value:
grant_type: client_credentials
scope: 'member:read member:write'
RefreshTokenRequest:
value:
grant_type: refresh_token
client_id: '3fa85f64-5717-4562-b3fc-2c963f66afa6'
refresh_token: '2fbd6ad96acc4fa99ef36a3e803b010b'
schemas:
AccessTokenRequest:
description: 'Describes all of the potential access token requests that can be received'
type: object
oneOf:
- $ref: '#/components/schemas/ClientCredentialsTokenRequest'
- $ref: '#/components/schemas/RefreshTokenRequest'
ClientCredentialsTokenRequest:
description: 'The client_id and client_secret properties should only be sent in form data if the client does not support basic authentication for sending client credentials.'
properties:
grant_type:
type: string
enum:
- client_credentials
example: 'client_credentials'
scope:
description: 'A space separated list of scopes requested for the token'
type: string
example: 'member:read member:write'
client_id:
description: 'The ID provided when the client application was registered'
type: string
example: '3fa85f64-5717-4562-b3fc-2c963f66afa6'
client_secret:
description: 'A secret code that would be setup for the client to exchange for an access token.'
type: string
example: 'fac663c0-e8b5-4c02-9ad3-ddbd1bbc6964'
required:
- grant_type
- scope
RefreshTokenRequest:
type: object
properties:
grant_type:
type: string
enum:
- refresh_token
example: 'refresh_token'
client_id:
description: 'The ID provided when the client application was registered'
type: string
example: '3fa85f64-5717-4562-b3fc-2c963f66afa6'
refresh_token:
description: 'A long lived one time use token that is issued only in cases where the client can be offline or restarted and where the authorization should persist.'
type: string
minLength: 32
example: '2fbd6ad96acc4fa99ef36a3e803b010b'
required:
- grant_type
- client_id
- refresh_token
`[1:]

loader := openapi3.NewLoader()

doc, err := loader.LoadFromData([]byte(spec))
require.NoError(t, err)

err = doc.Validate(loader.Context)
require.NoError(t, err)

router, err := gorillamux.NewRouter(doc)
require.NoError(t, err)

for _, testcase := range []struct {
ct, data string
}{
{
ct: "application/json",
data: `{"grant_type":"client_credentials", "scope":"testscope", "client_id":"myclient", "client_secret":"mypass"}`,
},
{
ct: "application/x-www-form-urlencoded",
data: "grant_type=client_credentials&scope=testscope&client_id=myclient&client_secret=mypass",
},
} {
t.Run(testcase.ct, func(t *testing.T) {
data := strings.NewReader(testcase.data)
req, err := http.NewRequest("POST", "/oauth2/token", data)
require.NoError(t, err)
req.Header.Add("Content-Type", testcase.ct)

route, pathParams, err := router.FindRoute(req)
require.NoError(t, err)

validationInput := &RequestValidationInput{
Request: req,
PathParams: pathParams,
Route: route,
}
err = ValidateRequest(loader.Context, validationInput)
require.NoError(t, err)
})
}
}
1 change: 1 addition & 0 deletions openapi3filter/req_resp_decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,7 @@ func urlencodedBodyDecoder(body io.Reader, header http.Header, schema *openapi3.
if schema.Value.Type != "object" {
return nil, errors.New("unsupported schema of request body")
}
// TODO: sum all properties possible first
for propName, propSchema := range schema.Value.Properties {
switch propSchema.Value.Type {
case "object":
Expand Down