IP Allowlist
Official plugin — allow/deny rules by client IP at the edge of the pipeline, with the same typed Forbidden denial the gate element produces.
ipAllowlist() enforces IP rules at onAuth, before any gate policy or flow body runs. Internal admin surfaces, staging environments, and webhook endpoints stop unknown clients at the edge with the same typed Forbidden denial the gate element produces.
Quick start
import { oke } from "okengine";
import { ipAllowlist } from "okengine/plugins";
export const app = oke({ name: "shop", env: "dev" }).plug(
ipAllowlist({ allow: ["203.0.113.7", "2001:db8::42"] }),
);A client whose IP is not on the list receives 403 with a typed denial:
{
"data": null,
"error": {
"code": "Forbidden",
"data": { "reason": "ip_not_allowed", "ip": "198.51.100.9" }
}
}Options
| Option | Type | Default | Does |
|---|---|---|---|
allow | string[] | — (everyone passes) | Exact IPs permitted — every other client is denied |
deny | string[] | — (nobody blocked) | Exact IPs blocked — checked first, so deny wins on overlap |
header | string | "x-forwarded-for" | Header carrying the client IP |
trustedProxyDepth | number | 1 | Trusted proxies that append XFF; client IP is that many from the right |
.plug(ipAllowlist({ deny: ["198.51.100.9"], trustedProxyDepth: 1 }))Standard reverse proxies append to X-Forwarded-For — left-side hops are attacker-controlled.
The plugin trusts the hop trustedProxyDepth from the right (default 1 = last hop). Set
this to your real proxy count; wrong depth bypasses the allowlist — topology-dependent, not
drop-in.
Notes
| Behavior | Detail |
|---|---|
| XFF parsing | Last hop (depth 1) is the client; left-side spoofed entries are ignored |
| Missing header | Denied when allow is set (unknown is not allowed); permitted for deny-only rules |
| Deny wins | An IP in both lists is blocked |
| Non-HTTP triggers | No-op — there is no client IP outside HTTP |
Runtime configuration
Block an abusive IP from the database and every instance picks it up on the next sync:
const rules = configSource({
plugin: "ip-allowlist",
code: { deny: [] },
db: { store: db },
kv: cache,
});
on(every("30s"), rules.sync());
export const app = oke({ name: "shop", env: "dev" }).plug(ipAllowlist(rules));See Plugins → Runtime configuration for the full contract.
Next
CSRF
Official plugin — cross-site request forgery defense using fetch metadata (Sec-Fetch-Site) with an Origin fallback. Stateless: no tokens, no cookies, no session reads.
Maintenance Mode
Official plugin — drain HTTP traffic with one flag: every flow returns a 503 ServiceUnavailable envelope with an optional Retry-After, while allow-listed paths and an operator bypass header stay alive.