Two separate discovery footguns, both found while debugging an Authentik
"Redirect URI Error" on a claude.ai custom connector.
RFC 9728 §3.1 puts the metadata for a resource identified by
`https://host/api/mcp` at `/.well-known/oauth-protected-resource/api/mcp`.
Only the root form was served, so clients that derive the metadata URL from
the MCP endpoint URL — rather than reading `resource_metadata` off our 401 —
got Next.js's HTML 404 and failed discovery with a JSON parse error.
Add a `[...path]` route serving the same document with `resource` naming the
suffixed identifier (§3.3 has the client compare it as an exact string, so
echoing the bare origin would be rejected). The document body moves to
`lib/auth/resource-metadata.ts` so the two routes cannot drift apart on
`scopes_supported` — a divergence there costs you the `aud` claim or the
refresh token. Paths are allowlisted rather than wildcarded so this cannot
advertise resources the app does not serve. `buildWwwAuthenticate()` still
points at the root URL; this change is purely additive.
Separately, the redirect URIs an MCP provider needs depend on how clients
reach it: a loopback URI for the CLI, `https://claude.ai/api/mcp/auth_callback`
for a claude.ai custom connector. Registering only the former is what produces
the "Redirect URI Error" page, and a portless `http://localhost/callback`
entry matches nothing the CLI sends. Document both, keyed on the literal
error text, and note that DCR is enterprise-gated on Authentik so these are
hand-registered on a FOSS instance.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Reviewer flagged two security-relevant items and two operational bugs
on the external-DB + Terraform module merge.
1. Terraform: `enable_execute_command = true` was hardcoded on the app
and embedder services. Production attack surface (anyone with
`ecs:ExecuteCommand` on the service gets a container shell) AND
non-functional today since the task roles have no `ssmmessages:*`
permission. Added a new `enable_execute_command` boolean input
variable defaulting to `false`; when flipped on, the SSM messages
policy is conditionally attached to both task roles so the feature
actually works. README's variable description tells operators to
flip on for incidents, off afterward.
2. Terraform: `secret_arns` output was not marked `sensitive`. The ARNs
themselves aren't secrets, but the embedded secret names print to
`terraform apply` stdout and CI logs. Marked sensitive on both the
module output and the example output. Operators wanting the values
can still `terraform output -json secret_arns`.
3. Terraform: embedder task definition was missing `HOST=0.0.0.0` and
`PORT=8080`. Fargate awsvpc tasks each get their own ENI; default
Node HTTP servers bind 127.0.0.1, which would make every
app→embedder Service Connect call time out. Added both vars to
`embedder_environment`. Also added `NEXT_TELEMETRY_DISABLED=1` to
`app_environment` per the spec's hardening checklist.
4. Compose: docker-compose.external-db.yml uses the `!override` YAML
tag, which requires Docker Compose >= 2.24.0. Silently ignored on
older Compose, causing the `db` dependency to survive the merge and
startup to fail. Documented the minimum version in the override
file's header AND in the main README prerequisites with a deep
link to the External Postgres section.
terraform fmt + validate (module + examples/basic) both clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a terraform/ directory with an opinionated module that deploys
shared-memory to ECS Fargate behind an ALB. The module assumes the
operator already provides the VPC, RDS Postgres, ACM cert, ECR images,
and OIDC clients, and creates everything else: ECS cluster + services,
ALB, Service Connect namespace for app-embedder discovery, EFS-backed
model cache for the embedder, Secrets Manager entries, IAM roles,
CloudWatch log groups, and a one-shot migrator task definition.
Includes examples/basic/ with a worked invocation and a README covering
prerequisites, quick start, the post-apply migrator run, image updates,
DNS setup, and a security note. Main README gains a short Mode C
pointer to the terraform/ guide.
Validated with `terraform fmt -check -recursive` and
`terraform validate` against AWS provider 5.x.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>