Compare commits

...

1 Commits

Author SHA1 Message Date
therealpandey
7c8b23813c fix(tokenizer): require a jwt secret when the provider is jwt
An empty secret signs and verifies tokens with an empty key. Fail at config
validation instead of warning at startup.
2026-09-18 01:55:01 +05:30
3 changed files with 58 additions and 4 deletions

View File

@@ -118,5 +118,10 @@ func (c Config) Validate() error {
return errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "rotation::duration must be smaller than rotation::interval")
}
// Ensure that the jwt secret is set when the provider is jwt, an empty secret signs and verifies tokens with an empty key
if c.Provider == "jwt" && c.JWT.Secret == "" {
return errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "jwt::secret must be set when provider is jwt, without a JWT secret, user sessions are vulnerable to tampering and unauthorized access")
}
return nil
}

View File

@@ -0,0 +1,53 @@
package tokenizer
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestValidate(t *testing.T) {
testCases := []struct {
name string
provider string
secret string
expectedError bool
}{
{
name: "JWTWithSecret",
provider: "jwt",
secret: "secret",
expectedError: false,
},
{
name: "JWTWithoutSecret",
provider: "jwt",
secret: "",
expectedError: true,
},
{
name: "OpaqueWithoutSecret",
provider: "opaque",
secret: "",
expectedError: false,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
config, ok := newConfig().(*Config)
assert.True(t, ok)
config.Provider = testCase.provider
config.JWT.Secret = testCase.secret
err := config.Validate()
if testCase.expectedError {
assert.Error(t, err)
return
}
assert.NoError(t, err)
})
}
}

View File

@@ -45,10 +45,6 @@ func NewFactory(cache cache.Cache, tokenStore authtypes.TokenStore) factory.Prov
func New(ctx context.Context, providerSettings factory.ProviderSettings, config tokenizer.Config, cache cache.Cache, tokenStore authtypes.TokenStore) (tokenizer.Tokenizer, error) {
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/tokenizer/jwttokenizer")
if config.JWT.Secret == "" {
settings.Logger().ErrorContext(ctx, "🚨 CRITICAL SECURITY ISSUE: No JWT secret key specified!", slog.String("error", "SIGNOZ_TOKENIZER_JWT_SECRET environment variable is not set. This has dire consequences for the security of the application. Without a JWT secret, user sessions are vulnerable to tampering and unauthorized access. Please set the SIGNOZ_TOKENIZER_JWT_SECRET environment variable immediately. For more information, please refer to https://github.com/SigNoz/signoz/issues/8400."))
}
lastObservedAtCache, err := ristretto.NewCache(&ristretto.Config[string, map[valuer.UUID]time.Time]{
NumCounters: 10 * expectedLastObservedAtCacheEntries, // 10x of expected entries
MaxCost: 1 << 19, // ~ 512 KB