Resources Docs Free Blog Contact
Log in Get started
SIG-355 · MASKBREAK RESEARCH
Integration guides

Can Maskbreak detect suspicious logins quickly in a Node.js app for free?

Add a server-side login risk check with the Maskbreak Node.js SDK. Handle allow, review, block, missing evidence and API errors without bypassing authentication.

In short
  • Use the official Node.js SDK to evaluate browser-collected evidence on your server before creating a login session.
  • Keep API keys out of the browser and preserve existing password, MFA, CSRF and rate-limit controls.
  • Only a usable production allow result passes this example’s fraud gate; review, failures and incomplete checks have separate paths.
  • Measure collection, network and server time in your own app instead of treating sample timing as a speed promise.
On this page
  1. 1. Collect evidence from the login page
  2. 2. Install the official Node.js SDK
  3. 3. Add a risk gate without replacing authentication
  4. 4. Read the decision and the evidence separately
  5. 5. Budget for latency, limits and failures
  6. How does this compare with other login tools?
  7. 6. Prove the real flow before enforcing it

Yes. Maskbreak can add a live login-risk check to a Node.js app, free during open beta. The standard allowance is 1,000 visitor checks per hour with no credit card. Your server sends browser-collected evidence to the API and receives decision, risk_score and reasons, together with available network and device signals.

The important part is what happens after the answer. A fraud API does not verify the user’s password, create a secure session or complete MFA. This guide adds a risk gate to an existing login flow and keeps those responsibilities in your application.

1. Collect evidence from the login page

Load the browser SDK on your existing login page. For an ordinary form, the enrichment class adds monocle and sentinel_fp fields at submission. Keep your current inputs and CSRF protection; use your actual login URL.

HTML · existing login form
<script async src="https://maskbreak.com/assets/sentinel.js"></script>

<form class="monocle-enriched" method="post" action="/login">
  <!-- Keep your login inputs, CSRF field and submit button here. -->
</form>

For a custom JavaScript submission, wait until the SDK has loaded, call window.Sentinel.collect(), and include the returned token and fingerprintEventId in the request to your backend. If collection is blocked or unavailable, do not substitute a demo token. The server example below holds the login because its policy requires both kinds of evidence.

2. Install the official Node.js SDK

Terminal · your backend project
npm install @sentinelsup/sdk

The package keeps its original @sentinelsup/sdk name. Set SENTINEL_KEY in your server’s environment or secret manager using your live account key. Do not use a frontend-exposed environment variable, commit the key, or copy it into a public support message. Use a supported Node.js release; the example uses CommonJS and SDK 0.3.1.

Try it

Wire it into your own app: a free key returns decision, risk_score and reasons for every visit, 1,000 requests an hour, no card.

Get an API key

3. Add a risk gate without replacing authentication

This is an Express integration fragment, not a standalone authentication system. Your app must already define app, loginRateLimit and existingLoginHandler. The latter verifies credentials, enforces required MFA and creates the session. Keep your existing CSRF/origin checks, and configure bounded JSON and URL-encoded body parsers before this route.

The four-second timeout below is an example application budget, not a promised API latency. No session is created on review, missing evidence or an unavailable check. The JSON responses need to be connected to your login UI and its verification/recovery flow.

Node.js · server-side Express route
const Sentinel = require('@sentinelsup/sdk');
const apiKey = process.env.SENTINEL_KEY;
if (!apiKey || apiKey.startsWith('sk_test_')) {
  throw new Error('Configure a live server-side Maskbreak key.');
}
const maskbreak = new Sentinel({ apiKey, timeoutMs: 4000 });

app.post('/login', loginRateLimit, async (req, res, next) => {
  const body = req.body || {};
  const token = body.token || body.monocle;
  const fingerprintEventId = body.fingerprintEventId || body.sentinel_fp;
  if (typeof token !== 'string' || !token.trim() || token.startsWith('test_') ||
      typeof fingerprintEventId !== 'string' || !fingerprintEventId.trim()) {
    return res.status(409).json({ error: 'Verification required.' });
  }
  try {
    const result = await maskbreak.evaluate({ token, fingerprintEventId });
    if (!result || !['allow', 'review', 'block'].includes(result.decision) ||
        result.test || result.sandbox || result.sample) {
      throw new Error('No production verdict.');
    }
    if (result.decision === 'block') {
      return res.status(403).json({ error: 'Request declined.' });
    }
    if (result.decision === 'review' || result.degraded ||
        typeof result.network?.vpn !== 'boolean' ||
        typeof result.device?.antidetect !== 'boolean' ||
        typeof result.device?.automation !== 'boolean') {
      return res.status(409).json({ error: 'Verification required.' });
    }
    return next(); // Existing authentication still runs; this is not a session.
  } catch {
    return res.status(503).json({ error: 'Verification unavailable. Try again later.' });
  }
}, existingLoginHandler);

The rate limiter runs before the paid-or-quota-bound dependency so a flood of login attempts cannot freely consume your allowance. The example also rejects fixture tokens and test-mode responses. Do not expose raw tokens, credentials or API keys in application logs. A trusted account identifier, if you later add account linking, must come from server-validated identity rather than an arbitrary field in the browser request.

