From 3008dc09db7cbf3c1d54b6f6281d893b37af550a Mon Sep 17 00:00:00 2001 From: kolaente Date: Sat, 11 Apr 2026 20:54:47 +0200 Subject: [PATCH] test(auth): cover env-var string booleans for oidc providers (#2599) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regression test for #2599. Exercises getProviderFromMap with native bools and with stringified booleans ("true"/"false"/"1"/"0") for all four boolean provider fields — emailfallback, usernamefallback, forceuserinfo, requireavailability. From env vars and from the GetConfigValueFromFile path every leaf arrives as a string, so the current .(bool) assertion silently zeros these fields. --- pkg/modules/auth/openid/providers_test.go | 104 ++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/pkg/modules/auth/openid/providers_test.go b/pkg/modules/auth/openid/providers_test.go index 902f140c9..1a089f526 100644 --- a/pkg/modules/auth/openid/providers_test.go +++ b/pkg/modules/auth/openid/providers_test.go @@ -175,6 +175,110 @@ func TestUniqueIssuersAllowed(t *testing.T) { assert.Len(t, providers, 2) } +func TestGetProviderFromMapStringBooleans(t *testing.T) { + // Regression test for #2599. When provider config is sourced from environment + // variables or `*.file` Docker secrets, every leaf value arrives as a string. + // The boolean fields (emailfallback, usernamefallback, forceuserinfo, + // requireavailability) must accept stringified bools, not silently fall back + // to zero values or reject the whole provider. + defer CleanupSavedOpenIDProviders() + + server := newMockOIDCServer() + defer server.Close() + + cases := []struct { + name string + emailFallback interface{} + usernameFallback interface{} + forceUserInfo interface{} + requireAvailability interface{} + wantEmailFallback bool + wantUsernameFallback bool + wantForceUserInfo bool + wantRequireAvailability bool + }{ + { + name: "native bool true", + emailFallback: true, + usernameFallback: true, + forceUserInfo: true, + requireAvailability: true, + wantEmailFallback: true, + wantUsernameFallback: true, + wantForceUserInfo: true, + wantRequireAvailability: true, + }, + { + name: "native bool false", + emailFallback: false, + usernameFallback: false, + forceUserInfo: false, + requireAvailability: false, + wantEmailFallback: false, + wantUsernameFallback: false, + wantForceUserInfo: false, + wantRequireAvailability: false, + }, + { + name: "string true", + emailFallback: "true", + usernameFallback: "true", + forceUserInfo: "true", + requireAvailability: "true", + wantEmailFallback: true, + wantUsernameFallback: true, + wantForceUserInfo: true, + wantRequireAvailability: true, + }, + { + name: "string false", + emailFallback: "false", + usernameFallback: "false", + forceUserInfo: "false", + requireAvailability: "false", + wantEmailFallback: false, + wantUsernameFallback: false, + wantForceUserInfo: false, + wantRequireAvailability: false, + }, + { + name: "string 1 and 0", + emailFallback: "1", + usernameFallback: "0", + forceUserInfo: "1", + requireAvailability: "0", + wantEmailFallback: true, + wantUsernameFallback: false, + wantForceUserInfo: true, + wantRequireAvailability: false, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + pi := map[string]interface{}{ + "name": "Test Provider", + "authurl": server.URL, + "clientid": "client1", + "clientsecret": "secret1", + "emailfallback": tc.emailFallback, + "usernamefallback": tc.usernameFallback, + "forceuserinfo": tc.forceUserInfo, + "requireavailability": tc.requireAvailability, + } + + provider, err := getProviderFromMap(pi, "test") + require.NoError(t, err) + require.NotNil(t, provider) + + assert.Equal(t, tc.wantEmailFallback, provider.EmailFallback, "EmailFallback") + assert.Equal(t, tc.wantUsernameFallback, provider.UsernameFallback, "UsernameFallback") + assert.Equal(t, tc.wantForceUserInfo, provider.ForceUserInfo, "ForceUserInfo") + assert.Equal(t, tc.wantRequireAvailability, provider.RequireAvailability, "RequireAvailability") + }) + } +} + func TestFailedDiscoverySkippedInIssuerCheck(t *testing.T) { defer CleanupSavedOpenIDProviders()