diff --git a/services/proxy/pkg/command/server.go b/services/proxy/pkg/command/server.go index 035af7f00..8b5a9a48d 100644 --- a/services/proxy/pkg/command/server.go +++ b/services/proxy/pkg/command/server.go @@ -294,6 +294,7 @@ func loadMiddlewares(logger log.Logger, cfg *config.Config, authenticators = append(authenticators, middleware.AppAuthAuthenticator{ Logger: logger, RevaGatewaySelector: gatewaySelector, + UserRoleAssigner: roleAssigner, }) } authenticators = append(authenticators, middleware.NewOIDCAuthenticator( diff --git a/services/proxy/pkg/middleware/account_resolver.go b/services/proxy/pkg/middleware/account_resolver.go index 313e3945c..b8155ad44 100644 --- a/services/proxy/pkg/middleware/account_resolver.go +++ b/services/proxy/pkg/middleware/account_resolver.go @@ -99,8 +99,7 @@ func (m accountResolver) ServeHTTP(w http.ResponseWriter, req *http.Request) { ctx := req.Context() claims := oidc.FromContext(ctx) user, ok := revactx.ContextGetUser(ctx) - token := "" - // TODO what if an X-Access-Token is set? happens eg for download requests to the /data endpoint in the reva frontend + token, hasToken := revactx.ContextGetToken(ctx) if claims == nil && !ok { m.next.ServeHTTP(w, req) @@ -192,10 +191,11 @@ func (m accountResolver) ServeHTTP(w http.ResponseWriter, req *http.Request) { req = req.WithContext(ctx) m.logger.Debug().Interface("claims", claims).Interface("user", user).Msg("associated claims with user") - } else if user != nil { + } else if user != nil && !hasToken { + // If we already have a token (e.g. the app auth middleware adds the token to the context) there is no need + // to get yet another one here. var err error _, token, err = m.userProvider.GetUserByClaims(req.Context(), "username", user.Username) - if errors.Is(err, backend.ErrAccountDisabled) { m.logger.Debug().Interface("user", user).Msg("Disabled") w.WriteHeader(http.StatusUnauthorized) diff --git a/services/proxy/pkg/middleware/app_auth.go b/services/proxy/pkg/middleware/app_auth.go index 5b4901525..166c75191 100644 --- a/services/proxy/pkg/middleware/app_auth.go +++ b/services/proxy/pkg/middleware/app_auth.go @@ -6,6 +6,7 @@ import ( gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" cs3rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" "github.com/opencloud-eu/opencloud/pkg/log" + "github.com/opencloud-eu/opencloud/services/proxy/pkg/userroles" revactx "github.com/opencloud-eu/reva/v2/pkg/ctx" "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" ) @@ -14,6 +15,7 @@ import ( type AppAuthAuthenticator struct { Logger log.Logger RevaGatewaySelector pool.Selectable[gateway.GatewayAPIClient] + UserRoleAssigner userroles.UserRoleAssigner } // Authenticate implements the authenticator interface to authenticate requests via app auth. @@ -43,11 +45,20 @@ func (m AppAuthAuthenticator) Authenticate(r *http.Request) (*http.Request, bool return nil, false } if authenticateResponse.GetStatus().GetCode() != cs3rpc.Code_CODE_OK { - // TODO: log??? + m.Logger.Debug().Str("msg", authenticateResponse.GetStatus().GetMessage()).Str("clientid", username).Msg("app auth failed") return nil, false } - r.Header.Set(revactx.TokenHeader, authenticateResponse.GetToken()) + user := authenticateResponse.GetUser() + if user, err = m.UserRoleAssigner.ApplyUserRole(r.Context(), user); err != nil { + m.Logger.Error().Err(err).Str("clientid", username).Msg("app auth: failed to load user roles") + return nil, false + } + + ctx := revactx.ContextSetUser(r.Context(), user) + ctx = revactx.ContextSetToken(ctx, authenticateResponse.GetToken()) + + r = r.WithContext(ctx) return r, true } diff --git a/services/proxy/pkg/middleware/app_auth_test.go b/services/proxy/pkg/middleware/app_auth_test.go index 61cdf5805..0b6d9242a 100644 --- a/services/proxy/pkg/middleware/app_auth_test.go +++ b/services/proxy/pkg/middleware/app_auth_test.go @@ -5,19 +5,24 @@ import ( "net/http/httptest" gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" + userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" - "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" - "google.golang.org/grpc" - . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/opencloud-eu/opencloud/pkg/log" + userRoleMocks "github.com/opencloud-eu/opencloud/services/proxy/pkg/userroles/mocks" + revactx "github.com/opencloud-eu/reva/v2/pkg/ctx" + "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" + "github.com/stretchr/testify/mock" + "google.golang.org/grpc" ) var _ = Describe("Authenticating requests", Label("AppAuthAuthenticator"), func() { var authenticator Authenticator BeforeEach(func() { pool.RemoveSelector("GatewaySelector" + "eu.opencloud.api.gateway") + ra := &userRoleMocks.UserRoleAssigner{} + ra.On("ApplyUserRole", mock.Anything, mock.Anything, mock.Anything).Return(&userv1beta1.User{}, nil) authenticator = AppAuthAuthenticator{ Logger: log.NewLogger(), RevaGatewaySelector: pool.GetSelector[gateway.GatewayAPIClient]( @@ -39,6 +44,7 @@ var _ = Describe("Authenticating requests", Label("AppAuthAuthenticator"), func( } }, ), + UserRoleAssigner: ra, } }) @@ -51,7 +57,12 @@ var _ = Describe("Authenticating requests", Label("AppAuthAuthenticator"), func( Expect(valid).To(Equal(true)) Expect(req2).ToNot(BeNil()) - Expect(req2.Header.Get("x-access-token")).To(Equal("reva-token")) + user, ok := revactx.ContextGetUser(req2.Context()) + Expect(ok).To(BeTrue()) + Expect(user).ToNot(BeNil()) + token, ok := revactx.ContextGetToken(req2.Context()) + Expect(ok).To(BeTrue()) + Expect(token).To(Equal("reva-token")) }) })