Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The function "GetGroups" doesn't return the list of all sub-groups #456

Open
hosseinjdk opened this issue Dec 22, 2023 · 8 comments
Open

Comments

@hosseinjdk
Copy link

hosseinjdk commented Dec 22, 2023

Describe the bug
After upgrading the Keycloak from "22.0.4" to "23.0.3", I found out that the gocloak function "GetGroups" only returns the parent groups of a realm. The following code is working perfect with Keycloak-v22.0.4:

func (kcClient *KeyCloakClient) getKeyCloakGroupByPath(realm, path string) (*gocloak.Group, error) 

	groups, err := kcClient.client.GetGroups(context.Background(), kcClient.token.AccessToken, realm, gocloak.GetGroupsParams{})
	if err != nil {
		return nil, err
	}

	for _, group := range groups {
		found := traverseGroup(group, path)
		if found != nil {
			return found, nil
		}
	}
	return nil, errors.New("No Group found")
}

However we upgraded the Keycloak to "23.0.3" and after that the "GetGroups" returns only the parent groups of a realm.

Expected behavior
"GetGroups" should recursively return all groups including all the sub-groups in tree just like before.

Environment:

  • Platform: Kubernetes-v1.26.9
  • OS: RHEL 8
  • Gocloak: v13.8.0
  • Keycloak: 23.0.3
@osmian
Copy link
Contributor

osmian commented Dec 28, 2023

@hosseinjdk Does it return the subgroups if you specify the params in the call you make gocloak.GetGroupsParams, specifically making BriefRepresentation false or Full as true.

@hosseinjdk
Copy link
Author

@hosseinjdk Does it return the subgroups if you specify the params in the call you make gocloak.GetGroupsParams, specifically making BriefRepresentation false or Full as true.

@osmian Thanks for your answer. I tested my function with these 3 variables as an input for "kcClient.client.GetGroups":

		grpParams := gocloak.GetGroupsParams{
			Full: gocloak.BoolP(true),
		}

		grpParams := gocloak.GetGroupsParams{
			BriefRepresentation: gocloak.BoolP(false),
		}

		grpParams := gocloak.GetGroupsParams{
			BriefRepresentation: gocloak.BoolP(false),
			Full: gocloak.BoolP(true),
		}

All return the same group as a result, I mean only the parent and no subgroups.

@hosseinjdk
Copy link
Author

hosseinjdk commented Jan 2, 2024

@osmian

The following api is new in keycloak 23.0.0 for this purpose maybe.
GET /admin/realms/{realm}/groups/{id}/children

Keycloak Admin REST API

@osmian
Copy link
Contributor

osmian commented Jan 7, 2024

@hosseinjdk @Nerzal it may be useful to make an MR and add this to the client.go so its available in future releases?

@Nerzal
Copy link
Owner

Nerzal commented Jan 7, 2024

Yes, that would make sense.
Keycloak loves to change the behaviour of stuff. It's hard to keep up with all these changes

@robson90
Copy link

As already mentioned here, this workaround will work for getting "all" Groups with their SubGroups

client.GetGroups(ctx, token.AccessToken, realm, gocloak.GetGroupsParams{Search: gocloak.StringP("%")})

@tduong2049
Copy link

tduong2049 commented Jan 24, 2024

Initial method for getting the child groups of a given group, using documentation from #456 (comment)

// client.go

// GetChildGroups get child groups of group with id in realm
func (g *GoCloak) GetChildGroups(ctx context.Context, token, realm, groupID string) ([]*Group, error) {
	const errMessage = "could not get child groups"

	var result []*Group

	resp, err := g.getRequestWithBearerAuth(ctx, token).
		SetResult(&result).
		Get(g.getAdminRealmURL(realm, "groups", groupID, "children"))

	if err := checkForError(resp, err, errMessage); err != nil {
		return nil, err
	}

	return result, nil
}

This method could be modified in the future to include a GetChildGroupsParams parameter

// client.go

// GetChildGroups get child groups of group with id in realm
func (g *GoCloak) GetChildGroups(ctx context.Context, token, realm, groupID string, params GetChildGroupsParams) ([]*Group, error) {
	const errMessage = "could not get child groups"

	var result []*Group
	queryParams, err := GetQueryParams(params)
	if err != nil {
		return nil, errors.Wrap(err, errMessage)
	}

	resp, err := g.getRequestWithBearerAuth(ctx, token).
		SetResult(&result).
		SetQueryParams(queryParams).
		Get(g.getAdminRealmURL(realm, "groups", groupID, "children"))

	if err := checkForError(resp, err, errMessage); err != nil {
		return nil, err
	}

	return result, nil
}
// models.go

// GetChildGroupsParams represents the optional parameters for getting child groups
type GetChildGroupsParams struct {
	First               *int    `json:"first,string,omitempty"`
	Max                 *int    `json:"max,string,omitempty"`
	BriefRepresentation *bool   `json:"briefRepresentation,string,omitempty"`
}

@hosseinjdk
Copy link
Author

As already mentioned here, this workaround will work for getting "all" Groups with their SubGroups

client.GetGroups(ctx, token.AccessToken, realm, gocloak.GetGroupsParams{Search: gocloak.StringP("%")})

Thank you very much. This workaround works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants