link-assistant-router 1.6.0

Link.Assistant.Router — Claude MAX OAuth proxy and token gateway for Anthropic APIs
Documentation
use super::*;

pub fn token_subject(token: &str) -> Result<String, AnyError> {
    token_claim(token)?
        .get("sub")
        .and_then(Value::as_str)
        .map(str::to_string)
        .ok_or_else(|| "router run token has no subject to revoke".into())
}

pub fn token_client_binding(token: &str) -> Result<(Option<String>, Option<String>), AnyError> {
    let claims = token_claim(token)?;
    Ok((
        claims
            .get("client_kind")
            .and_then(Value::as_str)
            .map(str::to_string),
        claims
            .get("principal_id")
            .and_then(Value::as_str)
            .map(str::to_string),
    ))
}

pub(super) fn exact_token_binding(token: &str, client: ClientKind) -> Result<String, AnyError> {
    let (bound, principal) = token_client_binding(token)?;
    if bound.as_deref() != Some(client.canonical_name()) {
        return Err(format!(
            "the supplied token must carry the exact `{}` client binding",
            client.canonical_name()
        )
        .into());
    }
    principal
        .filter(|value| !value.trim().is_empty())
        .ok_or_else(|| "the supplied token must carry a subscriber principal".into())
}

fn token_claim(token: &str) -> Result<Value, AnyError> {
    let payload = token
        .split('.')
        .nth(1)
        .ok_or("router returned a token without a JWT payload")?;
    let decoded = base64::engine::general_purpose::URL_SAFE_NO_PAD
        .decode(payload)
        .map_err(|error| format!("router returned an invalid JWT payload: {error}"))?;
    serde_json::from_slice(&decoded).map_err(Into::into)
}