diff options
Diffstat (limited to 'internal/handlers')
| -rw-r--r-- | internal/handlers/handler_configuration.go | 28 | ||||
| -rw-r--r-- | internal/handlers/handler_configuration_test.go | 140 | ||||
| -rw-r--r-- | internal/handlers/handler_extended_configuration.go | 32 | ||||
| -rw-r--r-- | internal/handlers/handler_extended_configuration_test.go | 159 | ||||
| -rw-r--r-- | internal/handlers/handler_user_info.go | 18 | ||||
| -rw-r--r-- | internal/handlers/handler_user_info_test.go | 8 | ||||
| -rw-r--r-- | internal/handlers/types.go | 7 |
7 files changed, 162 insertions, 230 deletions
diff --git a/internal/handlers/handler_configuration.go b/internal/handlers/handler_configuration.go index 08d08dc79..0166cab2b 100644 --- a/internal/handlers/handler_configuration.go +++ b/internal/handlers/handler_configuration.go @@ -1,18 +1,30 @@ package handlers -import "github.com/authelia/authelia/internal/middlewares" +import ( + "github.com/authelia/authelia/internal/authentication" + "github.com/authelia/authelia/internal/middlewares" +) -// ConfigurationBody configuration parameters exposed to the frontend. +// ConfigurationBody the content returned by the configuration endpoint. type ConfigurationBody struct { - RememberMe bool `json:"remember_me"` // whether remember me is enabled or not - ResetPassword bool `json:"reset_password"` + AvailableMethods MethodList `json:"available_methods"` + SecondFactorEnabled bool `json:"second_factor_enabled"` // whether second factor is enabled or not. + TOTPPeriod int `json:"totp_period"` } -// ConfigurationGet fetches configuration parameters for frontend mutation. +// ConfigurationGet get the configuration accessible to authenticated users. func ConfigurationGet(ctx *middlewares.AutheliaCtx) { - body := ConfigurationBody{ - RememberMe: ctx.Providers.SessionProvider.RememberMe != 0, - ResetPassword: !ctx.Configuration.AuthenticationBackend.DisableResetPassword, + body := ConfigurationBody{} + body.AvailableMethods = MethodList{authentication.TOTP, authentication.U2F} + body.TOTPPeriod = ctx.Configuration.TOTP.Period + + if ctx.Configuration.DuoAPI != nil { + body.AvailableMethods = append(body.AvailableMethods, authentication.Push) } + + body.SecondFactorEnabled = ctx.Providers.Authorizer.IsSecondFactorEnabled() + ctx.Logger.Tracef("Second factor enabled: %v", body.SecondFactorEnabled) + + ctx.Logger.Tracef("Available methods are %s", body.AvailableMethods) ctx.SetJSONBody(body) //nolint:errcheck // TODO: Legacy code, consider refactoring time permitting. } diff --git a/internal/handlers/handler_configuration_test.go b/internal/handlers/handler_configuration_test.go index d1b64d400..d5e821013 100644 --- a/internal/handlers/handler_configuration_test.go +++ b/internal/handlers/handler_configuration_test.go @@ -5,49 +5,155 @@ import ( "github.com/stretchr/testify/suite" + "github.com/authelia/authelia/internal/authorization" + "github.com/authelia/authelia/internal/configuration/schema" "github.com/authelia/authelia/internal/mocks" - "github.com/authelia/authelia/internal/session" ) -type ConfigurationSuite struct { +type SecondFactorAvailableMethodsFixture struct { suite.Suite - mock *mocks.MockAutheliaCtx } -func (s *ConfigurationSuite) SetupTest() { +func (s *SecondFactorAvailableMethodsFixture) SetupTest() { s.mock = mocks.NewMockAutheliaCtx(s.T()) + s.mock.Ctx.Providers.Authorizer = authorization.NewAuthorizer(schema.AccessControlConfiguration{ + DefaultPolicy: "deny", + Rules: []schema.ACLRule{}, + }) } -func (s *ConfigurationSuite) TearDownTest() { +func (s *SecondFactorAvailableMethodsFixture) TearDownTest() { s.mock.Close() } -func (s *ConfigurationSuite) TestShouldDisableRememberMe() { - s.mock.Ctx.Configuration.Session.RememberMeDuration = "0" - s.mock.Ctx.Providers.SessionProvider = session.NewProvider( - s.mock.Ctx.Configuration.Session) +func (s *SecondFactorAvailableMethodsFixture) TestShouldServeDefaultMethods() { + s.mock.Ctx.Configuration = schema.Configuration{ + TOTP: &schema.TOTPConfiguration{ + Period: schema.DefaultTOTPConfiguration.Period, + }, + } expectedBody := ConfigurationBody{ - RememberMe: false, - ResetPassword: true, + AvailableMethods: []string{"totp", "u2f"}, + SecondFactorEnabled: false, + TOTPPeriod: schema.DefaultTOTPConfiguration.Period, } ConfigurationGet(s.mock.Ctx) s.mock.Assert200OK(s.T(), expectedBody) } -func (s *ConfigurationSuite) TestShouldDisableResetPassword() { - s.mock.Ctx.Configuration.AuthenticationBackend.DisableResetPassword = true +func (s *SecondFactorAvailableMethodsFixture) TestShouldServeDefaultMethodsAndMobilePush() { + s.mock.Ctx.Configuration = schema.Configuration{ + DuoAPI: &schema.DuoAPIConfiguration{}, + TOTP: &schema.TOTPConfiguration{ + Period: schema.DefaultTOTPConfiguration.Period, + }, + } expectedBody := ConfigurationBody{ - RememberMe: true, - ResetPassword: false, + AvailableMethods: []string{"totp", "u2f", "mobile_push"}, + SecondFactorEnabled: false, + TOTPPeriod: schema.DefaultTOTPConfiguration.Period, } ConfigurationGet(s.mock.Ctx) s.mock.Assert200OK(s.T(), expectedBody) } -func TestRunHandlerConfigurationSuite(t *testing.T) { - s := new(ConfigurationSuite) +func (s *SecondFactorAvailableMethodsFixture) TestShouldCheckSecondFactorIsDisabledWhenNoRuleIsSetToTwoFactor() { + s.mock.Ctx.Configuration = schema.Configuration{ + TOTP: &schema.TOTPConfiguration{ + Period: schema.DefaultTOTPConfiguration.Period, + }, + } + s.mock.Ctx.Providers.Authorizer = authorization.NewAuthorizer(schema.AccessControlConfiguration{ + DefaultPolicy: "bypass", + Rules: []schema.ACLRule{ + { + Domains: []string{"example.com"}, + Policy: "deny", + }, + { + Domains: []string{"abc.example.com"}, + Policy: "single_factor", + }, + { + Domains: []string{"def.example.com"}, + Policy: "bypass", + }, + }, + }) + ConfigurationGet(s.mock.Ctx) + s.mock.Assert200OK(s.T(), ConfigurationBody{ + AvailableMethods: []string{"totp", "u2f"}, + SecondFactorEnabled: false, + TOTPPeriod: schema.DefaultTOTPConfiguration.Period, + }) +} + +func (s *SecondFactorAvailableMethodsFixture) TestShouldCheckSecondFactorIsEnabledWhenDefaultPolicySetToTwoFactor() { + s.mock.Ctx.Configuration = schema.Configuration{ + TOTP: &schema.TOTPConfiguration{ + Period: schema.DefaultTOTPConfiguration.Period, + }, + } + s.mock.Ctx.Providers.Authorizer = authorization.NewAuthorizer(schema.AccessControlConfiguration{ + DefaultPolicy: "two_factor", + Rules: []schema.ACLRule{ + { + Domains: []string{"example.com"}, + Policy: "deny", + }, + { + Domains: []string{"abc.example.com"}, + Policy: "single_factor", + }, + { + Domains: []string{"def.example.com"}, + Policy: "bypass", + }, + }, + }) + ConfigurationGet(s.mock.Ctx) + s.mock.Assert200OK(s.T(), ConfigurationBody{ + AvailableMethods: []string{"totp", "u2f"}, + SecondFactorEnabled: true, + TOTPPeriod: schema.DefaultTOTPConfiguration.Period, + }) +} + +func (s *SecondFactorAvailableMethodsFixture) TestShouldCheckSecondFactorIsEnabledWhenSomePolicySetToTwoFactor() { + s.mock.Ctx.Configuration = schema.Configuration{ + TOTP: &schema.TOTPConfiguration{ + Period: schema.DefaultTOTPConfiguration.Period, + }, + } + s.mock.Ctx.Providers.Authorizer = authorization.NewAuthorizer(schema.AccessControlConfiguration{ + DefaultPolicy: "bypass", + Rules: []schema.ACLRule{ + { + Domains: []string{"example.com"}, + Policy: "deny", + }, + { + Domains: []string{"abc.example.com"}, + Policy: "two_factor", + }, + { + Domains: []string{"def.example.com"}, + Policy: "bypass", + }, + }, + }) + ConfigurationGet(s.mock.Ctx) + s.mock.Assert200OK(s.T(), ConfigurationBody{ + AvailableMethods: []string{"totp", "u2f"}, + SecondFactorEnabled: true, + TOTPPeriod: schema.DefaultTOTPConfiguration.Period, + }) +} + +func TestRunSuite(t *testing.T) { + s := new(SecondFactorAvailableMethodsFixture) suite.Run(t, s) } diff --git a/internal/handlers/handler_extended_configuration.go b/internal/handlers/handler_extended_configuration.go deleted file mode 100644 index 2a06f3e90..000000000 --- a/internal/handlers/handler_extended_configuration.go +++ /dev/null @@ -1,32 +0,0 @@ -package handlers - -import ( - "github.com/authelia/authelia/internal/authentication" - "github.com/authelia/authelia/internal/middlewares" -) - -// ExtendedConfigurationBody the content returned by extended configuration endpoint. -type ExtendedConfigurationBody struct { - AvailableMethods MethodList `json:"available_methods"` - DisplayName string `json:"display_name"` - SecondFactorEnabled bool `json:"second_factor_enabled"` // whether second factor is enabled or not. - TOTPPeriod int `json:"totp_period"` -} - -// ExtendedConfigurationGet get the extended configuration accessible to authenticated users. -func ExtendedConfigurationGet(ctx *middlewares.AutheliaCtx) { - body := ExtendedConfigurationBody{} - body.AvailableMethods = MethodList{authentication.TOTP, authentication.U2F} - body.DisplayName = ctx.GetSession().DisplayName - body.TOTPPeriod = ctx.Configuration.TOTP.Period - - if ctx.Configuration.DuoAPI != nil { - body.AvailableMethods = append(body.AvailableMethods, authentication.Push) - } - - body.SecondFactorEnabled = ctx.Providers.Authorizer.IsSecondFactorEnabled() - ctx.Logger.Tracef("Second factor enabled: %v", body.SecondFactorEnabled) - - ctx.Logger.Tracef("Available methods are %s", body.AvailableMethods) - ctx.SetJSONBody(body) //nolint:errcheck // TODO: Legacy code, consider refactoring time permitting. -} diff --git a/internal/handlers/handler_extended_configuration_test.go b/internal/handlers/handler_extended_configuration_test.go deleted file mode 100644 index b974b0758..000000000 --- a/internal/handlers/handler_extended_configuration_test.go +++ /dev/null @@ -1,159 +0,0 @@ -package handlers - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/authelia/authelia/internal/authorization" - "github.com/authelia/authelia/internal/configuration/schema" - "github.com/authelia/authelia/internal/mocks" -) - -type SecondFactorAvailableMethodsFixture struct { - suite.Suite - mock *mocks.MockAutheliaCtx -} - -func (s *SecondFactorAvailableMethodsFixture) SetupTest() { - s.mock = mocks.NewMockAutheliaCtx(s.T()) - s.mock.Ctx.Providers.Authorizer = authorization.NewAuthorizer(schema.AccessControlConfiguration{ - DefaultPolicy: "deny", - Rules: []schema.ACLRule{}, - }) -} - -func (s *SecondFactorAvailableMethodsFixture) TearDownTest() { - s.mock.Close() -} - -func (s *SecondFactorAvailableMethodsFixture) TestShouldServeDefaultMethods() { - s.mock.Ctx.Configuration = schema.Configuration{ - TOTP: &schema.TOTPConfiguration{ - Period: schema.DefaultTOTPConfiguration.Period, - }, - } - expectedBody := ExtendedConfigurationBody{ - AvailableMethods: []string{"totp", "u2f"}, - SecondFactorEnabled: false, - TOTPPeriod: schema.DefaultTOTPConfiguration.Period, - } - - ExtendedConfigurationGet(s.mock.Ctx) - s.mock.Assert200OK(s.T(), expectedBody) -} - -func (s *SecondFactorAvailableMethodsFixture) TestShouldServeDefaultMethodsAndMobilePush() { - s.mock.Ctx.Configuration = schema.Configuration{ - DuoAPI: &schema.DuoAPIConfiguration{}, - TOTP: &schema.TOTPConfiguration{ - Period: schema.DefaultTOTPConfiguration.Period, - }, - } - expectedBody := ExtendedConfigurationBody{ - AvailableMethods: []string{"totp", "u2f", "mobile_push"}, - SecondFactorEnabled: false, - TOTPPeriod: schema.DefaultTOTPConfiguration.Period, - } - - ExtendedConfigurationGet(s.mock.Ctx) - s.mock.Assert200OK(s.T(), expectedBody) -} - -func (s *SecondFactorAvailableMethodsFixture) TestShouldCheckSecondFactorIsDisabledWhenNoRuleIsSetToTwoFactor() { - s.mock.Ctx.Configuration = schema.Configuration{ - TOTP: &schema.TOTPConfiguration{ - Period: schema.DefaultTOTPConfiguration.Period, - }, - } - s.mock.Ctx.Providers.Authorizer = authorization.NewAuthorizer(schema.AccessControlConfiguration{ - DefaultPolicy: "bypass", - Rules: []schema.ACLRule{ - { - Domains: []string{"example.com"}, - Policy: "deny", - }, - { - Domains: []string{"abc.example.com"}, - Policy: "single_factor", - }, - { - Domains: []string{"def.example.com"}, - Policy: "bypass", - }, - }, - }) - ExtendedConfigurationGet(s.mock.Ctx) - s.mock.Assert200OK(s.T(), ExtendedConfigurationBody{ - AvailableMethods: []string{"totp", "u2f"}, - SecondFactorEnabled: false, - TOTPPeriod: schema.DefaultTOTPConfiguration.Period, - }) -} - -func (s *SecondFactorAvailableMethodsFixture) TestShouldCheckSecondFactorIsEnabledWhenDefaultPolicySetToTwoFactor() { - s.mock.Ctx.Configuration = schema.Configuration{ - TOTP: &schema.TOTPConfiguration{ - Period: schema.DefaultTOTPConfiguration.Period, - }, - } - s.mock.Ctx.Providers.Authorizer = authorization.NewAuthorizer(schema.AccessControlConfiguration{ - DefaultPolicy: "two_factor", - Rules: []schema.ACLRule{ - { - Domains: []string{"example.com"}, - Policy: "deny", - }, - { - Domains: []string{"abc.example.com"}, - Policy: "single_factor", - }, - { - Domains: []string{"def.example.com"}, - Policy: "bypass", - }, - }, - }) - ExtendedConfigurationGet(s.mock.Ctx) - s.mock.Assert200OK(s.T(), ExtendedConfigurationBody{ - AvailableMethods: []string{"totp", "u2f"}, - SecondFactorEnabled: true, - TOTPPeriod: schema.DefaultTOTPConfiguration.Period, - }) -} - -func (s *SecondFactorAvailableMethodsFixture) TestShouldCheckSecondFactorIsEnabledWhenSomePolicySetToTwoFactor() { - s.mock.Ctx.Configuration = schema.Configuration{ - TOTP: &schema.TOTPConfiguration{ - Period: schema.DefaultTOTPConfiguration.Period, - }, - } - s.mock.Ctx.Providers.Authorizer = authorization.NewAuthorizer(schema.AccessControlConfiguration{ - DefaultPolicy: "bypass", - Rules: []schema.ACLRule{ - { - Domains: []string{"example.com"}, - Policy: "deny", - }, - { - Domains: []string{"abc.example.com"}, - Policy: "two_factor", - }, - { - Domains: []string{"def.example.com"}, - Policy: "bypass", - }, - }, - }) - ExtendedConfigurationGet(s.mock.Ctx) - s.mock.Assert200OK(s.T(), ExtendedConfigurationBody{ - AvailableMethods: []string{"totp", "u2f"}, - SecondFactorEnabled: true, - TOTPPeriod: schema.DefaultTOTPConfiguration.Period, - }) -} - -func TestRunSuite(t *testing.T) { - s := new(SecondFactorAvailableMethodsFixture) - suite.Run(t, s) -} diff --git a/internal/handlers/handler_user_info.go b/internal/handlers/handler_user_info.go index 7066c6402..410aedad5 100644 --- a/internal/handlers/handler_user_info.go +++ b/internal/handlers/handler_user_info.go @@ -13,7 +13,7 @@ import ( "github.com/authelia/authelia/internal/utils" ) -func loadInfo(username string, storageProvider storage.Provider, preferences *UserPreferences, logger *logrus.Entry) []error { +func loadInfo(username string, storageProvider storage.Provider, userInfo *UserInfo, logger *logrus.Entry) []error { var wg sync.WaitGroup wg.Add(3) @@ -32,9 +32,9 @@ func loadInfo(username string, storageProvider storage.Provider, preferences *Us } if method == "" { - preferences.Method = authentication.PossibleMethods[0] + userInfo.Method = authentication.PossibleMethods[0] } else { - preferences.Method = method + userInfo.Method = method } }() @@ -53,7 +53,7 @@ func loadInfo(username string, storageProvider storage.Provider, preferences *Us return } - preferences.HasU2F = true + userInfo.HasU2F = true }() go func() { @@ -71,7 +71,7 @@ func loadInfo(username string, storageProvider storage.Provider, preferences *Us return } - preferences.HasTOTP = true + userInfo.HasTOTP = true }() wg.Wait() @@ -83,15 +83,17 @@ func loadInfo(username string, storageProvider storage.Provider, preferences *Us func UserInfoGet(ctx *middlewares.AutheliaCtx) { userSession := ctx.GetSession() - preferences := UserPreferences{} - errors := loadInfo(userSession.Username, ctx.Providers.StorageProvider, &preferences, ctx.Logger) + userInfo := UserInfo{} + errors := loadInfo(userSession.Username, ctx.Providers.StorageProvider, &userInfo, ctx.Logger) if len(errors) > 0 { ctx.Error(fmt.Errorf("Unable to load user information"), operationFailedMessage) return } - ctx.SetJSONBody(preferences) //nolint:errcheck // TODO: Legacy code, consider refactoring time permitting. + userInfo.DisplayName = userSession.DisplayName + + ctx.SetJSONBody(userInfo) //nolint:errcheck // TODO: Legacy code, consider refactoring time permitting. } // MethodBody the selected 2FA method. diff --git a/internal/handlers/handler_user_info_test.go b/internal/handlers/handler_user_info_test.go index 4d925787c..44702ec28 100644 --- a/internal/handlers/handler_user_info_test.go +++ b/internal/handlers/handler_user_info_test.go @@ -31,7 +31,7 @@ func (s *FetchSuite) TearDownTest() { s.mock.Close() } -func setPreferencesExpectations(preferences UserPreferences, provider *storage.MockProvider) { +func setPreferencesExpectations(preferences UserInfo, provider *storage.MockProvider) { provider. EXPECT(). LoadPreferred2FAMethod(gomock.Eq("john")). @@ -65,7 +65,7 @@ func setPreferencesExpectations(preferences UserPreferences, provider *storage.M } func TestMethodSetToU2F(t *testing.T) { - table := []UserPreferences{ + table := []UserInfo{ { Method: "totp", }, @@ -97,7 +97,7 @@ func TestMethodSetToU2F(t *testing.T) { setPreferencesExpectations(expectedPreferences, mock.StorageProviderMock) UserInfoGet(mock.Ctx) - actualPreferences := UserPreferences{} + actualPreferences := UserInfo{} mock.GetResponseData(t, &actualPreferences) t.Run("expected method", func(t *testing.T) { @@ -132,7 +132,7 @@ func (s *FetchSuite) TestShouldGetDefaultPreferenceIfNotInDB() { Return("", storage.ErrNoTOTPSecret) UserInfoGet(s.mock.Ctx) - s.mock.Assert200OK(s.T(), UserPreferences{Method: "totp"}) + s.mock.Assert200OK(s.T(), UserInfo{Method: "totp"}) } func (s *FetchSuite) TestShouldReturnError500WhenStorageFailsToLoad() { diff --git a/internal/handlers/types.go b/internal/handlers/types.go index b42b2889b..bcd21f62d 100644 --- a/internal/handlers/types.go +++ b/internal/handlers/types.go @@ -11,8 +11,11 @@ type MethodList = []string type authorizationMatching int -// UserPreferences is the model of user second factor preferences. -type UserPreferences struct { +// UserInfo is the model of user info and second factor preferences. +type UserInfo struct { + // The users display name. + DisplayName string `json:"display_name"` + // The preferred 2FA method. Method string `json:"method" valid:"required"` |
