diff --git a/docs/settings.rst b/docs/settings.rst index 901fe8575..e15f5e395 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -56,7 +56,7 @@ A list of schemes that the ``redirect_uri`` field will be validated against. Setting this to ``["https"]`` only in production is strongly recommended. For Native Apps the ``http`` scheme can be safely used with loopback addresses in the -Application (``[::1]`` or ``127.0.0.1``). In this case the ``redirect_uri`` can be +Application (``[::1]`` or ``127.0.0.1`` or ``localhost``). In this case the ``redirect_uri`` can be configured without explicit port specification, so that the Application accepts randomly assigned ports. diff --git a/oauth2_provider/models.py b/oauth2_provider/models.py index 661bd7dfc..77def9ff7 100644 --- a/oauth2_provider/models.py +++ b/oauth2_provider/models.py @@ -778,7 +778,7 @@ def redirect_to_uri_allowed(uri, allowed_uris): allowed_uri_is_loopback = ( parsed_allowed_uri.scheme == "http" - and parsed_allowed_uri.hostname in ["127.0.0.1", "::1"] + and parsed_allowed_uri.hostname in ["127.0.0.1", "::1", "localhost"] and parsed_allowed_uri.port is None ) if ( diff --git a/tests/test_oauth2_backends.py b/tests/test_oauth2_backends.py index 21dd7a0c3..96e4dd0ad 100644 --- a/tests/test_oauth2_backends.py +++ b/tests/test_oauth2_backends.py @@ -205,9 +205,8 @@ def test_validate_authorization_request_unsafe_query(self): @pytest.mark.parametrize( "uri, expected_result", - # localhost is _not_ a loopback URI [ - ("http://localhost:3456", False), + ("http://localhost:3456", True), # localhost is supported # only http scheme is supported for loopback URIs ("https://127.0.0.1:3456", False), ("http://127.0.0.1:3456", True), @@ -216,7 +215,7 @@ def test_validate_authorization_request_unsafe_query(self): ], ) def test_uri_loopback_redirect_check(uri, expected_result): - allowed_uris = ["http://127.0.0.1", "http://[::1]"] + allowed_uris = ["http://127.0.0.1", "http://[::1]", "http://localhost"] if expected_result: assert redirect_to_uri_allowed(uri, allowed_uris) else: diff --git a/tests/test_validators.py b/tests/test_validators.py index b2bbb2970..4c016b1b8 100644 --- a/tests/test_validators.py +++ b/tests/test_validators.py @@ -8,7 +8,7 @@ @pytest.mark.usefixtures("oauth2_settings") class TestValidators(TestCase): def test_validate_good_uris(self): - validator = RedirectURIValidator(allowed_schemes=["https"]) + validator = RedirectURIValidator(allowed_schemes=["https", "http"]) good_uris = [ "https://example.com/", "https://example.org/?key=val", @@ -17,13 +17,14 @@ def test_validate_good_uris(self): "https://1.1.1.1", "https://127.0.0.1", "https://255.255.255.255", + "http://localhost", ] for uri in good_uris: # Check ValidationError not thrown validator(uri) def test_validate_custom_uri_scheme(self): - validator = RedirectURIValidator(allowed_schemes=["my-scheme", "https", "git+ssh"]) + validator = RedirectURIValidator(allowed_schemes=["my-scheme", "https", "git+ssh", "http"]) good_uris = [ "my-scheme://example.com", "my-scheme://example", @@ -31,6 +32,7 @@ def test_validate_custom_uri_scheme(self): "https://example.com", "HTTPS://example.com", "git+ssh://example.com", + "http://localhost", ] for uri in good_uris: # Check ValidationError not thrown