git.iko.soy/typeable/oauth2-proxy
on master help sign in
Merge pull request #3183 from Richard87/do-not-override-idle-timeout

fix: dont override parameters set in redis uri

commita279fece025204e85c143969f1c8af5b519869ec authorJoel Speed <Joel.speed@hotmail.co.uk> dateThu 19 Feb 2026, 10:37 (7 months ago) parente7724f37822698
3 files changed+67−8
CHANGELOG.md+2 pkg/sessions/redis/redis_store.go+15−8 pkg/sessions/redis/redis_store_test.go+50
CHANGELOG.md+2
@@ -8,6 +8,8 @@
88
99## Changes since v7.14.2
1010
11+- [#3183](https://github.com/oauth2-proxy/oauth2-proxy/pull/3183) fix: allow URL parameters to configure username, password and max idle connection timeout if the matching configuration is empty.
12+
1113# V7.14.2
1214
1315## Release Highlights
pkg/sessions/redis/redis_store.go+15−8
@@ -109,6 +109,9 @@ func buildSentinelClient(opts options.RedisStoreOptions) (Client, error) {
109109 if opts.Username != "" {
110110 opt.Username = opts.Username
111111 }
112+ if opts.IdleTimeout > 0 {
113+ opt.ConnMaxIdleTime = time.Duration(opts.IdleTimeout) * time.Second
114+ }
112115
113116 if err := setupTLSConfig(opts, opt); err != nil {
114117 return nil, err
@@ -118,10 +121,10 @@ func buildSentinelClient(opts options.RedisStoreOptions) (Client, error) {
118121 MasterName: opts.SentinelMasterName,
119122 SentinelAddrs: addrs,
120123 SentinelPassword: opts.SentinelPassword,
121− Username: opts.Username,
122− Password: opts.Password,
124+ Username: opt.Username,
125+ Password: opt.Password,
123126 TLSConfig: opt.TLSConfig,
124− ConnMaxIdleTime: time.Duration(opts.IdleTimeout) * time.Second,
127+ ConnMaxIdleTime: opt.ConnMaxIdleTime,
125128 })
126129 return newClient(client), nil
127130}
@@ -139,6 +142,9 @@ func buildClusterClient(opts options.RedisStoreOptions) (Client, error) {
139142 if opts.Username != "" {
140143 opt.Username = opts.Username
141144 }
145+ if opts.IdleTimeout > 0 {
146+ opt.ConnMaxIdleTime = time.Duration(opts.IdleTimeout) * time.Second
147+ }
142148
143149 if err := setupTLSConfig(opts, opt); err != nil {
144150 return nil, err
@@ -146,10 +152,10 @@ func buildClusterClient(opts options.RedisStoreOptions) (Client, error) {
146152
147153 client := redis.NewClusterClient(&redis.ClusterOptions{
148154 Addrs: addrs,
149− Username: opts.Username,
150− Password: opts.Password,
155+ Username: opt.Username,
156+ Password: opt.Password,
151157 TLSConfig: opt.TLSConfig,
152− ConnMaxIdleTime: time.Duration(opts.IdleTimeout) * time.Second,
158+ ConnMaxIdleTime: opt.ConnMaxIdleTime,
153159 })
154160 return newClusterClient(client), nil
155161}
@@ -168,13 +174,14 @@ func buildStandaloneClient(opts options.RedisStoreOptions) (Client, error) {
168174 if opts.Username != "" {
169175 opt.Username = opts.Username
170176 }
177+ if opts.IdleTimeout > 0 {
178+ opt.ConnMaxIdleTime = time.Duration(opts.IdleTimeout) * time.Second
179+ }
171180
172181 if err := setupTLSConfig(opts, opt); err != nil {
173182 return nil, err
174183 }
175184
176− opt.ConnMaxIdleTime = time.Duration(opts.IdleTimeout) * time.Second
177−
178185 client := redis.NewClient(opt)
179186 return newClient(client), nil
180187}
pkg/sessions/redis/redis_store_test.go+50
@@ -1,6 +1,7 @@
11package redis
22
33import (
4+ "fmt"
45 "time"
56
67 "github.com/Bose/minisentinel"
@@ -246,6 +247,55 @@ var _ = Describe("Redis SessionStore Tests", func() {
246247 })
247248
248249 Describe("Redis URL Parsing", func() {
250+ It("should prefer configured username password and timeout over URL parameters", func() {
251+ configuredUsername := "configured-user"
252+ configuredPassword := "configured-password"
253+ configuredIdleTimeout := 90
254+
255+ urlUsername := "url-user"
256+ urlPassword := "url-password"
257+ urlIdleTimeout := 30
258+
259+ redisClient, err := buildStandaloneClient(options.RedisStoreOptions{
260+ ConnectionURL: fmt.Sprintf("redis://%s:%s@localhost:6379?conn_max_idle_time=%d", urlUsername, urlPassword, urlIdleTimeout),
261+ Username: configuredUsername,
262+ Password: configuredPassword,
263+ IdleTimeout: configuredIdleTimeout,
264+ })
265+ Expect(err).ToNot(HaveOccurred())
266+
267+ rc, ok := redisClient.(*client)
268+ Expect(ok).To(BeTrue())
269+ Expect(rc.Close()).To(Succeed())
270+
271+ redisOptions := rc.Options()
272+ Expect(redisOptions.Username).To(Equal(configuredUsername))
273+ Expect(redisOptions.Password).To(Equal(configuredPassword))
274+ Expect(redisOptions.ConnMaxIdleTime).To(Equal(time.Duration(configuredIdleTimeout) * time.Second))
275+ })
276+ It("should prefer URL username password and timeout when configured values are empty", func() {
277+ urlUsername := "url-user"
278+ urlPassword := "url-password"
279+ urlIdleTimeout := 30
280+
281+ redisClient, err := buildStandaloneClient(options.RedisStoreOptions{
282+ ConnectionURL: fmt.Sprintf("redis://%s:%s@localhost:6379?conn_max_idle_time=%d", urlUsername, urlPassword, urlIdleTimeout),
283+ Username: "",
284+ Password: "",
285+ IdleTimeout: 0,
286+ })
287+ Expect(err).ToNot(HaveOccurred())
288+
289+ rc, ok := redisClient.(*client)
290+ Expect(ok).To(BeTrue())
291+ Expect(rc.Close()).To(Succeed())
292+
293+ redisOptions := rc.Options()
294+ Expect(redisOptions.Username).To(Equal(urlUsername))
295+ Expect(redisOptions.Password).To(Equal(urlPassword))
296+ Expect(redisOptions.ConnMaxIdleTime).To(Equal(time.Duration(urlIdleTimeout) * time.Second))
297+ })
298+
249299 It("should parse valid redis URL", func() {
250300 addrs, opts, err := parseRedisURLs([]string{"redis://localhost:6379"})
251301 Expect(err).ToNot(HaveOccurred())