Skip to content

Commit

Permalink
Check that token lifetime is long enough
Browse files Browse the repository at this point in the history
Check that the configured token lifetime is at least as long as
twice the minimum token lifetime so that we don't get weird redirect
loops with very short token lifetimes.
  • Loading branch information
rra committed Sep 19, 2024
1 parent 1881ca3 commit ec257f5
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 1 deletion.
3 changes: 3 additions & 0 deletions changelog.d/20240919_154251_rra_DM_46399.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Bug fixes

- Check that `tokenLifetime` is at least as long as twice the minimum token lifetime.
11 changes: 10 additions & 1 deletion src/gafaelfawr/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
from safir.logging import LogLevel, configure_logging
from safir.pydantic import EnvAsyncPostgresDsn, EnvRedisDsn, HumanTimedelta

from .constants import SCOPE_REGEX, USERNAME_REGEX
from .constants import MINIMUM_LIFETIME, SCOPE_REGEX, USERNAME_REGEX
from .exceptions import InvalidTokenError
from .keypair import RSAKeyPair
from .models.token import Token
Expand Down Expand Up @@ -993,6 +993,15 @@ def _validate_known_scopes(cls, v: dict[str, str]) -> dict[str, str]:
raise ValueError(f"required scope {required} missing")
return v

@field_validator("token_lifetime")
@classmethod
def _validate_token_lifetime(cls, v: timedelta) -> timedelta:
"""Ensure the token lifetime is longer than minimal lifetime."""
limit = MINIMUM_LIFETIME + MINIMUM_LIFETIME
if v < limit:
raise ValueError(f"must be longer than {limit.total_seconds}s")
return v

@model_validator(mode="before")
@classmethod
def _validate_optional(cls, data: Any) -> Any:
Expand Down
5 changes: 5 additions & 0 deletions tests/config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ def test_config_invalid_token(monkeypatch: pytest.MonkeyPatch) -> None:
parse_config(config_path("github"))


def test_config_invalid_lifetime() -> None:
with pytest.raises(ValidationError, match=r"must be longer than"):
parse_config(config_path("bad-lifetime"))


def test_config_bad_groups() -> None:
with pytest.raises(ValidationError, match="Input should be a valid list"):
parse_config(config_path("bad-groups"))
Expand Down
15 changes: 15 additions & 0 deletions tests/data/config/bad-lifetime.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Test too short of a token lifetime.

realm: "example.com"
slackAlerts: true
initialAdmins: ["admin"]
afterLogoutUrl: "https://example.com/landing"
groupMapping:
"exec:admin": ["admin"]
knownScopes:
"admin:token": "token administration"
"exec:admin": "admin description"
"user:token": "Can create and modify user tokens"
github:
clientId: "some-github-client-id"
tokenLifetime: "8m"

0 comments on commit ec257f5

Please sign in to comment.