AbuseGraphDocs
Guides

AbuseGraph + Auth0

Score Auth0 signups and logins from a Post-Login Action — block on deny, enable MFA on challenge.

Quick path

  1. Add ABUSEGRAPH_SECRET_KEY and ABUSEGRAPH_SITE as Action secrets.
  2. Create a Post-Login Action that POSTs to https://abusegraph.com/api/v1/check.
  3. Optionally forward browser toCheckBody from Universal Login custom UI.

Keys

KeyEnvUse
SecretABUSEGRAPH_SECRET_KEY (sk_test_… / sk_live_…)Server /api/v1/check
PublishableNEXT_PUBLIC_ABUSEGRAPH_PUBLISHABLE_KEY (pk_test_…)Browser SDK
SiteABUSEGRAPH_SITEDNS-verified domain

Free includes 1,000 live API checks / month after DNS verify. Test keys never bill.

Env

Action secrets (Auth0 Dashboard → Actions → Library):

ABUSEGRAPH_SITE=yourdomain.com
ABUSEGRAPH_CHECK_URL=https://abusegraph.com/api/v1/check
ABUSEGRAPH_SECRET_KEY=sk_test_…

Use sk_live_… in production after DNS verify.

Server check

Auth0 Actions use Deno fetch — POST directly to https://abusegraph.com/api/v1/check. Events: signup | login | password_reset | email_change. Optional sessionId.

init + collect + evaluate + toCheckBody — NEVER bare sdk.check() alone as the authoritative decision.

import { init } from "@abusegraph/sdk"

const sdk = init({
  publicKey: process.env.NEXT_PUBLIC_ABUSEGRAPH_PUBLISHABLE_KEY!, // pk_test_…
})

const collected = await sdk.collect()
const edge = await sdk.evaluate(collected, { email })
// Forward sdk.toCheckBody(collected, { email, event: "signup",
//   verdictToken: edge.verdictToken.token }) into your Action via app_metadata

Auth0 Post-Login Action

Detect signup via logins_count === 1 or screen_hint=signup. Block on block; enable MFA on challenge.

exports.onExecutePostLogin = async (event, api) => {
  const email = event.user.email
  if (!email) return

  const isSignup =
    event.stats?.logins_count === 1 ||
    event.request?.query?.screen_hint === "signup"

  const browser = event.user.app_metadata?.abusegraph ?? {}

  const res = await fetch(
    event.secrets.ABUSEGRAPH_CHECK_URL ||
      "https://abusegraph.com/api/v1/check",
    {
      method: "POST",
      headers: {
        "content-type": "application/json",
        "x-api-key": event.secrets.ABUSEGRAPH_SECRET_KEY,
        "x-abusegraph-site": event.secrets.ABUSEGRAPH_SITE,
      },
      body: JSON.stringify({
        email,
        userId: event.user.user_id,
        event: isSignup ? "signup" : "login",
        ip: event.request?.ip,
        site: event.secrets.ABUSEGRAPH_SITE,
        ...browser,
      }),
    },
  )

  if (res.status === 402) return // credits exhausted — fail open or deny

  const result = await res.json()
  if (result.verdict === "block") {
    api.access.deny("Account blocked by abuse checks")
  }
  if (result.verdict === "challenge") {
    api.multifactor.enable("any")
  }
}

Lifecycle events

  • login — same Action; isSignup is false when logins_count > 1.
  • password_reset — add a Post-Change-Password Action with event: "password_reset".
  • email_change — hook email update flow with event: "email_change".

Platform

Lists, rules, and linked accounts apply on every check — configure in the console. Optional session: POST /api/v1/session. Native apps: iOS, Android, React Native.

Verify

Sign up with screen_hint=signup using sk_test_…. Confirm Activity shows the check and blocked users cannot complete login.