Files
MealQuest/internal/secureurl/secureurl.go
T
dev_agentandClaude Opus 5.5 e8dafda534
CI / ci (push) Successful in 1m24s
CI / ci (pull_request) Successful in 1m24s
Require HTTPS for OIDC and public URLs; stop logging token responses
Address review findings on a10b24c:

- F1: the OIDC issuer and the discovered authorization, token and JWKS
  endpoints must be https://; plain http:// is allowed only for the
  loopback hosts localhost, 127.0.0.1 and [::1]. Config rejects a remote
  http:// issuer at startup; auth.New rejects a discovered remote http://
  endpoint, naming it, before it is used.
- F2: a failed code exchange is reduced to a fixed category plus the HTTP
  status; the token endpoint's body and error_description are never logged
  or wrapped into the returned error.
- F3: MEALQUEST_PUBLIC_URL must be https:// unless its host is loopback,
  so the Secure login cookie is always sent back on the callback.

The rule lives once, in internal/secureurl.Check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 09:45:33 -04:00

33 lines
1.0 KiB
Go

// Package secureurl holds the one transport rule for URLs that carry
// credentials or session cookies: HTTPS, or plain HTTP to a loopback host for
// local development and tests.
package secureurl
import (
"errors"
"fmt"
"net/url"
"strings"
)
// loopbackHosts are the only hosts plain HTTP is allowed for, compared
// case-insensitively. url.URL's Hostname strips the brackets from "[::1]".
var loopbackHosts = map[string]bool{"localhost": true, "127.0.0.1": true, "::1": true}
// Check reports an error unless u is an absolute https:// URL, or an http://
// URL whose host is localhost, 127.0.0.1 or ::1.
func Check(u *url.URL) error {
switch {
case u.Hostname() == "":
return errors.New("URL has no host")
case u.Scheme == "https":
return nil
case u.Scheme == "http" && loopbackHosts[strings.ToLower(u.Hostname())]:
return nil
case u.Scheme == "http":
return errors.New("plain http:// is allowed only for localhost, 127.0.0.1 or [::1]; use https://")
default:
return fmt.Errorf("unsupported scheme %q (want https://)", u.Scheme)
}
}