diff --git a/changelog/unreleased/respect_account_enabled_flag.md b/changelog/unreleased/respect_account_enabled_flag.md new file mode 100644 index 0000000000..80a635a269 --- /dev/null +++ b/changelog/unreleased/respect_account_enabled_flag.md @@ -0,0 +1,6 @@ +Enhancement: respect account_enabled flag + +If the account returned by the accounts service has the account_enabled flag +set to false, the proxy will return immediately with the status code unauthorized. + +https://github.com/owncloud/ocis-proxy/issues/53 diff --git a/go.sum b/go.sum index 38fee43570..ac3d08dd10 100644 --- a/go.sum +++ b/go.sum @@ -203,6 +203,7 @@ github.com/couchbase/ghistogram v0.1.0/go.mod h1:s1Jhy76zqfEecpNWJfWUiKZookAFaiG github.com/couchbase/moss v0.1.0/go.mod h1:9MaHIaRuy9pvLPUJxB8sh8OrLfyDczECVL37grCIubs= github.com/couchbase/vellum v1.0.1/go.mod h1:FcwrEivFpNi24R3jLOs3n+fs5RnuQnQqCLBJ1uAg1W4= github.com/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMElOWxok= +github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= @@ -785,6 +786,7 @@ github.com/rs/zerolog v1.18.0 h1:CbAm3kP2Tptby1i9sYy2MGRg0uxIN9cyDb59Ys7W8z8= github.com/rs/zerolog v1.18.0/go.mod h1:9nvC1axdVrAHcu/s9taAVfBuIdTZLVQmKQyvrUjF5+I= github.com/rs/zerolog v1.19.0 h1:hYz4ZVdUgjXTBUmrkrw55j1nHx68LfOKIQk5IYtyScg= github.com/rs/zerolog v1.19.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo= +github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= diff --git a/pkg/middleware/account_uuid.go b/pkg/middleware/account_uuid.go index e42f28eb84..071af181ac 100644 --- a/pkg/middleware/account_uuid.go +++ b/pkg/middleware/account_uuid.go @@ -92,6 +92,11 @@ func AccountUUID(opts ...Option) func(next http.Handler) http.Handler { w.WriteHeader(status) return } + if !account.AccountEnabled { + l.Debug().Interface("account", account).Msg("account is disabled") + w.WriteHeader(http.StatusUnauthorized) + return + } l.Debug().Interface("claims", claims).Interface("account", account).Msgf("Associated claims with uuid") token, err := tokenManager.MintToken(r.Context(), &revauser.User{ diff --git a/pkg/middleware/account_uuid_test.go b/pkg/middleware/account_uuid_test.go index a2b5dbc351..abf2e8515d 100644 --- a/pkg/middleware/account_uuid_test.go +++ b/pkg/middleware/account_uuid_test.go @@ -17,13 +17,13 @@ import ( // TODO testing the getAccount method should inject a cache func TestGetAccountSuccess(t *testing.T) { svcCache.Invalidate(AccountsKey, "success") - if _, status := getAccount(log.NewLogger(), &oidc.StandardClaims{Email: "success"}, mockAccountUUIDMiddlewareAccSvc(false)); status != 0 { + if _, status := getAccount(log.NewLogger(), &oidc.StandardClaims{Email: "success"}, mockAccountUUIDMiddlewareAccSvc(false, true)); status != 0 { t.Errorf("expected an account") } } func TestGetAccountInternalError(t *testing.T) { svcCache.Invalidate(AccountsKey, "failure") - if _, status := getAccount(log.NewLogger(), &oidc.StandardClaims{Email: "failure"}, mockAccountUUIDMiddlewareAccSvc(true)); status != http.StatusInternalServerError { + if _, status := getAccount(log.NewLogger(), &oidc.StandardClaims{Email: "failure"}, mockAccountUUIDMiddlewareAccSvc(true, false)); status != http.StatusInternalServerError { t.Errorf("expected an internal server error") } } @@ -34,7 +34,7 @@ func TestAccountUUIDMiddleware(t *testing.T) { m := AccountUUID( Logger(log.NewLogger()), TokenManagerConfig(config.TokenManager{JWTSecret: "secret"}), - AccountsClient(mockAccountUUIDMiddlewareAccSvc(false)), + AccountsClient(mockAccountUUIDMiddlewareAccSvc(false, true)), )(next) r := httptest.NewRequest(http.MethodGet, "http://www.example.com", nil) @@ -48,7 +48,30 @@ func TestAccountUUIDMiddleware(t *testing.T) { } } -func mockAccountUUIDMiddlewareAccSvc(retErr bool) proto.AccountsService { +func TestAccountUUIDMiddlewareWithDisabledAccount(t *testing.T) { + svcCache.Invalidate(AccountsKey, "failure") + next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + m := AccountUUID( + Logger(log.NewLogger()), + TokenManagerConfig(config.TokenManager{JWTSecret: "secret"}), + AccountsClient(mockAccountUUIDMiddlewareAccSvc(false, false)), + )(next) + + r := httptest.NewRequest(http.MethodGet, "http://www.example.com", nil) + w := httptest.NewRecorder() + ctx := oidc.NewContext(r.Context(), &oidc.StandardClaims{Email: "failure"}) + r = r.WithContext(ctx) + m.ServeHTTP(w, r) + + rsp := w.Result() + defer rsp.Body.Close() + + if rsp.StatusCode != http.StatusUnauthorized { + t.Errorf("expected a disabled account to be unauthorized, got: %d", rsp.StatusCode) + } +} + +func mockAccountUUIDMiddlewareAccSvc(retErr, accEnabled bool) proto.AccountsService { if retErr { return &proto.MockAccountsService{ ListFunc: func(ctx context.Context, in *proto.ListAccountsRequest, opts ...client.CallOption) (out *proto.ListAccountsResponse, err error) { @@ -62,7 +85,8 @@ func mockAccountUUIDMiddlewareAccSvc(retErr bool) proto.AccountsService { return &proto.ListAccountsResponse{ Accounts: []*proto.Account{ { - Id: "yay", + Id: "yay", + AccountEnabled: accEnabled, }, }, }, nil