Merge pull request #4544 from Infisical/lockout-improvements

optimized UA login for higher throughput
This commit is contained in:
x032205
2025-09-17 14:42:01 -04:00
committed by GitHub
2 changed files with 154 additions and 146 deletions
@@ -84,23 +84,6 @@ export const identityUaServiceFactory = ({
const LOCKOUT_KEY = `lockout:identity:${identityUa.identityId}:${IdentityAuthMethod.UNIVERSAL_AUTH}:${clientId}`; const LOCKOUT_KEY = `lockout:identity:${identityUa.identityId}:${IdentityAuthMethod.UNIVERSAL_AUTH}:${clientId}`;
let lock: Awaited<ReturnType<typeof keyStore.acquireLock>> | undefined;
if (identityUa.lockoutEnabled) {
try {
lock = await keyStore.acquireLock([KeyStorePrefixes.IdentityLockoutLock(LOCKOUT_KEY)], 500, {
retryCount: 3,
retryDelay: 300,
retryJitter: 100
});
} catch (e) {
logger.info(
`identity login failed to acquire lock [identityId=${identityUa.identityId}] [authMethod=${IdentityAuthMethod.UNIVERSAL_AUTH}]`
);
throw new RateLimitError({ message: "Failed to acquire lock: rate limit exceeded" });
}
}
try {
const lockoutRaw = await keyStore.getItem(LOCKOUT_KEY); const lockoutRaw = await keyStore.getItem(LOCKOUT_KEY);
let lockout: LockoutObject | undefined; let lockout: LockoutObject | undefined;
@@ -140,13 +123,31 @@ export const identityUaServiceFactory = ({
if (!validClientSecretInfo) { if (!validClientSecretInfo) {
if (identityUa.lockoutEnabled) { if (identityUa.lockoutEnabled) {
if (!lockout) { let lock: Awaited<ReturnType<typeof keyStore.acquireLock>> | undefined;
try {
lock = await keyStore.acquireLock([KeyStorePrefixes.IdentityLockoutLock(LOCKOUT_KEY)], 300, {
retryCount: 3,
retryDelay: 300,
retryJitter: 100
});
// Re-fetch the latest lockout data while holding the lock
const lockoutRawNew = await keyStore.getItem(LOCKOUT_KEY);
if (lockoutRawNew) {
lockout = JSON.parse(lockoutRawNew) as LockoutObject;
} else {
lockout = { lockout = {
lockedOut: false, lockedOut: false,
failedAttempts: 0 failedAttempts: 0
}; };
} }
if (lockout.lockedOut) {
throw new UnauthorizedError({
message: "This identity auth method is temporarily locked, please try again later"
});
}
lockout.failedAttempts += 1; lockout.failedAttempts += 1;
if (lockout.failedAttempts >= identityUa.lockoutThreshold) { if (lockout.failedAttempts >= identityUa.lockoutThreshold) {
lockout.lockedOut = true; lockout.lockedOut = true;
@@ -157,10 +158,24 @@ export const identityUaServiceFactory = ({
lockout.lockedOut ? identityUa.lockoutDurationSeconds : identityUa.lockoutCounterResetSeconds, lockout.lockedOut ? identityUa.lockoutDurationSeconds : identityUa.lockoutCounterResetSeconds,
JSON.stringify(lockout) JSON.stringify(lockout)
); );
} catch (e) {
if (lock === undefined) {
logger.info(
`identity login failed to acquire lock [identityId=${identityUa.identityId}] [authMethod=${IdentityAuthMethod.UNIVERSAL_AUTH}]`
);
throw new RateLimitError({ message: "Failed to acquire lock: rate limit exceeded" });
}
throw e;
} finally {
if (lock) {
await lock.release();
}
}
} }
throw new UnauthorizedError({ message: "Invalid credentials" }); throw new UnauthorizedError({ message: "Invalid credentials" });
} else if (lockout) { } else if (lockout) {
// If credentials are valid, clear any existing lockout record
await keyStore.deleteItem(LOCKOUT_KEY); await keyStore.deleteItem(LOCKOUT_KEY);
} }
@@ -258,9 +273,6 @@ export const identityUaServiceFactory = ({
identityMembershipOrg, identityMembershipOrg,
...accessTokenTTLParams ...accessTokenTTLParams
}; };
} finally {
if (lock) await lock.release();
}
}; };
const attachUniversalAuth = async ({ const attachUniversalAuth = async ({
@@ -40,14 +40,10 @@ To interact with various resources in Infisical, Machine Identities can authenti
## Identity Lockout ## Identity Lockout
Lockout is a feature that prevents brute-force attacks on identity login endpoints. Auth methods that support lockout include: [Universal Auth](/documentation/platform/identities/universal-auth). Lockout is a feature that prevents brute-force attacks on identity login endpoints. Auth methods that support lockout include: [Universal Auth](/documentation/platform/identities/universal-auth), [LDAP Auth](/documentation/platform/identities/ldap-auth/general).
Supported auth methods have lockout enabled by default. If triggered, lockout temporarily disables the login endpoint for 5 minutes after 3 consecutive failed login attempts within a 30-second window. Lockout can be configured and disabled in the identity auth method settings. Supported auth methods have lockout enabled by default. If triggered, lockout temporarily disables the login endpoint for 5 minutes after 3 consecutive failed login attempts within a 30-second window. Lockout can be configured and disabled in the identity auth method settings.
<Warning>
When Lockout is enabled, a rate limit of approximately 10 requests per second is enforced on relevant authentication endpoints. This security measure employs a protective lock to mitigate parallel login attacks. If this rate limitation interferes with your operational requirements, you may consider disabling Lockout.
</Warning>
## FAQ ## FAQ
<AccordionGroup> <AccordionGroup>