Skip to Content

Security API

The Security API provides tools for protecting the tenant against unauthorized access and malicious activity. Administrators can maintain IP allow/block lists, review suspicious login events, configure CAPTCHA verification, and manage account lockouts.

Auris evaluates security rules during every authentication attempt in this order: IP rules (block/allow) -> CAPTCHA verification -> rate limiting -> credential validation -> suspicious login analysis -> adaptive MFA. Each layer operates independently and can be configured separately.

IP Rules

IP rules define allow and block lists using CIDR notation. Block rules always take precedence over allow rules. Rules can be scoped to the entire tenant or to a specific application.

List IP Rules

GET/api/ip-rulesRequires: admin:all

List all IP allow/block rules configured for the tenant. Supports filtering by rule type, scope, and active status. Rules are ordered by creation date descending.

Query parameters

ParameterTypeDescription
typestringFilter by rule type: ALLOW or BLOCK
scopestringFilter by scope: TENANT or APPLICATION
isActivebooleanFilter by active status
searchstringSearch by CIDR, label, or note
applicationIdstringFilter rules scoped to a specific application
pageintegerPage number (default: 1)
limitintegerItems per page (default: 50, max: 100)

Success response

{ "success": true, "data": [ { "id": "ipr_abc123", "cidr": "203.0.113.0/24", "type": "BLOCK", "scope": "TENANT", "applicationId": null, "label": "Known bad actor range", "note": "Blocked after brute-force campaign on 2025-02-10", "isTemporary": true, "expiresAt": "2025-03-10T00:00:00Z", "isActive": true, "createdAt": "2025-02-10T14:30:00Z", "updatedAt": "2025-02-10T14:30:00Z" }, { "id": "ipr_def456", "cidr": "10.0.0.0/8", "type": "ALLOW", "scope": "TENANT", "applicationId": null, "label": "Corporate VPN", "note": "Internal network range", "isTemporary": false, "expiresAt": null, "isActive": true, "createdAt": "2025-01-15T09:00:00Z", "updatedAt": "2025-01-15T09:00:00Z" } ], "pagination": { "page": 1, "limit": 50, "total": 2, "totalPages": 1 } }

Create IP Rule

POST/api/ip-rulesRequires: admin:all

Create a new IP allow or block rule. CIDR notation is required — use /32 for a single IP address. Block rules always take precedence over allow rules during evaluation.

Request body

{ "cidr": "192.0.2.0/24", "type": "BLOCK", "scope": "TENANT", "label": "Datacenter range", "note": "Blocked due to automated scraping activity", "isTemporary": true, "expiresAt": "2025-04-01T00:00:00Z" }
FieldTypeRequiredDescription
cidrstringYesIP address or range in CIDR notation (e.g., 10.0.0.1/32, 192.168.0.0/16)
typestringYesALLOW or BLOCK
scopestringNoTENANT (applies to all apps) or APPLICATION (requires applicationId)
applicationIdstringNoRequired when scope is APPLICATION
labelstringNoHuman-readable label for the rule
notestringNoAdministrative note or reason
isTemporarybooleanNoWhether the rule expires automatically (default: false)
expiresAtstringNoISO 8601 expiry date. Required when isTemporary is true

Success response

{ "success": true, "data": { "id": "ipr_jkl012", "cidr": "192.0.2.0/24", "type": "BLOCK", "scope": "TENANT", "applicationId": null, "label": "Datacenter range", "note": "Blocked due to automated scraping activity", "isTemporary": true, "expiresAt": "2025-04-01T00:00:00Z", "isActive": true, "createdAt": "2025-02-18T10:00:00Z", "updatedAt": "2025-02-18T10:00:00Z" } }

Error codes

CodeHTTPDescription
VALIDATION_ERROR400Invalid CIDR notation, missing required fields, or invalid scope/type combination
DUPLICATE_RULE409A rule with the same CIDR and scope already exists

Temporary rules are automatically cleaned up after their expiresAt timestamp. You do not need to manually delete them.

Update IP Rule

PATCH/api/ip-rules/[id]Requires: admin:all

Update an existing IP rule. All fields are optional — only provided fields are updated. Changing the CIDR or type of a rule takes effect immediately for subsequent login attempts.

Request body

{ "label": "Updated label", "note": "Extended block after continued activity", "isActive": false }

Success response

