80 lines
2.9 KiB
Go
80 lines
2.9 KiB
Go
package telegramlogin
|
|
|
|
import (
|
|
"net/url"
|
|
"regexp"
|
|
"strings"
|
|
"unicode"
|
|
|
|
"telesrv/internal/domain"
|
|
)
|
|
|
|
var nativeApplicationIDPattern = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._-]{2,254}$`)
|
|
|
|
func normalizeNativeApplicationID(raw string) (string, error) {
|
|
raw = strings.TrimSpace(raw)
|
|
if !nativeApplicationIDPattern.MatchString(raw) || !strings.Contains(raw, ".") || strings.Contains(raw, "..") {
|
|
return "", domain.ErrTelegramLoginClientInvalid
|
|
}
|
|
return raw, nil
|
|
}
|
|
|
|
func normalizeNativeVerificationID(platform domain.TelegramLoginNativePlatform, raw string) (string, error) {
|
|
raw = strings.ToUpper(strings.TrimSpace(raw))
|
|
switch platform {
|
|
case domain.TelegramLoginNativeIOS:
|
|
if len(raw) != 10 || strings.IndexFunc(raw, func(r rune) bool {
|
|
return !((r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9'))
|
|
}) >= 0 {
|
|
return "", domain.ErrTelegramLoginClientInvalid
|
|
}
|
|
case domain.TelegramLoginNativeAndroid:
|
|
raw = strings.ReplaceAll(raw, ":", "")
|
|
if len(raw) != 64 || strings.IndexFunc(raw, func(r rune) bool {
|
|
return !((r >= 'A' && r <= 'F') || (r >= '0' && r <= '9'))
|
|
}) >= 0 {
|
|
return "", domain.ErrTelegramLoginClientInvalid
|
|
}
|
|
default:
|
|
return "", domain.ErrTelegramLoginClientInvalid
|
|
}
|
|
return raw, nil
|
|
}
|
|
|
|
// NormalizeNativeCallbackURI accepts the exact HTTPS universal/app link or a
|
|
// non-web custom scheme registered for a native application. Query and
|
|
// fragment components are forbidden because OAuth response fields are
|
|
// appended by the provider and must not collide with application input.
|
|
func NormalizeNativeCallbackURI(raw string, allowLoopbackHTTP bool) (string, error) {
|
|
if raw == "" || len(raw) > maxTelegramLoginURLLength || raw != strings.TrimSpace(raw) || strings.IndexFunc(raw, unicode.IsControl) >= 0 {
|
|
return "", domain.ErrTelegramLoginURLInvalid
|
|
}
|
|
u, err := url.Parse(raw)
|
|
if err != nil || !u.IsAbs() || u.Opaque != "" || u.User != nil || u.Host == "" || u.RawQuery != "" || u.Fragment != "" || u.RawPath != "" {
|
|
return "", domain.ErrTelegramLoginURLInvalid
|
|
}
|
|
if strings.EqualFold(u.Scheme, "http") || strings.EqualFold(u.Scheme, "https") {
|
|
normalized, _, err := NormalizeRedirectURI(raw, allowLoopbackHTTP)
|
|
return normalized, err
|
|
}
|
|
scheme := strings.ToLower(u.Scheme)
|
|
if !validAppScheme(scheme) || scheme == "tg" || scheme == "javascript" || scheme == "data" || scheme == "file" || u.Port() != "" {
|
|
return "", domain.ErrTelegramLoginURLInvalid
|
|
}
|
|
host := strings.ToLower(strings.TrimSuffix(u.Hostname(), "."))
|
|
if host == "" || strings.IndexFunc(host, func(r rune) bool {
|
|
return !((r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '-' || r == '.')
|
|
}) >= 0 {
|
|
return "", domain.ErrTelegramLoginURLInvalid
|
|
}
|
|
u.Scheme, u.Host = scheme, host
|
|
return u.String(), nil
|
|
}
|
|
|
|
func normalizeNativeDisplayName(raw string) (string, error) {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" || len(raw) > 128 || strings.IndexFunc(raw, unicode.IsControl) >= 0 {
|
|
return "", domain.ErrTelegramLoginClientInvalid
|
|
}
|
|
return raw, nil
|
|
}
|