Skip to main content

External HTTP authorization

AuthCrunch v1.5.0 can require an external policy-service decision on every authenticated request. Install the external-authorization-httpjson companion. Credential verification and local ACLs run first. Remote allow cannot override their denial, and local allow does not skip a configured external decision.

Configure the policy​

Add one flat block inside your existing authorization policy:

external authorization httpjson {
endpoint https://policy.example.com/decide
policy reports
version production
issuer https://auth.example.com/auth/login
realm local
attribute roles
timeout 500ms
tls ca file /etc/caddy/policy-ca.pem
tls client certificate /etc/caddy/policy-client.pem /etc/caddy/policy-client-key.pem
}

Retain ordinary token verification, discovery and allow roles app/member in the surrounding policy. Mount it before the protected handler using authorize with POLICY_NAME. The service must echo reports and production exactly; these identify your decision contract, not software release versions.

issuer and realm bind exact authenticated claims. subject claim defaults to sub; optionally select an authoritative immutable subject and a distinct tenant claim. Up to 16 repeated attribute statements select original top-level authenticated claims. Omitted attributes are not sent. Do not select passwords, tokens or credentials.

Bind a stable browser issuer​

Native and browser checkpoint login can otherwise produce different issuers. For a portal using the local realm, this fragment deliberately chooses the issuer used by the policy above:

transform user {
match realm local
action overwrite iss https://auth.example.com/auth/login
}

Place it inside that portal and inspect a newly issued token before enabling the external binding. Check all authentication methods using the transform. Unmodified direct Basic/API-key and direct OAuth sessions have different issuer/origin contracts; do not assume this browser value applies to them.

Implement the service contract​

The service receives POST JSON with policy, version, identity, action, resource and any selected attributes. Identity contains issuer, realm, subject and optionally tenant. Action is the HTTP method; resource is the path. Incoming query strings, headers, cookies and bodies are not implicitly forwarded. Claims enrichment affects local ACLs only; external attributes retain the original authenticated values.

A valid allow response is HTTP 200 with Content-Type: application/json:

{"decision":"allow","policy":"reports","version":"production"}

Return "deny" for denial. The body must contain exactly these three case-sensitive string fields and be at most 4096 bytes. Duplicate or unknown fields, obligations, a contract mismatch, malformed JSON, redirects, other statuses/media types, transport errors and late responses deny access. There is no decision cache or automatic application retry.

Transport and failure behavior​

Use HTTPS, or HTTP on a literal loopback IP for an isolated fixture. Endpoints cannot contain URL credentials, query or fragment. Optional CA files replace system roots for this backend. Optional mTLS files authenticate the service client; they do not identify the end user. TLS retains hostname verification. Fields in this block do not expand runtime placeholders or secret references.

The default timeout is 1s; allowed values are 1ms–30s. Request cancellation and credential expiry can shorten it. Every supported interpretation of an ambiguous path must allow within that shared deadline. Explicit bypass rules skip this check as well as authentication, so review them as deliberate access grants.

The decision is fresh for token cache hits, Basic/API-key requests and existing direct OAuth sessions. Direct OAuth also checks callback admission. An outage denies the protected request without silently reusing a previous allow or clearing an otherwise valid credential. Test local denial with remote allow, local allow with remote deny, service outage, TLS failure and changing decisions for repeated use of the same token. Confirm that the protected handler receives no denied requests and that the service receives no incoming credentials.

Agentic Prompts​

Use a prompt to investigate this topic against your deployed version.

Trace decision precedence
Primary authorities, before website documentation:
https://github.com/greenpau/caddy-security/blob/main/AGENTS.md
https://github.com/greenpau/caddy-security/tree/main/.codex/skills
https://github.com/greenpau/go-authcrunch/blob/main/AGENTS.md
https://github.com/greenpau/go-authcrunch/tree/main/.codex/skills
Read each root AGENTS.md first, any scoped AGENTS.md applying to inspected
paths, then relevant SKILL.md files and their implementation/test references.
Relevant skills to locate: configuration-authorization; external-authorization.
Distinguish main from caddy-security v1.5.0 / go-authcrunch v1.4.1 and my
deployed version. Resolve disagreements with linked code/tests; keep unverified
behavior uncertain. If sources are inaccessible, ask for pasted content.
Use only synthetic or redacted inputs.
Secondary context: https://docs.authcrunch.com/docs/authorize/external-authorization

