auth: add community token service seam

This commit is contained in:
a.tolmachev
2026-05-03 18:26:03 +00:00
parent 18b23fcc0d
commit ffcce360fc
10 changed files with 329 additions and 10 deletions
+88
View File
@@ -24,6 +24,7 @@ use crate::{
},
auth_profiles::{create_auth_profile, get_auth_profile, list_auth_profiles},
capabilities::get_capabilities,
machine_auth::{issue_agent_token, issue_one_time_agent_token},
observability::{get_agent_usage, get_log, get_operation_usage, get_usage, list_logs},
operations::{
archive_operation, create_operation, create_version, delete_operation,
@@ -209,6 +210,12 @@ pub fn build_app(state: AppState) -> Router {
.route("/login", post(login))
.merge(protected_auth_router),
)
.nest(
"/mcp-auth/v1",
Router::new()
.route("/token", post(issue_agent_token))
.route("/token/one-time", post(issue_one_time_agent_token)),
)
.nest("/api/admin", admin_router)
.layer(middleware::from_fn_with_state(
state.clone(),
@@ -1038,6 +1045,87 @@ mod tests {
assert_eq!(response["limits"]["max_agents_per_workspace"], 1);
}
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn rejects_short_lived_machine_token_issue_in_community() {
let registry = test_registry().await;
let storage_root = test_storage_root("community_short_lived_token_contract");
let base_url = spawn_admin_api(build_test_app(registry, storage_root)).await;
let root_url = base_url
.as_ref()
.split("/api/admin/workspaces/")
.next()
.unwrap();
let response = reqwest::Client::new()
.post(format!("{root_url}/mcp-auth/v1/token"))
.json(&json!({
"grant_type": "agent_key",
"agent_key": "crk_agent_demo_secret",
"scope": ["tools:call"]
}))
.send()
.await
.unwrap();
assert_eq!(response.status(), reqwest::StatusCode::FORBIDDEN);
let payload = response.json::<Value>().await.unwrap();
assert_eq!(payload["error"]["code"], "forbidden");
assert_eq!(
payload["error"]["message"],
"short-lived machine access is not available in Community"
);
assert_eq!(payload["error"]["context"]["edition"], "community");
assert_eq!(
payload["error"]["context"]["machine_access_mode"],
"short_lived_token"
);
assert_eq!(payload["error"]["context"]["grant_type"], "agent_key");
assert_eq!(payload["error"]["context"]["upgrade_required"], json!(true));
}
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn rejects_one_time_machine_token_issue_in_community() {
let registry = test_registry().await;
let storage_root = test_storage_root("community_one_time_token_contract");
let base_url = spawn_admin_api(build_test_app(registry, storage_root)).await;
let root_url = base_url
.as_ref()
.split("/api/admin/workspaces/")
.next()
.unwrap();
let response = reqwest::Client::new()
.post(format!("{root_url}/mcp-auth/v1/token/one-time"))
.json(&json!({
"agent_key": "crk_agent_demo_secret",
"operation_id": "op_sensitive_01",
"scope": ["tools:call"]
}))
.send()
.await
.unwrap();
assert_eq!(response.status(), reqwest::StatusCode::FORBIDDEN);
let payload = response.json::<Value>().await.unwrap();
assert_eq!(payload["error"]["code"], "forbidden");
assert_eq!(
payload["error"]["message"],
"one-time machine access is not available in Community"
);
assert_eq!(payload["error"]["context"]["edition"], "community");
assert_eq!(
payload["error"]["context"]["machine_access_mode"],
"one_time_token"
);
assert_eq!(
payload["error"]["context"]["operation_id"],
"op_sensitive_01"
);
assert_eq!(payload["error"]["context"]["upgrade_required"], json!(true));
}
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn returns_community_protocol_capabilities_only_for_supported_protocols() {