{ "success": true, "data": { "id": "ipr_abc123", "cidr": "203.0.113.0/24", "type": "BLOCK", "scope": "TENANT", "applicationId": null, "label": "Updated label", "note": "Extended block after continued activity", "isTemporary": true, "expiresAt": "2025-03-10T00:00:00Z", "isActive": false, "createdAt": "2025-02-10T14:30:00Z", "updatedAt": "2025-02-18T10:30:00Z" } }

Error codes

CodeHTTPDescription
NOT_FOUND404IP rule does not exist
VALIDATION_ERROR400Invalid field value

Delete IP Rule

DELETE/api/ip-rules/[id]Requires: admin:all

Permanently delete an IP rule. The rule is removed immediately and will no longer be evaluated during authentication attempts.

Success response

{ "success": true }

Error codes

CodeHTTPDescription
NOT_FOUND404IP rule does not exist

IP Rule Statistics

GET/api/ip-rules/statsRequires: admin:all

Get statistics about IP rules configured for the tenant.

Success response

{ "success": true, "data": { "total": 12, "active": 10, "allow": 4, "block": 8, "temporary": 3 } }

Test IP Against Rules

POST/api/ip-rules/testRequires: admin:all

Test an IP address against the current set of rules and return the evaluation result. Useful for verifying rule configuration before applying it to production traffic.

Request body

{ "ip": "203.0.113.50", "applicationId": "app_prod001" }
FieldTypeRequiredDescription
ipstringYesIP address to test
applicationIdstringNoScope the evaluation to a specific application

Success response

{ "success": true, "data": { "allowed": false, "matchedRule": { "id": "ipr_abc123", "cidr": "203.0.113.0/24", "type": "BLOCK", "scope": "TENANT", "label": "Known bad actor range" } } }

Suspicious Login Events

Auris monitors login attempts for anomalous behavior using five detection methods: new device, new IP address, new country, impossible travel, and VPN/proxy usage. When suspicious activity is detected, an event is logged and the configured action is taken (log only, require MFA, or block).

List Suspicious Login Events

GET/api/suspicious-login/eventsRequires: admin:all

List suspicious login events across the tenant. Events are ordered by creation date descending. Use the reviewed filter to find events that need administrator attention.

Query parameters

ParameterTypeDescription
userIdstringFilter events for a specific user
severitystringFilter by severity: low, medium, high, critical
reasonstringFilter by detection reason: new_device, new_ip, new_country, impossible_travel, vpn_detected
reviewedbooleantrue for reviewed events, false for unreviewed
pageintegerPage number (default: 1)
limitintegerItems per page (default: 50, max: 100)

Success response

{ "success": true, "data": [ { "id": "sle_abc123", "userId": "usr_xyz789", "userEmail": "[email protected]", "reason": "impossible_travel", "severity": "high", "actionTaken": "require_mfa", "details": { "previousLocation": { "country": "Italy", "city": "Rome", "lat": 41.9028, "lng": 12.4964 }, "currentLocation": { "country": "Brazil", "city": "Sao Paulo", "lat": -23.5505, "lng": -46.6333 }, "distanceKm": 9187, "timeDiffMinutes": 45, "requiredSpeedKmh": 12249 }, "ipAddress": "198.51.100.42", "reviewed": false, "reviewedAt": null, "reviewedBy": null, "createdAt": "2025-02-18T09:15:00Z" } ], "pagination": { "page": 1, "limit": 50, "total": 47, "totalPages": 1 } }

Mark Event as Reviewed

POST/api/suspicious-login/events/[id]/reviewRequires: admin:all

Mark a suspicious login event as reviewed. This is an administrative acknowledgment and does not affect the user’s access. Use this to track which events have been investigated.

Success response

{ "success": true, "data": { "id": "sle_abc123", "reviewed": true, "reviewedAt": "2025-02-18T11:00:00Z", "reviewedBy": "usr_admin001" } }

Error codes

CodeHTTPDescription
NOT_FOUND404Event does not exist
ALREADY_REVIEWED400Event has already been marked as reviewed

Suspicious Login Statistics

GET/api/suspicious-login/statsRequires: admin:all

Get statistics about suspicious login events for the tenant.

Success response

{ "success": true, "data": { "totalEvents": 142, "unreviewedEvents": 12, "eventsLast24h": 8, "byReason": { "new_device": 45, "new_ip": 60, "new_country": 20, "impossible_travel": 10, "vpn_detected": 7 }, "bySeverity": { "low": 80, "medium": 40, "high": 18, "critical": 4 } } }

Get Detection Config

