feat: sync HTTP callback OIDC setup
This commit is contained in:
parent
bf72c246b6
commit
f53579416e
26 changed files with 557 additions and 133 deletions
|
|
@ -4,7 +4,6 @@ package config
|
|||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"os"
|
||||
|
|
@ -93,9 +92,11 @@ type Config struct {
|
|||
// TelegramLoginEnabled mounts the self-hosted Telegram Login/OIDC provider
|
||||
// on PublicLinkWebAddr. Secrets are file-backed so they are not exposed in
|
||||
// process listings or accidentally copied into tracked .env templates.
|
||||
TelegramLoginEnabled bool
|
||||
TelegramLoginIssuer string
|
||||
TelegramLoginAllowLoopbackHTTP bool
|
||||
TelegramLoginEnabled bool
|
||||
TelegramLoginIssuer string
|
||||
// TelegramLoginAllowHTTP permits HTTP issuers and registered Login URLs on
|
||||
// any valid host/IP and port. HTTPS remains mandatory when false.
|
||||
TelegramLoginAllowHTTP bool
|
||||
TelegramLoginSigningKeysFile string
|
||||
TelegramLoginCodeKeysFile string
|
||||
TelegramLoginSecretPepperFile string
|
||||
|
|
@ -491,7 +492,7 @@ func Load() (Config, error) {
|
|||
PublicLinkWebAddr: envAllowEmptyOr("TELESRV_PUBLIC_LINK_WEB_ADDR", ""),
|
||||
TelegramLoginEnabled: envBoolOr("TELESRV_TELEGRAM_LOGIN_ENABLE", false),
|
||||
TelegramLoginIssuer: strings.TrimSuffix(envOr("TELESRV_TELEGRAM_LOGIN_ISSUER", publicBaseURL), "/"),
|
||||
TelegramLoginAllowLoopbackHTTP: envBoolOr("TELESRV_TELEGRAM_LOGIN_ALLOW_LOOPBACK_HTTP", false),
|
||||
TelegramLoginAllowHTTP: envBoolOr("TELESRV_TELEGRAM_LOGIN_ALLOW_HTTP", false),
|
||||
TelegramLoginSigningKeysFile: envOr("TELESRV_TELEGRAM_LOGIN_SIGNING_KEYS_FILE", "data/telegram-login/signing-keys.json"),
|
||||
TelegramLoginCodeKeysFile: envOr("TELESRV_TELEGRAM_LOGIN_CODE_KEYS_FILE", "data/telegram-login/code-keys.json"),
|
||||
TelegramLoginSecretPepperFile: envOr("TELESRV_TELEGRAM_LOGIN_SECRET_PEPPER_FILE", "data/telegram-login/client-secret-pepper"),
|
||||
|
|
@ -681,10 +682,8 @@ func validateTelegramLoginConfig(cfg Config) error {
|
|||
switch issuer.Scheme {
|
||||
case "https":
|
||||
case "http":
|
||||
host := issuer.Hostname()
|
||||
ip := net.ParseIP(host)
|
||||
if !cfg.TelegramLoginAllowLoopbackHTTP || (host != "localhost" && (ip == nil || !ip.IsLoopback())) {
|
||||
return fmt.Errorf("TELESRV_TELEGRAM_LOGIN_ISSUER http is allowed only for explicit loopback development")
|
||||
if !cfg.TelegramLoginAllowHTTP {
|
||||
return fmt.Errorf("TELESRV_TELEGRAM_LOGIN_ISSUER http requires TELESRV_TELEGRAM_LOGIN_ALLOW_HTTP=true")
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("TELESRV_TELEGRAM_LOGIN_ISSUER must use https")
|
||||
|
|
|
|||
|
|
@ -435,8 +435,8 @@ func TestLoadTelegramLoginConfig(t *testing.T) {
|
|||
disableDefaultConfigFile(t)
|
||||
t.Setenv("TELESRV_PUBLIC_LINK_WEB_ADDR", "127.0.0.1:2401")
|
||||
t.Setenv("TELESRV_TELEGRAM_LOGIN_ENABLE", "true")
|
||||
t.Setenv("TELESRV_TELEGRAM_LOGIN_ISSUER", "http://127.0.0.1:2401/")
|
||||
t.Setenv("TELESRV_TELEGRAM_LOGIN_ALLOW_LOOPBACK_HTTP", "true")
|
||||
t.Setenv("TELESRV_TELEGRAM_LOGIN_ISSUER", "http://192.0.2.25:2401/")
|
||||
t.Setenv("TELESRV_TELEGRAM_LOGIN_ALLOW_HTTP", "true")
|
||||
t.Setenv("TELESRV_TELEGRAM_LOGIN_SIGNING_KEYS_FILE", "secrets/signing.json")
|
||||
t.Setenv("TELESRV_TELEGRAM_LOGIN_CODE_KEYS_FILE", "secrets/codes.json")
|
||||
t.Setenv("TELESRV_TELEGRAM_LOGIN_SECRET_PEPPER_FILE", "secrets/pepper")
|
||||
|
|
@ -452,8 +452,8 @@ func TestLoadTelegramLoginConfig(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("Load: %v", err)
|
||||
}
|
||||
if !cfg.TelegramLoginEnabled || cfg.TelegramLoginIssuer != "http://127.0.0.1:2401" || !cfg.TelegramLoginAllowLoopbackHTTP {
|
||||
t.Fatalf("telegram login endpoint config = enabled:%v issuer:%q loopback:%v", cfg.TelegramLoginEnabled, cfg.TelegramLoginIssuer, cfg.TelegramLoginAllowLoopbackHTTP)
|
||||
if !cfg.TelegramLoginEnabled || cfg.TelegramLoginIssuer != "http://192.0.2.25:2401" || !cfg.TelegramLoginAllowHTTP {
|
||||
t.Fatalf("telegram login endpoint config = enabled:%v issuer:%q allow_http:%v", cfg.TelegramLoginEnabled, cfg.TelegramLoginIssuer, cfg.TelegramLoginAllowHTTP)
|
||||
}
|
||||
if cfg.TelegramLoginSigningKeysFile != "secrets/signing.json" || cfg.TelegramLoginCodeKeysFile != "secrets/codes.json" || cfg.TelegramLoginSecretPepperFile != "secrets/pepper" {
|
||||
t.Fatalf("telegram login secret files = %q / %q / %q", cfg.TelegramLoginSigningKeysFile, cfg.TelegramLoginCodeKeysFile, cfg.TelegramLoginSecretPepperFile)
|
||||
|
|
@ -484,11 +484,7 @@ func TestValidateTelegramLoginConfigRejectsUnsafeOrUnboundedSettings(t *testing.
|
|||
}{
|
||||
{name: "missing listener", mutate: func(c *Config) { c.PublicLinkWebAddr = "" }},
|
||||
{name: "issuer path", mutate: func(c *Config) { c.TelegramLoginIssuer = "https://login.example.test/oauth" }},
|
||||
{name: "public http", mutate: func(c *Config) {
|
||||
c.TelegramLoginIssuer = "http://login.example.test"
|
||||
c.TelegramLoginAllowLoopbackHTTP = true
|
||||
}},
|
||||
{name: "loopback http disabled", mutate: func(c *Config) { c.TelegramLoginIssuer = "http://127.0.0.1:2401" }},
|
||||
{name: "http disabled", mutate: func(c *Config) { c.TelegramLoginIssuer = "http://192.0.2.25:2401" }},
|
||||
{name: "missing key file", mutate: func(c *Config) { c.TelegramLoginSigningKeysFile = "" }},
|
||||
{name: "request ttl too long", mutate: func(c *Config) { c.TelegramLoginRequestTTL = 16 * time.Minute }},
|
||||
{name: "code ttl too short", mutate: func(c *Config) { c.TelegramLoginCodeTTL = 29 * time.Second }},
|
||||
|
|
@ -508,6 +504,22 @@ func TestValidateTelegramLoginConfigRejectsUnsafeOrUnboundedSettings(t *testing.
|
|||
}
|
||||
}
|
||||
|
||||
func TestValidateTelegramLoginConfigAcceptsHTTPHostAndIPWhenEnabled(t *testing.T) {
|
||||
valid := Config{
|
||||
TelegramLoginEnabled: true, TelegramLoginAllowHTTP: true, PublicLinkWebAddr: "127.0.0.1:2401",
|
||||
TelegramLoginSigningKeysFile: "signing.json", TelegramLoginCodeKeysFile: "codes.json", TelegramLoginSecretPepperFile: "pepper",
|
||||
TelegramLoginRequestTTL: 5 * time.Minute, TelegramLoginCodeTTL: 2 * time.Minute, TelegramLoginIDTokenTTL: time.Hour,
|
||||
TelegramLoginRetention: 7 * 24 * time.Hour, TelegramLoginSweepInterval: 5 * time.Minute, TelegramLoginSweepBatch: 500,
|
||||
}
|
||||
for _, issuer := range []string{"http://login.example.test:3000", "http://192.0.2.25:2401", "http://[2001:db8::25]:2401"} {
|
||||
cfg := valid
|
||||
cfg.TelegramLoginIssuer = issuer
|
||||
if err := validateTelegramLoginConfig(cfg); err != nil {
|
||||
t.Fatalf("issuer %q was rejected: %v", issuer, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadRejectsInvalidPublicBaseURL(t *testing.T) {
|
||||
disableDefaultConfigFile(t)
|
||||
t.Setenv("TELESRV_PUBLIC_BASE_URL", "https://links.example.test/root?tenant=one")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue