netbirdio/netbird · error

authentication failed: missing code

Error message

authentication failed: missing code

What it means

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.

Source

Thrown at client/internal/auth/pkce_flow.go:274

func (p *PKCEAuthorizationFlow) handleRequest(req *http.Request) (*oauth2.Token, error) {
	query := req.URL.Query()

	if authError := query.Get(queryError); authError != "" {
		authErrorDesc := query.Get(queryErrorDesc)
		if authErrorDesc != "" {
			return nil, fmt.Errorf("authentication failed: %s", authErrorDesc)
		}
		return nil, fmt.Errorf("authentication failed: %s", authError)
	}

	// Prevent timing attacks on the state
	if state := query.Get(queryState); subtle.ConstantTimeCompare([]byte(p.state), []byte(state)) == 0 {
		return nil, fmt.Errorf("authentication failed: Invalid state")
	}

	code := query.Get(queryCode)
	if code == "" {
		return nil, fmt.Errorf("authentication failed: missing code")
	}

	exchangeStart := time.Now()
	token, err := p.oAuthConfig.Exchange(
		req.Context(),
		code,
		oauth2.SetAuthURLParam("code_verifier", p.codeVerifier),
	)
	if err != nil {
		return nil, err
	}

	log.Infof("pkce flow: authorization code exchanged for token in %s", time.Since(exchangeStart).Round(time.Millisecond))
	return token, nil
}

func (p *PKCEAuthorizationFlow) parseOAuthToken(token *oauth2.Token) (TokenInfo, error) {
	tokenInfo := TokenInfo{

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Retry the login and complete it normally in the browser - the code is appended automatically by a correct redirect.
  2. 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.
  3. Check whether a proxy, extension, or security tool strips query parameters from redirects to localhost, and bypass it for the callback.
  4. If a custom IdP is in play, confirm it redirects with code in the query string per RFC 6749 section 4.1.2.
Defensive patterns

Strategy: try-catch

Try / catch

_, err := flow.WaitToken(ctx, info)
if err != nil {
    if strings.Contains(err.Error(), "missing code") {
        // nothing to exchange: restart the flow and complete it in-browser;
        // check for proxies/IdP config that drop or omit the code query param
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/339f6baf1bf06ea7. Report an issue: GitHub.