Blocking Events

Blocking events are triggered before the operation is performed.

Blocking events are triggered before the operation is performed, such as before user creation. This allow you to abort or alter the operations programmatically.

They are delivered to your hooks synchronously, right before changes are persisted to the database.

The list of events:

Your hooks must return a JSON document to indicate whether the operation should continue. For example, to let the operation proceed, return the following JSON:

{
  "is_allowed": true
}

Each of your hooks must respond within 5 seconds. All of your hooks must complete within 10 seconds. Otherwise, the delivery will fail to due timeout.

Supported fields in the JSON response:

Parameter
Description
Supported Blocking events

is_allowed

Allow or abort the current operation

All blocking events

reason

(When is_allowed is false) A human-readable explanation for rejecting the operation. This will be shown in the UI.

All blocking events

title

(When is_allowed is false) A human-readable title for rejecting the operation. This will be shown in the UI.

All blocking events

mutation

Mutate the object in the Event payload.

user.pre_create user.profile.pre_update user.pre_schedule_deletion user.pre_schedule_anonymization oidc.jwt.pre_create

constraints

Apply authentication constraints that are required for the authentication. For example, require Email OTP 2FA for this request.

authentication.pre_initialize authentication.post_identified authentication.pre_authenticated

rate_limits

Dynamically override rate limit weights.

authentication.pre_initialize authentication.post_identified authentication.pre_authenticated

bot_protection

Determines whether bot protection should be enabled for this request.

authentication.pre_initialize authentication.post_identified

Deny Access with "is_allowed"

To let the operation proceed, return a JSON document with is_allowed set to true.

{
  "is_allowed": true
}

To abort the operation, return a JSON document with is_allowed set to false, and a non-empty reason and title.

{
  "is_allowed": false,
  "reason": "some reason",
  "title": "some title"
}

If any of your hooks abort the operation, the operation is aborted. The reason and title will be shown to the end-user as an error message.

Mutations

Your hooks can optionally apply mutation for certain blocking events. The supported mutation is specific for each type of blocking event. Refer to the Event List to see what mutation is supported.

Mutations by a hook are applied only when the operation is allowed to proceed. Mutations take effect only when all hooks allow the operation to proceed.

  • Objects not appearing in mutations are left intact.

  • The mutated objects are NOT merged with the original ones.

  • The mutated objects are NOT validated, and are propagated along the hook chain. The mutated objects are validated after traversing the hook chain.

  • Mutations do NOT generate extra events to avoid infinite loops.

Mutations on the user object

When a blocking event supports mutations on the user object, your hooks can respond a JSON document to allow the operation, and specify the mutations you want to apply on the user object.

{
  "is_allowed": true,
  "mutations": {
    "user": {
      "standard_attributes": {
        "name": "John"
      },
      "custom_attributes": {
        "age": 30
      }
    }
  }
}

To mutate the user object, include user inside mutations. Only standard_attributes , custom_attributes , roles and groups of the user object are mutable.

You must include the WHOLE standard_attributes , custom_attributes , roles or groups when you specify the mutations. Otherwise, missing attributes WILL BE deleted.

Mutations on the JWT payload

When a blocking event supports mutations on the JWT payload, your hooks can respond a JSON document to allow the operation, and specify additional fields that you want to include in the JWT payload. However, you MUST NOT change or remove any existing fields in the JWT payload, as they are essential to the validity of the JWT.

{
  "is_allowed": true,
  "mutations": {
    "jwt": {
      "payload": {
        // The original payload you get from the event object.
        "iss": "https://myapp.authgear.cloud",
        "aud": ["YOUR_CLIENT_ID"],
        "sub": "THE_USER_ID",
        // Other essential JWT fields that you MUST retain.

        // Additional fields that you want to add.
        "https://myapp.com": {
          "custom_field": "custom_value"
        }
      }
    }
  }
}

To add additional fields to the JWT payload, include the WHOLE jwt.payload inside mutations. You MUST add your own fields only.

Apply Authentication Constraints

