"""The internal token's derivation, and its cross-language contract with the Go daemon. The daemon (backend/daemon/) and this app must compute byte-identical tokens from the same THERMOGRAPH_AUTH_SECRET. If they drift, every callback fails with 401 -- which reads like an auth bug rather than like the configuration drift it is, so the shared vector below is pinned on both sides. """ import hashlib import hmac import pytest from api import internal_routes # Must equal backend/daemon/internal/config/derive_test.go's sharedVector*. SHARED_VECTOR_SECRET = "test-auth-secret" SHARED_VECTOR_TOKEN = "4c3830b2158941ff52720d198b65f7924372a3a482b8da52540a4d9be38247ea" @pytest.fixture(autouse=True) def _clear_token_env(monkeypatch): """Both knobs start unset so each test states exactly the config it exercises.""" monkeypatch.delenv("THERMOGRAPH_INTERNAL_TOKEN", raising=False) monkeypatch.delenv("THERMOGRAPH_AUTH_SECRET", raising=False) def test_derived_token_matches_go(monkeypatch): """The pinned cross-language vector. Changing the label or construction here requires the identical change in the Go daemon's config package.""" monkeypatch.setenv("THERMOGRAPH_AUTH_SECRET", SHARED_VECTOR_SECRET) assert internal_routes.resolve_internal_token() == SHARED_VECTOR_TOKEN def test_vector_is_actually_hmac_of_the_label(): """Guards against the vector and the implementation drifting together if someone regenerates the constant from the code it is supposed to check.""" expected = hmac.new( SHARED_VECTOR_SECRET.encode(), internal_routes._DERIVE_LABEL, hashlib.sha256, ).hexdigest() assert expected == SHARED_VECTOR_TOKEN def test_explicit_token_wins_over_derivation(monkeypatch): monkeypatch.setenv("THERMOGRAPH_AUTH_SECRET", SHARED_VECTOR_SECRET) monkeypatch.setenv("THERMOGRAPH_INTERNAL_TOKEN", "explicit-wins") assert internal_routes.resolve_internal_token() == "explicit-wins" def test_no_secret_at_all_leaves_the_surface_closed(): """Neither knob set => no token => the router 404s. Fail closed, never open.""" assert internal_routes.resolve_internal_token() == "" def test_derivation_is_not_the_auth_secret_itself(monkeypatch): """Domain separation: a leak of the internal token must not hand over the session-signing key it was derived from.""" monkeypatch.setenv("THERMOGRAPH_AUTH_SECRET", SHARED_VECTOR_SECRET) token = internal_routes.resolve_internal_token() assert token != SHARED_VECTOR_SECRET assert SHARED_VECTOR_SECRET not in token def test_different_secrets_derive_different_tokens(monkeypatch): monkeypatch.setenv("THERMOGRAPH_AUTH_SECRET", "secret-a") a = internal_routes.resolve_internal_token() monkeypatch.setenv("THERMOGRAPH_AUTH_SECRET", "secret-b") b = internal_routes.resolve_internal_token() assert a != b