func (v *validator) IsValidRedirect(redirect string) bool {
	switch {
	case redirect == "":
		return false
	case strings.HasPrefix(redirect, "/") && !strings.HasPrefix(redirect, "//") && !invalidRedirectRegex.MatchString(redirect):
		return true
	case strings.HasPrefix(redirect, "http://") || strings.HasPrefix(redirect, "https://"):
		redirectURL, err := url.Parse(redirect)
		if err != nil {
			logger.Printf("Rejecting invalid redirect %q: scheme unsupported or missing", redirect)
			return false
		}
		redirectHostname := redirectURL.Hostname()
		for _, allowedDomain := range v.allowedDomains {
			allowedHost, allowedPort := splitHostPort(allowedDomain)
			if allowedHost == "" {
				continue
			}
			if redirectHostname == strings.TrimPrefix(allowedHost, ".") ||
				(strings.HasPrefix(allowedHost, ".") &&
					strings.HasSuffix(redirectHostname, allowedHost)) {
				redirectPort := redirectURL.Port()
				if allowedPort == "*" ||
					allowedPort == redirectPort ||
					(allowedPort == "" && redirectPort == "") {
					return true
				}
			}
		}
		logger.Printf("Rejecting invalid redirect %q: domain / port not in whitelist", redirect)
		return false
	default:
		logger.Printf("Rejecting invalid redirect %q: not an absolute or relative URL", redirect)
		return false
	}
}
IsValidRedirect checks whether the redirect URL is safe and allowed.
package redirect
import (
	"net/url"
	"regexp"
	"strings"
	"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
)
var (
	invalidRedirectRegex = regexp.MustCompile(`[/\\](?:[\s\v]*|\.{1,2})[/\\]`)
)
type Validator interface {
	IsValidRedirect(redirect string) bool
}
func NewValidator(allowedDomains []string) Validator {
	return &validator{
		allowedDomains: allowedDomains,
	}
}
type validator struct {
	allowedDomains []string
}