GET/api/suspicious-login/configRequires: admin:all

Retrieve the current suspicious login detection configuration for the tenant.

Success response

{ "success": true, "data": { "detectNewDevice": true, "detectNewIp": true, "detectNewCountry": true, "detectImpossibleTravel": true, "detectVpn": false, "actionOnNewDevice": "log", "actionOnNewIp": "log", "actionOnNewCountry": "require_mfa", "actionOnImpossibleTravel": "require_mfa", "actionOnVpn": "log", "maxTravelSpeedKmh": 900, "geoIpProvider": "ip-api", "updatedAt": "2025-02-01T12:00:00Z" } }
FieldTypeDescription
detectNewDevicebooleanFlag logins from previously unseen device fingerprints
detectNewIpbooleanFlag logins from previously unseen IP addresses
detectNewCountrybooleanFlag logins from a new country
detectImpossibleTravelbooleanFlag when consecutive logins are geographically impossible given the time elapsed
detectVpnbooleanFlag logins from known VPN/proxy/datacenter IPs
actionOn*stringAction to take: log (record only), require_mfa (force 2FA), block (deny access)
maxTravelSpeedKmhintegerSpeed threshold for impossible travel detection (default: 900 km/h)

Update Detection Config

PATCH/api/suspicious-login/configRequires: admin:all

Update the suspicious login detection configuration. All fields are optional. Changes take effect immediately for subsequent login attempts.

Request body

{ "detectVpn": true, "actionOnVpn": "require_mfa", "actionOnImpossibleTravel": "block", "maxTravelSpeedKmh": 1000 }

Success response

{ "success": true, "data": { "detectNewDevice": true, "detectNewIp": true, "detectNewCountry": true, "detectImpossibleTravel": true, "detectVpn": true, "actionOnNewDevice": "log", "actionOnNewIp": "log", "actionOnNewCountry": "require_mfa", "actionOnImpossibleTravel": "block", "actionOnVpn": "require_mfa", "maxTravelSpeedKmh": 1000, "geoIpProvider": "ip-api", "updatedAt": "2025-02-18T11:30:00Z" } }

Error codes

CodeHTTPDescription
VALIDATION_ERROR400Invalid action value or maxTravelSpeedKmh out of range (100-5000)

Setting actionOnImpossibleTravel or actionOnNewCountry to block can lock out legitimate users who travel frequently or use mobile networks. Consider using require_mfa instead, which adds a verification step without denying access entirely.

CAPTCHA

CAPTCHA verification adds a human challenge to authentication flows. Auris supports three providers: Cloudflare Turnstile, hCaptcha, and reCAPTCHA v3. CAPTCHA can be triggered on every attempt, only after suspicious activity, or after a configurable number of failed login attempts.

Verify CAPTCHA Token

POST/api/captcha/verify

Verify a CAPTCHA token against the tenant’s configured provider. This is a public endpoint — no authentication is required. It is called by client-side login flows immediately after the user completes the CAPTCHA challenge.

Request body

{ "token": "0.Abcd1234...", "action": "login", "tenantId": "ten_abc123" }
FieldTypeRequiredDescription
tokenstringYesCAPTCHA token returned by the provider’s widget
actionstringYesThe action being protected (e.g., login, register, reset)
tenantIdstringYesTenant identifier — used to look up the provider configuration

Success response

{ "success": true, "data": { "valid": true, "score": 0.9, "action": "login" } }

Error codes

CodeHTTPDescription
VALIDATION_ERROR400Missing token, action, or tenantId
CAPTCHA_FAILED422Token is invalid or score is below the configured threshold

CAPTCHA Verifications

GET/api/captcha/verificationsRequires: admin:all

List CAPTCHA verification attempts for the tenant, ordered by most recent first.

Query parameters

ParameterTypeDescription
successbooleanFilter by outcome: true for passed, false for failed
pageintegerPage number (default: 1)
limitintegerItems per page (default: 50, max: 100)

Success response

{ "success": true, "data": [ { "id": "cvr_abc123", "tenantId": "ten_abc123", "action": "login", "ipAddress": "203.0.113.50", "success": true, "score": 0.9, "createdAt": "2025-02-18T09:00:00Z" } ], "pagination": { "page": 1, "limit": 50, "total": 1240, "totalPages": 25 } }

CAPTCHA Statistics

GET/api/captcha/statsRequires: admin:all

Get CAPTCHA verification statistics for the last 24 hours.

Success response

