diff --git a/tests/test_mcp_obo_mint.py b/tests/test_mcp_obo_mint.py index 02f7a670..0fecde1d 100644 --- a/tests/test_mcp_obo_mint.py +++ b/tests/test_mcp_obo_mint.py @@ -8,8 +8,9 @@ BRIEFING.md ("Verified wire shapes") — every mock asserts the EXACT form payload posted to the IdP token endpoint (body-inspecting, not call-counting): -- entra: ONE refresh-token grant carrying ``scope=/.default`` - (or the per-server ``oauth_scopes`` override verbatim); +- entra: ONE refresh-token grant always carrying + ``scope=/.default`` (per-server ``oauth_scopes`` is ignored + on this leg — a bare scope list would drop the audience); - rfc8693: a refresh grant (NO scope key) for a subject token, then a token-exchange grant with ``audience=`` and the per-server scope only when configured. diff --git a/turnstone/core/mcp_crypto.py b/turnstone/core/mcp_crypto.py index e6140f0f..4c9d3866 100644 --- a/turnstone/core/mcp_crypto.py +++ b/turnstone/core/mcp_crypto.py @@ -596,13 +596,14 @@ def initialize_mcp_crypto_state(app_state: object, *, node_id: str = "") -> None 1. ``load_mcp_token_cipher_config()`` — wrapped in try/except. Raises :class:`SystemExit(1)` on :class:`MCPTokenKeyConfigError` after logging. - 2. Counts ``mcp_servers`` rows with ``auth_type='oauth_user'``. If + 2. Counts ``mcp_servers`` rows with a user-scoped ``auth_type`` + (``oauth_user`` or ``oauth_obo``; see ``is_user_scoped_auth``). If any exist AND no key is configured, raises ``SystemExit(1)``. Same enforcement when ``[oidc] capture_user_credential`` is enabled (the captured IdP credential must be encrypted at rest). 3. On success, sets ``app_state.mcp_token_cipher`` and ``app_state.mcp_token_store`` (both possibly ``None`` when no - key + no oauth_user rows). + key + no user-scoped rows). The helper is shared by ``turnstone/server.py:_lifespan`` and ``turnstone/console/server.py:_lifespan``. A separate