At one stage on the final climb Thomas looked dead and buried as Contador and Richie Porte surged off the front of the small front group, but the Welshman recovered 30 seconds in the descent to deny the Spaniard his third Paris-Nice win.
Tim Wellens (Lotto-Soudal) took the stage win, having been out in the break all day and then worked with Contador and Porte in the final kilometres to stay at the head of the race.
Contador put on a tactical masterclass as attacked from 50km out, with the benefit of two teammates in the breakaway up the road to work with. But the depleted Team Sky squad worked hard on the front of the peloton to bring the small escape group back at kilometre 26.
On to the Col d'Eze and Contador tried his luck as his last domestique Rafal Majka ran out of gas. Thomas and Team Sky couldn't hold on to the wheel of the attackers, but Contador was quickly brought back by Orica-GreenEdge.
Contador attacked on the final climb several times but the group reconnected each time, and although Thomas didn't look to be on great form at the end of a tough race he had Sergio Henao on hand to bring the Spaniard back.
Thomas finally cracked in the last kilometre of the climb as Contador and Majka pulled away up the road. Richie Porte bridged across to the Contador group as the Welshman slipped further back.
But the Sky rider wasn't dead and buried. As Porte and Contador sped down the other side of the Col d'Eze, Thomas worked with Henao and Tony Gallopin (Lotto-Soudal) to pull back a 30-second deficit as they reached sea level in Nice.
As Wellens sprinted past Contador for the stage win, Thomas nestled himself in a group of riders who crossed the line just five seconds down on the Spaniard to seal the general classification.
The win is Thomas's second of the season, having also beaten Contador at the Volta ao Algarve in February, and is the Welshman's fifth stage race win of his career.
Paris-Nice stage seven, Nice-Nice (141km)
1. Tim Wellens (Bel) Lotto-Soudal, 3-16-09
2. Alberto Contador (Esp) Tinkoff, st
3. Richie Porte (Aus) BMC, st
4. Tony Gallopin (Fra) Lotto-Soudal, at 5 secs
5. Simon Yates (GBr) Orica-GreenEdge, st
6. Arnold Jeannesson (Fra) Cofidis, st
7. Rui Costa (Por) Lampre-Merida, st
8. Jesus Herrada (Esp) Movistar, st
9. Romain Bardet (Fra) Ag2r La Mondiale, st
10. Ion Izagirre (Esp) Movistar, st
Final standings after stage seven
1. Geraint Thomas (GBr) Team Sky, 27-26-40
2. Alberto Contador (Esp) Tinkoff, at 4s
3. Richie Porte (Aus) BMC, at 12s
4. Ilnur Zakarin (Rus) Katusha, at 20s
5. Ion Izagirre (Esp) Movistar, at 37s
6. Sergio Henao (Col) Team Sky, at 44s
7. Simon Yates (GBr) Orica-GreenEdge, st
8. Tony Gallopin (Fra) Lotto-Soudal, at 51s
9. Romain Bardet (Fra) Ag2r La Mondiale, at 1-00
10. Rui Costa (Por) Lampre-Merida, 1-07
Thank you for reading 20 articles this month* Join now for unlimited access
Enjoy your first month for just £1 / $1 / €1
*Read 5 free articles per month without a subscription
Join now for unlimited access
Try first month for just £1 / $1 / €1