@@ -86,6 +86,7 @@ public function __construct(string $appName,
8686 /**
8787 * @PublicPage
8888 * @NoCSRFRequired
89+ * @BruteForceProtection(action=oauth2GetToken)
8990 *
9091 * @param string $grant_type
9192 * @param string $code
@@ -98,9 +99,11 @@ public function getToken($grant_type, $code, $refresh_token, $client_id, $client
9899
99100 // We only handle two types
100101 if ($ grant_type !== 'authorization_code ' && $ grant_type !== 'refresh_token ' ) {
101- return new JSONResponse ([
102+ $ response = new JSONResponse ([
102103 'error ' => 'invalid_grant ' ,
103104 ], Http::STATUS_BAD_REQUEST );
105+ $ response ->throttle (['invalid_grant ' => $ grant_type ]);
106+ return $ response ;
104107 }
105108
106109 // We handle the initial and refresh tokens the same way
@@ -111,17 +114,21 @@ public function getToken($grant_type, $code, $refresh_token, $client_id, $client
111114 try {
112115 $ accessToken = $ this ->accessTokenMapper ->getByCode ($ code );
113116 } catch (AccessTokenNotFoundException $ e ) {
114- return new JSONResponse ([
117+ $ response = new JSONResponse ([
115118 'error ' => 'invalid_request ' ,
116119 ], Http::STATUS_BAD_REQUEST );
120+ $ response ->throttle (['invalid_request ' => 'token not found ' , 'code ' => $ code ]);
121+ return $ response ;
117122 }
118123
119124 try {
120125 $ client = $ this ->clientMapper ->getByUid ($ accessToken ->getClientId ());
121126 } catch (ClientNotFoundException $ e ) {
122- return new JSONResponse ([
127+ $ response = new JSONResponse ([
123128 'error ' => 'invalid_request ' ,
124129 ], Http::STATUS_BAD_REQUEST );
130+ $ response ->throttle (['invalid_request ' => 'client not found ' , 'client_id ' => $ accessToken ->getClientId ()]);
131+ return $ response ;
125132 }
126133
127134 if (isset ($ this ->request ->server ['PHP_AUTH_USER ' ])) {
@@ -133,15 +140,18 @@ public function getToken($grant_type, $code, $refresh_token, $client_id, $client
133140 $ storedClientSecret = $ this ->crypto ->decrypt ($ client ->getSecret ());
134141 } catch (\Exception $ e ) {
135142 $ this ->logger ->error ('OAuth client secret decryption error ' , ['exception ' => $ e ]);
143+ // we don't throttle here because it might not be a bruteforce attack
136144 return new JSONResponse ([
137145 'error ' => 'invalid_client ' ,
138146 ], Http::STATUS_BAD_REQUEST );
139147 }
140148 // The client id and secret must match. Else we don't provide an access token!
141149 if ($ client ->getClientIdentifier () !== $ client_id || $ storedClientSecret !== $ client_secret ) {
142- return new JSONResponse ([
150+ $ response = new JSONResponse ([
143151 'error ' => 'invalid_client ' ,
144152 ], Http::STATUS_BAD_REQUEST );
153+ $ response ->throttle (['invalid_client ' => 'client ID or secret does not match ' ]);
154+ return $ response ;
145155 }
146156
147157 $ decryptedToken = $ this ->crypto ->decrypt ($ accessToken ->getEncryptedToken (), $ code );
@@ -154,9 +164,11 @@ public function getToken($grant_type, $code, $refresh_token, $client_id, $client
154164 } catch (InvalidTokenException $ e ) {
155165 //We can't do anything...
156166 $ this ->accessTokenMapper ->delete ($ accessToken );
157- return new JSONResponse ([
167+ $ response = new JSONResponse ([
158168 'error ' => 'invalid_request ' ,
159169 ], Http::STATUS_BAD_REQUEST );
170+ $ response ->throttle (['invalid_request ' => 'token is invalid ' ]);
171+ return $ response ;
160172 }
161173
162174 // Rotate the apptoken (so the old one becomes invalid basically)
0 commit comments