feat: rename ServiceJWTSecret to ServiceSecret with deprecation (#2502)

This commit is contained in:
kolaente 2026-03-30 12:07:01 +02:00 committed by GitHub
parent fb8c937d77
commit 83bac15841
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 27 additions and 10 deletions

View File

@ -3,10 +3,15 @@
{
"key": "service",
"children": [
{
"key": "secret",
"default_value": "\u003ca-secret\u003e",
"comment": "This secret is used to sign JWT tokens and for other cryptographic operations.\nDefault is a random secret which will be generated at each startup of Vikunja.\n(This means all already issued tokens will be invalid once you restart Vikunja)"
},
{
"key": "JWTSecret",
"default_value": "\u003cjwt-secret\u003e",
"comment": "This token is used to verify issued JWT tokens.\nDefault is a random token which will be generated at each startup of Vikunja.\n(This means all already issued tokens will be invalid once you restart Vikunja)"
"comment": "Deprecated: use service.secret instead. If set, its value will be copied to service.secret."
},
{
"key": "jwtttl",

View File

@ -41,7 +41,8 @@ type Key string
// These constants hold all config value keys
const (
// #nosec
ServiceJWTSecret Key = `service.JWTSecret`
ServiceSecret Key = `service.secret`
ServiceJWTSecret Key = `service.JWTSecret` // #nosec G101 -- Deprecated config key alias, not a credential
ServiceJWTTTL Key = `service.jwtttl`
ServiceJWTTTLLong Key = `service.jwtttllong`
ServiceJWTTTLShort Key = `service.jwtttlshort`
@ -333,7 +334,7 @@ func InitDefaultConfig() {
}
// Service
ServiceJWTSecret.setDefault(random)
ServiceSecret.setDefault(random)
ServiceJWTTTL.setDefault(259200) // 72 hours
ServiceJWTTTLLong.setDefault(2592000) // 30 days
ServiceJWTTTLShort.setDefault(600) // 10 minutes
@ -635,6 +636,17 @@ func InitConfig() {
readConfigValuesFromFiles()
// Deprecation: migrate service.JWTSecret → service.secret only when the
// user has not explicitly set service.secret (so the new key takes precedence).
if ServiceJWTSecret.GetString() != "" {
if viper.IsSet(string(ServiceSecret)) {
log.Warning("config: both service.secret and service.jwtsecret are set. Using service.secret. Please remove service.jwtsecret, it is deprecated and will be removed in a future release.")
} else {
log.Warning("config: service.jwtsecret is deprecated and will be removed in a future release. Please use service.secret instead.")
ServiceSecret.Set(ServiceJWTSecret.GetString())
}
}
if _, err := url.ParseRequestURI(AvatarGravatarBaseURL.GetString()); err != nil {
log.Fatalf("Could not parse gravatarbaseurl: %s", err)
}

View File

@ -78,7 +78,7 @@ func checkPublicURL() CheckResult {
func checkJWTSecret() CheckResult {
// We can't check the actual value, but we can check if it's the default length
// which would indicate it was auto-generated
secret := config.ServiceJWTSecret.GetString()
secret := config.ServiceSecret.GetString()
// Auto-generated secrets are 64 hex characters (32 bytes)
if len(secret) == 64 {

View File

@ -126,7 +126,7 @@ func addUserTokenToContext(t *testing.T, u *user.User, c *echo.Context) {
token, err := auth.NewUserJWTAuthtoken(u, "test-session-id")
require.NoError(t, err)
tken, err := jwt.Parse(token, func(_ *jwt.Token) (interface{}, error) {
return []byte(config.ServiceJWTSecret.GetString()), nil
return []byte(config.ServiceSecret.GetString()), nil
})
require.NoError(t, err)
c.Set("user", tken)

View File

@ -135,7 +135,7 @@ func NewUserJWTAuthtoken(u *user.User, sessionID string) (token string, err erro
claims["sid"] = sessionID
claims["jti"] = uuid.New().String()
return t.SignedString([]byte(config.ServiceJWTSecret.GetString()))
return t.SignedString([]byte(config.ServiceSecret.GetString()))
}
// NewLinkShareJWTAuthtoken creates a new jwt token from a link share
@ -156,7 +156,7 @@ func NewLinkShareJWTAuthtoken(share *models.LinkSharing) (token string, err erro
claims["exp"] = exp
// Generate encoded token and send it as response.
return t.SignedString([]byte(config.ServiceJWTSecret.GetString()))
return t.SignedString([]byte(config.ServiceSecret.GetString()))
}
// GetAuthFromClaims returns a web.Auth object from jwt claims

View File

@ -39,7 +39,7 @@ const ErrCodeInvalidToken = 11
func SetupTokenMiddleware() echo.MiddlewareFunc {
return echojwt.WithConfig(echojwt.Config{
SigningKey: []byte(config.ServiceJWTSecret.GetString()),
SigningKey: []byte(config.ServiceSecret.GetString()),
Skipper: func(c *echo.Context) bool {
authHeader := c.Request().Header.Values("Authorization")
if len(authHeader) == 0 {

View File

@ -134,7 +134,7 @@ func addUserTokenToContext(t *testing.T, user *user.User, c *echo.Context) {
require.NoError(t, err)
// We send the string token through the parsing function to get a valid jwt.Token
tken, err := jwt.Parse(token, func(_ *jwt.Token) (interface{}, error) {
return []byte(config.ServiceJWTSecret.GetString()), nil
return []byte(config.ServiceSecret.GetString()), nil
})
require.NoError(t, err)
c.Set("user", tken)
@ -146,7 +146,7 @@ func addLinkShareTokenToContext(t *testing.T, share *models.LinkSharing, c *echo
require.NoError(t, err)
// We send the string token through the parsing function to get a valid jwt.Token
tken, err := jwt.Parse(token, func(_ *jwt.Token) (interface{}, error) {
return []byte(config.ServiceJWTSecret.GetString()), nil
return []byte(config.ServiceSecret.GetString()), nil
})
require.NoError(t, err)
c.Set("user", tken)