GioJSdocs
On this page

[[guards]]

Session and cookie gates checked in Rust before routing: a request without the credential is redirected and never reaches Node.

gio.toml
[[guards]]
path = "/admin/*rest"
require_session = true
redirect_to = "/login"

Authentication walks through sessions and guards together.

Reference

KeyDefaultDescription
path (required)string-The path pattern to protect: literal segments, :param and a final *rest. /admin/*rest also covers /admin itself.
require_sessionbooleanfalseRequire a valid, unexpired session from createSessionStorage: the cookie's signature must verify with GIO_SESSION_SECRET (any of its rotated secrets). Read from gio_session, or from the cookie require_cookie names.
require_cookiestring""Alone: require a non-empty cookie of this name - a presence check that proves nothing, so validate the cookie in the page too. With require_session: the name of the session cookie.
redirect_to (required)string-Where a refused request is sent: a path on this site, starting with one /. //host and /\host are refused - a browser reads them as another site.

requireSession, requireCookie and redirectTo - the spellings middleware.ts uses - are accepted too.

Behavior

  • Guards run first, before redirects and rewrites, on the canonical path. Every guard that matches must admit the request; the first one that does not answers 302 to its redirect_to, with the original query string appended.
  • A page a guard admitted goes out Cache-Control: private, no-cache without an ETag, even from the page cache: a CDN never runs the guard.
  • A guard also covers a public/ file at both of its URLs, and the image optimizer refuses (403) to read a guarded file for a visitor the guard turns away.
  • Without a valid GIO_SESSION_SECRET, a require_session guard refuses every request and the server logs an error saying how to generate a secret.
  • Rust's own /_gio endpoints are not guarded.

Errors

A guard that would leave its path open stops startup instead of being skipped. Every such guard is reported in one run, one line each (giojs-server --check-config lists the same lines):

text
gio.toml:1: invalid [[guards]] entry for "/admin/*rest": names no requirement: set require_session = true or a non-empty require_cookie
gio.toml:5: invalid [[guards]] entry for "members/*rest": pattern must start with '/': members/*rest
gio.toml:10: invalid [[guards]] entry for "/a/*rest/c": catch-all segment must be the last segment: /a/*rest/c
gio.toml:15: invalid [[guards]] entry for "/b/*rest": target "//evil.example" is another site (a browser reads a leading // or /\ as one): redirect to another site from a route handler

A misspelled or mistyped key in a guard is reported, but the guards are checked as rules only once it is fixed: without the misspelled key, the guard would only seem to name no requirement.

text
gio.toml:3: unknown key `guards[0].require_sesion` - did you mean `guards[0].require_session`?

Examples

Protect an admin area

gio.toml
[[guards]]
path = "/admin/*rest"
require_session = true
redirect_to = "/login"

/admin/users?page=2 without a session goes to /login?page=2.

gio.toml
[[guards]]
path = "/account/*rest"
require_session = true
require_cookie = "app_session"
redirect_to = "/sign-in"

Keep anonymous traffic out cheaply

gio.toml
[[guards]]
path = "/beta/*rest"
require_cookie = "beta_invite"
redirect_to = "/waitlist"

Good to know

  • Do not guard the redirect_to page itself with the same guard: the browser would be sent in a loop.
  • The guard checks the session's signature and expiry only; roles and permissions belong in getServerSideProps or the route handler.
  • The rules are compiled once at startup; a new GIO_SESSION_SECRET needs a restart.

Not configurable

  • Guards fail closed. A broken guard never leaves its path open: in gio.toml it stops startup, and in middleware.ts (or a middleware.ts that throws while loading) it stops the worker at boot.
  • The refusal is always a 302.

Version history

VersionChanges
v0.1.0-beta.8Added require_session, verified in Rust. A guard with a misspelled key, no requirement, an invalid path or a redirect_to a browser reads as another site (//host) stops startup instead of being skipped. *rest matches zero segments, and admitted pages are never shared by caches.
v0.1.0-beta.6Introduced with require_cookie.