Use the constraints property to conditionally require additional authentication methods for the current request.

  • amr: An array of Authentication Methods References (AMR) values that are required for the authentication. The supported values are:

    • pwd

    • otp

    • sms

    • mfa

    • x_primary_password

    • x_primary_oob_otp_email

    • x_primary_oob_otp_sms

    • x_secondary_password

    • x_secondary_oob_otp_email

    • x_secondary_oob_otp_sms

    • x_secondary_totp

When multiple values are returned in amr, they are in AND relationship. For example, for "amr": ["mfa", "otp"], the user must fulfil mfa AND otp in the authentication flow.

Example response for requiring MFA in authentication:

{
  "is_allowed": true,
  "constraints": {
    "amr": ["mfa"]
  }
}

The constraints are enforced based on the authentication flow type:

  • Signup / Promote: Enforces thesetup of corresponding authenticator according to value of amr.

  • Login / Re-authentication: Enforces the use of corresponding authenticator according to value of amr.

  • Account Recovery: No effect (does not support 2FA)

Override Rate Limits

Use the rate_limits property in a blocking event response to dynamically override rate limit weights. The weight parameter define the amount of value contribute to the specified rate limit in subsequent operations. The default value is 1. A value of 0 means that subsequent operations will not be counted towards the rate limit.

For example, this hook response means in the next operation, the "account enumeration" rate limit is double counted. i.e. The user shall hit the rate limit with half the numbers of attempts.

{
  "is_allowed": true,
  "rate_limits": {
    "authentication.account_enumeration": {
      "weight": 2
    }
  }
}

The following rate limits are supported:

  • authentication.general : Verify any credentials, e.g. password, OTP

  • authentication.account_enumeration : Check existence of a login ID (username, email, phone number)

Bot Protection

Use bot_protection property to enable or disable for this request. This overrides the project's configuration.

Example response with bot protection override:

{
  "is_allowed": true,
  "bot_protection": {
    "mode": "always"
  }
}

This overrides the original mode of bot_protection in your config. Supported values are:

  • always : Require Captcha

  • never : Disable Captcha

Blocking Event List

user.pre_create

Occurs right before the user creation. User can be created by user signup, user signup as an anonymous user, or created by the admin via the Portal or Admin API.

This event supports Mutations on the user object

{
  "type": "user.pre_create",
  "payload": {
    "user": {
      "id": "338deafa-400b-4589-a922-2c92d670b757",
      "created_at": "2006-01-02T03:04:05.123456Z",
      "updated_at": "2006-01-02T03:04:05.123456Z",
      "is_anonymous": false,
      "is_verified": true,
      "is_disabled": false,
      "is_deactivated": false,
      "can_reauthenticate": true,
      "standard_attributes": {
        "email": "[email protected]",
        "email_verified": true,
        "updated_at": 1136171045
      }
    },
    "identities": [
      {
        "id": "239d585d-9b90-4148-9aa2-2e3131b5847a",
        "created_at": "2006-01-02T03:04:05.123456Z",
        "updated_at": "2006-01-02T03:04:05.123456Z",
        "type": "login_id",
        "claims": {
          "email": "[email protected]",
          "https://authgear.com/claims/login_id/key": "email",
          "https://authgear.com/claims/login_id/original_value": "[email protected]",
          "https://authgear.com/claims/login_id/type": "email",
          "https://authgear.com/claims/login_id/value": "[email protected]"
        }
      }
    ]
  }
}

user.profile.pre_update

Occurs right before the update of the user profile.

This event supports Mutations on the user object

{
  "type": "user.profile.pre_update",
  "payload": {
    "user": {
      "id": "338deafa-400b-4589-a922-2c92d670b757",
      "created_at": "2006-01-02T03:04:05.123456Z",
      "updated_at": "2006-01-02T03:04:05.123456Z",
      "last_login_at": "2006-01-02T03:04:05.123456Z",
      "is_anonymous": false,
      "is_verified": true,
      "is_disabled": false,
      "is_deactivated": false,
      "can_reauthenticate": true,
      "standard_attributes": {
        "email": "[email protected]",
        "email_verified": true,
        "name": "Chris",
        "updated_at": 1136171045
      }
    }
  }
}

