{"record":{"id":"afa358d4e85a5f62","repo":"clockworklabs/SpacetimeDB","slug":"issuer-too-long","errorCode":null,"errorMessage":"Issuer too long: {:?}","messagePattern":"Issuer too long: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/auth/src/identity.rs","lineNumber":108,"sourceCode":"    #[serde_as(as = \"serde_with::TimestampSeconds\")]\n    pub iat: SystemTime,\n    // See `SpacetimeIdentityClaims::exp`: absent and null both mean no expiration.\n    #[serde_as(as = \"Option<serde_with::TimestampSeconds>\")]\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    pub exp: Option<SystemTime>,\n\n    /// All remaining claims from the JWT payload\n    #[serde(flatten)]\n    pub extra: Option<HashMap<Box<str>, serde_json::Value>>,\n}\n\nimpl TryInto<SpacetimeIdentityClaims> for IncomingClaims {\n    type Error = anyhow::Error;\n\n    fn try_into(self) -> anyhow::Result<SpacetimeIdentityClaims> {\n        // The issuer and subject must be less than 128 bytes.\n        if self.issuer.len() > 128 {\n            return Err(anyhow::anyhow!(\"Issuer too long: {:?}\", self.issuer));\n        }\n        if self.subject.len() > 128 {\n            return Err(anyhow::anyhow!(\"Subject too long: {:?}\", self.subject));\n        }\n        // The issuer and subject must be non-empty.\n        if self.issuer.is_empty() {\n            return Err(anyhow::anyhow!(\"Issuer empty\"));\n        }\n        if self.subject.is_empty() {\n            return Err(anyhow::anyhow!(\"Subject empty\"));\n        }\n\n        let computed_identity = Identity::from_claims(&self.issuer, &self.subject);\n        // If an identity is provided, it must match the computed identity.\n        if let Some(token_identity) = self.identity\n            && token_identity != computed_identity\n        {\n            return Err(anyhow::anyhow!(","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/3653d2ed498fddbd83b7062aa6bf8970e18635ec/crates/auth/src/identity.rs#L90-L126","documentation":"When an incoming JWT is converted to SpacetimeIdentityClaims (crates/auth/src/identity.rs:103), the `iss` claim is capped at 128 bytes because issuer and subject are the two inputs hashed into the fixed-size Identity. A longer issuer is rejected before any identity computation. The debug form of the oversized issuer is included in the error.","triggerScenarios":"Authenticating with a JWT whose `iss` claim exceeds 128 bytes - typically identity providers that embed long tenant/instance paths in the issuer URL, or custom token services that put extra data into iss.","commonSituations":"Switching an OIDC provider or tenant whose issuer URL is long (multi-segment Azure AD / Auth0 tenant domains with region prefixes); hand-built token services stuffing parameters into iss; migrating from one provider to another without re-checking claim sizes.","solutions":["Shorten the issuer: use the provider's canonical short issuer URL (or a compact custom iss value) and reissue tokens.","If you control the token service, keep `iss` a short stable identifier and move metadata to other claims (they are preserved in `extra`).","Re-issue and re-distribute tokens after changing the issuer, since Identity is derived from iss+sub."],"exampleFix":"// before: JWT payload\n{ \"iss\": \"https://long-tenant-name.region.identity.example.com/v2/tenants/1234567890/delegation\", \"sub\": \"user-1\" }\n// after\n{ \"iss\": \"https://app.example.com\", \"sub\": \"user-1\" }","handlingStrategy":"validation","validationCode":"// Rust: validate claim sizes before converting.\nif claims.issuer.len() > 128 {\n    return Err(anyhow!(\"iss too long ({} bytes, max 128); reissue with a short issuer\", claims.issuer.len()));\n}","typeGuard":"fn issuer_within_limit(c: &IncomingClaims) -> bool {\n    (1..=128).contains(&c.issuer.len())\n}","tryCatchPattern":null,"preventionTips":["At your token service, enforce short canonical `iss` values (simple domain-style identifiers).","Keep multi-tenant or region metadata in custom claims, not in iss.","Add a test asserting issued tokens keep iss and sub under 128 bytes."],"tags":["spacetimedb","auth","jwt","identity","claims-validation"],"backgroundTag":"jwt-claims-validation","analyzedSha":"3653d2ed498fddbd83b7062aa6bf8970e18635ec","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}