(Q1) I’m not overly familiar with that sample, but if it follows the option described in your first link it is acceptable. I have a hard time in providing definitive recommendation myself because what it’s optimal for scenario A may not be for scenario B so depending on how you use them both the option on including the URL in the state itself and including the URL on session and then using it seem fine.
The real definitive recommendations around this situation are (in my opinion):
- you need to protect your OAuth redirection endpoint against CSRF attacks (usually done through the random value present in
state
and then validating that the received state matches the one the current session expects. - you need to validate any data that can be provided/modified by end-users.
(Q2) If you prefer to store the final redirection URL in session then you just need to verify the state so that you know the current response is associated with that URL. As you said you, in this manner you don’t need to include the URL in state.
(Q3) If the source of the final redirection URL is server-side storage which an end-user cannot modify/control in some way then you can implicitly trust it and perform no additional validation.
Personally, I would tend to consider the approach where you generate state from random data coming from a cryptographically secure pseudo-random number generator and then also include the final redirection URL to create a composed value. In addition, you could hash the complete representation of the state and associate the hash to the current session (for a regular web application could be done through a secure HTTP-Only cookie so you would not even have to technically keep anything on server-side storage). Upon receiving the response you would again hash the received state, validate that it matches the one associated with the current session and proceed to use the return URL. Have in mind that with a simple hash anyone that can access and control secure HTTP-Only cookies can modify both the hash and the state. You could upgrade from a simple hash to a keyed hash (MAC) to ensure that no one besides your server-side could have generated the values.
All of the above seems a bit to much when compared to just store the URL server-side and don’t let anyone know/control it, but you do get the nice benefit of not actually having to store per transaction state on your server-side which is a nice thing considering that this transaction state can be created by non-authenticated users .