forked from QuantumNous/new-api
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsession_cookie.go
More file actions
84 lines (75 loc) · 2.77 KB
/
Copy pathsession_cookie.go
File metadata and controls
84 lines (75 loc) · 2.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package common
import (
"fmt"
"net"
"net/url"
"os"
"strings"
)
// NormalizeOrigin validates and canonicalizes a browser origin. Only an exact
// scheme/host/effective-port match is meaningful; paths and wildcards are not
// accepted for authentication cookie endpoints.
func NormalizeOrigin(raw string) (string, error) {
raw = strings.TrimSpace(raw)
if raw == "" || raw == "null" || strings.ContainsAny(raw, "\r\n") {
return "", fmt.Errorf("origin is empty or invalid")
}
parsedURL, err := url.Parse(raw)
if err != nil {
return "", fmt.Errorf("invalid origin: %w", err)
}
if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" {
return "", fmt.Errorf("origin scheme must be http or https")
}
if parsedURL.Host == "" || parsedURL.User != nil || parsedURL.RawQuery != "" || parsedURL.Fragment != "" || (parsedURL.Path != "" && parsedURL.Path != "/") {
return "", fmt.Errorf("origin must contain only scheme and host")
}
hostname := strings.ToLower(parsedURL.Hostname())
if hostname == "" || strings.Contains(hostname, "*") {
return "", fmt.Errorf("origin host is empty")
}
port := parsedURL.Port()
normalizedHost := hostname
if strings.Contains(hostname, ":") {
normalizedHost = "[" + hostname + "]"
}
if port == "" || (parsedURL.Scheme == "http" && port == "80") || (parsedURL.Scheme == "https" && port == "443") {
return parsedURL.Scheme + "://" + normalizedHost, nil
}
return parsedURL.Scheme + "://" + net.JoinHostPort(hostname, port), nil
}
func InitSessionCookieSettings() error {
secureRaw := strings.TrimSpace(os.Getenv("SESSION_COOKIE_SECURE"))
trustedURLsRaw := strings.TrimSpace(os.Getenv("SESSION_COOKIE_TRUSTED_URL"))
SessionCookieSecure = false
SessionCookieTrustedURLs = nil
if secureRaw == "" || strings.EqualFold(secureRaw, "false") {
if trustedURLsRaw != "" {
return fmt.Errorf("SESSION_COOKIE_TRUSTED_URL requires SESSION_COOKIE_SECURE=true")
}
return nil
}
if !strings.EqualFold(secureRaw, "true") {
return fmt.Errorf("SESSION_COOKIE_SECURE must be true or false")
}
if trustedURLsRaw == "" {
return fmt.Errorf("SESSION_COOKIE_SECURE=true requires SESSION_COOKIE_TRUSTED_URL")
}
trustedURLs := strings.Split(trustedURLsRaw, ",")
for _, trustedURL := range trustedURLs {
trustedURL = strings.TrimSpace(trustedURL)
if trustedURL == "" {
return fmt.Errorf("SESSION_COOKIE_TRUSTED_URL contains an empty URL")
}
normalizedOrigin, err := NormalizeOrigin(trustedURL)
if err != nil {
return fmt.Errorf("invalid SESSION_COOKIE_TRUSTED_URL: %w", err)
}
if !strings.HasPrefix(normalizedOrigin, "https://") {
return fmt.Errorf("SESSION_COOKIE_TRUSTED_URL must contain only https URLs with hosts")
}
SessionCookieTrustedURLs = append(SessionCookieTrustedURLs, normalizedOrigin)
}
SessionCookieSecure = true
return nil
}