Caddy module to require at-proto authentication and restrict routes to DIDs
1package caddyatprotoauth
2
3import (
4 "net"
5 "net/http"
6 "strings"
7)
8
9// getRequestScheme infers the protocol scheme of the incoming request.
10func getRequestScheme(r *http.Request) string {
11 if r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https" {
12 return "https"
13 }
14 return "http"
15}
16
17// getRequestHost safely extracts the hostname, stripping the port and handling IPv6 literals.
18func getRequestHost(r *http.Request) string {
19 host, _, err := net.SplitHostPort(r.Host)
20 if err != nil {
21 // Fallback if there is no port or if it's malformed
22 return r.Host
23 }
24 return host
25}
26
27// matchDomain checks if the host matches the allowed pattern.
28// Supports exact matches and wildcard prefix matches (e.g., *.example.com).
29func matchDomain(host, pattern string) bool {
30 if host == pattern {
31 return true
32 }
33 if strings.HasPrefix(pattern, "*.") {
34 suffix := pattern[1:] // e.g., ".example.com"
35 return strings.HasSuffix(host, suffix)
36 }
37 return false
38}
39
40// isAllowedDomain checks if the host is allowed by the configured domains.
41func checkAllowedDomain(host string, allowedDomains []string) bool {
42 for _, allowed := range allowedDomains {
43 if matchDomain(host, allowed) {
44 return true
45 }
46 }
47 return false
48}