diff --git a/fido2/rpid.py b/fido2/rpid.py index 2f81fb9..3647b6f 100644 --- a/fido2/rpid.py +++ b/fido2/rpid.py @@ -65,7 +65,11 @@ def verify_rp_id(rp_id: str, origin: str) -> bool: # Note that Webauthn requires a secure context, i.e. an origin with https scheme. # However, most browsers also treat http://localhost as a secure context. See # https://groups.google.com/a/chromium.org/g/blink-dev/c/RC9dSw-O3fE/m/E3_0XaT0BAAJ - if url.scheme != "https" and (url.scheme, host) != ("http", "localhost"): + if ( + url.scheme != "https" + and (url.scheme, host) != ("http", "localhost") + and not (url.scheme == "http" and host and host.endswith(".localhost")) + ): return False if host == rp_id: return True diff --git a/tests/test_rpid.py b/tests/test_rpid.py index fae423b..fd95470 100644 --- a/tests/test_rpid.py +++ b/tests/test_rpid.py @@ -58,3 +58,11 @@ def test_suffix_list(self): self.assertTrue( verify_rp_id("example.appspot.com", "https://example.appspot.com") ) + + def test_localhost_http_secure_context(self): + # Localhost and subdomains are secure contexts in most browsers + self.assertTrue(verify_rp_id("localhost", "http://localhost")) + self.assertTrue(verify_rp_id("localhost", "http://example.localhost")) + self.assertTrue(verify_rp_id("example.localhost", "http://example.localhost")) + self.assertTrue(verify_rp_id("localhost", "http://localhost:8000")) + self.assertFalse(verify_rp_id("localhost", "http://"))