{ "success": true, "data": { "totalLast24h": 850, "passedLast24h": 820, "failedLast24h": 30, "passRate": 0.965 } }

Get CAPTCHA Config

GET/api/captcha/configRequires: admin:all

Retrieve the current CAPTCHA configuration for the tenant.

Success response

{ "success": true, "data": { "provider": "CLOUDFLARE_TURNSTILE", "trigger": "ON_SUSPICIOUS", "siteKey": "0x4AAAAAAA...", "scoreThreshold": 0.5, "enableOnLogin": true, "enableOnRegister": true, "enableOnReset": false, "updatedAt": "2025-02-15T10:00:00Z" } }

The secretKey is never returned in API responses. It can only be set via the update endpoint.

Update CAPTCHA Config

PATCH/api/captcha/configRequires: admin:all

Update the CAPTCHA configuration. All fields are optional. Set provider to null to disable CAPTCHA entirely. The siteKey and secretKey must be valid for the selected provider.

Request body

{ "provider": "CLOUDFLARE_TURNSTILE", "trigger": "AFTER_FAILURES", "siteKey": "0x4AAAAAAA_your_site_key", "secretKey": "0x4AAAAAAA_your_secret_key", "scoreThreshold": 0.5, "enableOnLogin": true, "enableOnRegister": true, "enableOnReset": true }
FieldTypeDescription
providerstringCLOUDFLARE_TURNSTILE, HCAPTCHA, RECAPTCHA_V3, or null to disable
triggerstringALWAYS (every attempt), ON_SUSPICIOUS (after suspicious activity detected), AFTER_FAILURES (after N failed logins)
siteKeystringPublic site key from the CAPTCHA provider
secretKeystringSecret key from the CAPTCHA provider (write-only, never returned)
scoreThresholdnumberScore threshold for reCAPTCHA v3 (0.0 - 1.0, default: 0.5). Ignored for other providers
enableOnLoginbooleanEnable CAPTCHA on the login page
enableOnRegisterbooleanEnable CAPTCHA on the registration page
enableOnResetbooleanEnable CAPTCHA on the password reset page

Success response

{ "success": true, "data": { "provider": "CLOUDFLARE_TURNSTILE", "trigger": "AFTER_FAILURES", "siteKey": "0x4AAAAAAA_your_site_key", "scoreThreshold": 0.5, "enableOnLogin": true, "enableOnRegister": true, "enableOnReset": true, "updatedAt": "2025-02-18T12:00:00Z" } }

Error codes

CodeHTTPDescription
VALIDATION_ERROR400Invalid provider, missing siteKey/secretKey when provider is set, or scoreThreshold out of range

Account Lockouts

When a user exceeds the maxAttempts threshold configured in attack protection settings, their account is temporarily locked. Administrators can view locked accounts and manually unlock them.

List Locked Accounts

GET/api/attack-protection/lockoutsRequires: admin:all

List account lockout records for the tenant. By default returns only active (unresolved) lockouts. Use the resolved parameter to include previously resolved lockouts.

Query parameters

ParameterTypeDescription
resolvedbooleanfalse (default) for active lockouts only, true for resolved lockouts
pageintegerPage number (default: 1)
limitintegerItems per page (default: 50, max: 100)

Success response

{ "success": true, "data": [ { "id": "lock_abc123", "userId": "usr_xyz789", "email": "[email protected]", "reason": "brute_force", "lockedAt": "2025-02-18T09:00:00Z", "unlocksAt": "2025-02-18T09:30:00Z", "resolved": false } ], "pagination": { "page": 1, "limit": 50, "total": 2, "totalPages": 1 } }

Unlock Account

POST/api/attack-protection/lockouts/[id]/unlockRequires: admin:all

Immediately unlock a user account. The failed attempt counter is reset to zero. The user can attempt to log in again immediately after being unlocked.

Success response

{ "success": true, "data": { "unlocked": true, "userId": "usr_xyz789" } }

Error codes

CodeHTTPDescription
NOT_FOUND404User is not currently locked out

Account lockouts expire automatically based on the lockoutDurationMins configured in attack protection settings. Manual unlock is only needed when a legitimate user is locked out and cannot wait for the lockout to expire.

Attack Protection Configuration

GET/api/attack-protection/configRequires: admin:all

Retrieve the current attack protection configuration for the tenant, covering brute-force lockout, breached password checks, and suspicious IP blocking.

Success response

