@@ -191,55 +191,54 @@ func handleRefreshTokenExchange(c *gin.Context) {
191191 return
192192 }
193193
194- entityID , _ := claims ["sub" ].(string )
195- scope , _ := claims ["scope" ].(string )
196-
197- if ! service .ScopesContain (scope , "refresh_token" ) {
194+ refreshClaims , err := parseRefreshTokenClaims (claims , clientID )
195+ if err != nil {
198196 c .JSON (http .StatusUnauthorized , gin.H {"error" : "provided token is not a refresh token" })
199197 return
200198 }
201199
202- // Revoke the old refresh token
203- if tokenID , ok := claims ["jti" ].(string ); ok {
204- sentinel .Delete ("/api/core/token/" + tokenID , nil )
200+ if err := sentinel .Delete ("/api/core/token/" + refreshClaims .TokenID , nil ); err != nil {
201+ logger .SugarLogger .Errorf ("Failed to revoke OAuth refresh token %s: %v" , refreshClaims .TokenID , err )
202+ c .JSON (http .StatusBadGateway , gin.H {"error" : "failed to rotate refresh token" })
203+ return
205204 }
206205
207206 // Re-check the gate on refresh — group membership may have changed
208207 // since the original grant. If the user no longer qualifies, the
209208 // refresh fails and they have to re-authenticate (which will hit the
210209 // gate again at the authorize step).
211- if err := service .CheckAccessGate (entityID , clientID ); err != nil {
210+ if err := service .CheckAccessGate (refreshClaims . EntityID , clientID ); err != nil {
212211 writeGateError (c , err )
213212 return
214213 }
215214
216215 // Strip refresh_token from scope for the access token
217- accessScope := service .RemoveScope (scope , "refresh_token" )
216+ accessScope := service .RemoveScope (refreshClaims . Scope , "refresh_token" )
218217
219- newClaims , err := service .BuildTokenClaims (entityID , clientID , accessScope )
218+ newClaims , err := service .BuildTokenClaims (refreshClaims . EntityID , clientID , accessScope )
220219 if err != nil {
221220 logger .SugarLogger .Errorf ("Failed to build token claims: %v" , err )
222221 c .JSON (http .StatusBadGateway , gin.H {"error" : "server_error" })
223222 return
224223 }
225224
226225 // Generate new access token
227- accessToken , accessTokenID , err := generateToken (entityID , clientID , accessScope , config .AccessTokenTTL , newClaims )
226+ accessToken , accessTokenID , err := generateToken (refreshClaims . EntityID , clientID , accessScope , config .AccessTokenTTL , newClaims )
228227 if err != nil {
229228 c .JSON (http .StatusInternalServerError , gin.H {"error" : "failed to generate access token" })
230229 return
231230 }
232231
233232 // Generate new refresh token (keep refresh_token in scope)
234- newRefreshToken , newRefreshTokenID , err := generateToken (entityID , clientID , scope , config .RefreshTokenTTL , newClaims )
233+ newRefreshToken , newRefreshTokenID , err := generateToken (refreshClaims . EntityID , clientID , refreshClaims . Scope , config .RefreshTokenTTL , newClaims )
235234 if err != nil {
236235 logger .SugarLogger .Errorf ("Failed to generate refresh token: %v" , err )
237236 newRefreshToken = ""
238237 newRefreshTokenID = ""
239238 }
240239
241240 sentinel .Post ("/api/core/entity/logins" , map [string ]string {
242- "entity_id" : entityID ,
241+ "entity_id" : refreshClaims . EntityID ,
243242 "client_id" : clientID ,
244243 "scope" : accessScope ,
245244 "access_token_id" : accessTokenID ,
@@ -253,13 +252,13 @@ func handleRefreshTokenExchange(c *gin.Context) {
253252 // carried forward.
254253 var idToken string
255254 if service .ScopesContain (accessScope , "openid" ) {
256- idClaims , idErr := service .BuildIDTokenClaims (entityID , clientID , accessScope , "" , accessToken , time .Now ().Unix ())
255+ idClaims , idErr := service .BuildIDTokenClaims (refreshClaims . EntityID , clientID , accessScope , "" , accessToken , time .Now ().Unix ())
257256 if idErr != nil {
258257 logger .SugarLogger .Errorf ("Failed to build id token claims: %v" , idErr )
259258 c .JSON (http .StatusBadGateway , gin.H {"error" : "server_error" })
260259 return
261260 }
262- idToken , _ , err = generateToken (entityID , clientID , accessScope , config .AccessTokenTTL , idClaims )
261+ idToken , _ , err = generateToken (refreshClaims . EntityID , clientID , accessScope , config .AccessTokenTTL , idClaims )
263262 if err != nil {
264263 logger .SugarLogger .Errorf ("Failed to generate id token: %v" , err )
265264 idToken = ""
0 commit comments