Skip to main content
Account security starts with knowing when something looks wrong. Immutable tracks every login with IP geolocation, then uses alert rules to automatically flag suspicious patterns — logins from new countries, access at unusual hours, and brute force attempts. When an alert fires, your security team gets notified instantly via email or webhook.

Tracking Logins with Geolocation

Every event sent to Immutable is automatically enriched with IP geolocation data (country and city). Track login events to build a baseline of normal access patterns:
import { ImmutableClient } from "getimmutable";

const client = new ImmutableClient({
  apiKey: "imk_sk_a1b2c3d4e5f6g7h8i9j0",
  baseUrl: "https://getimmutable.dev",
});

await client
  .actor("user_5a3c8f", { name: "Jordan Mitchell", type: "user" })
  .session("sess_7b2d4e6f")
  .track("auth.login", "account", {
    login_method: "password",
    mfa_used: true,
    mfa_method: "totp",
    device: "Chrome 122 / macOS",
    tenant_id: "org_acme_corp",
  });
The event response includes automatically enriched geolocation:
{
  "id": "evt_9f3a2c1d-4b5e-6f7a-8b9c-0d1e2f3a4b5c",
  "actor_id": "user_5a3c8f",
  "actor_name": "Jordan Mitchell",
  "action": "auth.login",
  "ip_address": "198.51.100.42",
  "ip_country": "US",
  "ip_city": "San Francisco",
  "occurred_at": "2026-03-27T14:32:18.291034Z"
}
Also track failed login attempts — these are critical for detecting brute force attacks:
await client
  .actor("unknown", { name: "Unknown", type: "anonymous" })
  .track("auth.login_failed", "account", {
    attempted_email: "jordan@acmecorp.com",
    failure_reason: "invalid_password",
    attempt_number: 4,
  });

Configuring Alert Rules

New Country Alert

Triggers when an actor logs in from a country they haven’t been seen in before:
{
  "name": "Login from New Country",
  "rule_type": "new_country",
  "conditions": {
    "action_pattern": "auth.login"
  },
  "channels": ["email", "webhook"]
}
When Jordan — who normally logs in from the US — suddenly logs in from Romania, Immutable sends an alert immediately.

Off-Hours Alert

Triggers when logins occur outside of normal business hours:
{
  "name": "Off-Hours Login",
  "rule_type": "off_hours",
  "conditions": {
    "action_pattern": "auth.login",
    "timezone": "America/New_York",
    "start_hour": 22,
    "end_hour": 6
  },
  "channels": ["email", "webhook"]
}
A login at 3:17 AM Eastern triggers this alert, sending a notification to your security team.

Brute Force Detection with Repeated Action

Triggers when the same action occurs too many times in a short window:
{
  "name": "Brute Force Detection",
  "rule_type": "repeated_action",
  "conditions": {
    "action_pattern": "auth.login_failed",
    "threshold": 5,
    "window_minutes": 10
  },
  "channels": ["email", "webhook"]
}
Combine multiple alert rules for layered security. A new country login on its own might be a traveling employee. But a new country login at 3 AM with no MFA? That deserves immediate investigation.

Webhook Alert Payload

When an alert fires, Immutable sends a webhook to your configured endpoint. The payload includes the triggering event and alert context:
{
  "alert_id": "alt_8f3a2c1d",
  "rule_name": "Login from New Country",
  "rule_type": "new_country",
  "triggered_at": "2026-03-27T03:17:42.000000Z",
  "event": {
    "id": "evt_4b5e6f7a-8b9c-0d1e-2f3a-4b5c6d7e8f9a",
    "actor_id": "user_5a3c8f",
    "actor_name": "Jordan Mitchell",
    "action": "auth.login",
    "ip_address": "91.203.144.12",
    "ip_country": "RO",
    "ip_city": "Bucharest",
    "occurred_at": "2026-03-27T03:17:41.482910Z"
  },
  "context": {
    "previous_countries": ["US"],
    "new_country": "RO"
  }
}
The webhook includes an HMAC signature in the X-Immutable-Signature header for verification:
X-Immutable-Signature: sha256=a1b2c3d4e5f6...
Always verify the HMAC signature before processing webhook payloads. This prevents attackers from spoofing alert notifications.

Querying Alerts via API

Retrieve recent alerts to build a security dashboard or feed into your incident management system:
const alerts = await client.getAlerts({
  rule_type: "new_country",
  limit: 10,
});

alerts.data.forEach((alert) => {
  console.log(
    `${alert.triggered_at} | ${alert.rule_name} | ` +
    `${alert.event.actor_name} from ${alert.event.ip_country}`
  );
});

Full Security Monitoring Workflow

Here is the complete flow from login to investigation:
  1. Track all logins — both successful and failed, with session IDs
  2. Alert rules fire — new country, off-hours, and brute force detections run automatically
  3. Webhook delivers alert — your security team gets a Slack/PagerDuty notification
  4. Investigate via API — query the actor’s recent events to understand the full context
  5. Take action — lock the account, require MFA re-enrollment, or confirm it was legitimate
// Step 4: Investigate the flagged actor's recent activity
const recentActivity = await client.getEvents({
  actor_id: "user_5a3c8f",
  limit: 20,
});

// Check for other suspicious patterns
const suspiciousEvents = recentActivity.data.filter(
  (e) => e.ip_country !== "US" || e.action === "auth.login_failed"
);

console.log(`Found ${suspiciousEvents.length} suspicious events for user_5a3c8f`);
suspiciousEvents.forEach((e) => {
  console.log(`  ${e.occurred_at} | ${e.action} | ${e.ip_country} (${e.ip_city})`);
});

What’s Next

Alert Rules

Full reference for all alert rule types and configuration.

Geolocation

How IP geolocation enrichment works.

Webhook Signatures

Verify the authenticity of alert webhook payloads.

Activity Intelligence

Learn about the full alert rules engine and delivery system.