In Section 4.1.2 of the OAuth 2.0 spec, there is the following set of sentences:
The authorization code MUST expire shortly after it is issued to mitigate the risk of leaks. A maximum authorization code lifetime of 10 minutes is RECOMMENDED. The client MUST NOT use the authorization code more than once. If an authorization code is used more than once, the authorization server MUST deny the request and SHOULD revoke (when possible) all tokens previously issued based on that authorization code.
My question is why must the authorization code be used only once? This seems to force implementers of the authorization server to use an ACID database, which introduces scalability issues. Relaxation of this constraint would allow storage to be dispensed with completely.
I can see that allowing re-use of the auth codes would mean that if a malicious agent could get hold of an unexpired code, they could gain access to the protected resource. But OAuth 2.0 mandates TLS for some transactions and recommends it for all, which reduces the risk of code theft, and assuming that there is an agent which can listen on the channel this requirement introduces the possibility of denial of service (the agent could simply submit any auth code they found.) DoS can be a greater or lesser threat than breach of confidentiality, depending on the circumstances.
Hope this will helpful to find a reason for your question: The authorization process utilizes two authorization server endpoints (HTTP resources):
o Authorization endpoint - used by the client to obtain authorization from the resource owner via user-agent redirection.
o Token endpoint - used by the client to exchange an authorization code for an access token, typically with client authentication. Reference
Also as per Sec 3.2.1
Client authentication is critical when an authorization code is transmitted to the redirection endpoint over an insecure channel or when the redirection URI has not been registered in full.
Reference
To achieve the above it follows five step
The flow illustrated in Figure includes the following steps:
(A) The client initiates the flow by directing the resource owner's user-agent to the authorization endpoint. The client includes its client identifier, requested scope, local state, and a redirection URI to which the authorization server will send the user-agent back once access is granted (or denied).
(B) The authorization server authenticates the resource owner (via the user-agent) and establishes whether the resource owner grants or denies the client's access request.
(C) Assuming the resource owner grants access, the authorization server redirects the user-agent back to the client using the redirection URI provided earlier (in the request or during client registration). The redirection URI includes an authorization code and any local state provided by the client earlier.
(D) The client requests an access token from the authorization server's token endpoint by including the authorization code received in the previous step. When making the request, the client authenticates with the authorization server. The client includes the redirection URI used to obtain the authorization code for verification.
(E) The authorization server authenticates the client, validates the authorization code, and ensures that the redirection URI received matches the URI used to redirect the client in step (C). If valid, the authorization server responds back with an access token and, optionally, a refresh token.
The authorization code is delivered to the client through user's agent (e.g. web browser). This poses certain threats (e.g. applications might be susceptible to XSS or other attacks) possibly enabling attackers to steal the token. Also, the OAuth 2.0 library doesn't mandate usage of SSL/TLS in communication between user agent and authorization server, it's only recommended as "SHOULD", so token could possibly be stolen from transport:
The transmission of authorization codes SHOULD be made over a secure channel, and the client SHOULD require the use of TLS with its redirection URI if the URI identifies a network resource.
Making validity of the authorization code limited partly mitigates these threats, as the attacker needs to perform whole attack in a limited timeframe and must succeed in preventing the original requestor from exchanging the code (this would make subsequent attempts done by the attacker futile because the token has already been used).
Possible DOS attacks can be mitigated by regular rotation of client credentials, or their change in case of a suspected attack - as anyone who wants to exchange authorization code for access token still needs to be able to provide client credentials when doing so (with exception of public clients of course). These credentials MUST be presented to the authorization server over TLS, so attackers may not be able to sniff them in the same way as the authorization code.
The OAuth 2.0 also covers your use case. In case you need to be able to obtain multiple access tokens throughout lifecycle of your application you should use refresh tokens.
Refresh tokens are typically issued and delivered to your application together with the access token in the same flow. You can see the refresh token as an "authorization code with long validity". The spec says:
Because refresh tokens are typically long-lasting credentials used to request additional access tokens, the refresh token is bound to the client to which it was issued.
It's definitely preferable to store the refresh tokens on the server side (e.g. with an ACID database as you state), but no one can prevent you from using e.g. a secure cookie for this purpose and avoid server-side storage altogether.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With