{"record":{"id":"edca644c5bee1170","repo":"fatedier/frp","slug":"token-in-newworkconn-doesn-t-match-token-from-conf","errorCode":null,"errorMessage":"token in NewWorkConn doesn't match token from configuration","messagePattern":"token in NewWorkConn doesn't match token from configuration","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/auth/token.go","lineNumber":88,"sourceCode":"\nfunc (auth *TokenAuthSetterVerifier) VerifyPing(m *msg.Ping) error {\n\tif !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeHeartBeats) {\n\t\treturn nil\n\t}\n\n\tif !util.ConstantTimeEqString(util.GetAuthKey(auth.token, m.Timestamp), m.PrivilegeKey) {\n\t\treturn fmt.Errorf(\"token in heartbeat doesn't match token from configuration\")\n\t}\n\treturn nil\n}\n\nfunc (auth *TokenAuthSetterVerifier) VerifyNewWorkConn(m *msg.NewWorkConn) error {\n\tif !slices.Contains(auth.additionalAuthScopes, v1.AuthScopeNewWorkConns) {\n\t\treturn nil\n\t}\n\n\tif !util.ConstantTimeEqString(util.GetAuthKey(auth.token, m.Timestamp), m.PrivilegeKey) {\n\t\treturn fmt.Errorf(\"token in NewWorkConn doesn't match token from configuration\")\n\t}\n\treturn nil\n}\n","sourceCodeStart":70,"sourceCodeEnd":92,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/auth/token.go#L70-L92","documentation":"Same constant-time static-token check applied to NewWorkConn messages, only when 'NewWorkConns' is in the additional auth scopes. frps computes md5(token + newWorkConn.Timestamp) and compares it to newWorkConn.PrivilegeKey; a mismatch aborts the new work connection.","triggerScenarios":"NewWorkConns scope enabled and a work-connection request carries a PrivilegeKey derived from a different token — e.g. only one side has the scope enabled, a custom visitor implementation skips signing NewWorkConn, or the token differs between frps and the visiting frpc.","commonSituations":"Hardening configs by adding NewWorkConns to additionalAuthScopes on frps while frpc (or a custom visitor) still sends unsigned NewWorkConn messages; token drift between environments after a rotation.","solutions":["Mirror authentication.additionalScopes with NewWorkConns on frpc so it signs NewWorkConn messages","Ensure authentication.token matches exactly on frps and every frpc/visitor","For custom clients, set NewWorkConn.PrivilegeKey = md5(token || timestamp) when the scope is enabled","Restart all peers after scope or token changes"],"exampleFix":"# before — only frps requires NewWorkConn auth\n# frps.toml\nauthentication.additionalAuthScopes = [\"NewWorkConns\"]\n\n# after — frpc signs NewWorkConn too\n# frpc.toml\nauthentication.additionalAuthScopes = [\"NewWorkConns\"]","handlingStrategy":"validation","validationCode":"expected := md5hex(authToken + strconv.FormatInt(newWorkConn.Timestamp, 10))\nif expected != newWorkConn.PrivilegeKey {\n    return errors.New(\"NewWorkConn auth failed; token or scope mismatch\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Include NewWorkConns in additionalAuthScopes on both frps and frpc/visitor","Custom visitors must set NewWorkConn.PrivilegeKey = md5(token||timestamp)","Test with one work connection after enabling the scope"],"tags":["frp","authentication","token","work-connection","config-mismatch"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}