Neymar carried then hosts Brazil to gold in Rio in 2016 but this time around it was Zenit St-Petersburg winger Malcom who came off the bench to fire home the decisive strike.
Spain had loaded their Olympic squad with players who also played in the Euros in a bid to win gold for the first time since 1992, but Brazil had the better of the first half.
They should have taken the lead from the spot but Richarlison blazed his effort over the crossbar.
Matheus Cunha did put Brazil ahead in stoppage time at the end of the first half, converting a pass from veteran Dani Alves – who played every minute of the tournament at the age of 38.
But Mikel Oyarzabal levelled the scores just after the hour after good work from Carlos Soler. The final went to extra time and Malcom won the gold with a crisp, low finish.