The hugely impressive Teimana Harrison and Mike Haywood both dotted down after the break to haul Jim Mallinder’s men back from a 14-0 deficit.
And Stephen Myler kept his cool from the tee to land a penalty and the conversion that won the match to the relief of the Franklin’s Gardens faithful.
Saints dominated the majority of the game, but they were struck by two smash and grab tries during the opening 20 minutes.
Jeff Williams took advantage of a slip from Harry Mallinder and a loss of possession by Luther Burrell to register a couple of opportunistic scores.
But Saints showed their fighting spirit as they kept knocking on the door, and Harrison, Haywood and Myler made sure they would get the win that took them up to fifth.
Mallinder’s side cannot make the top four now due to Leicester’s win against Worcester earlier in the day, but they have ensured they will remain in the top six going into the final game of the season, at Gloucester next Saturday.
Saints will hope to have Ben Foden available for that match after he was forced to withdraw before kick-off against Bath.
And the man who came in, Mallinder, was unfortunate to give Bath the opening try as his fall allowed Williams to dive over for the score.
Rhys Priestland added the conversion and Bath were soon over the line again as some dazzling footwork from Anthony Watson left Saints trailing.
But the try was ruled out for a forward pass from Jonathan Joseph in the build-up, giving Saints a huge let-off.
However, at the end of what was a bizarre opening 20 minutes, Williams was to score again for Bath.
Burrell lost the ball and after Joseph kicked ahead, Williams did likewise, chasing his own punt to score, to the delight of the visiting bench.
Priestland added the conversion to make it 14-0 in a gleeful opening period for the men in blue and white.
The home fans were growing increasingly agitated, while they and the coaching staff’s anger at the refereeing of the scrum was growing.
Saints finally got a penalty at the set piece 10 minutes before the break and they desperately tried to break Bath down.
The home side finally thought they had registered a minute before the break as Mallinder offloaded for North to put the ball down in the corner.
But Barnes went to the TMO and Sean Davey opted to disallow the try for a forward pass from Mallinder, prompting more boos.
Having been unable to take anything from the first half, Saints needed a strong start to the second, but they were hampered by an injury to Kieran Brookes.
However, Bath soon gave themselves a problem as scrum-half Chris Cook was yellow carded for a deliberate knock-on.
Saints tried to ramp up the pressure, but their lack of accuracy was costing them dear, allowing Bath to get off the hook.
But Saints finally got their try in the 57th minute as Harrison kept his composure to score in the corner.
Myler misses the conversion in a swirling wind, but he registered a penalty soon after to cut the gap to just six points with more than 17 minutes to go.
Bath threatened to extend their lead, but George Ford’s clever chip just evaded Williams, who had a hat-trick in his sights.
And Saints were soon back up the other end as Tom Wood bundled over the line, only to be held up when it mattered most.
But the appetite for a second try was soon sated as a lineout drive set up Haywood for the score.
Myler needed to hold his nerve with the conversion that would give his team the lead - and he did.
Bath, having been ahead for so long, had six minutes to respond at 15-14 down.
But they couldn’t do it and a huge roar rang around the Gardens as Myler booted the ball out to secure a superb comeback win for his side.
Saints: Mallinder; K Pisi, G Pisi (Wilson 59), Burrell, North; Myler, Dickson (c) (Fotuali’i 64); A Waller (Ma’afu 59), Haywood, Brookes (Hill 44); Lawes, Day (Matfield 59); Gibson, Wood, Harrison (Nutley 72).
Replacements not used: Marshall, Hanrahan.
Bath: Watson; Williams, Joseph, Devoto, Banahan; Priestland (Ford 62), Cook (W Homer 59); Catt (Auterac 55), Webber (Dunn 62), Wilson (Lahiff 55); Ewels, Attwood (Day 57); Garvey (Houston 64), Louw (c), Denton.
Referee: Wayne Barnes