@@ -1568,15 +1568,27 @@ func (server *ArgoCDServer) getClaims(ctx context.Context) (jwt.Claims, string,
15681568 return nil , "" , ErrNoSession
15691569 }
15701570 // A valid argocd-issued token is automatically refreshed here prior to expiration.
1571- // OIDC tokens will be verified but will not be refreshed here.
1571+ // OIDC tokens will be verified and reactively refreshed here if the ID token has expired .
15721572 claims , newToken , err := server .sessionMgr .VerifyToken (ctx , tokenString )
1573+ oidcConfig := server .settings .OIDCConfig ()
1574+ if err != nil && claims != nil && (oidcConfig != nil || server .settings .IsDexConfigured ()) {
1575+ // VerifyToken returns claims without sub/sid on expiry, parse JWT directly to recover sub/sid for refresh token cache lookup
1576+ expiredClaims := jwt.MapClaims {}
1577+ if _ , _ , parseErr := jwt .NewParser ().ParseUnverified (tokenString , expiredClaims ); parseErr == nil {
1578+ if refreshedToken , refreshErr := server .ssoClientApp .CheckAndRefreshToken (ctx , expiredClaims , server .settings .RefreshTokenThresholdWithConfig (oidcConfig )); refreshErr == nil && refreshedToken != "" {
1579+ if refreshedClaims , _ , vErr := server .sessionMgr .VerifyToken (ctx , refreshedToken ); vErr == nil {
1580+ claims , newToken , err = refreshedClaims , refreshedToken , nil
1581+ log .Infof ("refreshed token for subject: %v" , jwtutil .StringField (expiredClaims , "sub" ))
1582+ }
1583+ }
1584+ }
1585+ }
15731586 if err != nil {
15741587 span .SetStatus (otel_codes .Error , err .Error ())
15751588 return claims , "" , status .Errorf (codes .Unauthenticated , "invalid session: %v" , err )
15761589 }
15771590
15781591 finalClaims := claims
1579- oidcConfig := server .settings .OIDCConfig ()
15801592 if oidcConfig != nil || server .settings .IsDexConfigured () {
15811593 updatedClaims , err := server .ssoClientApp .SetGroupsFromUserInfo (ctx , claims , util_session .SessionManagerClaimsIssuer )
15821594 if err != nil {
0 commit comments