UsefulKey
Plugins

IP Access Control (Memory)

Mutable allow/deny lists with runtime controls. Enforce source IP checks and manage lists at runtime.

How it works

  • Keeps allow and deny lists in memory, configurable at startup and mutable at runtime.
  • On verify, pass the caller IP (ip) so the plugin can evaluate.
  • Behavior is the same as the static variant with the addition of runtime management helpers.

Settings

OptionTypeDefaultDescription
allowstring[][]Initial whitelist of allowed IPs. If non-empty, only these are permitted.
denystring[][]Initial blacklist of denied IPs. Deny takes precedence.

Usage

import { usefulkey } from "betterkey";
import { ipAccessControlMemory, ipAccessControlStatic } from "usefulkey/plugins";

const uk = usefulkey({}, { plugins: [ipAccessControlMemory()] });

// Manage lists at runtime
uk.ipAccessControl.addAllow("127.0.0.1");
uk.ipAccessControl.addDeny("10.0.0.1");
const allow = uk.ipAccessControl.getAllow();
const deny = uk.ipAccessControl.getDeny();

// On verify, provide the caller IP
const res = await uk.verifyKey({ key, ip: "127.0.0.1" });

Functions added

The plugin extends your uk instance with uk.ipAccessControl methods:

  • addAllow(ip: string): void
  • removeAllow(ip: string): void
  • clearAllow(): void
  • addDeny(ip: string): void
  • removeDeny(ip: string): void
  • clearDeny(): void
  • getAllow(): string[]
  • getDeny(): string[]

Verification behavior

  • Deny list match → { valid: false, reason: "ip_denied" }
  • Allow list present and no match → { valid: false, reason: "ip_not_allowed" }

Emitted analytics on block: "ip_access.blocked" with { ip, rule: "deny" | "allow_list_missing", plugin: "ip-access-control:memory", ts }.

Using with Static IP Access Control

You can enable the static and memory variants at the same time. Both plugins run on each verification and the decision is combined:

  • Deny lists are a union: if the IP appears in any plugin's deny, it is blocked.
  • Allow lists act as an intersection: if any plugin has a non-empty allow, the IP must be present in all such allow lists.
  • Order does not change the outcome. It only affects which plugin logs the block event.
import { usefulkey } from "betterkey";

const uk = usefulkey({}, {
  plugins: [
    ipAccessControlStatic({ allow: ["1.2.3.4"], deny: ["9.9.9.9"] }),
    ipAccessControlMemory({ allow: ["1.2.3.4", "2.2.2.2"] }),
  ],
});

// On verify, provide the caller IP
await uk.verifyKey({ key, ip: "1.2.3.4" });