Throttle the token endpoint per account and address, not per address
POST /api/v1/auth/token was limited to 6 requests a minute per IP. The deployed MCP server signs every user in from a single container, so under a per-IP budget one person's mistyped password, or a stranger's guesses, would lock every other user out of it. The named `auth-token` limiter keys on the lower-cased username (or the refresh token) plus the address, still 6 a minute, with a 30-a-minute ceiling per address to bound how many accounts one client can try. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -103,6 +103,38 @@ class TokenEndpointTest extends TestCase
|
||||
->assertJsonValidationErrors('grant_type');
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function one_account_exhausting_its_budget_does_not_lock_out_another_on_the_same_address(): void
|
||||
{
|
||||
// Everyone the MCP server signs in arrives from its one container.
|
||||
// Registered first so it wins over fakePireon()'s token stub, which
|
||||
// would otherwise accept every password.
|
||||
Http::fake(["{$this->pireonServer}/oauth/token" => fn ($request) => $request['username'] === 'ada@example.com'
|
||||
? Http::response(['access_token' => 'fake-access-token', 'token_type' => 'Bearer', 'expires_in' => 3600])
|
||||
: Http::response(['error' => 'invalid_grant'], 400)]);
|
||||
$this->fakePireon();
|
||||
|
||||
foreach (range(1, 6) as $attempt) {
|
||||
$this->postJson('/api/v1/auth/token', [
|
||||
'grant_type' => 'password',
|
||||
'username' => 'mallory@example.com',
|
||||
'password' => "guess-{$attempt}",
|
||||
])->assertStatus(422);
|
||||
}
|
||||
|
||||
$this->postJson('/api/v1/auth/token', [
|
||||
'grant_type' => 'password',
|
||||
'username' => 'MALLORY@example.com',
|
||||
'password' => 'guess-7',
|
||||
])->assertTooManyRequests();
|
||||
|
||||
$this->postJson('/api/v1/auth/token', [
|
||||
'grant_type' => 'password',
|
||||
'username' => 'ada@example.com',
|
||||
'password' => 'secret',
|
||||
])->assertOk();
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function repeated_calls_with_the_same_token_hit_the_identity_server_once(): void
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user