redirects and their effect on browser history

By: Johnathon Wright on: August 31, 2023

I'm working on an app that asks for oauth permission from Google and other orgs.

The workflow for getting tokens to act as another user via oauth is:

  1. Get a key and a secret from the other party.
  2. redirect the user to the other party with parameters including your token and what you want permission to do. You also send back a 'redirect' url, where they will send the user when they're done with authorization.
  3. The other party authenticates the user and asks whether it's OK
  4. The other party redirects the user back to the 'redirect' url you provided along with (amongst other things) a "code".
  5. You exchange secrets (ie their code for their token). You do this by issuing a back-end request with your token, their code, your secret and some other things. You receive a token and some other stuff in return. Note that the code you sent can (hopefully) only be used once, and only for the purpose of exchanging it for a token. (but the token can be used repeatedly until it expires.)

In my app, I have some page where the user clicks on a button that says "connect me with Google" (or whomever)

I send them to a URL on my server... the "auth request" link (something like /partners/google/auth/request). This provides me the option of some visibility (ie I know how many people theoretically went to google vs how many came back). Also, if they previously exchanged tokens in another tab, I can have this URL just send them back ... "You already did that, move along."

I have the redirect go to a "auth grant" page (like /partners/google/auth/grant). The third party will send back a GET request with a code. Once I perform the secret exchange, I then redirect the user to some page in my app, presumably the page they were on when they requested access to the third party.

Because it isn't a POST (as it should be if you're going to be pedantic about resources), there's an issue. If a user clicks the "back" button, they go back to the "grant" page with the same code. This then triggers my app to try to re-request the token, which it can't because codes are single-use. I could track which codes were already used. I could also check again to see if the user has a grant and ignore, which I probably should. Still, I'd like to see if I can send a different kind of redirect that would remove the GET with the code from browser history. (This means if they click back they'll go back to the third party... in my fantasy world, I would have them go back to the page where this all started.)

List of every kind of redirect

type description does it change the history back button
300 Multiple Choice I saw the 'redirect' page but wasn't redirected.
301 moved permanently 3 elements in history ( new, index, final ) goes back to index
302 Found 3 elements in history ( new, index, final ) goes back to index
303 See Other 3 elements in history ( new, index, final ) goes back to index
304 Not Modified did nothing. I stayed on the index page?
307 Temporary Redirect 3 elements in history ( new, index, final ) goes back to index
308 Moved Permanently 3 elements in history ( new, index, final ) goes back to index
js redirect
meta HTML meta-element redirect

So all the redirects remove the redirecting page from history... so how was I able to cause this problem?


Looking at redirect_to, I can set the redirect status via parameter. I create a rails app that allows me to easily test:


Just checking that you are human. What would be the result of this code?

a = 3*(4/2); b = 1; a+b