Skip to main content
When a user requests a scope grant via POST /v1/session/stepup/request, Prelude calls your step-up hook — the delegation_hook you registered for that scope in the step-up configuration when its mode is delegated. Your hook decides whether to grant the scope immediately, require a multi-step challenge, or block the request.

Hook request

Prelude sends a signed POST request to your hook URL with the following JSON body:

Request fields

Request headers

Request signature

The hook request is signed using the same mechanism as webhooks. Verify the X-Webhook-Signature header using the public key matching the X-Webhook-Signature-Key-Id from your application’s JWKS endpoint.

Hook response

Your endpoint must return a JSON response with a verdict.

Grant immediately

Return status: "continue" to grant the scope without any challenge:

Require a challenge

Return status: "review" with one or more steps the user must complete:

Block the request

Return status: "block" to deny the scope entirely:

Response fields

Grant modes

Response constraints

Response HTTP status

Your hook must return HTTP 200 with the JSON body. Any non-200 response or timeout (5 seconds) will cause the step-up request to fail.

Monitoring hook failures

When a call to your delegation hook fails — because the request could not be completed, the response had a non-2xx status code, or the body was malformed — Prelude emits a step_up.hook_failed webhook event with a reason field identifying the failure category. Subscribe to this event to alert on hook outages or misconfiguration.

Example implementation

Here is a minimal Node.js example of a step-up hook:

Custom steps and verification tokens

If your hook returns custom step keys (anything other than verify_sms or verify_email), your backend must issue verification tokens to advance the challenge. See Custom Steps for the full verification token format, requirements, and code examples.