mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 21:27:42 +00:00
fix: generalise permission check for query user information (#8458)
# Which Problems Are Solved IDPLinks list and other list endpoints can provide you with empty results if the used user has no permission for the information. # How the Problems Are Solved List endpoints with subelements to users, and provided userIDQuery, will return a PermissionDenied error if no permission for the user exsists. # Additional Changes Function to check for permission is re-used from the GetUserByID. # Additional Context Closes #8451
This commit is contained in:
@@ -468,7 +468,7 @@ func (s *Server) getUserLinks(ctx context.Context, orgID string) (_ []*idp_pb.ID
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
idpUserLinks, err := s.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{Queries: []query.SearchQuery{userLinksResourceOwner}}, false)
|
||||
idpUserLinks, err := s.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{Queries: []query.SearchQuery{userLinksResourceOwner}}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -112,7 +112,7 @@ func (s *Server) RemoveIDP(ctx context.Context, req *admin_pb.RemoveIDPRequest)
|
||||
}
|
||||
userLinks, err := s.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{
|
||||
Queries: []query.SearchQuery{idpQuery},
|
||||
}, true)
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@ func (s *Server) ListMyLinkedIDPs(ctx context.Context, req *auth_pb.ListMyLinked
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
links, err := s.query.IDPUserLinks(ctx, q, false)
|
||||
links, err := s.query.IDPUserLinks(ctx, q, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ func (s *Server) ListMyAuthFactors(ctx context.Context, _ *auth_pb.ListMyAuthFac
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authMethods, err := s.query.SearchUserAuthMethods(ctx, query, false)
|
||||
authMethods, err := s.query.SearchUserAuthMethods(ctx, query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -30,7 +30,7 @@ func (s *Server) ListMyPasswordless(ctx context.Context, _ *auth_pb.ListMyPasswo
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authMethods, err := s.query.SearchUserAuthMethods(ctx, query, false)
|
||||
authMethods, err := s.query.SearchUserAuthMethods(ctx, query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -91,7 +91,7 @@ func (s *Server) RemoveOrgIDP(ctx context.Context, req *mgmt_pb.RemoveOrgIDPRequ
|
||||
}
|
||||
userLinks, err := s.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{
|
||||
Queries: []query.SearchQuery{idpQuery},
|
||||
}, true)
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -608,7 +608,7 @@ func (s *Server) ListHumanAuthFactors(ctx context.Context, req *mgmt_pb.ListHuma
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authMethods, err := s.query.SearchUserAuthMethods(ctx, query, false)
|
||||
authMethods, err := s.query.SearchUserAuthMethods(ctx, query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -671,7 +671,7 @@ func (s *Server) ListHumanPasswordless(ctx context.Context, req *mgmt_pb.ListHum
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authMethods, err := s.query.SearchUserAuthMethods(ctx, query, false)
|
||||
authMethods, err := s.query.SearchUserAuthMethods(ctx, query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -892,7 +892,7 @@ func (s *Server) ListHumanLinkedIDPs(ctx context.Context, req *mgmt_pb.ListHuman
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res, err := s.query.IDPUserLinks(ctx, queries, false)
|
||||
res, err := s.query.IDPUserLinks(ctx, queries, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -30,11 +30,10 @@ func (s *Server) ListIDPLinks(ctx context.Context, req *user.ListIDPLinksRequest
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res, err := s.query.IDPUserLinks(ctx, queries, false)
|
||||
res, err := s.query.IDPUserLinks(ctx, queries, s.checkPermission)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res.RemoveNoPermission(ctx, s.checkPermission)
|
||||
return &user.ListIDPLinksResponse{
|
||||
Result: IDPLinksToPb(res.Links),
|
||||
Details: object.ToListDetails(res.SearchResponse),
|
||||
|
@@ -122,6 +122,16 @@ func TestServer_ListIDPLinks(t *testing.T) {
|
||||
want *user.ListIDPLinksResponse
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "list links, missing userID",
|
||||
args: args{
|
||||
IamCTX,
|
||||
&user.ListIDPLinksRequest{
|
||||
UserId: "",
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "list links, no permission",
|
||||
args: args{
|
||||
@@ -130,13 +140,7 @@ func TestServer_ListIDPLinks(t *testing.T) {
|
||||
UserId: userOrgResp.GetUserId(),
|
||||
},
|
||||
},
|
||||
want: &user.ListIDPLinksResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 0,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Result: []*user.IDPLink{},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "list links, no permission, org",
|
||||
@@ -146,13 +150,7 @@ func TestServer_ListIDPLinks(t *testing.T) {
|
||||
UserId: userOrgResp.GetUserId(),
|
||||
},
|
||||
},
|
||||
want: &user.ListIDPLinksResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 0,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Result: []*user.IDPLink{},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "list idp links, org, ok",
|
||||
|
@@ -142,8 +142,7 @@ func (s *Server) ListPasskeys(ctx context.Context, req *user.ListPasskeysRequest
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authMethods, err := s.query.SearchUserAuthMethods(ctx, query, false)
|
||||
authMethods.RemoveNoPermission(ctx, s.checkPermission)
|
||||
authMethods, err := s.query.SearchUserAuthMethods(ctx, query, s.checkPermission)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -471,6 +471,16 @@ func TestServer_ListPasskeys(t *testing.T) {
|
||||
want *user.ListPasskeysResponse
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "list passkeys, no userID",
|
||||
args: args{
|
||||
IamCTX,
|
||||
&user.ListPasskeysRequest{
|
||||
UserId: "",
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "list passkeys, no permission",
|
||||
args: args{
|
||||
@@ -479,18 +489,12 @@ func TestServer_ListPasskeys(t *testing.T) {
|
||||
UserId: userIDVerified,
|
||||
},
|
||||
},
|
||||
want: &user.ListPasskeysResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 0,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Result: []*user.Passkey{},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "list passkeys, none",
|
||||
args: args{
|
||||
UserCTX,
|
||||
IamCTX,
|
||||
&user.ListPasskeysRequest{
|
||||
UserId: userIDWithout,
|
||||
},
|
||||
@@ -506,7 +510,7 @@ func TestServer_ListPasskeys(t *testing.T) {
|
||||
{
|
||||
name: "list passkeys, registered",
|
||||
args: args{
|
||||
UserCTX,
|
||||
IamCTX,
|
||||
&user.ListPasskeysRequest{
|
||||
UserId: userIDRegistered,
|
||||
},
|
||||
|
@@ -6,7 +6,6 @@ import (
|
||||
"github.com/muhlemmer/gu"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object/v2"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
@@ -15,15 +14,10 @@ import (
|
||||
)
|
||||
|
||||
func (s *Server) GetUserByID(ctx context.Context, req *user.GetUserByIDRequest) (_ *user.GetUserByIDResponse, err error) {
|
||||
resp, err := s.query.GetUserByID(ctx, true, req.GetUserId())
|
||||
resp, err := s.query.GetUserByIDWithPermission(ctx, true, req.GetUserId(), s.checkPermission)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if authz.GetCtxData(ctx).UserID != req.GetUserId() {
|
||||
if err := s.checkPermission(ctx, domain.PermissionUserRead, resp.ResourceOwner, req.GetUserId()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &user.GetUserByIDResponse{
|
||||
Details: object.DomainToDetailsPb(&domain.ObjectDetails{
|
||||
Sequence: resp.Sequence,
|
||||
|
@@ -421,7 +421,7 @@ func (s *Server) checkLinkedExternalUser(ctx context.Context, idpID, externalUse
|
||||
queries := []query.SearchQuery{
|
||||
idQuery, externalIDQuery,
|
||||
}
|
||||
links, err := s.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{Queries: queries}, false)
|
||||
links, err := s.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{Queries: queries}, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@@ -6,7 +6,6 @@ import (
|
||||
"github.com/muhlemmer/gu"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
object "github.com/zitadel/zitadel/internal/api/grpc/object/v2beta"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
@@ -15,15 +14,10 @@ import (
|
||||
)
|
||||
|
||||
func (s *Server) GetUserByID(ctx context.Context, req *user.GetUserByIDRequest) (_ *user.GetUserByIDResponse, err error) {
|
||||
resp, err := s.query.GetUserByID(ctx, true, req.GetUserId())
|
||||
resp, err := s.query.GetUserByIDWithPermission(ctx, true, req.GetUserId(), s.checkPermission)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if authz.GetCtxData(ctx).UserID != req.GetUserId() {
|
||||
if err := s.checkPermission(ctx, domain.PermissionUserRead, resp.ResourceOwner, req.GetUserId()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &user.GetUserByIDResponse{
|
||||
Details: object.DomainToDetailsPb(&domain.ObjectDetails{
|
||||
Sequence: resp.Sequence,
|
||||
|
@@ -434,7 +434,7 @@ func (s *Server) checkLinkedExternalUser(ctx context.Context, idpID, externalUse
|
||||
queries := []query.SearchQuery{
|
||||
idQuery, externalIDQuery,
|
||||
}
|
||||
links, err := s.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{Queries: queries}, false)
|
||||
links, err := s.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{Queries: queries}, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@@ -420,7 +420,7 @@ func (h *Handler) checkExternalUser(ctx context.Context, idpID, externalUserID s
|
||||
queries := []query.SearchQuery{
|
||||
idQuery, externalIDQuery,
|
||||
}
|
||||
links, err := h.queries.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{Queries: queries}, false)
|
||||
links, err := h.queries.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{Queries: queries}, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@@ -479,7 +479,7 @@ func (l *Login) resourceOwnerOfUserIDPLink(ctx context.Context, idpConfigID stri
|
||||
queries := []query.SearchQuery{
|
||||
idQuery, externalIDQuery,
|
||||
}
|
||||
links, err := l.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{Queries: queries}, false)
|
||||
links, err := l.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{Queries: queries}, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@@ -846,7 +846,7 @@ func (l *Login) updateExternalUsername(ctx context.Context, user *query.User, ex
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
links, err := l.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{Queries: []query.SearchQuery{externalIDQuery, idpIDQuery, userIDQuery}}, false)
|
||||
links, err := l.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{Queries: []query.SearchQuery{externalIDQuery, idpIDQuery, userIDQuery}}, nil)
|
||||
if err != nil || len(links.Links) == 0 {
|
||||
return err
|
||||
}
|
||||
@@ -1326,6 +1326,6 @@ func (l *Login) getUserLinks(ctx context.Context, userID, idpID string) (*query.
|
||||
userIDQuery,
|
||||
idpIDQuery,
|
||||
},
|
||||
}, false,
|
||||
}, nil,
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user