Protecting Your Users

This chapter assumes that you have completed the Baseline Integration.

Intro to Account Recovery

Denying malicious login attempts is a great starting point, but if you are concerned about protecting your users, it is important to support them through an Account Recovery process. Whenever you deny a $login.succeeded event, we can make the assumption that a bad actor has gained access to your user's credentials. Therefore, in order to fully protect your users, it's key that you take additional steps on top of blocking an event inline.

A complete Account Recovery process would include the following:

  1. Lock the user's account
  2. Alert the user that malicious activity was detected
  3. Direct them to a Password Reset flow
  4. Unlock your user's account

Automating this Account Recovery flow is an effective way of letting your users resolve their own risky activity without manual involvement of analysts or support personnel.

This guide is for building an automated Account Recovery flow by subscribing to Castle's $incident.confirmed webhook and hosting your own email delivery and password reset flow.

Step 1. Subscribe to Incident Webhooks

To get started, head over to the webhook settings in the Castle Dashboard and subscribe to the $incident.confirmed event. This event will be triggered whenever the risk of a device exceeds 90, and will only trigger once per device.

Here is an example of the payload delivered in an $incident.confirmed webhook:

Sample Payload - Incident webhook

  "api_version": "v1",
  "app_id": "382395555537961",
  "type": "$incident.confirmed",
  "created_at": "2018-06-01T19:38:28.483Z",
  "data": {
    "id": "test",
    "device_token": "eyJhbGciOiJI1NiJ9.eyJ0b2tlbiI6InRlc3QiLCJzaW9uIjowLjF9._-0l6TlDH7m78l19z1amMQ02m7s",
    "user_id": "2",
    "trigger": "$login.succeeded",
    "context": {
      "ip": "",
      "isp": {
        "isp_name": "CastleNet",
        "isp_organization": "Castle"
      "location": {
        "country_code": "US",
        "country": "United States",
        "region": "California",
        "region_code": "CA",
        "city": "San Francisco",
        "lat": 37.8019832,
        "lon": -122.3870544
      "user_agent": {
        "raw": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko)",
        "browser": "Chrome",
        "version": "42.0.2311",
        "os": "Mac OS X 10.9.5",
        "mobile": false,
        "platform": "Mac OS X",
        "device": "Unknown",
        "family": "Chrome"

Handling the Incident Webhook

Whenever you receive a webhook, first check the type to determine if it is $incident.confirmed. If it is, you will want to begin Account Recovery process. You should immediately lock the user's account.

In the wehbook's payload, locate the user_id within the data object. For this user, you should immediately log them out of any active sessions and lock/put a hold on their account.

Note: If you don't have any way to "lock" an account, you can reset their password. This will effectively secure the account and make sure any attackers that had access to their previous credentials can not take further action.

Step 2. Alert the User

Next, you need to alert the user that malicious activity was detected, and encourage them to reset their password in order to recover/unlock their account.

You can parse the data in the payload of the webhook in order to customize an email to your user. Here is an example of an email that you could send your user:

Sample Password Reset Email

Review email

Note: We recommend providing details about the device and location that triggered the incident. This provides evidence to the account owner that the triggering activity was not their own, and will further encourage them to take swift action in resetting their password.

Step 3. Track Password Resets

In the email example above, when the user clicks on the "Reset your password" button, direct them to a Password Reset flow hosted on your website.

Once the user saves their new password, track a $password_reset.succeeded event to Castle from your backend. This will inform Castle that this user has recovered their account, lowering the user's risk score.

Example Request

  event: '$password_reset.succeeded',
        'event': '$password_reset.succeeded',
    'event' => '$password_reset.succeeded',
    'user_id' => $user->id
castle.Track(new ActionRequest()
    Event = "$password_reset.succeeded",
    UserId = userId
curl \
  -X POST \
  -H "Content-Type: application/json" \
  -d '
      "event": "$password_reset.succeeded",
      "user_id": "1234",
      "context": {
        "client_id": "a97b492d-dcc3-4fc1-87d6-65682955afa5",
        "ip": "",
        "headers": {
          "User-Agent": "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko",
          "Accept": "text/html",
          "Accept-Language": "en-us,en;q=0.5"

Important: It is important to enforce that the user resets their password to something new. Do not let them resave their old password, as we know it has already been compromised.

Reinstate your users account

Now that your user has reset their password, you can unlock their account. Castle will continue to monitor this user's behavior and apply adaptive risk scores as we did before the incident occured. There are no further steps needed.

Note: After a password reset, devices that triggered an incident will still be visible in the dashboard for that user, but they will marked as "Mitigated".

Congratulations, you have automated the Account Recovery process!