CtrlK
BlogDocsLog inGet started
Tessl Logo

configuration-http-integrations

caddy-security HTTP integration Caddyfile configuration. Use when creating, reviewing, or modifying route-level authenticate and authorize directives, portal and protected route separation, matcher forms, same-host or split-host auth wiring, auth URL routing and alignment, auth-path collisions such as upstream /auth routes, dedicated auth hosts with root-mounted portals, portal-owned path prefixes to avoid, or unnecessary global Caddy directive-order overrides.

76

Quality

96%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

SKILL.md
Quality
Evals
Security

Configuration HTTP Integrations

Purpose

Use this skill to wire caddy-security's route-level HTTP integrations: authenticate [<matcher>] with <portal> and authorize [<matcher>] with <policy>.

The security app defines authentication portals and authorization policies; the HTTP integrations attach those configured objects to Caddy routes. Use configuration-authentication for portal internals and configuration-authorization for policy internals.

Prefer names that reveal the referenced object type in generated examples, such as myportal or local_portal for portals and app_policy or local_policy for policies. Policy names are not required to end in _policy, but the suffix makes authorize with <policy> intent clear.

Read these files when details matter:

  • plugin_authn.go for authenticate syntax and directive order.
  • plugin_authz.go for authorize syntax and directive order.
  • assets/config/Caddyfile, assets/config/home.Caddyfile, and assets/config/multiportal.Caddyfile for current route shapes.
  • testdata/caddyfile_adapt/testcase_authenticate_ok.Caddyfile, testdata/caddyfile_adapt/testcase_authorize_ok.Caddyfile, and testdata/caddyfile_adapt/testcase_authenticate_with_registration.Caddyfile for focused adapt fixtures.

Route Roles

authenticate serves the authentication portal. Put it on the portal host or portal path, such as /auth*. It is not the access-control layer for a file server or upstream app.

authorize protects resource routes. It loads an authorization policy, checks tokens or configured auth proxy methods, injects authenticated identity where configured, and redirects unauthenticated browser users to the policy's auth URL.

Keep portal and protected-resource routes separate:

example.com {
	route /auth* {
		authenticate with myportal
	}

	route /app* {
		authorize with app_policy
		reverse_proxy 127.0.0.1:8080
	}
}

For same-host browser login, put the portal route before a catch-all protected route so the portal is not itself protected by authorize:

https://localhost:8443 {
	route /auth* {
		authenticate with local_portal
	}

	route {
		authorize with local_policy
		root * /srv/files
		file_server browse
	}
}

The referenced policy should point browser users to the portal:

authorization policy local_policy {
	crypto key verify {env.JWT_SHARED_KEY}
	set auth url /auth
	allow roles authp/user
}

For split-host deployments, put authenticate on the auth host and authorize only on the protected app or asset host. Use a full auth URL when the portal is on a different host.

Portal Path Selection

The authorization policy's set auth url must align with the path where the authentication portal is actually served:

  • Same host: use the portal route path, such as /auth for route /auth*.
  • Same host with path conflict: use /xauth for route /xauth*.
  • Dedicated auth host at root: use the full root URL, such as https://auth.example.com/.

Do not leave set auth url at the /auth default when the portal is mounted at /xauth, /, or a different host. For split-host deployments, prefer the full portal URL over a relative path.

Use /auth as the default portal route path in new examples:

route /auth* {
	authenticate with myportal
}

Use a different portal path, commonly /xauth, when the protected upstream application already owns /auth for its own login, callbacks, API endpoints, or framework routes. In that case, do not shadow the upstream's /auth path with caddy-security's portal route; mount the portal elsewhere and point the authorization policy's set auth url to that path:

authorization policy app_policy {
	crypto key verify {env.JWT_SHARED_KEY}
	set auth url /xauth
	allow roles authp/user
}