Express is only the HTTP adapter here. Fastify and NestJS can call the same SDK from their handlers or services; adapt their request, reply and authentication lifecycle explicitly. There is no special framework plugin required for this SDK call. The SDK does not currently forward the collector’s optional tz field; use the raw HTTP example if your integration needs that input.

4. Read the decision and the evidence separately

FieldMeaning for your login flow
decisionFinal allow, review or block recommendation, including applicable customer rules and exceptions.
risk_score and reasonsSignal score and machine-readable explanations. The score is not a probability of fraud.
networkVPN, proxy, Tor and related network evidence. The service is named when known.
deviceAvailable browser/device evidence, which can include automation, antidetect and tampering signals.
degradedUnavailable network evidence. Do not treat an otherwise allow response as a complete clean check.

A VPN alone yields review in the base evaluation policy. Your account rules or exceptions may change the final decision, so route on decision rather than treating every VPN flag or legacy isSuspicious value as a block. Read the full response contract for optional fields.

For review, hold session creation and offer an additional check appropriate to the action, such as the account’s configured MFA. Bind the challenge to the attempted login and verify it on your server before completing authentication. A browser-supplied “passed” flag must never release the hold. OWASP’s authentication guidance covers layered controls, reauthentication and MFA.

5. Budget for latency, limits and failures

Measure the complete journey: browser collection, the request to your backend, the API round trip and your authentication work. evaluated_in_ms measures server processing, not all of those steps. Neither a synthetic response’s timing value nor a single fast request establishes a global speed guarantee.

The standard free allowance is hourly, not monthly; evaluation and authenticated IP lookup share the key’s bucket. HTTP 429 includes Retry-After. The SDK throws an error with status for HTTP failures but does not expose response headers, so use raw HTTP if you need those headers for capacity management. This login example returns a temporary unavailable state rather than automatically retrying or silently allowing the request.

Do not make people wait in a retry loop for the quota to reset. Offer a clear recovery path, investigate sustained capacity errors, and choose your application’s fallback deliberately. See how to handle fraud API timeouts. The free service is open beta under the published terms, not a contractual availability or latency guarantee.

How does this compare with other login tools?

This is a Maskbreak-authored implementation guide, not a head-to-head accuracy test. These are different integration choices, checked against the linked product documentation on 9 September 2026:

  • Maskbreak: live browser collection plus server-side evaluation for network and available device signals; 1,000 hourly checks free during open beta, no card.
  • LoginLlama: a login-focused API advertising 1,000 free checks each month without a card, with a risk score and codes for signals such as new devices and impossible travel. Compare its required inputs and fallback policy with your own.
  • Cloudflare Turnstile: a bot-challenge flow. Its token must be validated server-side, is single-use and expires after five minutes. Challenge validation is not a replacement for checking credentials or deciding how to handle account risk.

If your main problem is choosing a free tool for signup, read the EU signup-protection comparison. Whichever service you select, preserve the authentication controls you already depend on.

6. Prove the real flow before enforcing it

Test allow, review, block, missing device evidence, timeout, invalid JSON, invalid credentials and quota exhaustion. Confirm that only the intended path reaches your existing session handler. Then run a controlled live browser visit and check the resulting event in your dashboard. A successful demo call tests branching; it does not prove your frontend is sending real evidence.

Keep the tests and observations distinct. Deterministic fixtures are useful for repeatable CI checks. Live tests establish that collection and your deployed backend are connected. Neither justifies claiming perfect detection, and both are worth doing before turning a new risk signal into a customer-facing refusal.


FAQ

Questions people ask

Is the Node.js login check free to start?
Yes. Maskbreak is free during open beta with no credit card and a standard allowance of 1,000 visitor checks per hour. Evaluation and authenticated IP lookup share the key’s hourly allowance.
Does Maskbreak work with Express, Fastify or NestJS?
The framework-independent Node.js SDK and HTTP API can be called from those backends. This article includes an Express route example; Fastify and NestJS require adapting the request and response handling, not a separate Maskbreak plugin.
Does an allow result authenticate a user?
No. An allow recommendation only passes the fraud gate in this example. Your existing login handler must still verify credentials, apply MFA where required and create the session securely.
What should a Node.js app do with review?
Hold session creation and offer your application’s additional verification or review path. Verify that outcome on the server and bind it to the attempted login; do not accept a client-side passed flag.
Does Maskbreak guarantee a fixed login-check latency?
No global response-time guarantee is made here. Measure browser collection and server round trips in your deployment, set a deadline and give unavailable checks an explicit fallback.
Get started

Paste it in, then watch the verdicts

The public sk_test_sandbox key returns the documented allow, review and block shapes with no account, so the failure path is testable before you go live. SDKs for Node, Python and PHP, or plain HTTP. The <a href="/api">API reference</a> and the <a href="/pricing">free tier</a> cover the rest.

Get started freeRead the API docs