{"record":{"id":"2e73ca495e134e48","repo":"netbirdio/netbird","slug":"pkce-authorization-flow-failed-v","errorCode":null,"errorMessage":"PKCE authorization flow failed: %v","messagePattern":"PKCE authorization flow failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/internal/auth/pkce_flow.go","lineNumber":242,"sourceCode":"\tmux := http.NewServeMux()\n\tmux.HandleFunc(\"/\", func(w http.ResponseWriter, req *http.Request) {\n\t\tlog.Infof(\"pkce flow: received authorization callback from IdP\")\n\t\tcert := p.providerConfig.ClientCertPair\n\t\tif cert != nil {\n\t\t\ttr := &http.Transport{\n\t\t\t\tTLSClientConfig: &tls.Config{\n\t\t\t\t\tCertificates: []tls.Certificate{*cert},\n\t\t\t\t},\n\t\t\t}\n\t\t\tsslClient := &http.Client{Transport: tr}\n\t\t\tctx := context.WithValue(req.Context(), oauth2.HTTPClient, sslClient)\n\t\t\treq = req.WithContext(ctx)\n\t\t}\n\n\t\ttoken, err := p.handleRequest(req)\n\t\tif err != nil {\n\t\t\trenderPKCEFlowTmpl(w, err)\n\t\t\terrChan <- fmt.Errorf(\"PKCE authorization flow failed: %v\", err)\n\t\t\treturn\n\t\t}\n\n\t\trenderPKCEFlowTmpl(w, nil)\n\t\ttokenChan <- token\n\t})\n\n\tserver.Handler = mux\n\tif err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {\n\t\terrChan <- err\n\t}\n}\n\nfunc (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)","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/internal/auth/pkce_flow.go#L224-L260","documentation":"Top-level wrapper emitted by the local callback HTTP handler inside the PKCE Authorization Code flow. It fires when handleRequest fails at any step after the IdP redirects back to the localhost redirect URL: the IdP reported an OAuth error, the state parameter mismatched, the authorization code was missing, or the token exchange at the TokenEndpoint failed. The %v carries the specific underlying cause.","triggerScenarios":"WaitToken's callback server receives a request whose query has error/error_description set; or the state query param fails subtle.ConstantTimeCompare against p.state; or the code query param is empty; or p.oAuthConfig.Exchange against providerConfig.TokenEndpoint returns an error (network failure, wrong client credentials, expired or already-consumed authorization code, code_verifier mismatch).","commonSituations":"IdP application missing the localhost callback URL registration; a second login started and overwrote p.state/p.codeVerifier while the first browser tab finished; clock skew expiring the short-lived code; management's IdP configuration (TokenEndpoint, AuthorizationEndpoint, ClientID) pointing at wrong endpoints; corporate proxy or TLS interception blocking the token endpoint; user refreshing the callback page replaying a consumed code.","solutions":["Read the wrapped text after 'PKCE authorization flow failed:' - it names the exact sub-cause (IdP error description, Invalid state, missing code, or the token exchange error).","Retry the login (netbird up) for a fresh state and code_verifier; close stale browser tabs and do not refresh the callback page.","Verify the IdP application's allowed redirect/callback URLs include the localhost redirect URL logged by the client.","If the wrapped cause is an exchange failure, verify TokenEndpoint reachability from the client and that the system clock is synced (codes live for minutes).","If it persists, have the NetBird administrator re-check the IdP configuration (ClientID, endpoints, scopes) in management."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"tokenInfo, err := flow.WaitToken(ctx, info)\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) {\n        // flow expired before the user finished login; call RequestAuthInfo again\n    }\n    // return err verbatim: the wrapped text after 'PKCE authorization flow failed:'\n    // identifies the failed step (IdP error, state, code, or exchange)\n    return TokenInfo{}, err\n}","preventionTips":["Complete the browser login within the flow timeout (defaultPKCETimeoutSeconds = 300s).","Run one login flow at a time; a second flow invalidates the first's state and verifier.","Register the localhost redirect URL in the IdP application before starting.","Keep the system clock synced; authorization codes and states are short-lived.","Never refresh or bookmark the localhost callback page."],"tags":["oauth2","pkce","authentication","idp","network"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}