NGINX edge verification
wayid-nginx verifies the WayID of inbound agents at
the NGINX edge — before a request ever reaches your application. It’s a single njs handler plus a
sample config; passive v1 verification needs no crypto, so there’s no sidecar process to run.
Like the language SDKs, it reads the self-asserted WayID request header,
resolves it against {issuer}/api/v1/agent/{did}, caches the result, and fails open by default.
How it works
Section titled “How it works”The njs handler (njs/wayid.js), wired with js_content, reads the header, resolves it, and:
- forwards
X-WayID-Decision/X-WayID-Verified/X-WayID-DID/X-WayID-Identity-Level/X-WayID-Statusto your upstream (viajs_vars), theninternalRedirects to it; - returns
403instead when$wayid_enforceisonand the decision isdeny.
Resolutions are cached in a shared dict for the zone TTL, so the edge doesn’t hit the issuer on every request.
Why
js_content, notauth_request? njs’sngx.fetchdoes not run inside anauth_requestsubrequest, so the natural-lookingauth_requestdesign doesn’t work for a handler that calls the issuer. The working pattern isjs_content→ resolve →internalRedirectto the upstream. (If your NGINX build lacks njs, you can instead run the JS package’swithWayIdworker adapter as a small HTTP service and pointauth_requestat it.)
Install
Section titled “Install”-
Build/run NGINX with the njs module (
ngx_http_js_module). On Debian/Ubuntu:apt-get install nginx-module-njs, thenload_module modules/ngx_http_js_module.so;. The officialnginxDocker image already ships the module. -
Copy
njs/wayid.jsto/etc/nginx/njs/. -
In
http {}:js_path "/etc/nginx/njs/";js_import wayid from wayid.js;js_var $wayid_decision;js_var $wayid_verified;js_var $wayid_did;js_var $wayid_level;js_var $wayid_status;resolver 1.1.1.1 ipv6=off; # ngx.fetch needs a resolverjs_shared_dict_zone zone=wayid:1m timeout=60s; # optional resolution cache -
Use
conf/wayid.confas the template for theserver {}block — alocation /withjs_content wayid.gate;and aninternallocation @wayid_upstreamthatproxy_passes to your app.
Configuration
Section titled “Configuration”| nginx variable | default | meaning |
|---|---|---|
$wayid_issuer | https://way.je | issuer origin that minted the DIDs |
$wayid_enforce | off | on ⇒ return 403 on a deny decision |
$wayid_require_verified | off | on ⇒ require owner identityLevel == "verified" |
Distribution
Section titled “Distribution”There’s no package-registry artifact — it’s a single handler plus a sample config. Get it one of two ways:
- Tagged GitHub release (recommended). Each
v*tag publishes a release withnjs/wayid.jsandconf/wayid.confattached. Downloadwayid.js, drop it in/etc/nginx/njs/, and wire up your config. - Clone / vendor. Copy
njs/wayid.jsinto your repo or config management (Ansible, Docker build, etc.). Pin to a tag for reproducibility.
test/run.sh in the repo runs the handler in real NGINX + njs (Docker) against a mock issuer and
asserts allow / deny / flag behaviour.
Status
Section titled “Status”Prototype for WayID issue #373. Passive v1 only; cryptographic proof-of-possession (v2) is a planned layer — see Verified Agent Gateway.