mirror of
https://github.com/LukeHagar/connexion.git
synced 2025-12-06 12:27:45 +00:00
* Fix uri parsing for query parameter with empty brackets (#1501) * Update tests for changed werkzeug behavior in 2.1 (#1506) https://github.com/pallets/werkzeug/issues/2352 * Bugfix/async security check (#1512) * Add failing tests * Use for else construct * openapi: remove JSON body second validation and type casting (#1170) * openapi: remove body preprocessing Body is already validated using jsonschema. There was also some type casting but it was wrong: e.g. not recurring deeply into dicts and lists, relying on existence of "type" in schema (which is not there e.g. if oneOf is used). Anyway, the only reason why types should be casted is converting integer values to float if the type is number. But this is in most cases irrelevant. Added an example, which did not work before this commit (echoed `{}`) e.g. for ``` curl localhost:8080/api/foo -H 'content-type: application/json' -d '{"foo": 1}' ``` but now the example works (echoes `{"foo": 1}`). * test with oneOf in the requestBody * remove oneof examples: superseded by tests Co-authored-by: Pavol Vargovcik <pavol.vargovcik@kiwi.com> Co-authored-by: Ruwann <ruwanlambrichts@gmail.com> Co-authored-by: Pavol Vargovčík <pavol.vargovcik@gmail.com> Co-authored-by: Pavol Vargovcik <pavol.vargovcik@kiwi.com>
132 lines
6.6 KiB
Python
132 lines
6.6 KiB
Python
import json
|
|
|
|
|
|
def test_security_over_nonexistent_endpoints(oauth_requests, secure_api_app):
|
|
app_client = secure_api_app.app.test_client()
|
|
headers = {"Authorization": "Bearer 300"}
|
|
get_inexistent_endpoint = app_client.get('/v1.0/does-not-exist-invalid-token',
|
|
headers=headers) # type: flask.Response
|
|
assert get_inexistent_endpoint.status_code == 401
|
|
assert get_inexistent_endpoint.content_type == 'application/problem+json'
|
|
|
|
headers = {"Authorization": "Bearer 100"}
|
|
get_inexistent_endpoint = app_client.get('/v1.0/does-not-exist-valid-token',
|
|
headers=headers) # type: flask.Response
|
|
assert get_inexistent_endpoint.status_code == 404
|
|
assert get_inexistent_endpoint.content_type == 'application/problem+json'
|
|
|
|
get_inexistent_endpoint = app_client.get('/v1.0/does-not-exist-no-token') # type: flask.Response
|
|
assert get_inexistent_endpoint.status_code == 401
|
|
|
|
swagger_ui = app_client.get('/v1.0/ui/') # type: flask.Response
|
|
assert swagger_ui.status_code == 401
|
|
|
|
headers = {"Authorization": "Bearer 100"}
|
|
post_greeting = app_client.post('/v1.0/greeting/rcaricio', data={}, headers=headers) # type: flask.Response
|
|
assert post_greeting.status_code == 200
|
|
|
|
post_greeting = app_client.post('/v1.0/greeting/rcaricio', data={}) # type: flask.Response
|
|
assert post_greeting.status_code == 401
|
|
|
|
|
|
def test_security(oauth_requests, secure_endpoint_app):
|
|
app_client = secure_endpoint_app.app.test_client()
|
|
|
|
get_bye_no_auth = app_client.get('/v1.0/byesecure/jsantos') # type: flask.Response
|
|
assert get_bye_no_auth.status_code == 401
|
|
assert get_bye_no_auth.content_type == 'application/problem+json'
|
|
get_bye_no_auth_reponse = json.loads(get_bye_no_auth.data.decode('utf-8', 'replace')) # type: dict
|
|
assert get_bye_no_auth_reponse['detail'] == "No authorization token provided"
|
|
|
|
headers = {"Authorization": "Bearer 100"}
|
|
get_bye_good_auth = app_client.get('/v1.0/byesecure/jsantos', headers=headers) # type: flask.Response
|
|
assert get_bye_good_auth.status_code == 200
|
|
assert get_bye_good_auth.data == b'Goodbye jsantos (Secure: test-user)'
|
|
|
|
headers = {"Authorization": "Bearer 200"}
|
|
get_bye_wrong_scope = app_client.get('/v1.0/byesecure/jsantos', headers=headers) # type: flask.Response
|
|
assert get_bye_wrong_scope.status_code == 403
|
|
assert get_bye_wrong_scope.content_type == 'application/problem+json'
|
|
get_bye_wrong_scope_reponse = json.loads(get_bye_wrong_scope.data.decode('utf-8', 'replace')) # type: dict
|
|
assert get_bye_wrong_scope_reponse['detail'] == "Provided token doesn't have the required scope"
|
|
|
|
headers = {"Authorization": "Bearer 300"}
|
|
get_bye_bad_token = app_client.get('/v1.0/byesecure/jsantos', headers=headers) # type: flask.Response
|
|
assert get_bye_bad_token.status_code == 401
|
|
assert get_bye_bad_token.content_type == 'application/problem+json'
|
|
get_bye_bad_token_reponse = json.loads(get_bye_bad_token.data.decode('utf-8', 'replace')) # type: dict
|
|
assert get_bye_bad_token_reponse['detail'] == "Provided token is not valid"
|
|
|
|
response = app_client.get('/v1.0/more-than-one-security-definition') # type: flask.Response
|
|
assert response.status_code == 401
|
|
|
|
# also tests case-insensitivity
|
|
headers = {"X-AUTH": "mykey"}
|
|
response = app_client.get('/v1.0/more-than-one-security-definition', headers=headers) # type: flask.Response
|
|
assert response.status_code == 200
|
|
|
|
headers = {"Authorization": "Bearer 100"}
|
|
get_bye_good_auth = app_client.get('/v1.0/byesecure-ignoring-context/hjacobs',
|
|
headers=headers) # type: flask.Response
|
|
assert get_bye_good_auth.status_code == 200
|
|
assert get_bye_good_auth.data == b'Goodbye hjacobs (Secure!)'
|
|
|
|
headers = {"Authorization": "Bearer 100"}
|
|
get_bye_from_flask = app_client.get('/v1.0/byesecure-from-flask', headers=headers) # type: flask.Response
|
|
assert get_bye_from_flask.data == b'Goodbye test-user (Secure!)'
|
|
|
|
headers = {"Authorization": "Bearer 100"}
|
|
get_bye_from_connexion = app_client.get('/v1.0/byesecure-from-connexion', headers=headers) # type: flask.Response
|
|
assert get_bye_from_connexion.data == b'Goodbye test-user (Secure!)'
|
|
|
|
headers = {"Authorization": "Bearer 100"}
|
|
get_bye_from_connexion = app_client.get('/v1.0/byesecure-jwt/test-user', headers=headers) # type: flask.Response
|
|
assert get_bye_from_connexion.data == b'Goodbye test-user (Secure: 100)'
|
|
|
|
# has optional auth
|
|
response = app_client.get('/v1.0/optional-auth') # type: flask.Response
|
|
assert response.status_code == 200
|
|
assert response.data == b'"Unauthenticated"\n'
|
|
headers = {"X-AUTH": "mykey"}
|
|
response = app_client.get('/v1.0/optional-auth', headers=headers) # type: flask.Response
|
|
assert response.status_code == 200
|
|
assert response.data == b'"Authenticated"\n'
|
|
headers = {"X-AUTH": "wrong-key"}
|
|
response = app_client.get('/v1.0/optional-auth', headers=headers) # type: flask.Response
|
|
assert response.data == b'"Unauthenticated"\n'
|
|
assert response.status_code == 200
|
|
|
|
# security function throws exception
|
|
response = app_client.get('/v1.0/auth-exception', headers={'X-Api-Key': 'foo'})
|
|
assert response.status_code == 401
|
|
|
|
|
|
def test_checking_that_client_token_has_all_necessary_scopes(
|
|
oauth_requests, secure_endpoint_app):
|
|
app_client = secure_endpoint_app.app.test_client()
|
|
|
|
# has only one of the required scopes
|
|
headers = {"Authorization": "Bearer has_myscope"}
|
|
response = app_client.get('/v1.0/more-than-one-scope', headers=headers) # type: flask.Response
|
|
assert response.status_code == 403
|
|
|
|
# has none of the necessary scopes
|
|
headers = {"Authorization": "Bearer has_wrongscope"}
|
|
response = app_client.get('/v1.0/more-than-one-scope', headers=headers) # type: flask.Response
|
|
assert response.status_code == 403
|
|
|
|
# is not auth
|
|
headers = {"Authorization": "Bearer is_not_invalid"}
|
|
response = app_client.get('/v1.0/more-than-one-scope', headers=headers) # type: flask.Response
|
|
assert response.status_code == 401
|
|
|
|
# has all necessary scopes
|
|
headers = {"Authorization": "Bearer has_myscope_otherscope"}
|
|
response = app_client.get('/v1.0/more-than-one-scope', headers=headers) # type: flask.Response
|
|
assert response.status_code == 200
|
|
|
|
# has all necessary scopes but under key 'scopes'
|
|
headers = {"Authorization": "Bearer has_scopes_in_scopes_with_s"}
|
|
response = app_client.get('/v1.0/more-than-one-scope', headers=headers) # type: flask.Response
|
|
assert response.status_code == 200
|