1package openapi3
2
3import (
4	"context"
5	"testing"
6
7	"github.com/stretchr/testify/require"
8)
9
10type securitySchemeExample struct {
11	title string
12	raw   []byte
13	valid bool
14}
15
16func TestSecuritySchemaExample(t *testing.T) {
17	for _, example := range securitySchemeExamples {
18		t.Run(example.title, testSecuritySchemaExample(t, example))
19	}
20}
21
22func testSecuritySchemaExample(t *testing.T, e securitySchemeExample) func(*testing.T) {
23	return func(t *testing.T) {
24		var err error
25		ss := &SecurityScheme{}
26		err = ss.UnmarshalJSON(e.raw)
27		require.NoError(t, err)
28		err = ss.Validate(context.Background())
29		if e.valid {
30			require.NoError(t, err)
31		} else {
32			require.Error(t, err)
33		}
34	}
35}
36
37// from https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#fixed-fields-23
38var securitySchemeExamples = []securitySchemeExample{
39	{
40		title: "Basic Authentication Sample",
41		raw: []byte(`
42{
43  "type": "http",
44  "scheme": "basic"
45}
46`),
47		valid: true,
48	},
49	{
50		title: "Negotiate Authentication Sample",
51		raw: []byte(`
52{
53  "type": "http",
54  "scheme": "negotiate"
55}
56`),
57		valid: true,
58	},
59	{
60		title: "Unknown http Authentication Sample",
61		raw: []byte(`
62{
63  "type": "http",
64  "scheme": "notvalid"
65}
66`),
67		valid: false,
68	},
69	{
70		title: "API Key Sample",
71		raw: []byte(`
72{
73  "type": "apiKey",
74  "name": "api_key",
75  "in": "header"
76}
77`),
78		valid: true,
79	},
80	{
81		title: "apiKey with bearerFormat",
82		raw: []byte(`
83{
84  "type": "apiKey",
85	"in": "header",
86	"name": "X-API-KEY",
87  "bearerFormat": "Arbitrary text"
88}
89`),
90		valid: false,
91	},
92	{
93		title: "Bearer Sample with arbitrary format",
94		raw: []byte(`
95{
96  "type": "http",
97  "scheme": "bearer",
98  "bearerFormat": "Arbitrary text"
99}
100`),
101		valid: true,
102	},
103	{
104		title: "Implicit OAuth2 Sample",
105		raw: []byte(`
106{
107  "type": "oauth2",
108  "flows": {
109    "implicit": {
110      "authorizationUrl": "https://example.com/api/oauth/dialog",
111      "scopes": {
112        "write:pets": "modify pets in your account",
113        "read:pets": "read your pets"
114      }
115    }
116  }
117}
118`),
119		valid: true,
120	},
121	{
122		title: "OAuth Flow Object Sample",
123		raw: []byte(`
124{
125  "type": "oauth2",
126  "flows": {
127    "implicit": {
128      "authorizationUrl": "https://example.com/api/oauth/dialog",
129      "scopes": {
130        "write:pets": "modify pets in your account",
131        "read:pets": "read your pets"
132      }
133    },
134    "authorizationCode": {
135      "authorizationUrl": "https://example.com/api/oauth/dialog",
136      "tokenUrl": "https://example.com/api/oauth/token",
137      "scopes": {
138        "write:pets": "modify pets in your account",
139        "read:pets": "read your pets"
140      }
141    }
142  }
143}
144`),
145		valid: true,
146	},
147	{
148		title: "OAuth Flow Object clientCredentials/password",
149		raw: []byte(`
150{
151  "type": "oauth2",
152  "flows": {
153    "clientCredentials": {
154      "tokenUrl": "https://example.com/api/oauth/token",
155      "scopes": {
156        "write:pets": "modify pets in your account"
157      }
158    },
159    "password": {
160      "tokenUrl": "https://example.com/api/oauth/token",
161      "scopes": {
162        "read:pets": "read your pets"
163      }
164    }
165  }
166}
167`),
168		valid: true,
169	},
170	{
171		title: "Invalid Basic",
172		raw: []byte(`
173{
174  "type": "https",
175  "scheme": "basic"
176}
177`),
178		valid: false,
179	},
180	{
181		title: "Apikey Cookie",
182		raw: []byte(`
183{
184  "type": "apiKey",
185	"in": "cookie",
186	"name": "somecookie"
187}
188`),
189		valid: true,
190	},
191
192	{
193		title: "OAuth Flow Object with no scopes",
194		raw: []byte(`
195{
196  "type": "oauth2",
197  "flows": {
198    "password": {
199      "tokenUrl": "https://example.com/api/oauth/token"
200    }
201  }
202}
203`),
204		valid: false,
205	},
206	{
207		title: "OAuth Flow Object with empty scopes",
208		raw: []byte(`
209{
210  "type": "oauth2",
211  "flows": {
212    "password": {
213			"tokenUrl": "https://example.com/api/oauth/token",
214			"scopes": {}
215    }
216  }
217}
218`),
219		valid: true,
220	},
221	{
222		title: "OIDC Type With URL",
223		raw: []byte(`
224{
225  "type": "openIdConnect",
226  "openIdConnectUrl": "https://example.com/.well-known/openid-configuration"
227}
228`),
229		valid: true,
230	},
231	{
232		title: "OIDC Type Without URL",
233		raw: []byte(`
234{
235  "type": "openIdConnect",
236  "openIdConnectUrl": ""
237}
238`),
239		valid: false,
240	},
241}
242