The credentials matched.The machine did not.
One verify call at the login says whether the machine behind the password has ever signed this account in.
Eight accounts, one machine, ninety-four seconds
Credential stuffing arrives as ordinary logins, one account at a time.
A correct password is where the decision starts
A machine it has never seen
Your session, read the way a login gate reads it
identity.returningintegrity.automationintegrity.tamperednetworkvelocity.devicerisk.reason_codesOne call on the client, one check before the session
import { useTrustSig } from "@trustsig/react";
const { getResponse } = useTrustSig();
const { token } = await getResponse();import { TrustSig } from '@trustsig/server';
const ts = new TrustSig({ secretKey: process.env.TRUSTSIG_SECRET_KEY });
app.post('/login', async (req, res) => {
const token = req.headers['x-trustsig-response'];
const result = await ts.verifyRemote(token);
// Fail closed: proceed only on an explicit ALLOW.
if (result.action !== 'ALLOW') {
return res.status(403).json({ error: 'Access denied.' });
}
const user = await authenticate(req.body.email, req.body.password);
const { device_id, degraded } = result.identity;
// Your table: the machines this account has signed in from before.
const known = degraded || (await devicesFor(user.id)).includes(device_id);
if (!known) {
return sendSecondFactor(user, { request_id: result.request_id, device_id });
}
return completeLogin(req, res, { user, device_id });
});What the reading at login does not claim
- A new machine is usually a new phone
identity.returning - An upgrade and an attacker both come back as returning false, so the network and integrity readings decide which one you are looking at.
- One id can cover two people
identity.device_id - A family desktop signs two people in, which is why a known id raises confidence without settling anything.
- Some ids name a cohort
identity.degraded - A locked-down browser can produce an id a crowd shares, so an unfamiliar id is not always an unfamiliar machine.
- The verdict is returned, never enforced
action - The response carries the grade and the evidence behind it, and your login route decides what to do with both.
Takeover at login, answered
identity.returning and identity.first_seen say whether this account has ever signed in from this machine. A correct password from a machine with no history becomes a step-up instead of a silent success.
Once, on the first sign-in from it. A new machine is a new id by design, so the honest new phone and the attacker's machine look alike on arrival. The network block, the integrity findings and integrity.automation are what tell them apart.
One machine against many accounts, so velocity.device runs high while each login looks ordinary on its own. integrity.automation reports a driver or a headless build, and network.datacenter reports the hosting range the burst arrived from.
No. It decides who needs to be asked. A returning machine with a clean reading signs in, and a session with no history behind it gets the second factor you already have.
No. The token is verified server side and the nonce is spent at the edge, so a captured token is not a reusable device. identity.device_id arrives in the verify result on your server, never in anything the browser sends.
Then the device is genuinely known and device intelligence says so. Resolving whether the person behind a known machine changed is TrustSig Pro.
Read the machine before the session opens.
Two calls, and the login has the machine's history before it opens the session.