There are two things that everybody misses about OAuth and they fly under the radar.
Nice to hear someone touch on one of them: you absolutely NEED to use a transaction as a distributed locking mechanism when you use a token.
This goes double/quadruple for refresh tokens. Use the same token more than once, and that user is now signed out.
It doesn't matter if your system runs on one machine or N machines; if you have more than one request with a refresh token attached in flight at once - happens all the time - you are signing out users, often via 500.
Refresh tokens are one-time use.
The other thing devs and auth frameworks miss is the "state" parameter.
Too complicated, not suitable for everyday authentication in my opinion.
Seriously, the way auth in general is developing right now, I think we approach a point of insecurity through obscurity.
And with applications states, you need to adapt the application logic to authentication and the application then would have to check if someone maybe stole your refresh token.
Most systems implement a grace period for refresh token reuse for similar reasons. Transactions don’t really solve it. (Ex: You open two tabs quickly, hitting the server with the original refresh token twice)
Sorry, but that doesn't work in real world applications. Multiple requests are fired simultaneously all the time. E. g. browsers starting with multiple tabs, smartphone apps starting and firing multiple requests etc.
Nice to hear someone touch on one of them: you absolutely NEED to use a transaction as a distributed locking mechanism when you use a token.
This goes double/quadruple for refresh tokens. Use the same token more than once, and that user is now signed out.
It doesn't matter if your system runs on one machine or N machines; if you have more than one request with a refresh token attached in flight at once - happens all the time - you are signing out users, often via 500.
Refresh tokens are one-time use.
The other thing devs and auth frameworks miss is the "state" parameter.