juanfont/headscale · error

auth request rejected

Error message

auth request rejected

What it means

Wrapped error from doLoginURLWithClient when resp.Location() fails on a 3xx response. Location() errors when the Location header exists but cannot be parsed as a URL, or (per stdlib) when there are multiple Location headers. Note the body is still returned alongside the error.

Solutions

  1. Log the raw Location header and fix the configuration producing it (headscale server_url, OIDC issuer).
  2. If using a custom/mock OIDC provider in tests, make it emit an absolute, well-formed Location.
  3. Use the returned body in the error handler for diagnostics.
Defensive patterns

Strategy: validation

Validate before calling

if resp.StatusCode >= 300 && resp.StatusCode < 400 {
    if loc := resp.Header.Get("Location"); loc != "" {
        if _, err := url.Parse(loc); err != nil {
            return fmt.Errorf("malformed Location %q: %w", loc, err)
        }
    }
}

Prevention

When it happens

Trigger: A 3xx response whose Location header is malformed (unparseable URL) — e.g. a misconfigured OIDC issuer_url or server_url producing a broken redirect target.

Common situations: Wrong server_url / issuer base URL configuration in headscale or the OIDC provider (missing scheme, bad characters), or a test stub returning a relative/malformed Location.

Related errors


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/f6242286aad53652. Report an issue: GitHub.

Appendix: source

Thrown at hscontrol/api/v1/auth.go:19

package apiv1

import (
	"context"
	"errors"
	"net/http"

	"github.com/danielgtaylor/huma/v2"
	"github.com/juanfont/headscale/hscontrol/types"
	"github.com/juanfont/headscale/hscontrol/util"
)

func init() {
	registrations = append(registrations, registerAuth)
}

// errAuthRejected is the verdict handed to the waiting registration flow when
// an auth session is rejected.
var errAuthRejected = errors.New("auth request rejected")

// AuthRegisterRequestBody is the v1.AuthRegisterRequest body.
type AuthRegisterRequestBody struct {
	User   string `json:"user,omitempty"`
	AuthID string `json:"authId,omitempty"`
}

// AuthApproveRequestBody is the v1.AuthApproveRequest body.
type AuthApproveRequestBody struct {
	AuthID string `json:"authId,omitempty"`
}

// AuthRejectRequestBody is the v1.AuthRejectRequest body.
type AuthRejectRequestBody struct {
	AuthID string `json:"authId,omitempty"`
}

type (

View on GitHub (pinned to 565fd254d0)