CLI: positional rp-id/rp-name; init adds domains to an existing database
- 'paskia init [rp-id] [rp-name]' and 'paskia migrate [rp-id]' are now positional; comma separation and the --rp-id/--rp-name flags are gone. - With an existing paskia.kantadb, init adds the rp-id as a new domain (seeding its OIDC provider) or updates an existing domain's rp-name. - Origin allow-list semantics clarified: the bare '*' entry allows anything within the rp-id domain on any scheme and port (also the empty-list default and its display in the admin UI, replacing the synthetic '*.rp-id' row); '*.x' wildcards are https-only; exact entries match scheme, host and port. Legacy '*.rp-id' wildcards migrate to '*' to preserve their any-scheme meaning.
This commit is contained in:
+42
-2
@@ -227,6 +227,21 @@ class TestValidateConfig:
|
||||
)
|
||||
)
|
||||
|
||||
def test_star_origin_accepted_not_auth_host(self):
|
||||
domains.validate_config(
|
||||
Config(domains={"a.com": DomainConfig(origins={"*": True})})
|
||||
)
|
||||
with pytest.raises(ValueError, match="cannot be the auth host"):
|
||||
domains.validate_config(
|
||||
Config(
|
||||
domains={
|
||||
"a.com": DomainConfig(
|
||||
origins={"*": OriginEntry(auth_host=True)}
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
def test_auth_host_collision(self):
|
||||
with pytest.raises(ValueError, match="collides with a related origin"):
|
||||
domains.validate_config(
|
||||
@@ -417,6 +432,30 @@ class TestOriginValidation:
|
||||
with pytest.raises(ValueError, match="not allowed"):
|
||||
p.validate_origin("https://other.com")
|
||||
|
||||
def test_wildcard_is_https_only(self):
|
||||
"""A '*.example.com' entry does not fall back to other schemes."""
|
||||
p = Passkey(rp_id="example.com", origins=["*.example.com"])
|
||||
with pytest.raises(ValueError, match="not allowed"):
|
||||
p.validate_origin("http://example.com")
|
||||
with pytest.raises(ValueError, match="not allowed"):
|
||||
p.validate_origin("http://app.example.com:8080")
|
||||
|
||||
def test_star_entry_matches_any_scheme_and_port(self):
|
||||
"""The bare '*' entry allows anything within the rp-id domain."""
|
||||
p = Passkey(rp_id="example.com", origins=["*"])
|
||||
assert p.validate_origin("https://example.com")
|
||||
assert p.validate_origin("http://app.example.com:8080")
|
||||
with pytest.raises(ValueError, match="not allowed"):
|
||||
p.validate_origin("https://other.com")
|
||||
|
||||
def test_exact_entry_matches_scheme_and_port(self):
|
||||
p = Passkey(rp_id="localhost", origins=["http://localhost:4403"])
|
||||
assert p.validate_origin("http://localhost:4403")
|
||||
with pytest.raises(ValueError, match="not allowed"):
|
||||
p.validate_origin("https://localhost:4403")
|
||||
with pytest.raises(ValueError, match="not allowed"):
|
||||
p.validate_origin("http://localhost:4404")
|
||||
|
||||
def test_sub_wildcard_matches_only_its_subtree(self):
|
||||
p = Passkey(rp_id="example.com", origins=["*.app.example.com"])
|
||||
assert p.validate_origin("https://app.example.com")
|
||||
@@ -643,7 +682,7 @@ class TestLegacyConversion:
|
||||
kanta.data.config = LegacyConfig(
|
||||
rp_id="example.com",
|
||||
rp_name="Example",
|
||||
origins=["https://app.example.com"],
|
||||
origins=["https://app.example.com", "*.example.com"],
|
||||
)
|
||||
kanta.data.credentials[cred_uuid] = LegacyCredential(
|
||||
credential_id=b"credential-id",
|
||||
@@ -668,7 +707,8 @@ class TestLegacyConversion:
|
||||
config = convert_legacy_database(src_file, tmp_path / "paskia.kantadb")
|
||||
domain = config.domains["example.com"]
|
||||
assert domain.rp_name == "Example"
|
||||
assert domain.origins == {"app.example.com": True}
|
||||
# A legacy wildcard over the rp-id itself becomes the bare '*'
|
||||
assert domain.origins == {"app.example.com": True, "*": True}
|
||||
|
||||
converted = _read_db(tmp_path / "paskia.kantadb")
|
||||
assert converted.credentials[cred_uuid].rp_id == "example.com"
|
||||
|
||||
Reference in New Issue
Block a user