@@ -6,6 +6,7 @@ package setting
6
6
import (
7
7
"math"
8
8
"path/filepath"
9
+ "sync/atomic"
9
10
10
11
"code.gitea.io/gitea/modules/generate"
11
12
"code.gitea.io/gitea/modules/log"
@@ -96,7 +97,6 @@ var OAuth2 = struct {
96
97
RefreshTokenExpirationTime int64
97
98
InvalidateRefreshTokens bool
98
99
JWTSigningAlgorithm string `ini:"JWT_SIGNING_ALGORITHM"`
99
- JWTSecretBase64 string `ini:"JWT_SECRET"`
100
100
JWTSigningPrivateKeyFile string `ini:"JWT_SIGNING_PRIVATE_KEY_FILE"`
101
101
MaxTokenLength int
102
102
DefaultApplications []string
@@ -128,28 +128,50 @@ func loadOAuth2From(rootCfg ConfigProvider) {
128
128
return
129
129
}
130
130
131
- OAuth2 . JWTSecretBase64 = loadSecret (sec , "JWT_SECRET_URI" , "JWT_SECRET" )
131
+ jwtSecretBase64 : = loadSecret (sec , "JWT_SECRET_URI" , "JWT_SECRET" )
132
132
133
133
if ! filepath .IsAbs (OAuth2 .JWTSigningPrivateKeyFile ) {
134
134
OAuth2 .JWTSigningPrivateKeyFile = filepath .Join (AppDataPath , OAuth2 .JWTSigningPrivateKeyFile )
135
135
}
136
136
137
137
if InstallLock {
138
- if _ , err := generate .DecodeJwtSecretBase64 (OAuth2 .JWTSecretBase64 ); err != nil {
139
- _ , OAuth2 .JWTSecretBase64 , err = generate .NewJwtSecretWithBase64 ()
138
+ jwtSecretBytes , err := generate .DecodeJwtSecretBase64 (jwtSecretBase64 )
139
+ if err != nil {
140
+ jwtSecretBytes , jwtSecretBase64 , err = generate .NewJwtSecretWithBase64 ()
140
141
if err != nil {
141
142
log .Fatal ("error generating JWT secret: %v" , err )
142
143
}
143
-
144
144
saveCfg , err := rootCfg .PrepareSaving ()
145
145
if err != nil {
146
146
log .Fatal ("save oauth2.JWT_SECRET failed: %v" , err )
147
147
}
148
- rootCfg .Section ("oauth2" ).Key ("JWT_SECRET" ).SetValue (OAuth2 . JWTSecretBase64 )
149
- saveCfg .Section ("oauth2" ).Key ("JWT_SECRET" ).SetValue (OAuth2 . JWTSecretBase64 )
148
+ rootCfg .Section ("oauth2" ).Key ("JWT_SECRET" ).SetValue (jwtSecretBase64 )
149
+ saveCfg .Section ("oauth2" ).Key ("JWT_SECRET" ).SetValue (jwtSecretBase64 )
150
150
if err := saveCfg .Save (); err != nil {
151
151
log .Fatal ("save oauth2.JWT_SECRET failed: %v" , err )
152
152
}
153
153
}
154
+ generalSigningSecret .Store (& jwtSecretBytes )
155
+ }
156
+ }
157
+
158
+ // generalSigningSecret is used as container for a []byte value
159
+ // instead of an additional mutex, we use CompareAndSwap func to change the value thread save
160
+ var generalSigningSecret atomic.Pointer [[]byte ]
161
+
162
+ func GetGeneralTokenSigningSecret () []byte {
163
+ old := generalSigningSecret .Load ()
164
+ if old == nil || len (* old ) == 0 {
165
+ jwtSecret , _ , err := generate .NewJwtSecretWithBase64 ()
166
+ if err != nil {
167
+ log .Fatal ("Unable to generate general JWT secret: %s" , err .Error ())
168
+ }
169
+ if generalSigningSecret .CompareAndSwap (old , & jwtSecret ) {
170
+ // FIXME: in main branch, the signing token should be refactored (eg: one unique for LFS/OAuth2/etc ...)
171
+ log .Warn ("OAuth2 is not enabled, unable to use a persistent signing secret, a new one is generated, which is not persistent between restarts and cluster nodes" )
172
+ return jwtSecret
173
+ }
174
+ return * generalSigningSecret .Load ()
154
175
}
176
+ return * old
155
177
}
0 commit comments