mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-26 14:29:08 +01:00
[management] fix: device redirect uri wasn't registered (#6191)
* fix: device redirect uri wasn't registered * fix lint
This commit is contained in:
committed by
Viktor Liu
parent
757037b927
commit
e6a05af1ba
@@ -6,7 +6,9 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/dexidp/dex/storage"
|
"github.com/dexidp/dex/storage"
|
||||||
@@ -138,10 +140,13 @@ func (c *EmbeddedIdPConfig) ToYAMLConfig() (*dex.YAMLConfig, error) {
|
|||||||
return nil, fmt.Errorf("invalid IdP storage config: %w", err)
|
return nil, fmt.Errorf("invalid IdP storage config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build CLI redirect URIs including the device callback (both relative and absolute)
|
// Build CLI redirect URIs including the device callback. Dex uses the issuer-relative
|
||||||
|
// path (for example, /oauth2/device/callback) when completing the device flow, so
|
||||||
|
// include it explicitly in addition to the legacy bare path and absolute URL.
|
||||||
cliRedirectURIs := c.CLIRedirectURIs
|
cliRedirectURIs := c.CLIRedirectURIs
|
||||||
cliRedirectURIs = append(cliRedirectURIs, "/device/callback")
|
cliRedirectURIs = append(cliRedirectURIs, "/device/callback")
|
||||||
cliRedirectURIs = append(cliRedirectURIs, c.Issuer+"/device/callback")
|
cliRedirectURIs = append(cliRedirectURIs, issuerRelativeDeviceCallback(c.Issuer))
|
||||||
|
cliRedirectURIs = append(cliRedirectURIs, strings.TrimSuffix(c.Issuer, "/")+"/device/callback")
|
||||||
|
|
||||||
// Build dashboard redirect URIs including the OAuth callback for proxy authentication
|
// Build dashboard redirect URIs including the OAuth callback for proxy authentication
|
||||||
dashboardRedirectURIs := c.DashboardRedirectURIs
|
dashboardRedirectURIs := c.DashboardRedirectURIs
|
||||||
@@ -154,6 +159,10 @@ func (c *EmbeddedIdPConfig) ToYAMLConfig() (*dex.YAMLConfig, error) {
|
|||||||
// MGMT api and the dashboard, adding baseURL means less configuration for the instance admin
|
// MGMT api and the dashboard, adding baseURL means less configuration for the instance admin
|
||||||
dashboardPostLogoutRedirectURIs = append(dashboardPostLogoutRedirectURIs, baseURL)
|
dashboardPostLogoutRedirectURIs = append(dashboardPostLogoutRedirectURIs, baseURL)
|
||||||
|
|
||||||
|
redirectURIs := make([]string, 0)
|
||||||
|
redirectURIs = append(redirectURIs, cliRedirectURIs...)
|
||||||
|
redirectURIs = append(redirectURIs, dashboardRedirectURIs...)
|
||||||
|
|
||||||
cfg := &dex.YAMLConfig{
|
cfg := &dex.YAMLConfig{
|
||||||
Issuer: c.Issuer,
|
Issuer: c.Issuer,
|
||||||
Storage: dex.Storage{
|
Storage: dex.Storage{
|
||||||
@@ -179,14 +188,14 @@ func (c *EmbeddedIdPConfig) ToYAMLConfig() (*dex.YAMLConfig, error) {
|
|||||||
ID: staticClientDashboard,
|
ID: staticClientDashboard,
|
||||||
Name: "NetBird Dashboard",
|
Name: "NetBird Dashboard",
|
||||||
Public: true,
|
Public: true,
|
||||||
RedirectURIs: dashboardRedirectURIs,
|
RedirectURIs: redirectURIs,
|
||||||
PostLogoutRedirectURIs: sanitizePostLogoutRedirectURIs(dashboardPostLogoutRedirectURIs),
|
PostLogoutRedirectURIs: sanitizePostLogoutRedirectURIs(dashboardPostLogoutRedirectURIs),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: staticClientCLI,
|
ID: staticClientCLI,
|
||||||
Name: "NetBird CLI",
|
Name: "NetBird CLI",
|
||||||
Public: true,
|
Public: true,
|
||||||
RedirectURIs: cliRedirectURIs,
|
RedirectURIs: redirectURIs,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
StaticConnectors: c.StaticConnectors,
|
StaticConnectors: c.StaticConnectors,
|
||||||
@@ -217,6 +226,14 @@ func (c *EmbeddedIdPConfig) ToYAMLConfig() (*dex.YAMLConfig, error) {
|
|||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func issuerRelativeDeviceCallback(issuer string) string {
|
||||||
|
u, err := url.Parse(issuer)
|
||||||
|
if err != nil || u.Path == "" {
|
||||||
|
return "/device/callback"
|
||||||
|
}
|
||||||
|
return path.Join(u.Path, "/device/callback")
|
||||||
|
}
|
||||||
|
|
||||||
// Due to how the frontend generates the logout, sometimes it appends a trailing slash
|
// Due to how the frontend generates the logout, sometimes it appends a trailing slash
|
||||||
// and because Dex only allows exact matches, we need to make sure we always have both
|
// and because Dex only allows exact matches, we need to make sure we always have both
|
||||||
// versions of each provided uri
|
// versions of each provided uri
|
||||||
@@ -299,7 +316,7 @@ func resolveSessionCookieEncryptionKey(configuredKey string) (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", fmt.Errorf("invalid embedded IdP session cookie encryption key: %s (or sessionCookieEncryptionKey) must be 16, 24, or 32 bytes as a raw string or base64-encoded to one of those lengths; got %d raw bytes", sessionCookieEncryptionKeyEnv, len([]byte(key)))
|
return "", fmt.Errorf("invalid embedded IdP session cookie encryption key:%s (or sessionCookieEncryptionKey) must be 16, 24, or 32 bytes as a raw string or base64-encoded to one of those lengths; got %d raw bytes", sessionCookieEncryptionKeyEnv, len([]byte(key)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func validSessionCookieEncryptionKeyLength(length int) bool {
|
func validSessionCookieEncryptionKeyLength(length int) bool {
|
||||||
|
|||||||
@@ -314,6 +314,34 @@ func TestEmbeddedIdPManager_UpdateUserPassword(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEmbeddedIdPConfig_ToYAMLConfig_IncludesDeviceCallbackRedirectURI(t *testing.T) {
|
||||||
|
config := &EmbeddedIdPConfig{
|
||||||
|
Enabled: true,
|
||||||
|
Issuer: "https://example.com/oauth2",
|
||||||
|
Storage: EmbeddedStorageConfig{
|
||||||
|
Type: "sqlite3",
|
||||||
|
Config: EmbeddedStorageTypeConfig{
|
||||||
|
File: filepath.Join(t.TempDir(), "dex.db"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
yamlConfig, err := config.ToYAMLConfig()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var cliRedirectURIs []string
|
||||||
|
for _, client := range yamlConfig.StaticClients {
|
||||||
|
if client.ID == staticClientCLI {
|
||||||
|
cliRedirectURIs = client.RedirectURIs
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.NotEmpty(t, cliRedirectURIs)
|
||||||
|
assert.Contains(t, cliRedirectURIs, "/device/callback")
|
||||||
|
assert.Contains(t, cliRedirectURIs, "/oauth2/device/callback")
|
||||||
|
assert.Contains(t, cliRedirectURIs, "https://example.com/oauth2/device/callback")
|
||||||
|
}
|
||||||
|
|
||||||
func TestEmbeddedIdPConfig_ToYAMLConfig_SessionCookieEncryptionKey(t *testing.T) {
|
func TestEmbeddedIdPConfig_ToYAMLConfig_SessionCookieEncryptionKey(t *testing.T) {
|
||||||
t.Setenv(sessionCookieEncryptionKeyEnv, "")
|
t.Setenv(sessionCookieEncryptionKeyEnv, "")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user