Skip to content

Verify each Auth0 signup before the account exists

Integration Signups and authentication

Refuse an Auth0 signup whose address cannot receive mail: a Pre User Registration Action asks PricklyMails about it before the user is created.

No connector needed: at each signup, Auth0 calls the PricklyMails API from a Pre User Registration Action, and an address that cannot receive mail is refused before the account exists.

Verify for free

Step by step

Check each signup in four steps

  1. In PricklyMails

    Create an API key in PricklyMails

    1. In the dashboard, open API Keys and click New key.
    2. Under Environment, pick Test first: the key starts with pm_test_, answers from canned results, bills nothing and contacts no mail server.
    3. Copy the key as soon as it shows: it is shown only once.

    Tip

    The Free plan holds one key: once everything works, revoke the test key, then create the one under Live.

  2. In Auth0

    Create the Action in Auth0

    The key goes in the Action's secrets, which Auth0 encrypts and never shows again, so it stays out of the code.

    1. In Actions then Library, select Create Action, then Create Custom Action.
    2. Enter a Name, such as pricklymails-check, and choose Pre User Registration as the Trigger and Node 22 as the Runtime.
    3. Select Create: the Actions code editor opens.
    4. In the editor's sidebar, select the key icon, then Add Secret.
    5. Enter PRICKLYMAILS_KEY as the Name and your test key as the Value, then select Create.
    6. Replace the code in the editor with the code below, then select Save Draft.

    The code asks PricklyMails to answer within a few seconds (Prefer: wait) and stops waiting soon after, so a signup never hangs on the answer. It refuses the signup only when the recommendation is remove, and lets it through otherwise: a risky address, no answer in time, an error.

    pricklymails-check.js
    const VERIFY_URL = 'https://api.pricklymails.com/api/verify'
    const REFUSAL =
        'This email address cannot receive mail. ' +
        'Check it for a typo, or use another one.'
    
    // Auth0 gives the trigger 20 seconds: wait 4 for the answer, give up at 5.
    async function recommendationFor(email, key) {
        try {
            const response = await fetch(VERIFY_URL, {
                method: 'POST',
                headers: {
                    Authorization: `Bearer ${key}`,
                    'Content-Type': 'application/json',
                    Prefer: 'wait=4',
                },
                body: JSON.stringify({ email }),
                signal: AbortSignal.timeout(5000),
            })
            if (200 !== response.status) {
                return null
            }
            const { verification } = await response.json()
            return verification?.recommendation ?? null
        } catch {
            return null
        }
    }
    
    exports.onExecutePreUserRegistration = async (event, api) => {
        const email = event.user.email
        const key = event.secrets.PRICKLYMAILS_KEY
        if (email && 'remove' === (await recommendationFor(email, key))) {
            api.access.deny('undeliverable_email', REFUSAL)
        }
    }
    
    How the API answers in one call

    Tip

    Before you deploy, you can run the code from the editor: select Test (the play icon) in its sidebar, set the user's email in the payload to invalid@example.com, then select Run. The results show the steps the Action took.

  3. In Auth0

    Turn the Action on in Auth0

    Auth0 runs only the deployed version of an Action, and only once it sits in a trigger's flow.

    1. In the code editor, select Deploy.
    2. Go to Actions then Triggers, then select Pre User Registration.
    3. In the Add Action section on the right, under Custom, drag pricklymails-check into the flow, between Start and Complete.
    4. Select Apply.

    Warning

    Secrets are tied to the versions of an Action, and a change takes effect only once deployed: when you replace the test key with your live key, select Deploy again.

  4. In Auth0

    Try it with the test key

    1. Sign up with an address that starts with invalid, such as invalid@example.com: the test key answers remove, and the signup is refused.
    2. Sign up with another address, such as valid@example.com: the account is created.
    3. Where you stored the key, replace it with a key created under Live, which starts with pm_live_: from then on, each signup is verified for real and billed like any verification.

What each signup gets

The code reads the recommendation the API gives the address, the same one a list's report gives.

Remove

Refused: the address does not exist, its domain cannot receive mail, or it is disposable.

Auth0 stops the signup at once and creates no account. Its docs say the message passed to api.access.deny may be shown directly to the person signing up, and keep the reason, undeliverable_email, in your tenant logs.

Review

Let through: a domain that accepts any address, a generic address such as contact@, or a server that did not answer. The address may work.

Send

Let through: the address is valid, or hosted by a large provider that accepts every address.

No answer in time
Auth0 gives each run of the trigger 20 seconds, past which the signup ends in an error, and its guidelines ask for a timeout under 10 seconds on each HTTP request. The code waits 4 seconds for the answer and gives up after 5: without an answer, it lets the signup through, well within both limits.

Frequently asked questions

Which Auth0 signups does the Action check?

Those through a database connection, such as an email and a password, or a passwordless connection: Auth0 runs the Pre User Registration trigger for these alone, before the user is created. A person who signs up through a social or enterprise connection never goes through it, and neither does a bulk user import, so those accounts are created without the check. A signup that carries no email address, such as one by phone number, is let through by the code.

Where do I see the signups the Action refused?

In Monitoring then Logs: a refused signup appears as a Failed Signup event, with the reason the code passes to api.access.deny, undeliverable_email. Select the event, then the Action Details view, to see how the Action ran and any error it hit.

What if the trigger already runs other Actions?

Auth0 runs them one after the other, in the order they sit in the flow, and a call to api.access.deny stops the signup at once: no Action after it runs. The 20 seconds Auth0 allows apply to each run of the trigger, all its Actions together, and the code takes 5 at most. Placed first, pricklymails-check refuses an address before the others run.

Is there a PricklyMails extension for Auth0?

No, and there is nothing to install: the code above calls the PricklyMails API with your key.

These trademarks belong to their respective owners. Naming them implies no partnership.

Check your list before your next send.

1,000 tokens free when you sign up, no credit card. After that, you only pay for answers.