oidc, types: validate pkce.method when OIDC is active

This commit is contained in:
Kristoffer Dalby committed 2026-06-17 16:12:19 +02:00
1 parent 4f4e95fc80
commit 4b693a1320
3 files changed
+44 -1

No files matched your search

+5 -1
View File
@@ -558,7 +558,11 @@ func validateServerConfig() error {
// Removed: oidc.expiry -> node.expiry
depr.fatalIfSet("oidc.expiry", "node.expiry")
if viper.GetBool("oidc.enabled") {
// OIDC is activated by setting oidc.issuer (see app.go), not by a
// dedicated oidc.enabled key. Gate PKCE method validation on the real
// activation condition so an invalid method fails at startup instead of
// silently disabling PKCE at runtime.
if viper.GetString("oidc.issuer") != "" {
err := validatePKCEMethod(viper.GetString("oidc.pkce.method"))
if err != nil {
return err
+32
View File
@@ -412,6 +412,38 @@ tls_letsencrypt_challenge_type: TLS-ALPN-01
require.NoError(t, err)
}
func TestPKCEMethodValidation(t *testing.T) {
tmpDir := t.TempDir()
// OIDC is active (issuer set) with PKCE enabled and an invalid method.
// There is no oidc.enabled key. validateServerConfig must reject the
// invalid method rather than silently skipping the check.
configYaml := []byte(`---
noise:
private_key_path: noise_private.key
server_url: http://127.0.0.1:8080
dns:
override_local_dns: false
oidc:
issuer: https://idp.example.com
client_id: headscale
pkce:
enabled: true
method: S256-typo
`)
configFilePath := filepath.Join(tmpDir, "config.yaml")
err := os.WriteFile(configFilePath, configYaml, 0o600)
require.NoError(t, err)
err = LoadConfig(tmpDir, false)
require.NoError(t, err)
err = validateServerConfig()
require.Error(t, err)
assert.Contains(t, err.Error(), errInvalidPKCEMethod.Error())
}
// OK
// server_url: headscale.com, base: clients.headscale.com
// server_url: headscale.com, base: headscale.net