authshield-js
v0.1.1
Published
Embeddable Node.js middleware library to detect and mitigate authentication account attacks.
Maintainers
Readme
AuthShield.js
Embeddable middleware for Node.js authentication protection.
Install
npm install authshield-jsRepository
- GitHub:
https://github.com/iambant/authshield - Issues:
https://github.com/iambant/authshield/issues
Threat-informed defaults
Registration protection defaults are tuned for modern identity abuse patterns highlighted in Microsoft security reporting:
- high automation volume against identity surfaces
- bot-driven fake account creation waves
- disposable-email based account farming
See threat-model notes: docs/registration-threat-model.md.
Quick start (TypeScript)
import express from "express";
import {
authShield,
preLoginGuard,
postLoginReporter,
preRegistrationGuard,
postRegistrationReporter,
tokenGuard,
revokeHandler,
} from "authshield-js";
const app = express();
app.use(express.json());
const shield = authShield({
redisUrl: process.env.REDIS_URL,
mode: "enforce", // "monitor" or "enforce"
loginRateLimit: {
windowMs: 60_000,
maxPerIp: 30,
maxPerIpAndUser: 10,
},
captcha: {
enabled: true,
thresholdPerIpAndUser: 5,
singleAsk: false,
tokenField: "captchaToken",
},
onIncident: (incident) => {
console.log("[authshield]", incident.attackType, incident.reason);
},
});
app.post("/login", preLoginGuard(shield), loginHandler, postLoginReporter(shield));
app.post("/register", preRegistrationGuard(shield), registerHandler, postRegistrationReporter(shield));
app.get("/profile", tokenGuard(shield), profileHandler);
app.post("/logout", revokeHandler(shield));If postLoginReporter is placed after loginHandler, call next() in loginHandler after sending the response.
Quick start (JavaScript)
const express = require("express");
const {
authShield,
preLoginGuard,
postLoginReporter,
preRegistrationGuard,
postRegistrationReporter,
tokenGuard,
revokeHandler,
} = require("authshield-js");
const app = express();
app.use(express.json());
const shield = authShield({ mode: "enforce" });
app.post("/login", preLoginGuard(shield), loginHandler, postLoginReporter(shield));
app.post("/register", preRegistrationGuard(shield), registerHandler, postRegistrationReporter(shield));
app.get("/profile", tokenGuard(shield), profileHandler);
app.post("/logout", revokeHandler(shield));AuthShield is written in TypeScript and distributed as JavaScript, so it works in plain JS Node.js projects.
What it detects
- Brute force
- Password spraying
- Credential stuffing
- Account enumeration
- Phishing-like login anomalies
- Impossible travel (heuristic)
- Token hijack / token replay
- Session fixation
- Session fanout
- Success-after-fail burst
- Registration burst / fake account signup spikes
- Disposable-email signup abuse
Main config options
mode:"monitor" | "enforce"redisUrlorredisClientloginRateLimit:windowMs,maxPerIp,maxPerIpAndUserregistrationRateLimit:windowMs,maxPerIpcaptcha:enabled,thresholdPerIpAndUser,singleAsk,tokenField,verifyTokenonIncident(incident)onDecision(payload)onLimitEvent(event, req)replayWindowMs,replayActionimpossibleTravelMinDeltaMs,impossibleTravelActionenumWindowSec,enumUniqueUsersThreshold,enumFailsThreshold,enumActionfixationActionsessionFanoutWindowMs,sessionFanoutDistinctIpThreshold,sessionFanoutActiondistributedFailWindowMs,distributedFailThreshold,distributedFailActionsuccessAfterFailWindowMs,successAfterFailThreshold,successAfterFailActionregistrationBurstWindowMs,registrationBurstThreshold,registrationBurstActiondisposableEmailWindowMs,disposableEmailThreshold,disposableEmailActionregistrationDisposableDomains(defaults to upstream blocklist fromdisposable-email-domains/disposable-email-domains)blockDisposableEmailOnRegistration(instant pre-check at registration stage)
To refresh disposable domains list:
npm run update:disposable-domainsRuntime actions
allowchallenge_loginblock_iprevoke_token
Notes
- Use only in controlled/lab environments.
- Intended for defensive security research and adversary simulation.
Release (GitHub + npm)
npm run typechecknpm testnpm run buildnpm pack --dry-runnpm version patch(orminor/major)git add . && git commit -m "release: vX.Y.Z"git tag vX.Y.Zgit push origin main --tagsnpm publish --access public
