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

Client Credentials Grant / machine-to-machine auth in organizations #163

Open
martivo opened this issue Feb 5, 2024 · 10 comments
Open

Client Credentials Grant / machine-to-machine auth in organizations #163

martivo opened this issue Feb 5, 2024 · 10 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@martivo
Copy link

martivo commented Feb 5, 2024

Hello!

I am currently using Organizations successfully with "human" users, but now I have a need to authenticate machine-to-machine communication. I am strugling to figure out how to achieve this with organizations.

As far as I know, we are supposed to use clients(CLient authentication: ON, Auth flow: Service accounts flow).
How could I place this client into an Organization? Or the service account created/used by this Client?

I am also unable to assign an organization role to a Client. Only the regular KK roles are availabe.

Has anyone done something like this or can point me to the right direction?

@xgp
Copy link
Member

xgp commented Feb 5, 2024

Great question. 2 ideas:

  1. The client service account that gets generated is an actual User. You should be able to use the normal organization API methods to assign organization membership and roles. However, I don't think you'll be able to "see" the service account User in the admin UI in order to do this.
  2. There is an organization admin User created when an organization is created. The purpose of this account is to create a "machine" account with full organization permissions. You'd have to use grant_type=password, but it would work in a similar way.

@martivo
Copy link
Author

martivo commented Feb 5, 2024

Great question. 2 ideas:

  1. The client service account that gets generated is an actual User. You should be able to use the normal organization API methods to assign organization membership and roles. However, I don't think you'll be able to "see" the service account User in the admin UI in order to do this.

I can confirm, the user is not visible. I can get to the user details page (Clients->...->Service accounts roles->service-account-sample-...) but in the user details there is no option to add it to an organization.
And from the Organizations -> ... -> Members -> Add Member it does not show the Service account users.

Would it be possible to display these users in the "Add member" menu somehow? Or make the search find it when entering specific user ID?

I will try to add this service account user through the API calls.

  1. There is an organization admin User created when an organization is created. The purpose of this account is to create a "machine" account with full organization permissions. You'd have to use grant_type=password, but it would work in a similar way.

I think this would grant too many permissions? Since it is the admin user? I require fine grained control and multiple macine-to-macine accounts, each with specific set of permissions(roles) in the organization. I can confirm the "org-admin" user is visible and already a member of the organization.

@martivo
Copy link
Author

martivo commented Feb 5, 2024

I used
curl -X PUT -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" https://HOST/realms/master/orgs/ORG_ID/members/USER_ID
It did not result in an error. When I use an invalid USER_ID then it does show an error. So I assume this worked.
curl -X GET -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" https://HOST/realms/master/orgs/ORG_ID/members
However this request will not display it. Hard to predict if it works or not.
I will try to test if the organization parameters are present when authenticating.

However it is rather difficult to administrate it when even the API does not show it as a member. I wonder if I am missing some api parameter to include the service accounts in the results?

@xgp
Copy link
Member

xgp commented Feb 5, 2024

@martivo thank you for doing the validations.

Regarding the "org-admin" user, you are correct. It is meant to be an organization "superuser" that has all permissions within an organization.

I'll tag this as a feature request, as it would be nice to have the ability to add service accounts to organizations, it's currently encumbered by how Keycloak itself treats / "hides" those Users.

@xgp xgp added enhancement New feature or request help wanted Extra attention is needed labels Feb 5, 2024
@ljani
Copy link

ljani commented Feb 7, 2024

I was just researching the same topic. Thanks for all the pointers! Managing/debugging this through the UI would be helpful, but I'm glad it is already supported.

Finding the USER_ID was a little hard for me initially though, although @martivo explained it correctly. This can be found from Realm > Clients > CLIENTNAME > Service account roles tab > "click on the user name service-account-CLIENTNAME" > ID

I will try to test if the organization parameters are present when authenticating.

I did try this and I can confirm the organization roles do come through when using the organization role mapper. This should work for assigning the role:

curl -X PUT -H "Authorization: Bearer $ACCESS_TOKEN" https://HOST/realms/master/orgs/ORG_ID/roles/ROLE_NAME/users/USER_ID

@martivo
Copy link
Author

martivo commented Feb 7, 2024

I can confirm that the organization is present for the client when it's service account is added to the organization.
It is also needed to configure mappers for each of the added clients(machine accounts). In the client scope->(*-dedicated)->Add mapper->By configuration->Organization Role. Since in my case the service account uses it's own client to get the token. This behaviour/configuration seems to be the default for loki, prometheus etc using oauth2 configuraton block.

But administrating this is a nightmare - the API won't tell you if it is a member or not. Unless there is some API request that would show these hidden users.

@xgp
Copy link
Member

xgp commented Feb 7, 2024

This method in the Keycloak Admin API gets a service account user for a specific client: https://www.keycloak.org/docs-api/23.0.6/rest-api/index.html#_get_adminrealmsrealmclientsidservice_account_user

GET /admin/realms/{realm}/clients/{id}/service-account-user

@martivo
Copy link
Author

martivo commented Feb 7, 2024

This method in the Keycloak Admin API gets a service account user for a specific client: https://www.keycloak.org/docs-api/23.0.6/rest-api/index.html#_get_adminrealmsrealmclientsidservice_account_user

GET /admin/realms/{realm}/clients/{id}/service-account-user

This is great for finding the user ID of the clients service account user. How could I check what service account users are the members of an organization?

@xgp
Copy link
Member

xgp commented Feb 7, 2024

the GET /:realm/orgs/:orgId/members method needs to be updated. I'll keep this issue open if someone wants to do that.

@kedare
Copy link

kedare commented Apr 29, 2024

Hello
I guess in term of code change, for the implementation to work we only have to remove the && u.getServiceAccountClientLink() == null from this method ?

public Stream<UserModel> getMembersStream() {
return org.getMembers().stream()
.map(m -> m.getUserId())
.map(uid -> session.users().getUserById(realm, uid))
.filter(u -> u != null && u.getServiceAccountClientLink() == null);
}

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants