Files
connexion/tests/api/test_secure_api.py
Robbe Sneyders 156bf79ee6 Merge V2 to main (#1518)
* 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>
2022-05-04 17:31:04 +02:00

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