{"record":{"id":"877765c4d763630b","repo":"elsa-workflows/elsa-core","slug":"token-payload-is-not-a-valid-non-expiring-token","errorCode":null,"errorMessage":"Token payload is not a valid non-expiring token.","messagePattern":"Token payload is not a valid non-expiring token\\.","errorType":"exception","errorClass":"CryptographicException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.SasTokens/Contracts/DataProtectorTokenService.cs","lineNumber":98,"sourceCode":"        try\n        {\n            return _timeLimitedDataProtector.Unprotect(token);\n        }\n        catch (CryptographicException)\n        {\n            var json = _dataProtector.Unprotect(token);\n\n            // Expired time-limited tokens can be decrypted by the base protector,\n            // but the result includes the expiration header.\n            // Only accept fallback payloads that are standalone JSON produced by CreateToken(payload).\n            try\n            {\n                using var _ = JsonDocument.Parse(json);\n                return json;\n            }\n            catch (JsonException e)\n            {\n                throw new CryptographicException(\"Token payload is not a valid non-expiring token.\", e);\n            }\n        }\n    }\n}\n","sourceCodeStart":80,"sourceCodeEnd":103,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.SasTokens/Contracts/DataProtectorTokenService.cs#L80-L103","documentation":"DataProtectorTokenService.Unprotect decrypts a SAS token and, for non-expiring tokens, expects the plaintext payload to be valid JSON. If JsonDocument.Parse throws JsonException, the service wraps it in a CryptographicException with this message, signaling that decryption succeeded but the payload is not a token this service produced.","triggerScenarios":"Calling Unprotect on a token whose decrypted content is not JSON — tokens minted by a different service/format, manually crafted or corrupted strings, truncated tokens, or binary payloads passed as tokens.","commonSituations":"Passing a plain connection string or API key where an Elsa SAS token is expected; tokens generated by an older Elsa version with a different payload format; copy/paste truncation or encoding corruption of the token value.","solutions":["Regenerate the token with the same DataProtectorTokenService (and matching Data Protection key ring) that will consume it.","Verify you are not passing a raw secret or a different token type to Unprotect.","Check the token was not truncated/whitespace-mangled in transport (query strings, config files, logs).","If tokens must survive across environments, ensure ASP.NET Core Data Protection keys are shared/persisted; note the payload was decryptable here, so focus on token format/version."],"exampleFix":"// before\nvar json = tokenService.Unprotect(rawConnectionString);\n// after\nvar sasToken = await tokenService.CreateTokenAsync(resource, expiresAt: null);\nvar json = tokenService.Unprotect(sasToken);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try\n{\n    var json = tokenService.Unprotect(token);\n}\ncatch (System.Security.Cryptography.CryptographicException ex)\n{\n    logger.LogWarning(ex, \"Token rejected: not a valid non-expiring token payload.\");\n    // treat as unauthenticated / re-issue token\n}","preventionTips":["Only pass tokens produced by DataProtectorTokenService to Unprotect.","Persist tokens without truncation/whitespace mangling.","Share Data Protection keys and format expectations across issuing and consuming services."],"tags":["token","cryptography","json","sas-tokens"],"backgroundTag":"unexpected-response-shape","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}