Match ends, Oxford United 1(5), Portsmouth 1(4).
Oxford United beat Portsmouth 5-4 on penalties to reach the League One play-off final as Cameron Brannagan's decisive spot-kick sent them to Wembley after a tense 2-2 draw on aggregate.
Oxford keeper Simon Eastwood saved from Cameron McGeehan to keep out Pompey's fourth penalty, with what was the only miss of the shootout, as the hosts netted five from five to stay in the promotion race.
The two sides could not be separated after 210 minutes of their hard-fought semi-final, drawing 1-1 at the Kassam Stadium to keep the tie level on aggregate and ensure it had to be decided with spot kicks.
Marcus Harness had put Kenny Jackett's men in front in with a good touch and low finish to complete a swift, route-one move but Ellis Harrison's own-goal deep in first-half stoppage time saw Oxford pull level.
Both sides had key chances to win the tie before the shootout but Eastwood and Brannagan became the heroes for Karl Robinson's men, who were jubilant at the end.
They go onto the final at Wembley on 13 July where they will face Wycombe, who drew their second leg 2-2 with Fleetwood to secure a 6-3 aggregate victory.
Victory kept alive Oxford's hopes of returning to the second tier for the first time since 1999, while Pompey's narrow defeat ensured they will face a ninth consecutive season playing below the Championship.
Monday's late drama saw the Hampshire club exit the play-offs at the semi-final stage for a second straight year, after their defeat by Sunderland over two legs in 2019.
Oxford and Pompey had been level on points in the table before the coronavirus pandemic saw football suspended in March, both sitting just two points off an automatic promotion place, and they were placed fourth and fifth respectively when the division was curtailed using an average points-per-game system.
And, just as they had been mathematically in the table, the two teams were extremely evenly matched across their two-legged semi-final.
Hero keeper Eastwood haunts former club
That changed at long last when Eastwood kept out McGeehan's spot-kick, which was struck to his right but at a nice height for the former Portsmouth goalkeeper, against his old side.
The match very nearly did not go beyond the normal 90 minutes, but Oxford's Robert Dickie headed narrowly off target in the final few seconds of second-half stoppage time, from James Henry's cross.
Pompey's John Marquis - who had hit the post in normal time - then nodded just wide in the second half of extra time, after United's Matty Taylor had seen a close-range shot bravely blocked by James Bolton in the first 15 additional minutes.
The hosts' Alex Gorrin was a little fortunate not to be sent off during the extra 30 minutes, receiving a yellow card for a rash-looking challenge, with his boot off the ground as he slid in on Andrew Cannon.
Earlier, the visitors had applied slightly more pressure on goal in the first half and led brilliantly on 38 minutes when Harrison expertly flicked on goalkeeper Alex Bass' long punt forward into Harness' path, the winger clinically netting his ninth goal of the campaign.
But Jackett's side's first-half endeavours were undone when Harrison inadvertently headed in to his own net from a corner on the stroke of half-time, getting in Bass' way amid what appeared to be a communication breakdown in the six-yard box.
That defensive lapse proved costly, in a tactical tie ultimately decide by the slimmest of margins.
How the shootout played out
Oxford 0-1 Portsmouth: John Marquis scored, sent keeper the wrong way
Oxford 1-1 Portsmouth: Ben Woodburn scored, down the middle
Oxford 1-2 Portsmouth: Gareth Evans scored, send keeper the wrong way
Oxford 2-2 Portsmouth: Anthony Forde scored, low in to the corner under the keeper's dive
Oxford 2-3 Portsmouth: Lee Brown scored, down the middle
Oxford 3-3 Portsmouth: Matty Taylor scored, finding the roof of the net
Oxford 3-3 Portsmouth: Cameron McGeehan's strike saved by Simon Eastwood
Oxford 4-3 Portsmouth: John Mousinho scored, down the middle
Oxford 4-4 Portsmouth: Oliver Hawkins scored, finding the bottom corner
Oxford 5-4 Portsmouth: Cameron Brannagan scored to send Oxford through
Oxford manager Karl Robinson:
"I'm just full of admiration for the players. We're in the final, what more can you say?
"When you think that I've had to sell my two best players in January and we came into this game with three or four struggling with injuries, it's incredible.
"I had asked a few people in the game who have been in big penalty shootouts for their advice, and they passed that on, and through our sports psychologist too who was telling the players to be composed and just believe in themselves.
"But for Oxford United to be in the final is unbelievable. Jamie Mackie's in tears in the dressing room, and he got me going too."
Portsmouth boss Kenny Jackett:
"I'm obviously very disappointed. We got our noses in front twice in the two matches and we've given away two sloppy goals.
"We've been able to take control by scoring the vital first goal but we've not been able to capitalise on it.
"We've been in the play-offs two years in a row now. We need to dust ourselves down, raise our standards and try to go one better next season and go up.
"And when training starts again we've got to make sure there is no hangover from this."
- 12LongBooked at 58minsSubstituted forWoodburnat 120'minutes
- 4DickieBooked at 91mins
- 17HenrySubstituted forFordeat 100'minutes
- 6GorrinBooked at 103minsSubstituted forMousinhoat 120'minutes
- 18SykesSubstituted forAgyeiat 85'minutes
- 19MackieSubstituted forTaylorat 63'minutesBooked at 107mins
- 30BrowneBooked at 73minsSubstituted forHansonat 86'minutes
- 13BoltonSubstituted forEvansat 120+1'minutes
- 42SeddonSubstituted forBrownat 60'minutes
- 7WilliamsSubstituted forHawkinsat 114'minutes
- 19HarnessSubstituted forCannonat 81'minutes
- 11CurtisBooked at 90mins
- 22HarrisonSubstituted forMarquisat 60'minutesBooked at 64mins
- Darren England
- Shots on Target
Penalty Shootout ends, Oxford United 1(5), Portsmouth 1(4).
Goal! Oxford United 1(5), Portsmouth 1(4). Cameron Brannagan (Oxford United) converts the penalty with a right footed shot to the bottom left corner.
Goal! Oxford United 1(4), Portsmouth 1(4). Oliver Hawkins (Portsmouth) converts the penalty with a right footed shot to the bottom right corner.
Goal! Oxford United 1(4), Portsmouth 1(3). John Mousinho (Oxford United) converts the penalty with a right footed shot to the centre of the goal.
Penalty saved! Cameron McGeehan (Portsmouth) fails to capitalise on this great opportunity, right footed shot saved in the bottom left corner.
Goal! Oxford United 1(3), Portsmouth 1(3). Matty Taylor (Oxford United) converts the penalty with a right footed shot to the high centre of the goal.
Goal! Oxford United 1(2), Portsmouth 1(3). Lee Brown (Portsmouth) converts the penalty with a left footed shot to the centre of the goal.
Goal! Oxford United 1(2), Portsmouth 1(2). Anthony Forde (Oxford United) converts the penalty with a right footed shot to the bottom left corner.
Goal! Oxford United 1(1), Portsmouth 1(2). Gareth Evans (Portsmouth) converts the penalty with a right footed shot to the bottom right corner.
Goal! Oxford United 1(1), Portsmouth 1(1). Ben Woodburn (Oxford United) converts the penalty with a right footed shot to the high centre of the goal.
Goal! Oxford United 1, Portsmouth 1(1). John Marquis (Portsmouth) converts the penalty with a right footed shot to the bottom right corner.
Penalty Shootout begins Oxford United 1, Portsmouth 1.
Second Half Extra Time ends, Oxford United 1, Portsmouth 1.
Substitution, Portsmouth. Gareth Evans replaces James Bolton.
Substitution, Oxford United. John Mousinho replaces Alex Rodriguez.
Substitution, Oxford United. Ben Woodburn replaces Sam Long.
Simon Eastwood (Oxford United) wins a free kick in the defensive half.
Foul by Oliver Hawkins (Portsmouth).
Offside, Portsmouth. Cameron McGeehan tries a through ball, but Oliver Hawkins is caught offside.