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>
33 lines
1.0 KiB
Go
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)
|
|
}
|
|
}
|