diff options
Diffstat (limited to 'internal/handlers')
| -rw-r--r-- | internal/handlers/const.go | 1 | ||||
| -rw-r--r-- | internal/handlers/handler_extended_configuration_test.go | 18 | ||||
| -rw-r--r-- | internal/handlers/handler_firstfactor_test.go | 14 | ||||
| -rw-r--r-- | internal/handlers/handler_register_u2f_step1_test.go | 7 | ||||
| -rw-r--r-- | internal/handlers/handler_register_u2f_step2.go | 4 | ||||
| -rw-r--r-- | internal/handlers/handler_user_info_test.go | 9 | ||||
| -rw-r--r-- | internal/handlers/handler_verify.go | 40 | ||||
| -rw-r--r-- | internal/handlers/handler_verify_test.go | 62 | ||||
| -rw-r--r-- | internal/handlers/types.go | 6 |
9 files changed, 69 insertions, 92 deletions
diff --git a/internal/handlers/const.go b/internal/handlers/const.go index 5d57ff1db..b2afb2855 100644 --- a/internal/handlers/const.go +++ b/internal/handlers/const.go @@ -33,4 +33,3 @@ const unableToRegisterOneTimePasswordMessage = "Unable to set up one-time passwo const unableToRegisterSecurityKeyMessage = "Unable to register your security key." const unableToResetPasswordMessage = "Unable to reset your password." const mfaValidationFailedMessage = "Authentication failed, please retry later." -const badBasicAuthFormatMessage = "Content of Proxy-Authorization header is wrong." diff --git a/internal/handlers/handler_extended_configuration_test.go b/internal/handlers/handler_extended_configuration_test.go index 9f41b3ecf..1065899b8 100644 --- a/internal/handlers/handler_extended_configuration_test.go +++ b/internal/handlers/handler_extended_configuration_test.go @@ -67,15 +67,15 @@ func (s *SecondFactorAvailableMethodsFixture) TestShouldCheckSecondFactorIsDisab s.mock.Ctx.Providers.Authorizer = authorization.NewAuthorizer(schema.AccessControlConfiguration{ DefaultPolicy: "bypass", Rules: []schema.ACLRule{ - schema.ACLRule{ + { Domain: "example.com", Policy: "deny", }, - schema.ACLRule{ + { Domain: "abc.example.com", Policy: "single_factor", }, - schema.ACLRule{ + { Domain: "def.example.com", Policy: "bypass", }, @@ -98,15 +98,15 @@ func (s *SecondFactorAvailableMethodsFixture) TestShouldCheckSecondFactorIsEnabl s.mock.Ctx.Providers.Authorizer = authorization.NewAuthorizer(schema.AccessControlConfiguration{ DefaultPolicy: "two_factor", Rules: []schema.ACLRule{ - schema.ACLRule{ + { Domain: "example.com", Policy: "deny", }, - schema.ACLRule{ + { Domain: "abc.example.com", Policy: "single_factor", }, - schema.ACLRule{ + { Domain: "def.example.com", Policy: "bypass", }, @@ -129,15 +129,15 @@ func (s *SecondFactorAvailableMethodsFixture) TestShouldCheckSecondFactorIsEnabl s.mock.Ctx.Providers.Authorizer = authorization.NewAuthorizer(schema.AccessControlConfiguration{ DefaultPolicy: "bypass", Rules: []schema.ACLRule{ - schema.ACLRule{ + { Domain: "example.com", Policy: "deny", }, - schema.ACLRule{ + { Domain: "abc.example.com", Policy: "two_factor", }, - schema.ACLRule{ + { Domain: "def.example.com", Policy: "bypass", }, diff --git a/internal/handlers/handler_firstfactor_test.go b/internal/handlers/handler_firstfactor_test.go index e15bf13b3..7d8901716 100644 --- a/internal/handlers/handler_firstfactor_test.go +++ b/internal/handlers/handler_firstfactor_test.go @@ -10,7 +10,6 @@ import ( "github.com/authelia/authelia/internal/models" "github.com/golang/mock/gomock" - "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" @@ -31,13 +30,6 @@ func (s *FirstFactorSuite) TearDownTest() { s.mock.Close() } -func (s *FirstFactorSuite) assertError500(err string) { - assert.Equal(s.T(), 500, s.mock.Ctx.Response.StatusCode()) - assert.Equal(s.T(), []byte(InternalError), s.mock.Ctx.Response.Body()) - assert.Equal(s.T(), err, s.mock.Hook.LastEntry().Message) - assert.Equal(s.T(), logrus.ErrorLevel, s.mock.Hook.LastEntry().Level) -} - func (s *FirstFactorSuite) TestShouldFailIfBodyIsNil() { FirstFactorPost(s.mock.Ctx) @@ -288,7 +280,7 @@ func (s *FirstFactorRedirectionSuite) SetupTest() { s.mock.Ctx.Configuration.DefaultRedirectionURL = "https://default.local" s.mock.Ctx.Configuration.AccessControl.DefaultPolicy = "bypass" s.mock.Ctx.Configuration.AccessControl.Rules = []schema.ACLRule{ - schema.ACLRule{ + { Domain: "default.local", Policy: "one_factor", }, @@ -384,11 +376,11 @@ func (s *FirstFactorRedirectionSuite) TestShouldReply200WhenUnsafeTargetURLProvi s.mock.Ctx.Providers.Authorizer = authorization.NewAuthorizer(schema.AccessControlConfiguration{ DefaultPolicy: "one_factor", Rules: []schema.ACLRule{ - schema.ACLRule{ + { Domain: "test.example.com", Policy: "one_factor", }, - schema.ACLRule{ + { Domain: "example.com", Policy: "two_factor", }, diff --git a/internal/handlers/handler_register_u2f_step1_test.go b/internal/handlers/handler_register_u2f_step1_test.go index d806518d5..b8cf61fce 100644 --- a/internal/handlers/handler_register_u2f_step1_test.go +++ b/internal/handlers/handler_register_u2f_step1_test.go @@ -46,13 +46,6 @@ func createToken(secret string, username string, action string, expiresAt time.T return ss } -func newFinishArgs() middlewares.IdentityVerificationFinishArgs { - return middlewares.IdentityVerificationFinishArgs{ - ActionClaim: U2FRegistrationAction, - IsTokenUserValidFunc: func(ctx *middlewares.AutheliaCtx, username string) bool { return true }, - } -} - func (s *HandlerRegisterU2FStep1Suite) TestShouldRaiseWhenXForwardedProtoIsMissing() { token := createToken(s.mock.Ctx.Configuration.JWTSecret, "john", U2FRegistrationAction, time.Now().Add(1*time.Minute)) diff --git a/internal/handlers/handler_register_u2f_step2.go b/internal/handlers/handler_register_u2f_step2.go index 6d3856fdd..0c7e63ca1 100644 --- a/internal/handlers/handler_register_u2f_step2.go +++ b/internal/handlers/handler_register_u2f_step2.go @@ -15,6 +15,10 @@ func SecondFactorU2FRegister(ctx *middlewares.AutheliaCtx) { responseBody := u2f.RegisterResponse{} err := ctx.ParseBody(&responseBody) + if err != nil { + ctx.Error(fmt.Errorf("Unable to parse response body: %v", err), unableToRegisterSecurityKeyMessage) + } + userSession := ctx.GetSession() if userSession.U2FChallenge == nil { diff --git a/internal/handlers/handler_user_info_test.go b/internal/handlers/handler_user_info_test.go index 102a62845..1177c45e3 100644 --- a/internal/handlers/handler_user_info_test.go +++ b/internal/handlers/handler_user_info_test.go @@ -62,25 +62,24 @@ func setPreferencesExpectations(preferences UserPreferences, provider *storage.M LoadTOTPSecret(gomock.Eq("john")). Return("", storage.ErrNoTOTPSecret) } - } func TestMethodSetToU2F(t *testing.T) { table := []UserPreferences{ - UserPreferences{ + { Method: "totp", }, - UserPreferences{ + { Method: "u2f", HasU2F: true, HasTOTP: true, }, - UserPreferences{ + { Method: "u2f", HasU2F: true, HasTOTP: false, }, - UserPreferences{ + { Method: "mobile_push", HasU2F: false, HasTOTP: false, diff --git a/internal/handlers/handler_verify.go b/internal/handlers/handler_verify.go index acf54c511..84753ba0c 100644 --- a/internal/handlers/handler_verify.go +++ b/internal/handlers/handler_verify.go @@ -27,7 +27,7 @@ func isSchemeWSS(url *url.URL) bool { return url.Scheme == "wss" } -// getOriginalURL extract the URL from the request headers (X-Original-URI or X-Forwarded-* headers). +// getOriginalURL extract the URL from the request headers (X-Original-URI or X-Forwarded-* headers) func getOriginalURL(ctx *middlewares.AutheliaCtx) (*url.URL, error) { originalURL := ctx.XOriginalURL() if originalURL != nil { @@ -65,8 +65,8 @@ func getOriginalURL(ctx *middlewares.AutheliaCtx) (*url.URL, error) { return url, nil } -// parseBasicAuth parses an HTTP Basic Authentication string. -// "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" returns ("Aladdin", "open sesame", true). +// parseBasicAuth parses an HTTP Basic Authentication string +// "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" returns ("Aladdin", "open sesame", true) func parseBasicAuth(auth string) (username, password string, err error) { if !strings.HasPrefix(auth, authPrefix) { return "", "", fmt.Errorf("%s prefix not found in %s header", strings.Trim(authPrefix, " "), AuthorizationHeader) @@ -83,10 +83,9 @@ func parseBasicAuth(auth string) (username, password string, err error) { return cs[:s], cs[s+1:], nil } -// isTargetURLAuthorized check whether the given user is authorized to access the resource. +// isTargetURLAuthorized check whether the given user is authorized to access the resource func isTargetURLAuthorized(authorizer *authorization.Authorizer, targetURL url.URL, username string, userGroups []string, clientIP net.IP, authLevel authentication.Level) authorizationMatching { - level := authorizer.GetRequiredLevel(authorization.Subject{ Username: username, Groups: userGroups, @@ -98,10 +97,10 @@ func isTargetURLAuthorized(authorizer *authorization.Authorizer, targetURL url.U } else if username != "" && level == authorization.Denied { // If the user is not anonymous, it means that we went through // all the rules related to that user and knowing who he is we can - // deduce the access is forbidden. + // deduce the access is forbidden // For anonymous users though, we cannot be sure that she // could not be granted the rights to access the resource. Consequently - // for anonymous users we send Unauthorized instead of Forbidden. + // for anonymous users we send Unauthorized instead of Forbidden return Forbidden } else { if level == authorization.OneFactor && @@ -116,8 +115,8 @@ func isTargetURLAuthorized(authorizer *authorization.Authorizer, targetURL url.U } // verifyBasicAuth verify that the provided username and password are correct and -// that the user is authorized to target the resource. -func verifyBasicAuth(auth []byte, targetURL url.URL, ctx *middlewares.AutheliaCtx) (username string, groups []string, authLevel authentication.Level, err error) { +// that the user is authorized to target the resource +func verifyBasicAuth(auth []byte, targetURL url.URL, ctx *middlewares.AutheliaCtx) (username string, groups []string, authLevel authentication.Level, err error) { //nolint:unparam username, password, err := parseBasicAuth(string(auth)) if err != nil { @@ -130,7 +129,7 @@ func verifyBasicAuth(auth []byte, targetURL url.URL, ctx *middlewares.AutheliaCt return "", nil, authentication.NotAuthenticated, fmt.Errorf("Unable to check credentials extracted from %s header: %s", AuthorizationHeader, err) } - // If the user is not correctly authenticated, send a 401. + // If the user is not correctly authenticated, send a 401 if !authenticated { // Request Basic Authentication otherwise return "", nil, authentication.NotAuthenticated, fmt.Errorf("User %s is not authenticated", username) @@ -145,7 +144,7 @@ func verifyBasicAuth(auth []byte, targetURL url.URL, ctx *middlewares.AutheliaCt return username, details.Groups, authentication.OneFactor, nil } -// setForwardedHeaders set the forwarded User and Groups headers. +// setForwardedHeaders set the forwarded User and Groups headers func setForwardedHeaders(headers *fasthttp.ResponseHeader, username string, groups []string) { if username != "" { headers.Set(remoteUserHeader, username) @@ -153,9 +152,8 @@ func setForwardedHeaders(headers *fasthttp.ResponseHeader, username string, grou } } -// hasUserBeenInactiveLongEnough check whether the user has been inactive for too long. -func hasUserBeenInactiveLongEnough(ctx *middlewares.AutheliaCtx) (bool, error) { - +// hasUserBeenInactiveLongEnough check whether the user has been inactive for too long +func hasUserBeenInactiveLongEnough(ctx *middlewares.AutheliaCtx) (bool, error) { //nolint:unparam maxInactivityPeriod := int64(ctx.Providers.SessionProvider.Inactivity.Seconds()) if maxInactivityPeriod == 0 { return false, nil @@ -174,10 +172,10 @@ func hasUserBeenInactiveLongEnough(ctx *middlewares.AutheliaCtx) (bool, error) { return false, nil } -// verifyFromSessionCookie verify if a user identified by a cookie is allowed to access target URL. -func verifyFromSessionCookie(targetURL url.URL, ctx *middlewares.AutheliaCtx) (username string, groups []string, authLevel authentication.Level, err error) { +// verifyFromSessionCookie verify if a user identified by a cookie is allowed to access target URL +func verifyFromSessionCookie(targetURL url.URL, ctx *middlewares.AutheliaCtx) (username string, groups []string, authLevel authentication.Level, err error) { //nolint:unparam userSession := ctx.GetSession() - // No username in the session means the user is anonymous. + // No username in the session means the user is anonymous isUserAnonymous := userSession.Username == "" if isUserAnonymous && userSession.AuthenticationLevel != authentication.NotAuthenticated { @@ -191,7 +189,7 @@ func verifyFromSessionCookie(targetURL url.URL, ctx *middlewares.AutheliaCtx) (u } if inactiveLongEnough { - // Destroy the session a new one will be regenerated on next request. + // Destroy the session a new one will be regenerated on next request err := ctx.Providers.SessionProvider.DestroySession(ctx.RequestCtx) if err != nil { return "", nil, authentication.NotAuthenticated, fmt.Errorf("Unable to destroy user session after long inactivity: %s", err) @@ -203,7 +201,7 @@ func verifyFromSessionCookie(targetURL url.URL, ctx *middlewares.AutheliaCtx) (u return userSession.Username, userSession.Groups, userSession.AuthenticationLevel, nil } -// VerifyGet is the handler verifying if a request is allowed to go through. +// VerifyGet is the handler verifying if a request is allowed to go through func VerifyGet(ctx *middlewares.AutheliaCtx) { ctx.Logger.Tracef("Headers=%s", ctx.Request.Header.String()) targetURL, err := getOriginalURL(ctx) @@ -256,7 +254,7 @@ func VerifyGet(ctx *middlewares.AutheliaCtx) { } else if authorization == NotAuthorized { // Kubernetes ingress controller and Traefik use the rd parameter of the verify // endpoint to provide the URL of the login portal. The target URL of the user - // is computed from X-Fowarded-* headers or X-Original-URL. + // is computed from X-Fowarded-* headers or X-Original-URL rd := string(ctx.QueryArgs().Peek("rd")) if rd != "" { redirectionURL := fmt.Sprintf("%s?rd=%s", rd, url.QueryEscape(targetURL.String())) @@ -273,7 +271,7 @@ func VerifyGet(ctx *middlewares.AutheliaCtx) { setForwardedHeaders(&ctx.Response.Header, username, groups) } - // We mark activity of the current user if he comes with a session cookie. + // We mark activity of the current user if he comes with a session cookie if !hasBasicAuth && username != "" { // Mark current activity userSession := ctx.GetSession() diff --git a/internal/handlers/handler_verify_test.go b/internal/handlers/handler_verify_test.go index 6bd8e23b5..1fed911a7 100644 --- a/internal/handlers/handler_verify_test.go +++ b/internal/handlers/handler_verify_test.go @@ -147,21 +147,21 @@ func TestShouldCheckAuthorizationMatching(t *testing.T) { ExpectedMatching authorizationMatching } rules := []Rule{ - Rule{"bypass", authentication.NotAuthenticated, Authorized}, - Rule{"bypass", authentication.OneFactor, Authorized}, - Rule{"bypass", authentication.TwoFactor, Authorized}, + {"bypass", authentication.NotAuthenticated, Authorized}, + {"bypass", authentication.OneFactor, Authorized}, + {"bypass", authentication.TwoFactor, Authorized}, - Rule{"one_factor", authentication.NotAuthenticated, NotAuthorized}, - Rule{"one_factor", authentication.OneFactor, Authorized}, - Rule{"one_factor", authentication.TwoFactor, Authorized}, + {"one_factor", authentication.NotAuthenticated, NotAuthorized}, + {"one_factor", authentication.OneFactor, Authorized}, + {"one_factor", authentication.TwoFactor, Authorized}, - Rule{"two_factor", authentication.NotAuthenticated, NotAuthorized}, - Rule{"two_factor", authentication.OneFactor, NotAuthorized}, - Rule{"two_factor", authentication.TwoFactor, Authorized}, + {"two_factor", authentication.NotAuthenticated, NotAuthorized}, + {"two_factor", authentication.OneFactor, NotAuthorized}, + {"two_factor", authentication.TwoFactor, Authorized}, - Rule{"deny", authentication.NotAuthenticated, NotAuthorized}, - Rule{"deny", authentication.OneFactor, Forbidden}, - Rule{"deny", authentication.TwoFactor, Forbidden}, + {"deny", authentication.NotAuthenticated, NotAuthorized}, + {"deny", authentication.OneFactor, Forbidden}, + {"deny", authentication.TwoFactor, Forbidden}, } url, _ := url.ParseRequestURI("https://test.example.com") @@ -169,7 +169,7 @@ func TestShouldCheckAuthorizationMatching(t *testing.T) { for _, rule := range rules { authorizer := authorization.NewAuthorizer(schema.AccessControlConfiguration{ DefaultPolicy: "deny", - Rules: []schema.ACLRule{schema.ACLRule{ + Rules: []schema.ACLRule{{ Domain: "test.example.com", Policy: rule.Policy, }}, @@ -419,23 +419,23 @@ func (p Pair) String() string { func TestShouldVerifyAuthorizationsUsingSessionCookie(t *testing.T) { testCases := []Pair{ - Pair{"https://test.example.com", "", authentication.NotAuthenticated, 401}, - Pair{"https://bypass.example.com", "", authentication.NotAuthenticated, 200}, - Pair{"https://one-factor.example.com", "", authentication.NotAuthenticated, 401}, - Pair{"https://two-factor.example.com", "", authentication.NotAuthenticated, 401}, - Pair{"https://deny.example.com", "", authentication.NotAuthenticated, 401}, - - Pair{"https://test.example.com", "john", authentication.OneFactor, 403}, - Pair{"https://bypass.example.com", "john", authentication.OneFactor, 200}, - Pair{"https://one-factor.example.com", "john", authentication.OneFactor, 200}, - Pair{"https://two-factor.example.com", "john", authentication.OneFactor, 401}, - Pair{"https://deny.example.com", "john", authentication.OneFactor, 403}, - - Pair{"https://test.example.com", "john", authentication.TwoFactor, 403}, - Pair{"https://bypass.example.com", "john", authentication.TwoFactor, 200}, - Pair{"https://one-factor.example.com", "john", authentication.TwoFactor, 200}, - Pair{"https://two-factor.example.com", "john", authentication.TwoFactor, 200}, - Pair{"https://deny.example.com", "john", authentication.TwoFactor, 403}, + {"https://test.example.com", "", authentication.NotAuthenticated, 401}, + {"https://bypass.example.com", "", authentication.NotAuthenticated, 200}, + {"https://one-factor.example.com", "", authentication.NotAuthenticated, 401}, + {"https://two-factor.example.com", "", authentication.NotAuthenticated, 401}, + {"https://deny.example.com", "", authentication.NotAuthenticated, 401}, + + {"https://test.example.com", "john", authentication.OneFactor, 403}, + {"https://bypass.example.com", "john", authentication.OneFactor, 200}, + {"https://one-factor.example.com", "john", authentication.OneFactor, 200}, + {"https://two-factor.example.com", "john", authentication.OneFactor, 401}, + {"https://deny.example.com", "john", authentication.OneFactor, 403}, + + {"https://test.example.com", "john", authentication.TwoFactor, 403}, + {"https://bypass.example.com", "john", authentication.TwoFactor, 200}, + {"https://one-factor.example.com", "john", authentication.TwoFactor, 200}, + {"https://two-factor.example.com", "john", authentication.TwoFactor, 200}, + {"https://deny.example.com", "john", authentication.TwoFactor, 403}, } for _, testCase := range testCases { @@ -628,7 +628,6 @@ func TestSchemeIsHTTPS(t *testing.T) { GetURL("wss://mytest.example.com/abc/?query=abc"))) assert.True(t, isSchemeHTTPS( GetURL("https://mytest.example.com/abc/?query=abc"))) - } func TestSchemeIsWSS(t *testing.T) { @@ -646,5 +645,4 @@ func TestSchemeIsWSS(t *testing.T) { GetURL("https://mytest.example.com/abc/?query=abc"))) assert.True(t, isSchemeWSS( GetURL("wss://mytest.example.com/abc/?query=abc"))) - } diff --git a/internal/handlers/types.go b/internal/handlers/types.go index f6b65b1c8..f6c4baf3b 100644 --- a/internal/handlers/types.go +++ b/internal/handlers/types.go @@ -49,12 +49,6 @@ type firstFactorRequestBody struct { KeepMeLoggedIn *bool `json:"keepMeLoggedIn"` } -// FirstFactorMessageResponse represents the response sent by the first factor endpoint -// when no redirection URL has been provided by the user. -type firstFactorMessageResponse struct { - Message string `json:"message"` -} - // redirectResponse represent the response sent by the first factor endpoint // when a redirection URL has been provided. type redirectResponse struct { |
