|
4 | 4 | package setting
|
5 | 5 |
|
6 | 6 | import (
|
| 7 | + "fmt" |
7 | 8 | "math"
|
8 | 9 | "path/filepath"
|
| 10 | + "sync/atomic" |
9 | 11 |
|
10 | 12 | "code.gitea.io/gitea/modules/generate"
|
11 | 13 | "code.gitea.io/gitea/modules/log"
|
@@ -96,7 +98,6 @@ var OAuth2 = struct {
|
96 | 98 | RefreshTokenExpirationTime int64
|
97 | 99 | InvalidateRefreshTokens bool
|
98 | 100 | JWTSigningAlgorithm string `ini:"JWT_SIGNING_ALGORITHM"`
|
99 |
| - JWTSecretBase64 string `ini:"JWT_SECRET"` |
100 | 101 | JWTSigningPrivateKeyFile string `ini:"JWT_SIGNING_PRIVATE_KEY_FILE"`
|
101 | 102 | MaxTokenLength int
|
102 | 103 | DefaultApplications []string
|
@@ -128,28 +129,45 @@ func loadOAuth2From(rootCfg ConfigProvider) {
|
128 | 129 | return
|
129 | 130 | }
|
130 | 131 |
|
131 |
| - OAuth2.JWTSecretBase64 = loadSecret(sec, "JWT_SECRET_URI", "JWT_SECRET") |
| 132 | + jwtSecretBase64 := loadSecret(sec, "JWT_SECRET_URI", "JWT_SECRET") |
132 | 133 |
|
133 | 134 | if !filepath.IsAbs(OAuth2.JWTSigningPrivateKeyFile) {
|
134 | 135 | OAuth2.JWTSigningPrivateKeyFile = filepath.Join(AppDataPath, OAuth2.JWTSigningPrivateKeyFile)
|
135 | 136 | }
|
136 | 137 |
|
137 | 138 | if InstallLock {
|
138 |
| - if _, err := generate.DecodeJwtSecretBase64(OAuth2.JWTSecretBase64); err != nil { |
139 |
| - _, OAuth2.JWTSecretBase64, err = generate.NewJwtSecretWithBase64() |
| 139 | + jwtSecretBytes, err := generate.DecodeJwtSecretBase64(jwtSecretBase64) |
| 140 | + if err != nil { |
| 141 | + jwtSecretBytes, jwtSecretBase64, err = generate.NewJwtSecretWithBase64() |
140 | 142 | if err != nil {
|
141 | 143 | log.Fatal("error generating JWT secret: %v", err)
|
142 | 144 | }
|
143 |
| - |
144 | 145 | saveCfg, err := rootCfg.PrepareSaving()
|
145 | 146 | if err != nil {
|
146 | 147 | log.Fatal("save oauth2.JWT_SECRET failed: %v", err)
|
147 | 148 | }
|
148 |
| - rootCfg.Section("oauth2").Key("JWT_SECRET").SetValue(OAuth2.JWTSecretBase64) |
149 |
| - saveCfg.Section("oauth2").Key("JWT_SECRET").SetValue(OAuth2.JWTSecretBase64) |
| 149 | + rootCfg.Section("oauth2").Key("JWT_SECRET").SetValue(jwtSecretBase64) |
| 150 | + saveCfg.Section("oauth2").Key("JWT_SECRET").SetValue(jwtSecretBase64) |
150 | 151 | if err := saveCfg.Save(); err != nil {
|
151 | 152 | log.Fatal("save oauth2.JWT_SECRET failed: %v", err)
|
152 | 153 | }
|
153 | 154 | }
|
| 155 | + generalSigningSecret.Store(&jwtSecretBytes) |
| 156 | + } |
| 157 | +} |
| 158 | + |
| 159 | +var generalSigningSecret atomic.Pointer[[]byte] |
| 160 | + |
| 161 | +func GetGeneralTokenSigningSecret() []byte { |
| 162 | + ptr := generalSigningSecret.Load() |
| 163 | + if ptr == nil { |
| 164 | + if jwtSecret, _, err := generate.NewJwtSecretWithBase64(); err != nil { |
| 165 | + panic(fmt.Errorf("unable to generate general JWT secret: %w", err)) |
| 166 | + } else { |
| 167 | + if generalSigningSecret.CompareAndSwap(nil, &jwtSecret) { |
| 168 | + 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") |
| 169 | + } |
| 170 | + } |
154 | 171 | }
|
| 172 | + return *generalSigningSecret.Load() |
155 | 173 | }
|
0 commit comments