package http import ( errorsAs "errors" "fmt" "io" "net" "net/http" "github.com/zitadel/zitadel/internal/zerrors" ) type CheckType int const ( CheckTypeHTTP CheckType = iota CheckTypeDNS HTTPPattern = "https://%s/.well-known/zitadel-challenge/%s.txt" DNSPattern = "_zitadel-challenge.%s" ) func ValidateDomain(domain, token, verifier string, checkType CheckType) error { switch checkType { case CheckTypeHTTP: return ValidateDomainHTTP(domain, token, verifier) case CheckTypeDNS: return ValidateDomainDNS(domain, verifier) default: return zerrors.ThrowInvalidArgument(nil, "HTTP-Iqd11", "Errors.Internal") } } func ValidateDomainHTTP(domain, token, verifier string) error { resp, err := http.Get(tokenUrlHTTP(domain, token)) if err != nil { return zerrors.ThrowInternal(err, "HTTP-BH42h", "Errors.Internal") } if resp.StatusCode != 200 { if resp.StatusCode == 404 { return zerrors.ThrowNotFound(err, "ORG-F4zhw", "Errors.Org.DomainVerificationHTTPNotFound") } return zerrors.ThrowInternal(err, "HTTP-G2zsw", "Errors.Internal") } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return zerrors.ThrowInternal(err, "HTTP-HB432", "Errors.Internal") } if string(body) == verifier { return nil } return zerrors.ThrowNotFound(err, "ORG-GH422", "Errors.Org.DomainVerificationHTTPNoMatch") } func ValidateDomainDNS(domain, verifier string) error { txtRecords, err := net.LookupTXT(tokenUrlDNS(domain)) if err != nil { var dnsError *net.DNSError if errorsAs.As(err, &dnsError) { if dnsError.IsNotFound { return zerrors.ThrowNotFound(err, "ORG-G241f", "Errors.Org.DomainVerificationTXTNotFound") } if dnsError.IsTimeout { return zerrors.ThrowNotFound(err, "ORG-K563l", "Errors.Org.DomainVerificationTimeout") } } return zerrors.ThrowInternal(err, "HTTP-Hwsw2", "Errors.Internal") } for _, record := range txtRecords { if record == verifier { return nil } } return zerrors.ThrowNotFound(err, "ORG-G28if", "Errors.Org.DomainVerificationTXTNoMatch") } func TokenUrl(domain, token string, checkType CheckType) (string, error) { switch checkType { case CheckTypeHTTP: return tokenUrlHTTP(domain, token), nil case CheckTypeDNS: return tokenUrlDNS(domain), nil default: return "", zerrors.ThrowInvalidArgument(nil, "HTTP-Iqd11", "") } } func tokenUrlHTTP(domain, token string) string { return fmt.Sprintf(HTTPPattern, domain, token) } func tokenUrlDNS(domain string) string { return fmt.Sprintf(DNSPattern, domain) }