Trace local authentication, ACLs and external decisions for four allow/deny combinations. Include explicit bypass and a cached access token.
Bind the right identity
Primary authorities, before website documentation:
https://github.com/greenpau/caddy-security/blob/main/AGENTS.md
https://github.com/greenpau/caddy-security/tree/main/.codex/skills
https://github.com/greenpau/go-authcrunch/blob/main/AGENTS.md
https://github.com/greenpau/go-authcrunch/tree/main/.codex/skills
Read each root AGENTS.md first, any scoped AGENTS.md applying to inspected
paths, then relevant SKILL.md files and their implementation/test references.
Relevant skills to locate: configuration-authorization; external-authorization.
Distinguish main from caddy-security v1.5.0 / go-authcrunch v1.4.1 and my
deployed version. Resolve disagreements with linked code/tests; keep unverified
behavior uncertain. If sources are inaccessible, ask for pasted content.
Use only synthetic or redacted inputs.
Secondary context: https://docs.authcrunch.com/docs/authorize/external-authorization

Explain issuer differences between native login, browser checkpoints, Basic/API-key and direct OAuth. Derive a stable browser issuer configuration from the parser and test it without weakening exact binding.
Implement a decision service
Primary authorities, before website documentation:
https://github.com/greenpau/caddy-security/blob/main/AGENTS.md
https://github.com/greenpau/caddy-security/tree/main/.codex/skills
https://github.com/greenpau/go-authcrunch/blob/main/AGENTS.md
https://github.com/greenpau/go-authcrunch/tree/main/.codex/skills
Read each root AGENTS.md first, any scoped AGENTS.md applying to inspected
paths, then relevant SKILL.md files and their implementation/test references.
Relevant skills to locate: configuration-authorization; external-authorization.
Distinguish main from caddy-security v1.5.0 / go-authcrunch v1.4.1 and my
deployed version. Resolve disagreements with linked code/tests; keep unverified
behavior uncertain. If sources are inaccessible, ask for pasted content.
Use only synthetic or redacted inputs.
Secondary context: https://docs.authcrunch.com/docs/authorize/external-authorization

Describe exact request/response schemas and negative responses for a synthetic HTTP JSON service. Identify data intentionally omitted and why enriched ACL values do not become authenticated service attributes.
Analyze service failures
Primary authorities, before website documentation:
https://github.com/greenpau/caddy-security/blob/main/AGENTS.md
https://github.com/greenpau/caddy-security/tree/main/.codex/skills
https://github.com/greenpau/go-authcrunch/blob/main/AGENTS.md
https://github.com/greenpau/go-authcrunch/tree/main/.codex/skills
Read each root AGENTS.md first, any scoped AGENTS.md applying to inspected
paths, then relevant SKILL.md files and their implementation/test references.
Relevant skills to locate: configuration-authorization; external-authorization.
Distinguish main from caddy-security v1.5.0 / go-authcrunch v1.4.1 and my
deployed version. Resolve disagreements with linked code/tests; keep unverified
behavior uncertain. If sources are inaccessible, ask for pasted content.
Use only synthetic or redacted inputs.
Secondary context: https://docs.authcrunch.com/docs/authorize/external-authorization

Analyze timeout, cancellation, mTLS failure, redirects, oversized JSON and an ambiguous path. Explain fail-closed outcomes and the absence of decision caching or automatic retries.
Plan acceptance checks
Primary authorities, before website documentation:
https://github.com/greenpau/caddy-security/blob/main/AGENTS.md
https://github.com/greenpau/caddy-security/tree/main/.codex/skills
https://github.com/greenpau/go-authcrunch/blob/main/AGENTS.md
https://github.com/greenpau/go-authcrunch/tree/main/.codex/skills
Read each root AGENTS.md first, any scoped AGENTS.md applying to inspected
paths, then relevant SKILL.md files and their implementation/test references.
Relevant skills to locate: configuration-authorization; external-authorization.
Distinguish main from caddy-security v1.5.0 / go-authcrunch v1.4.1 and my
deployed version. Resolve disagreements with linked code/tests; keep unverified
behavior uncertain. If sources are inaccessible, ask for pasted content.
Use only synthetic or redacted inputs.
Secondary context: https://docs.authcrunch.com/docs/authorize/external-authorization

Design a trusted local policy-service fixture testing changing decisions for one token, local denial precedence and credential isolation. Separate TLS provisioning from parser adaptation.

Source Code References​