{"record":{"id":"6f707cad560e0a93","repo":"crowdsecurity/crowdsec","slug":"invalid-token-for-auto-registration","errorCode":null,"errorMessage":"invalid token for auto registration","messagePattern":"invalid token for auto registration","errorType":"http","errorClass":null,"httpStatus":403,"severity":"error","filePath":"pkg/apiserver/controllers/v1/machines.go","lineNumber":35,"sourceCode":"\tif c.AutoRegisterCfg == nil || c.AutoRegisterCfg.Enable == nil || !*c.AutoRegisterCfg.Enable {\n\t\treturn false, nil\n\t}\n\n\tclientIP := net.ParseIP(gctx.ClientIP())\n\n\t// Can probaby happen if using unix socket ?\n\tif clientIP == nil {\n\t\tlog.Warnf(\"Failed to parse client IP for watcher self registration: %s\", gctx.ClientIP())\n\t\treturn false, nil\n\t}\n\n\tif token == \"\" {\n\t\treturn false, nil\n\t}\n\n\t// Check the token\n\tif token != c.AutoRegisterCfg.Token {\n\t\treturn false, errors.New(\"invalid token for auto registration\")\n\t}\n\n\t// Check the source IP\n\tfor _, ipRange := range c.AutoRegisterCfg.AllowedRangesParsed {\n\t\tif ipRange.Contains(clientIP) {\n\t\t\treturn true, nil\n\t\t}\n\t}\n\n\treturn false, errors.New(\"IP not in allowed range for auto registration\")\n}\n\nfunc (c *Controller) CreateMachine(gctx *gin.Context) {\n\tctx := gctx.Request.Context()\n\n\tvar input models.WatcherRegistrationRequest\n\n\tif err := gctx.ShouldBindJSON(&input); err != nil {","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/apiserver/controllers/v1/machines.go#L17-L53","documentation":"When a watcher hits the machines enrollment endpoint with a pre-existing token, shouldAutoRegister compares it against the controller's auto-registration token (api.server.auto_register.token in the LAPI config). A mismatch rejects the enrollment attempt.","triggerScenarios":"POST /v1/watchers with an authorization token that is non-empty but differs from the LAPI's auto_register token value.","commonSituations":"Stale token after the LAPI config was regenerated; token copied from a different crowdsec instance; whitespace/quoting differences in YAML; machine enrolling against the wrong LAPI.","solutions":["Compare the token sent by the watcher with api.server.auto_register.token on the LAPI host and align them.","Regenerate the enrollment token if needed (cscli or config) and re-enroll the machine with cscli lapi register -u ... -t <token>.","If manual registration is intended, don't send the auto-register token header at all (empty token skips the check)."],"exampleFix":"# before (LAPI config)\nauto_register:\n  token: ${AUTOADD_TOKEN}\n# after - verify the watcher registers with the same token:\n# cscli lapi register -u http://lapi:8080 -t <value of AUTOADD_TOKEN on the server>","handlingStrategy":"validation","validationCode":"if enrollmentToken != lapiAutoRegisterToken {\n    return errors.New(\"token mismatch with LAPI auto_register token\")\n}","typeGuard":null,"tryCatchPattern":"_, err := client.Register(ctx, url, token)\nif err != nil && strings.Contains(err.Error(), \"invalid token\") {\n    // re-read token from the LAPI host and retry registration\n    token = readServerToken()\n    _, err = client.Register(ctx, url, token)\n}","preventionTips":["Copy the token exactly from the LAPI's config (beware shell quoting/whitespace).","Re-sync tokens after regenerating LAPI configuration.","Use `cscli lapi register -u <url> -t <token>` rather than hand-crafted requests."],"tags":["authentication","lapi","auto-registration"],"backgroundTag":"invalid-api-key","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}