{"record":{"id":"6171c125da333ca1","repo":"gotify/server","slug":"invalid-token","errorCode":null,"errorMessage":"invalid token","messagePattern":"invalid token","errorType":"validation","errorClass":"errInvalidToken","httpStatus":null,"severity":"error","filePath":"auth/token.go","lineNumber":22,"sourceCode":"\t\"crypto\"\n\t\"crypto/ed25519\"\n\t\"crypto/rand\"\n\t\"crypto/sha512\"\n\t\"encoding/base64\"\n\t\"errors\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nconst (\n\tmaxTimestampDiffSeconds = 15 * 60\n\trandomTokenLength       = 22 // ~2^132 keyspace\n)\n\nvar (\n\terrInvalidToken     = errors.New(\"invalid token\")\n\terrCannotParseToken = errors.New(\"cannot parse token\")\n\terrNoPrivateKey     = errors.New(\"no private key\")\n\ttokenCharacters     = []byte(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_\")\n\tpluginPrefix        = \"P\"\n\tenhancedTokenPrefix = \"gtfy\"\n\n\trandReader = rand.Reader\n)\n\ntype EnhancedToken struct {\n\tident        string\n\tpubOrPrivKey []byte\n\ttimestamp    int64\n\tsignature    []byte\n}\n\n// PublicForm returns the a canonicalized representation of the public key.\nfunc (c *EnhancedToken) PublicForm() string {","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/gotify/server/blob/14bfc256276775c425f988d621dccfe705de18ac/auth/token.go#L4-L40","documentation":"errInvalidToken is the sentinel error (errors.Is-able) returned by ParseEnhancedToken when an enhanced token ('gtfy'-prefixed, signed) fails cryptographic verification — e.g. the ed25519 signature over the timestamp/payload does not verify against the server's public key. TestNewComplexToken also surfaces it when a crafted token fails verification.","triggerScenarios":"Parsing a token whose signature was mutated/truncated (see token_test.go:44), a token signed by a different key than the server expects, a token replayed outside maxTimestampDiffSeconds (15 min) or with a corrupted timestamp, or a token whose payload was tampered with.","commonSituations":"Copying tokens between environments (staging token on production server); truncating the token in a shell variable or config; manually editing a token; clock skew beyond 15 minutes between issuance and validation after token regen.","solutions":["Request a fresh token from the server (login / token generation) and use it verbatim — no truncation or reformatting","Ensure the token was issued by the same server/key you are validating against; do not share tokens across instances","Check client clock skew: keep it well under 15 minutes or sync with NTP","If you hand-build tokens, re-sign them with the correct ed25519 private key and the SHA-512 options the server uses"],"exampleFix":"// before: reconstructed token string\ntoken := 'gtfy' + payloadPart + guessedSig\nuser, err := auth.ParseEnhancedToken(token)\n// after: use the token exactly as issued by the server\ntoken := os.Getenv(\"GITEA_TOKEN\")\nuser, err := auth.ParseEnhancedToken(token)\n// handle with errors.Is(err, auth.ErrInvalidToken)","handlingStrategy":"try-catch","validationCode":"// structural + provenance sanity checks before parsing\nif (!token || !token.startsWith('gtfy')) throw new Error('not an enhanced token');\nif (token !== tokenIssuedByThisServer) throw new Error('token from a different server/key');","typeGuard":"function isEnhancedToken(t) {\n  return typeof t === 'string' && t.startsWith('gtfy') && t.length > 4;\n}","tryCatchPattern":"user, err := ParseEnhancedToken(token)\nif err != nil {\n    if errors.Is(err, errInvalidToken) {\n        // signature verification failed: token tampered, wrong key, or stale\n        return nil, fmt.Errorf(\"token rejected; request a fresh token from the server\")\n    }\n    return nil, err\n}","preventionTips":["Store and transmit tokens verbatim — no trimming, reformatting, or truncation","Do not share tokens across server instances (different signing keys)","Keep clocks synced (NTP); tokens are time-windowed (15 min)","Regenerate the token after any key rotation or suspected compromise"],"tags":["authentication","token","signature","ed25519","crypto"],"backgroundTag":"invalid-token-signature","analyzedSha":"14bfc256276775c425f988d621dccfe705de18ac","analyzedAt":"2026-09-05T12:52:36.781Z","contentChangedAt":"2026-09-05T12:52:36.781Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}