{ "success": true, "data": { "bruteForce": { "enabled": true, "maxAttempts": 10, "lockoutDurationMins": 30, "resetAfterMins": 60 }, "breachedPassword": { "enabled": false, "blockSeverity": "warn" }, "suspiciousIp": { "enabled": false, "maxFailedFromIp": 50, "blockDurationMins": 60 } } }
FieldTypeDescription
bruteForce.enabledbooleanEnable brute-force lockout protection
bruteForce.maxAttemptsintegerNumber of failed attempts before lockout
bruteForce.lockoutDurationMinsintegerHow long the lockout lasts (minutes)
bruteForce.resetAfterMinsintegerInactivity window that resets the failed attempt counter
breachedPassword.enabledbooleanCheck passwords against known-breached password databases (HIBP)
breachedPassword.blockSeveritystringblock (deny login), warn (alert user), or off
suspiciousIp.enabledbooleanBlock IPs with excessive failed attempts across the tenant
suspiciousIp.maxFailedFromIpintegerThreshold of failed attempts from one IP before blocking
suspiciousIp.blockDurationMinsintegerHow long the IP block lasts (minutes)
PATCH/api/attack-protection/configRequires: admin:all

Update the attack protection configuration. All fields are optional — only provided fields are merged. Changes take effect immediately for subsequent login attempts.

Request body

{ "bruteForce": { "maxAttempts": 5, "lockoutDurationMins": 15 }, "breachedPassword": { "enabled": true, "blockSeverity": "block" } }

Success response

{ "success": true, "data": { "bruteForce": { "enabled": true, "maxAttempts": 5, "lockoutDurationMins": 15, "resetAfterMins": 60 }, "breachedPassword": { "enabled": true, "blockSeverity": "block" }, "suspiciousIp": { "enabled": false, "maxFailedFromIp": 50, "blockDurationMins": 60 } } }

Login Attempts

GET/api/attack-protection/attemptsRequires: admin:all

List login attempts across the tenant, ordered by most recent first. Supports filtering by email, IP address, and success status.

Query parameters

ParameterTypeDescription
emailstringFilter attempts for a specific email address (partial match)
ipAddressstringFilter attempts from a specific IP address (exact match)
successbooleantrue for successful logins, false for failed attempts
pageintegerPage number (default: 1)
limitintegerItems per page (default: 50, max: 100)

Success response

{ "success": true, "data": [ { "id": "lat_abc123", "userId": "usr_xyz789", "email": "[email protected]", "ipAddress": "203.0.113.50", "userAgent": "Mozilla/5.0 ...", "success": false, "reason": "invalid_password", "createdAt": "2025-02-18T09:05:00Z" } ], "pagination": { "page": 1, "limit": 50, "total": 324, "totalPages": 7 } }

Attack Protection Statistics

GET/api/attack-protection/statsRequires: admin:all

Get attack protection statistics for the last 24 hours.

Success response

{ "success": true, "data": { "attemptsLast24h": 1240, "failedAttemptsLast24h": 87, "activeLockouts": 3, "blockedIps": 5 } }
FieldTypeDescription
attemptsLast24hintegerTotal login attempts in the last 24 hours
failedAttemptsLast24hintegerFailed login attempts in the last 24 hours
activeLockoutsintegerNumber of accounts currently locked out
blockedIpsintegerNumber of IPs blocked due to excessive failed attempts in the last 24 hours

Security Evaluation Order

During every authentication attempt, Auris evaluates security layers in this order:

  1. IP Rules — If the client IP matches a BLOCK rule, the request is denied immediately with 403 IP_BLOCKED.
  2. CAPTCHA — If CAPTCHA is configured and the trigger condition is met, the client must provide a valid CAPTCHA token.
  3. Rate Limiting — Sliding window rate limits are checked (configurable per tier).
  4. Credential Validation — Username/password or other credential verification via Keycloak.
  5. Brute Force / Lockout — Failed attempt counter is incremented. If threshold is reached, account is locked.
  6. Suspicious Login Analysis — Post-authentication analysis of device, IP, geography, and travel patterns.
  7. Adaptive MFA — Risk scoring may trigger step-up authentication if the risk score exceeds thresholds.

Each layer is independent and can be disabled without affecting the others.

Permissions Reference

PermissionDescription
admin:allManage IP rules, review suspicious login events, configure CAPTCHA, and unlock accounts

Security management operations are grouped under the admin:all permission. This ensures that only administrators with full administrative access can modify security settings that affect authentication for all users in the tenant.