user.pre_schedule_deletion

Occurs right before account deletion is scheduled.

This event supports Mutations on the user object

{
  "type": "user.pre_schedule_deletion",
  "payload": {
    "user": {
      "id": "338deafa-400b-4589-a922-2c92d670b757",
      "created_at": "2006-01-02T03:04:05.123456Z",
      "updated_at": "2006-01-02T03:04:05.123456Z",
      "last_login_at": "2006-01-02T03:04:05.123456Z",
      "is_anonymous": false,
      "is_verified": true,
      "is_disabled": true,
      "is_deactivated": true,
      "delete_at": "2022-09-30T15:18:19.040081Z",
      "can_reauthenticate": true,
      "standard_attributes": {
        "email": "[email protected]",
        "email_verified": true,
        "updated_at": 1136171045
      }
    }
  }
}

user.pre_schedule_anonymization

Occurs right before the account anonymization is scheduled.

This event supports Mutations on the user object

{
  "type": "user.pre_schedule_anonymization",
  "payload": {
    "user": {
      "id": "338deafa-400b-4589-a922-2c92d670b757",
      "created_at": "2006-01-02T03:04:05.123456Z",
      "updated_at": "2006-01-02T03:04:05.123456Z",
      "last_login_at": "2006-01-02T03:04:05.123456Z",
      "is_anonymous": false,
      "is_verified": true,
      "is_disabled": true,
      "is_deactivated": true,
      "delete_at": "2022-09-30T15:18:19.040081Z",
      "can_reauthenticate": true,
      "standard_attributes": {
        "email": "[email protected]",
        "email_verified": true,
        "updated_at": 1136171045
      }
    }
  }
}

authentication.pre_initialize

Occurs right before any authentication flow started.

This event supports Apply Authentication Constraints, Bot Protection, Override Rate Limits

{
  "type": "authentication.pre_initialize",
  "payload": {
    "authentication_context": {
      "user": null,
      "asserted_authentications": [],
      "asserted_identifications": [],
      "amr": [],
      "authentication_flow": {
        "type": "login",
        "name": "default"
      }
    }
  }
}
  • The authentication_context object contains details about the current authentication.

authentication.post_identified

Occurs right after an identity is identified during authentication, for example after user enters their email address, username or phone number.

This event supports Apply Authentication Constraints, Bot Protection, Override Rate Limits

{
  "type": "authentication.post_identified",
  "payload": {
    "authentication_context": {
      "authentication_flow": {
        "type": "login",
        "name": "default"
      },
      "user": { /* The identified user */
        "id": "c1397fc7-10ff-4cbd-bdc9-6fd9ae829c86",
        "is_anonymized": false,
        "is_anonymous": false,
        "is_deactivated": false,
        "is_disabled": false,
        "is_verified": true,
        "last_login_at": "2025-05-27T06:32:54.072273Z",
        "roles": [],
        "groups": [],
        "standard_attributes": {
          "email": "[email protected]",
          "email_verified": true
        },
        "custom_attributes": {},
        "created_at": "2025-05-27T06:32:54.005206Z",
        "updated_at": "2025-05-27T06:32:54.066087Z"
      },
      "asserted_identifications": [
        { /* The identification methods asserted in the current authentication */
          "identification": "oauth",
          "identity": {
            "id": "8f84ed75-5c8b-45c1-b657-b0c65ac3affe",
            "claims": {
              "email": "[email protected]",
              "email_verified": true,
              "family_name": "Authgear",
              "given_name": "Test",
              "https://authgear.com/claims/oauth/provider_alias": "google",
              "https://authgear.com/claims/oauth/provider_type": "google",
              "https://authgear.com/claims/oauth/subject_id": "1234567",
              "name": "Test Authgear"
            },
            "type": "oauth",
            "created_at": "2025-05-27T06:32:54.02264Z",
            "updated_at": "2025-05-27T06:32:54.02264Z"
          }
        }
      ],
      "asserted_authentications": [],
      "amr": []
    },
    "identification": {
      "identification": "oauth",
      "identity": { /* The identified identity */
        "id": "8f84ed75-5c8b-45c1-b657-b0c65ac3affe",
        "claims": {
          "email": "[email protected]",
          "email_verified": true,
          "family_name": "Authgear",
          "given_name": "Test",
          "https://authgear.com/claims/oauth/provider_alias": "google",
          "https://authgear.com/claims/oauth/provider_type": "google",
          "https://authgear.com/claims/oauth/subject_id": "1234567",
          "name": "Test Authgear"
        },
        "type": "oauth",
        "created_at": "2025-05-27T06:32:54.02264Z",
        "updated_at": "2025-05-27T06:32:54.02264Z"
      }
    }
  }
}
  • The authentication_context object contains details about the current authentication.

  • The identification object contains details about the identity entered and identified.

