{"record":{"id":"339f6baf1bf06ea7","repo":"netbirdio/netbird","slug":"authentication-failed-missing-code","errorCode":null,"errorMessage":"authentication failed: missing code","messagePattern":"authentication failed: missing code","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/internal/auth/pkce_flow.go","lineNumber":274,"sourceCode":"func (p *PKCEAuthorizationFlow) handleRequest(req *http.Request) (*oauth2.Token, error) {\n\tquery := req.URL.Query()\n\n\tif authError := query.Get(queryError); authError != \"\" {\n\t\tauthErrorDesc := query.Get(queryErrorDesc)\n\t\tif authErrorDesc != \"\" {\n\t\t\treturn nil, fmt.Errorf(\"authentication failed: %s\", authErrorDesc)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"authentication failed: %s\", authError)\n\t}\n\n\t// Prevent timing attacks on the state\n\tif state := query.Get(queryState); subtle.ConstantTimeCompare([]byte(p.state), []byte(state)) == 0 {\n\t\treturn nil, fmt.Errorf(\"authentication failed: Invalid state\")\n\t}\n\n\tcode := query.Get(queryCode)\n\tif code == \"\" {\n\t\treturn nil, fmt.Errorf(\"authentication failed: missing code\")\n\t}\n\n\texchangeStart := time.Now()\n\ttoken, err := p.oAuthConfig.Exchange(\n\t\treq.Context(),\n\t\tcode,\n\t\toauth2.SetAuthURLParam(\"code_verifier\", p.codeVerifier),\n\t)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tlog.Infof(\"pkce flow: authorization code exchanged for token in %s\", time.Since(exchangeStart).Round(time.Millisecond))\n\treturn token, nil\n}\n\nfunc (p *PKCEAuthorizationFlow) parseOAuthToken(token *oauth2.Token) (TokenInfo, error) {\n\ttokenInfo := TokenInfo{","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/internal/auth/pkce_flow.go#L256-L292","documentation":"The callback carried no error and passed the state check, but the code query parameter was empty. Without an authorization code there is nothing to exchange at the token endpoint, so the flow aborts before any token request is made.","triggerScenarios":"The IdP (or an intermediary) redirects to the redirect URL without appending a code parameter; someone navigates to the localhost callback URL manually; a nonstandard IdP returns the code in the URL fragment (implicit-style) instead of the query; a proxy or security product strips query parameters from the redirect.","commonSituations":"User manually opens the localhost callback URL in a browser; IdP application configured with the wrong response type (must be code for PKCE); reverse proxies or endpoint protection rewriting redirects to localhost; custom IdP builds that deviate from RFC 6749 redirect format.","solutions":["Retry the login and complete it normally in the browser - the code is appended automatically by a correct redirect.","Verify the IdP application uses response_type=code (Authorization Code with PKCE); implicit or hybrid flow variants that put the token in a fragment do not work here.","Check whether a proxy, extension, or security tool strips query parameters from redirects to localhost, and bypass it for the callback.","If a custom IdP is in play, confirm it redirects with code in the query string per RFC 6749 section 4.1.2."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"_, err := flow.WaitToken(ctx, info)\nif err != nil {\n    if strings.Contains(err.Error(), \"missing code\") {\n        // nothing to exchange: restart the flow and complete it in-browser;\n        // check for proxies/IdP config that drop or omit the code query param\n    }\n}","preventionTips":["Ensure the IdP application uses response_type=code; PKCE does not work with implicit-flow redirects that use fragments.","Keep intermediaries (reverse proxies, security tools) from rewriting redirects to localhost.","Complete the login via the normal browser redirect - never hand-navigate to the callback URL."],"tags":["oauth2","pkce","callback","redirect"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}