-
Notifications
You must be signed in to change notification settings - Fork 154
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Changes to default_unauthz_handler to remove use of referrer header.
Also - if a configured callable returns None or empty - return a 403, just as the default behavior does. Document precisely what happens. closes #904
- Loading branch information
Showing
6 changed files
with
88 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,8 @@ | |
get_form_input, | ||
get_num_queries, | ||
hash_password, | ||
init_app_with_options, | ||
is_authenticated, | ||
json_authenticate, | ||
logout, | ||
populate_data, | ||
|
@@ -463,34 +465,64 @@ def test_unauthorized_access(client, get_message): | |
assert response.status_code == 403 | ||
|
||
|
||
@pytest.mark.settings(unauthorized_view=lambda: None) | ||
def test_unauthorized_access_with_referrer(client, get_message): | ||
authenticate(client, "[email protected]") | ||
response = client.get("/admin", headers={"referer": "/admin"}) | ||
assert response.location != "/admin" | ||
client.get(response.location) | ||
def test_unauthorized_callable_view(app, sqlalchemy_datastore, get_message): | ||
# Test various options using custom unauthorized view | ||
def unauthz_view(): | ||
from flask import request | ||
|
||
if request.path == "/admin": | ||
return None | ||
elif request.path == "/admin_perm": | ||
return "" | ||
elif request.path == "/admin_and_editor": | ||
return "/profile" | ||
elif request.path == "/simple": | ||
# N.B. security issue - app should verify this is local | ||
return request.referrer | ||
else: | ||
return "not_implemented" | ||
|
||
app.config["SECURITY_UNAUTHORIZED_VIEW"] = unauthz_view | ||
init_app_with_options(app, sqlalchemy_datastore) | ||
client = app.test_client() | ||
# activate tiya | ||
with app.test_request_context("/"): | ||
user = app.security.datastore.find_user(email="[email protected]") | ||
app.security.datastore.activate_user(user) | ||
app.security.datastore.commit() | ||
authenticate(client, "[email protected]") | ||
assert is_authenticated(client, get_message) | ||
|
||
response = client.get( | ||
"/admin?a=b", headers={"referer": "http://localhost/admin?x=y"} | ||
) | ||
assert "/" in response.location | ||
client.get(response.headers["Location"]) | ||
response = client.get("/admin") | ||
assert response.status_code == 403 | ||
response = client.get("/admin_perm") | ||
assert response.status_code == 403 | ||
|
||
response = client.get("/admin_and_editor", follow_redirects=False) | ||
assert check_location(app, response.location, "/profile") | ||
response = client.get(response.location) | ||
assert response.data.count(get_message("UNAUTHORIZED")) == 1 | ||
|
||
response = client.get( | ||
"/admin", headers={"referer": "/admin"}, follow_redirects=True | ||
"/simple", headers={"referer": "/myhome"}, follow_redirects=False | ||
) | ||
assert response.data.count(get_message("UNAUTHORIZED")) == 1 | ||
assert check_location(app, response.location, "/myhome") | ||
|
||
|
||
# When referrer is from another path and unauthorized, | ||
# we expect a temp redirect (302) to the referer | ||
response = client.get("/admin?w=s", headers={"referer": "/profile"}) | ||
def test_unauthorized_url_view(app, sqlalchemy_datastore): | ||
# Test unknown endpoint basically results in redirect to the given string. | ||
app.config["SECURITY_UNAUTHORIZED_VIEW"] = ".myendpoint" | ||
init_app_with_options(app, sqlalchemy_datastore) | ||
client = app.test_client() | ||
authenticate(client, "[email protected]") | ||
response = client.get("/admin") | ||
assert response.status_code == 302 | ||
assert "/profile" in response.location | ||
check_location(app, response.location, ".myendpoint") | ||
|
||
|
||
@pytest.mark.settings(unauthorized_view="/unauthz") | ||
def test_roles_accepted(clients): | ||
# This specificaly tests that we can pass a URL for unauthorized_view. | ||
# This specifically tests that we can pass a URL for unauthorized_view. | ||
for user in ("[email protected]", "[email protected]"): | ||
authenticate(clients, user) | ||
response = clients.get("/admin_or_editor") | ||
|