Skip to content

fix: run verification, fraud, and MFA checks on every method and persist callbacks - #8

Open
jhickmanit wants to merge 2 commits into
mainfrom
fix/verification-fraud-mfa-messaging-integrations
Open

jhickmanit wants to merge 2 commits into
mainfrom
fix/verification-fraud-mfa-messaging-integrations

Conversation

@jhickmanit

@jhickmanit jhickmanit commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Corrects the identity verification, fraud, MFA, SMS, and email integrations: hook placement, blocking responses, callback reliability, and courier configuration.

Changes

  • Actions:
    • Hooks sit in method-specific lists, with session last. Each config aliases its password list, with YAML anchors, into the oidc, code, passkey, and webauthn lists. Verification, fraud, and MFA checks therefore run for every sign-in method, not only password.
    • A blocking response is 403 with the nested messages[].messages[] shape.
    • Jsonnet is null-safe.
  • Callbacks: the Persona, Onfido, Jumio, and Socure callbacks return 2xx only after the identity is updated, and 500 when the update fails, so the vendor retries.
  • Persona:
    • The callback parses Persona's event envelope (data.attributes.name and data.attributes.payload.data).
    • It verifies Persona-Signature with a five-minute tolerance.
    • It fetches the current inquiry before writing.
    • It constructs a hosted URL from the inquiry ID and supports a custom PERSONA_HOSTED_URL.
  • Handlers that now block (they used to return 200):
    • Equifax, GBG, and Socure block on decline, fail, refer, and high-risk results.
    • LexisNexis compares scores on InstantID's native scales and fails closed when the vendor is unreachable.
  • Castle: the login check uses parse. A deny returns 403, and a challenge returns required_aal: aal2. The registration check reports only.
  • Jumio, Onfido, Persona, and Prove:
    • The login validators only decide.
    • Onfido verification is started from the application backend.
    • Prove no longer runs a registration.before lookup and uses the SDK’s typed enrollment and identity lookup responses, so successful lookups reach the phone-mismatch check.
    • Metadata updates patch individual keys. Null parents are initialized with an updated_at test and retry to avoid overwriting data written since the GET.
  • Socure: an early callback whose external ID is not yet saved returns 500 for retry instead of being discarded.
  • reCAPTCHA: checks run in method-specific lists, missing/null transient payloads render safely, and failures return detailed Kratos messages.
  • Duo and Okta Verify: push polling is replaced by passcode verification inside the flow. The handlers never return 5xx, so retries do not trigger extra prompts.
  • Courier:
    • Brevo and SparkPost use working SMTP URIs and an HTTP request_config with ctx.body and ctx.html_body.
    • The Twilio, Vonage, MessageBird, and Plivo bodies send the payload each vendor expects.
    • WhatsApp passes the OTP from template_data.
  • Other: the YubiKey rp example, the ID.me issuer, and Sift's hook placement and score scale are corrected.

Deployment notes

  • Required environment variables. LexisNexis needs the three INSTANTID_*_THRESHOLD variables and exits at startup without them. The Socure callback returns 503 until its Ory credentials are set.
  • Guessed defaults. Review Equifax's EQUIFAX_PASS_DECISIONS default (APPROVE,PASS,ACCEPT) for your product. The custom UI message IDs are in the 9xxxxxx range.
  • Failure policy. LexisNexis fails closed when the vendor is unreachable; Prove validation fails open.
  • Jumio. If callback processing can outlast Jumio's callback timeout, put a durable queue in front of the handler.
  • CAPTCHA scope. This PR repairs the reCAPTCHA handler and hook configuration. docs: point CAPTCHA integrations to built-in Turnstile support #4 adds built-in Turnstile guidance for the CAPTCHA entries.

Validation

  • tsc --noEmit passes in every changed handler, and all Jsonnet evaluates with go-jsonnet 0.21.
  • Persona, Onfido, Jumio, and Socure callbacks were tested at runtime for persisted success and 500 on vendor or Admin API failure.
  • LexisNexis, Duo, and Okta block paths were smoke-tested.
  • Seven isolated regression tests cover Prove phone matching, Persona hosted URLs, metadata preservation and stale initialization, early Socure callbacks, and reCAPTCHA messages. A GitHub Actions workflow runs them against lockfile dependencies.
  • Not verified: live vendor API acceptance or vendor field names beyond the tested fixtures.

@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d4854f31-d6aa-44dd-b8fc-77ed3e966886
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Signed-off-by: jhickmanit <jeff.hickman@ory.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant