I've been looking into the oAuth 2 authorization framework for a while now. Yesterday I started wondering how to prevent a brute force attack during the Authorization Code Grant flow (https://www.rfc-editor.org/rfc/rfc6749#section-4.1). To clarify, the flow works as follows:
Browser sends a requests for a protected resource on an oAuth 2 client (
client.example.com
).Browser is redirected to the authorization endpoint on the authorization server:
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
with state being some kind of random string generated by the oAuth 2 client
Browser logs in on Authorization server
When correctly logged in, the browser is redirected back to the
redirect-uri
with some query parametershttps://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz
the state string should be the same as sent by the client, and the token a string generated, by the authorization server.
The client verifies whether the state parameter belongs to the session of the user agent (to prevent XSRF) and requests the access token from the authorization server using the
code
query parameter and basic authentication with the clients credentials:POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
It is possible for an attacker to repeat steps 2 and 4 over and over again, without actually logging in to the authorization server:
- Go to a restricted resource on
client.example.com
. - Parse the
state
request parameter in the redirect (and store the cookie/session id) - Try getting a token for
value1
by going to https://client.example.com/cb?code=value1&state=xyz (with cookie/session id received in 1)
Do this again and again for code=value2
, code=value3
, ...
Nothing stays the same in between two attempts of the attacker, which makes it hard for the authorization server to store a number of attempts and block after a certain number.
However, there is probably a small time window for the attacker to perform the attack, since the code is only valid on the server between steps 4 and 5 in the flow (except if the client crashes somewhere between 4 and 5).
Other then
- having a large code generated by the authorization server
- making the codes available only for a limited amount of time
is there anything else we can do to prevent the described attack?