diff --git a/idp/dex/config.go b/idp/dex/config.go index c0d7edaae..46d034c12 100644 --- a/idp/dex/config.go +++ b/idp/dex/config.go @@ -504,6 +504,29 @@ func (c *YAMLConfig) Validate() error { return nil } +func buildTotpConfig(auth MFAAuthenticator) (*server.TOTPProvider, error) { + var cfg TOTPConfig + if err := json.Unmarshal(auth.Config, &cfg); err != nil { + return nil, fmt.Errorf("failed to parse TOTP config id: %s - %w", auth.ID, err) + } + + return server.NewTOTPProvider(cfg.Issuer, auth.ConnectorTypes), nil +} + +func buildWebAuthnConfig(auth MFAAuthenticator, issuerURL string) (*server.WebAuthnProvider, error) { + var cfg WebAuthnConfig + if err := json.Unmarshal(auth.Config, &cfg); err != nil { + return nil, fmt.Errorf("failed to parse WebAuthn config id: %s - %w", auth.ID, err) + } + provider, err := server.NewWebAuthnProvider(cfg.RPDisplayName, cfg.RPID, cfg.RPOrigins, + cfg.AttestationPreference, cfg.Timeout, issuerURL, auth.ConnectorTypes) + if err != nil { + return nil, fmt.Errorf("failed to create WebAuthn provider id: %s - err: %w", auth.ID, err) + } + + return provider, nil +} + func buildMFAProviders(authenticators []MFAAuthenticator, issuerURL string, logger *slog.Logger) map[string]server.MFAProvider { if len(authenticators) == 0 { return nil @@ -513,23 +536,17 @@ func buildMFAProviders(authenticators []MFAAuthenticator, issuerURL string, logg for _, auth := range authenticators { switch auth.Type { case "TOTP": - var cfg TOTPConfig - if err := json.Unmarshal(auth.Config, &cfg); err != nil { + provider, err := buildTotpConfig(auth) + if err != nil { logger.Error("failed to parse TOTP config", "id", auth.ID, "err", err) continue } - providers[auth.ID] = server.NewTOTPProvider(cfg.Issuer, auth.ConnectorTypes) + providers[auth.ID] = provider logger.Info("MFA authenticator configured", "id", auth.ID, "type", auth.Type) case "WebAuthn": - var cfg WebAuthnConfig - if err := json.Unmarshal(auth.Config, &cfg); err != nil { - logger.Error("failed to parse WebAuthn config", "id", auth.ID, "err", err) - continue - } - provider, err := server.NewWebAuthnProvider(cfg.RPDisplayName, cfg.RPID, cfg.RPOrigins, - cfg.AttestationPreference, cfg.Timeout, issuerURL, auth.ConnectorTypes) + provider, err := buildWebAuthnConfig(auth, issuerURL) if err != nil { - logger.Error("failed to create WebAuthn provider", "id", auth.ID, "err", err) + logger.Error("failed to parse WebAuthn config", "id", auth.ID, "err", err) continue } providers[auth.ID] = provider diff --git a/management/server/idp/embedded.go b/management/server/idp/embedded.go index d3b3685cb..701779374 100644 --- a/management/server/idp/embedded.go +++ b/management/server/idp/embedded.go @@ -177,37 +177,8 @@ func (c *EmbeddedIdPConfig) ToYAMLConfig() (*dex.YAMLConfig, error) { } if c.EnableMFA { - totpConfig := dex.TOTPConfig{ - Issuer: "Netbird", - } - - rawTotpConfig, err := json.Marshal(totpConfig) - if err != nil { - return nil, fmt.Errorf("failed to marshal TOTP config: %v", err) - } - - cfg.MFA.Authenticators = []dex.MFAAuthenticator{{ - ID: "default-totp", - // Has to be caps otherwise it will fail - Type: "TOTP", - Config: rawTotpConfig, - ConnectorTypes: []string{}, - }} - - rememberMeEnabled := false - - cfg.Sessions = &dex.Sessions{ - CookieName: "netbird-session", - AbsoluteLifetime: "24h", - ValidIfNotUsedFor: "1h", - RememberMeCheckedByDefault: &rememberMeEnabled, - SSOSharedWithDefault: "", - } - // Absolutely required, otherwsise the dex server will omit the MFA configuration entirely - os.Setenv("DEX_SESSIONS_ENABLED", "true") - - for i := range cfg.StaticClients { - cfg.StaticClients[i].MFAChain = []string{"default-totp"} + if err := configureMFA(cfg); err != nil { + return nil, err } } @@ -230,6 +201,42 @@ func (c *EmbeddedIdPConfig) ToYAMLConfig() (*dex.YAMLConfig, error) { return cfg, nil } +func configureMFA(cfg *dex.YAMLConfig) error { + totpConfig := dex.TOTPConfig{ + Issuer: "Netbird", + } + + rawTotpConfig, err := json.Marshal(totpConfig) + if err != nil { + return fmt.Errorf("failed to marshal TOTP config: %v", err) + } + + cfg.MFA.Authenticators = []dex.MFAAuthenticator{{ + ID: "default-totp", + // Has to be caps otherwise it will fail + Type: "TOTP", + Config: rawTotpConfig, + ConnectorTypes: []string{}, + }} + + rememberMeEnabled := false + + cfg.Sessions = &dex.Sessions{ + CookieName: "netbird-session", + AbsoluteLifetime: "24h", + ValidIfNotUsedFor: "1h", + RememberMeCheckedByDefault: &rememberMeEnabled, + SSOSharedWithDefault: "", + } + // Absolutely required, otherwsise the dex server will omit the MFA configuration entirely + os.Setenv("DEX_SESSIONS_ENABLED", "true") + + for i := range cfg.StaticClients { + cfg.StaticClients[i].MFAChain = []string{"default-totp"} + } + return nil +} + // Compile-time check that EmbeddedIdPManager implements Manager interface var _ Manager = (*EmbeddedIdPManager)(nil)