Skip to main content
A proxied route can ask its visitors to sign in before they get through, like Cloudflare Access. They sign in with the provider your people already use, and only the emails, email domains or groups you list get in. The servers behind the route learn who it is from headers, so an internal app needs no login of its own. It works on every proxy kind: DNZ Proxy nodes check visitors themselves; a Traefik or Caddy asks DNZ on every visit (forward auth).

How it works

1

Visitor without a session

The proxy sends the browser to DNZ’s sign-in address, e.g. https://dnz.example.com/api/proxy/access/start.
2

Off to the provider

DNZ sends it on to the provider (authorization code flow with PKCE and a nonce).
3

Back to DNZ

The provider returns to DNZ’s redirect URI. DNZ reads the email, name and groups and checks the route’s policy. Someone not listed sees “Not allowed in”.
4

Back to the site

The browser returns to https://app.example.com/.dnz/access/callback with a two-minute ticket, which the site turns into its own session cookie, then goes on to the page it asked for.
Every later visit carries the cookie, and the servers get: Copies of these headers a visitor sends are always removed first, so the servers can trust them. /.dnz/access/logout on the site signs the visitor out. An API call without a session gets 401 and the “Sign in to continue” page as HTML, JSON or text.
Changing who may come in signs everyone out of that route: a session names the policy it was let in by. Sessions last 5 minutes to 30 days (24 hours by default).

Set it up

1. The sign-in address

Settings → Proxy → Sign-in: DNZ’s address as visitors’ browsers reach it. DNZ suggests the address you opened it on and warns about localhost / 127.0.0.1. The page shows the redirect URI to give your provider, with a copy button.

2. A provider

Add provider picks a guide with the steps at the provider, the redirect URI filled in. Paste the client ID and secret; DNZ tests the issuer right away.

3. A route

In the route dialog, switch on Require sign-in, pick the provider and session length, and list these people, anyone at (email domains, exact) and anyone in group. At least one is needed: a provider like Google signs in anyone with an account.

Each proxy kind

  • DNZ Proxy: each node gets the route’s own key and checks the cookie itself; a signed-in visit never waits on DNZ.
  • Traefik: DNZ sends a forwardAuth middleware pointing at its check, at the address Traefik polls DNZ on.
  • Caddy: a reverse_proxy to DNZ’s check with handle_response copying the identity headers.
With Traefik and Caddy every visit is a round trip to DNZ, so they must reach it. Over HTTPS they check DNZ’s certificate as usual.

Audit, metrics and MCP

Sign-ins are in the audit log as access.sign_in and access.denied, by the email that signed in. dnz_access_sign_ins_total{result} counts them. The MCP tool sign_in_providers lists the providers and the hosts each signs in to; assistants can’t change who may get in.