authentication.pre_authenticated

Occurs right before any authentication flows completed. It is triggered when the remaining flow no longer contains any of the steps: identify / authenticate / create_authenticator / verify

This event supports Apply Authentication Constraints, Override Rate Limits

{
  "payload": {
    "authentication_context": {
      "authentication_flow": { 
        "type": "login",
        "name": "default"
      },
      "user": { /* The identified user */
        "id": "c1397fc7-10ff-4cbd-bdc9-6fd9ae829c86",
        "is_anonymized": false,
        "is_anonymous": false,
        "is_deactivated": false,
        "is_disabled": false,
        "is_verified": true,
        "last_login_at": "2025-05-27T06:32:54.072273Z",
        "roles": [],
        "groups": [],
        "standard_attributes": {
          "email": "[email protected]",
          "email_verified": true
        },
        "custom_attributes": {},
        "created_at": "2025-05-27T06:32:54.005206Z",
        "updated_at": "2025-05-27T06:32:54.066087Z"
      },
      "asserted_identifications": [ /* The identification methods asserted in the current authentication */
        {
          "identification": "oauth",
          "identity": {
            "id": "8f84ed75-5c8b-45c1-b657-b0c65ac3affe",
            "claims": {
              "email": "[email protected]",
              "email_verified": true,
              "family_name": "Authgear",
              "given_name": "Test",
              "https://authgear.com/claims/oauth/provider_alias": "google",
              "https://authgear.com/claims/oauth/provider_type": "google",
              "https://authgear.com/claims/oauth/subject_id": "1234567",
              "name": "Test Authgear"
            },
            "type": "oauth",
            "created_at": "2025-05-27T06:32:54.02264Z",
            "updated_at": "2025-05-27T06:32:54.02264Z"
          }
        },
      ],
      "asserted_authentications": [ /* Authentication methods asserted during the authentication */
        {
          "authentication": "primary_oob_otp_sms",
          "authenticator": {
            "id": "2a6f9927-c76c-4112-868a-879547239266",
            "type": "oob_otp_sms",
            "kind": "primary"
          }
        }
      ],
      "amr": ["sms", "otp", "x_primary_oob_otp_sms"]
    },
  }
}
  • The authentication_context object contains details about the current authentication.

oidc.jwt.pre_create

Occurs right before the access token is issued. Use this event to add custom fields to the JWT access token.

This event supports Mutations on the JWT payload

{
  "type": "oidc.jwt.pre_create",
  "payload": {
    "user": {
      "id": "338deafa-400b-4589-a922-2c92d670b757",
      "created_at": "2006-01-02T03:04:05.123456Z",
      "updated_at": "2006-01-02T03:04:05.123456Z",
      "last_login_at": "2006-01-02T03:04:05.123456Z",
      "is_anonymous": false,
      "is_verified": true,
      "is_disabled": true,
      "is_deactivated": true,
      "delete_at": "2022-09-30T15:18:19.040081Z",
      "can_reauthenticate": true,
      "standard_attributes": {
        "email": "[email protected]",
        "email_verified": true,
        "updated_at": 1136171045
      }
    },
    "jwt": {
      "payload": {
        "iss": "https://myapp.authgear.cloud",
        "aud": ["YOUR_CLIENT_ID"],
        "sub": "338deafa-400b-4589-a922-2c92d670b757"
      }
    }
  }
}

Last updated

Was this helpful?