@@ -54,7 +54,8 @@ func (cs *CombinedSessionStore) AddSession(w http.ResponseWriter, r *http.Reques
5454
5555 clientSession := cs .getCookieSession (r )
5656 clientSession .sessionToken .Values ["session-token" ] = ls .sessionToken
57- clientSession .refreshToken .Values ["refresh-token" ] = ls .refreshToken
57+ // Store only the small reference ID in the cookie, not the full refresh token
58+ clientSession .refreshToken .Values ["refresh-token-id" ] = ls .refreshTokenID
5859
5960 return ls , clientSession .save (r , w )
6061}
@@ -89,12 +90,19 @@ func (cs *CombinedSessionStore) GetSession(w http.ResponseWriter, r *http.Reques
8990 // Get always returns a session, even if empty.
9091 clientSession := cs .getCookieSession (r )
9192
92- var sessionToken , refreshToken string
93+ var (
94+ sessionToken string
95+ refreshToken string
96+ )
97+
9398 if sessionTokenIface , ok := clientSession .sessionToken .Values ["session-token" ]; ok {
9499 sessionToken = sessionTokenIface .(string )
95100 }
96- if refreshTokenIface , ok := clientSession .refreshToken .Values ["refresh-token" ]; ok {
97- refreshToken = refreshTokenIface .(string )
101+ if refreshTokenID , ok := clientSession .refreshToken .Values ["refresh-token-id" ]; ok {
102+ // Look up the actual refresh token from the ID
103+ if actualToken , exists := cs .serverStore .byRefreshTokenID [refreshTokenID .(string )]; exists {
104+ refreshToken = actualToken
105+ }
98106 }
99107
100108 loginState := cs .serverStore .GetSession (sessionToken , refreshToken )
@@ -104,16 +112,23 @@ func (cs *CombinedSessionStore) GetSession(w http.ResponseWriter, r *http.Reques
104112func (cs * CombinedSessionStore ) GetCookieRefreshToken (r * http.Request ) string {
105113 // Get always returns a session, even if empty.
106114 clientSession , _ := cs .clientStore .Get (r , openshiftRefreshTokenCookieName )
107- if refreshToken , ok := clientSession .Values ["refresh-token" ].(string ); ok {
108- return refreshToken
115+ if refreshTokenID , ok := clientSession .Values ["refresh-token-id" ].(string ); ok {
116+ // Look up the actual refresh token using the ID
117+ if actualToken , exists := cs .serverStore .byRefreshTokenID [refreshTokenID ]; exists {
118+ return actualToken
119+ }
109120 }
110121 return ""
111122}
112123
113124func (cs * CombinedSessionStore ) UpdateCookieRefreshToken (w http.ResponseWriter , r * http.Request , refreshToken string ) error {
114- // no need to lock here since there shouldn't be any races around the client session
125+ // Generate a new ID for the refresh token
126+ newID := RandomString (32 )
127+ cs .serverStore .byRefreshTokenID [newID ] = refreshToken
128+
129+ // Store the ID in the cookie, not the full token
115130 clientSession , _ := cs .clientStore .Get (r , openshiftRefreshTokenCookieName )
116- clientSession .Values ["refresh-token" ] = refreshToken
131+ clientSession .Values ["refresh-token-id " ] = newID
117132 return clientSession .Save (r , w )
118133}
119134
@@ -122,13 +137,25 @@ func (cs *CombinedSessionStore) UpdateTokens(w http.ResponseWriter, r *http.Requ
122137 defer cs .sessionLock .Unlock ()
123138
124139 clientSession := cs .getCookieSession (r )
140+ var oldRefreshTokenID string
125141 var oldRefreshToken string
126- if oldToken , ok := clientSession .refreshToken .Values ["refresh-token" ]; ok {
127- oldRefreshToken = oldToken .(string )
142+ if oldID , ok := clientSession .refreshToken .Values ["refresh-token-id" ]; ok {
143+ oldRefreshTokenID = oldID .(string )
144+ // Look up the actual refresh token from the ID
145+ if actualToken , exists := cs .serverStore .byRefreshTokenID [oldRefreshTokenID ]; exists {
146+ oldRefreshToken = actualToken
147+ }
128148 }
129149
130- refreshToken := tokenResponse .RefreshToken
131- clientSession .refreshToken .Values ["refresh-token" ] = refreshToken
150+ // Generate a new ID for the new refresh token
151+ newRefreshTokenID := RandomString (32 )
152+ newRefreshToken := tokenResponse .RefreshToken
153+ if newRefreshToken != "" {
154+ cs .serverStore .byRefreshTokenID [newRefreshTokenID ] = newRefreshToken
155+ }
156+
157+ // Store the new ID in the cookie
158+ clientSession .refreshToken .Values ["refresh-token-id" ] = newRefreshTokenID
132159
133160 var loginState * LoginState
134161 sessionToken , ok := clientSession .sessionToken .Values ["session-token" ]
@@ -142,16 +169,22 @@ func (cs *CombinedSessionStore) UpdateTokens(w http.ResponseWriter, r *http.Requ
142169 return nil , fmt .Errorf ("failed to add session to server store: %w" , err )
143170 }
144171 clientSession .sessionToken .Values ["session-token" ] = loginState .sessionToken
172+ // AddSession already generated an ID, so update the cookie with it
173+ clientSession .refreshToken .Values ["refresh-token-id" ] = loginState .refreshTokenID
145174 } else {
146175 // loginState is a pointer to the cache so this effectively mutates it for everyone
147176 if err := loginState .UpdateTokens (tokenVerifier , tokenResponse ); err != nil {
148177 return nil , err
149178 }
179+ // Update the ID in the LoginState
180+ loginState .refreshTokenID = newRefreshTokenID
150181 }
151182
152183 // index by the old refresh token so that any follow-up requests that arrived
153184 // before their cookie was updated with an actual session can still find the login state
154- cs .serverStore .byRefreshToken [oldRefreshToken ] = loginState
185+ if oldRefreshToken != "" {
186+ cs .serverStore .byRefreshToken [oldRefreshToken ] = loginState
187+ }
155188 return loginState , clientSession .save (r , w )
156189}
157190
@@ -168,8 +201,14 @@ func (cs *CombinedSessionStore) DeleteSession(w http.ResponseWriter, r *http.Req
168201 }
169202
170203 cookieSession := cs .getCookieSession (r )
171- if refreshToken , ok := cookieSession .refreshToken .Values ["refresh-token" ]; ok {
172- cs .serverStore .DeleteByRefreshToken (refreshToken .(string ))
204+ if refreshTokenID , ok := cookieSession .refreshToken .Values ["refresh-token-id" ]; ok {
205+ refreshTokenIDStr := refreshTokenID .(string )
206+ // Look up the actual refresh token from the ID and delete
207+ if actualToken , exists := cs .serverStore .byRefreshTokenID [refreshTokenIDStr ]; exists {
208+ cs .serverStore .DeleteByRefreshToken (actualToken )
209+ // Clean up the ID mapping
210+ delete (cs .serverStore .byRefreshTokenID , refreshTokenIDStr )
211+ }
173212 }
174213
175214 if sessionToken , ok := cookieSession .sessionToken .Values ["session-token" ]; ok {
@@ -185,3 +224,9 @@ func (cs *CombinedSessionStore) DeleteSession(w http.ResponseWriter, r *http.Req
185224
186225 return nil
187226}
227+
228+ // ServerStore returns the underlying server session store.
229+ // This is primarily used for testing purposes.
230+ func (cs * CombinedSessionStore ) ServerStore () * SessionStore {
231+ return cs .serverStore
232+ }
0 commit comments