Skip to content

Commit fbebb31

Browse files
committed
Security HTTP scheme type support
1 parent d915f23 commit fbebb31

File tree

5 files changed

+47
-14
lines changed

5 files changed

+47
-14
lines changed

openapi_core/schema/security_schemes/enums.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,9 @@ class ApiKeyLocation(Enum):
1919
@classmethod
2020
def has_value(cls, value):
2121
return (any(value == item.value for item in cls))
22+
23+
24+
class HttpAuthScheme(Enum):
25+
26+
BASIC = 'basic'
27+
BEARER = 'bearer'

openapi_core/schema/security_schemes/models.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""OpenAPI core security schemes models module"""
22
from openapi_core.schema.security_schemes.enums import (
3-
SecuritySchemeType, ApiKeyLocation,
3+
SecuritySchemeType, ApiKeyLocation, HttpAuthScheme,
44
)
55

66

@@ -16,7 +16,7 @@ def __init__(
1616
self.description = description
1717
self.name = name
1818
self.apikey_in = apikey_in and ApiKeyLocation(apikey_in)
19-
self.scheme = scheme
19+
self.scheme = scheme and HttpAuthScheme(scheme)
2020
self.bearer_format = bearer_format
2121
self.flows = flows
2222
self.open_id_connect_url = open_id_connect_url

openapi_core/validation/request/validators.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
"""OpenAPI core validation request validators module"""
2+
import base64
3+
import binascii
24
from itertools import chain
35
from six import iteritems
46
import warnings
@@ -12,7 +14,9 @@
1214
)
1315
from openapi_core.schema.paths.exceptions import InvalidPath
1416
from openapi_core.schema.request_bodies.exceptions import MissingRequestBody
15-
from openapi_core.schema.security_schemes.enums import SecuritySchemeType
17+
from openapi_core.schema.security_schemes.enums import (
18+
SecuritySchemeType, HttpAuthScheme,
19+
)
1620
from openapi_core.schema.servers.exceptions import InvalidServer
1721
from openapi_core.unmarshalling.schemas.exceptions import (
1822
UnmarshalError, ValidateError,
@@ -103,7 +107,7 @@ def _get_operation(self, request):
103107
def _get_security(self, request, operation):
104108
security = operation.security or self.spec.security
105109
if not security:
106-
return
110+
return {}
107111

108112
for security_requirement in security:
109113
data = {
@@ -113,6 +117,8 @@ def _get_security(self, request, operation):
113117
if all(value for value in data.values()):
114118
return data
115119

120+
return {}
121+
116122
def _get_parameters(self, request, params):
117123
errors = []
118124
seen = set()
@@ -195,6 +201,22 @@ def _get_security_value(self, scheme_name, request):
195201
if scheme.type == SecuritySchemeType.API_KEY:
196202
source = getattr(request.parameters, scheme.apikey_in.value)
197203
return source.get(scheme.name)
204+
elif scheme.type == SecuritySchemeType.HTTP:
205+
auth_header = request.parameters.header.get('Authorization')
206+
try:
207+
auth_type, encoded_credentials = auth_header.split(' ', 1)
208+
except ValueError:
209+
raise ValueError('Could not parse authorization header.')
210+
211+
if auth_type.lower() != scheme.scheme.value:
212+
raise ValueError(
213+
'Unknown authorization method %s' % auth_type)
214+
try:
215+
return base64.b64decode(
216+
encoded_credentials.encode('ascii'), validate=True
217+
).decode('latin1')
218+
except binascii.Error:
219+
raise ValueError('Invalid base64 encoding.')
198220

199221
warnings.warn("Only api key security scheme type supported")
200222

tests/integration/data/v3.0/petstore.yaml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,6 @@ paths:
7575
externalDocs:
7676
url: https://example.com
7777
description: Find more info here
78-
security:
79-
- petstore_auth:
80-
- write:pets
81-
- read:pets
8278
servers:
8379
- url: https://development.gigantic-server.com/v1
8480
description: Development server
@@ -128,6 +124,10 @@ paths:
128124
schema:
129125
type: integer
130126
format: int64
127+
security:
128+
- petstore_auth:
129+
- write:pets
130+
- read:pets
131131
responses:
132132
'200':
133133
description: Expected response to a valid request
@@ -371,6 +371,5 @@ components:
371371
name: api_key
372372
in: query
373373
petstore_auth:
374-
type: apiKey
375-
name: api_key
376-
in: header
374+
type: http
375+
scheme: basic

tests/integration/validation/test_validators.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,7 @@ def test_post_pets(self, validator, spec_dict):
235235
'user': 123,
236236
},
237237
)
238-
assert result.security == {
239-
'petstore_auth': self.api_key_encoded,
240-
}
238+
assert result.security == {}
241239

242240
schemas = spec_dict['components']['schemas']
243241
pet_model = schemas['PetCreate']['x-model']
@@ -251,9 +249,14 @@ def test_post_pets(self, validator, spec_dict):
251249
assert result.body.address.city == pet_city
252250

253251
def test_get_pet(self, validator):
252+
authorization = 'Basic ' + self.api_key_encoded
253+
headers = {
254+
'Authorization': authorization,
255+
}
254256
request = MockRequest(
255257
self.host_url, 'get', '/v1/pets/1',
256258
path_pattern='/v1/pets/{petId}', view_args={'petId': '1'},
259+
headers=headers,
257260
)
258261

259262
result = validator.validate(request)
@@ -265,6 +268,9 @@ def test_get_pet(self, validator):
265268
'petId': 1,
266269
},
267270
)
271+
assert result.security == {
272+
'petstore_auth': self.api_key,
273+
}
268274

269275

270276
class TestPathItemParamsValidator(object):

0 commit comments

Comments
 (0)