app.example.com {
	route /xauth* {
		authenticate with app_portal
	}

	route {
		authorize with app_policy
		reverse_proxy 127.0.0.1:8080
	}
}

Use / when a dedicated auth host serves only the authentication portal for a parent domain. For example, if auth.myfiosgateway.com exists only to serve the portal for the myfiosgateway.com domain and has no upstream app or static content of its own, mounting the portal at root keeps the login URL short and avoids reserving an unnecessary path prefix:

authorization policy app_policy {
	crypto key verify {env.JWT_SHARED_KEY}
	set auth url https://auth.myfiosgateway.com/
	allow roles authp/user
}

auth.myfiosgateway.com {
	route {
		authenticate with domain_portal
	}
}

app.myfiosgateway.com {
	route {
		authorize with app_policy
		reverse_proxy 127.0.0.1:8080
	}
}

Do not mount the portal at / on a host that also needs to serve an upstream application or other site content; use /auth or /xauth in that case.

Avoid Portal-Owned Prefixes

Do not use a portal-owned endpoint family as the public mount prefix for authenticate. These names are valid internal endpoints below the chosen base path, such as /auth/login, but they SHOULD NOT be the base path itself:

  • /api, including /api/refresh_token, /api/profile, and admin API endpoints.
  • /qrcode.
  • /assets and /favicon.
  • /profile.
  • /portal.
  • /recover and /forgot.
  • /register.
  • /whoami.
  • /apps, especially /apps/sso and /apps/mobile-access.
  • /oauth2 and /saml.
  • /basic and /basic/login.
  • /barcode, especially /barcode/mfa.
  • /sandbox.
  • /login and /logout.
  • /beacon for JSON/API-style requests.

go-authcrunch dispatches several portal requests with substring or suffix checks before falling back to generic base-path inference. A mount such as /api, /profile, /portal, or /login can therefore make ordinary portal login, callback, static asset, refresh-token, or JSON requests hit the wrong internal handler.

Prefer /auth for ordinary same-host portals, /xauth when /auth collides with the protected upstream, or / only on a dedicated auth-only host. If an upstream application owns one of the reserved names, leave that upstream path alone and mount the portal at /xauth or a dedicated auth host.

Avoid:

route /api* {
	authenticate with app_portal
}

route /profile* {
	authenticate with app_portal
}

Prefer:

authorization policy app_policy {
	crypto key verify {env.JWT_SHARED_KEY}
	set auth url /xauth
	allow roles authp/user
}

route /xauth* {
	authenticate with app_portal
}

Syntax

Prefer route blocks for clarity:

route /auth* {
	authenticate with myportal
}

route /api/* {
	authorize with api_policy
	reverse_proxy 127.0.0.1:9000
}

The optional matcher form is valid when it keeps the surrounding Caddyfile smaller:

authenticate /auth* with myportal
authorize /api/* with api_policy

The portal or policy name must match a configured object in the security app. Keep subconfiguration inside authentication portal <name> and authorization policy <name> blocks. Do not put policy internals, such as with api key auth ..., under the route-level authorize directive; the route handler parser reads only the directive arguments.

Directive Order

Do not generate global Caddy directive-order overrides for caddy-security:

{
	order authenticate before respond
	order authorize before file_server
}

Also do not generate order authorize before basicauth by default. The plugin already registers its order in code:

  • authenticate before respond
  • authorize before basicauth

Only add global order directives when debugging a proven directive-order conflict with another third-party plugin, and explain the conflicting directive order. Do not use global order directives as a default fix for login failures, redirect loops, or authorization denials.

Legacy docs-site examples and old solution briefs may still include global order authenticate before respond and order authorize before basicauth lines. Treat those examples as historical route-shape references, not as current guidance to copy into new Caddyfiles.

Validation

When changing Caddyfile examples or fixtures, validate with the narrowest adapt-focused test from testing-and-ci. For skill-only edits, run the skill validator from skill-creator.

Repository
greenpau/caddy-security
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.