From e7c0682e45728be5eb6e826292a85b308a31683a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20Sonck?= Date: Mon, 7 Oct 2024 10:57:14 +0200 Subject: [PATCH] feat: also allow localhost equivalent IP addresses (#3778) Instead of only checking for "localhost", also validate through net.ParseIP + IsLoopback whether the host is numerically localhost Signed-off-by: Daniel Sonck --- server/oauth2.go | 18 ++++++++++++++---- server/oauth2_test.go | 21 +++++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/server/oauth2.go b/server/oauth2.go index ec972bea..cc81a8a5 100644 --- a/server/oauth2.go +++ b/server/oauth2.go @@ -668,7 +668,8 @@ func validateRedirectURI(client storage.Client, redirectURI string) bool { return true } - // verify that the host is of form "http://localhost:(port)(path)" or "http://localhost(path)" + // verify that the host is of form "http://localhost:(port)(path)", "http://localhost(path)" or numeric form like + // "http://127.0.0.1:(port)(path)" u, err := url.Parse(redirectURI) if err != nil { return false @@ -676,11 +677,20 @@ func validateRedirectURI(client storage.Client, redirectURI string) bool { if u.Scheme != "http" { return false } - if u.Host == "localhost" { + return isHostLocal(u.Host) +} + +func isHostLocal(host string) bool { + if host == "localhost" || net.ParseIP(host).IsLoopback() { return true } - host, _, err := net.SplitHostPort(u.Host) - return err == nil && host == "localhost" + + host, _, err := net.SplitHostPort(host) + if err != nil { + return false + } + + return host == "localhost" || net.ParseIP(host).IsLoopback() } func validateConnectorID(connectors []storage.Connector, connectorID string) bool { diff --git a/server/oauth2_test.go b/server/oauth2_test.go index 5f5fc3b6..2b733df8 100644 --- a/server/oauth2_test.go +++ b/server/oauth2_test.go @@ -452,6 +452,27 @@ func TestValidRedirectURI(t *testing.T) { redirectURI: "http://localhost", wantValid: true, }, + { + client: storage.Client{ + Public: true, + }, + redirectURI: "http://127.0.0.1:8080/", + wantValid: true, + }, + { + client: storage.Client{ + Public: true, + }, + redirectURI: "http://127.0.0.1:991/bar", + wantValid: true, + }, + { + client: storage.Client{ + Public: true, + }, + redirectURI: "http://127.0.0.1", + wantValid: true, + }, // Both Public + RedirectURIs configured: Could e.g. be a PKCE-enabled web app. { client: storage.Client{