How to add multiple owners on single resource in keycloak - keycloak

I am working with keycloak UMA. With the help of keycloak I can create the resources in keycloak Authorization option with some basic details name, type, URI, scope, etc and we also have the option for resource owner, with UI we are not able to change the owner,
But I've some question regarding resource owner:
Is there any way to add multiple owners to resources (if using API). If yes then how?
If yes, then multiple owners can able to share that particular projects to others using username or email address
I've also tried with below CURL, but I am not able to add multiple owner names.
curl -v -X POST \
http://${host}:${port}/auth/realms/${realm_name}/authz/protection/resource_set \
-H 'Authorization: Bearer '$pat \
-H 'Content-Type: application/json' \
-d '{
"name":"Alice Resource",
"owner": "alice"
}'

You can't assign multiple users as owners to a single resource. you can assign all the resource scopes to access to any users associated within keycloak.
Another user can able to share the resources with others on behalf of the resource owner if that particular user has the resource owner's token. You can get the resource owner token with the help token exchange or Impersonation feature provided by keycloak.
You can refer keycloak official documentation

Related

How to get custom attributes for a user in Keycloak using the RESTful API?

I would assume this to be straight forward but I can't find it in the docs.
The following curl command:
curl \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
'https://$URL/auth/realms/$REALM/protocol/openid-connect/userinfo'
results in:
{
"sub": "8182...415",
"email_verified": true,
"name": "n.a. n.a.",
"groups": [],
"preferred_username": "foo#example.com",
"given_name": "n.a.",
"family_name": "n.a.",
"email": "foo#example.com"
}
How do I get the custom attributes for a user?
You can get the user attributes with the get users endpoint from Admin Rest API:
GET /{realm}/users
with the query parameters, exact=true and username.
Step-by-Step:
You can get that information using the Keycloak Admin REST API; to call that API, you need an access token from a user with the proper permissions. For now, I will be using the admin user from the master realm:
curl https://${KEYCLOAK_HOST}/auth/realms/master/protocol/openid-connect/token \
-d "client_id=admin-cli" \
-d "username=$ADMIN_NAME" \
-d "password=$ADMIN_PASSWORD" \
-d "grant_type=password"
You will get a JSON response with the admin's token. Extract the value of property access_token from that response. Let us save it in the variable $ACCESS_TOKEN for later reference.
To get the user attributes from your realm $REALM_NAME:
curl -X GET https://${KEYCLOAK_HOST}/auth/admin/realms/${REALM_NAME}/users/?username=${USERNAME}&exact=true \
-H "Content-Type: application/json" \
-H "Authorization: bearer $ACCESS_TOKEN"
From the response extract the user attributes for example as follows:
jq -r .[].attributes
To retrieve custom user attributes via the userinfo endpoint you need to create a protocol Mapper for the client used to authenticate the user.
That mapper can also be created with the Keycloak Admin rest API. For a more detailed answer on how to create Protocol Mappers for user-attributes (including for the old and new Keycloak APIs) please have a look at the this SO answer.
Or you can do it via Keycloak Admin UI as follows, in the Keycloak go to:
Select your realm
Go to clients
Select the appropriate client for your use-case
(For the OLD Keycloak UI)
Go to Mappers
Click Create
Select Mapper Type as User Attribute
Fill up the field User Attribute with your custom user attribute
Set to be added to the userinfo endpoint
Fill up the remaining fields, accordingly
Click on Save
(For the NEW Keycloak UI)
Go to the tab Client Scopes
Click on the scope -dedicated (e.g., test-dedicated in my example)
Click on Configure a new mapper (or Add Mapper > By configuration if you have already created mappers before for this client)
Select User Attribute
Fill up the field User Attribute with your custom user attribute
Set to be added to the userinfo endpoint
Fill up the remaining fields, accordingly
Click on Save
This is enough to enabled your custom user attribute to be retrieved from the userinfo endpoint

How to solve - Keycloak - Client not allowed to exchange

I tried to implement Keycloak direct naked impersonation from documentation, but in the end I got the error:
"error": "access_denied",
"error_description": "Client not allowed to exchange"
This is the Postman setup, with the admin-cli, clientId and with the user, justin, that I want to get the token for, that exists in the Users section.
The admin-cli secret that I used in Postman:
I followed all the steps that are in the Keycloak Direct Naked Impersonation documentation.
Toggle Users Permissions Enabled to On.
Define a policy for this permission.
Add the client policy, "client-impersonators" in my case, to the users' impersonation permission
This is the request setup that Keycloak recommads to have this direct naked impersonation working. You saw this in my above Postman setup.
curl -X POST \
-d "client_id=starting-client" \
-d "client_secret=the client secret" \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d "requested_subject=wburke" \
http://localhost:8080/realms/myrealm/protocol/openid-connect/token
Inside Docker I have the setup for token_exchange=enabled and admin_fine_grained_authz=enabled
- name: "KEYCLOAK_EXTRA_ARGS"
value: "-Dkeycloak.profile.feature.admin=enabled -Dkeycloak.profile.feature.admin_fine_grained_authz=enabled -Dkeycloak.profile.feature.token_exchange=enabled"
I searched days after days about this topic and I tested all the available options that are on internet right now, about this subject, but without any success.
Please anyone if this worked for you, be nice an share how you solved. Or at least please give some ideas, maybe I missed something.
New Policy created for user-impersonate, where I added the user Justin
Then inside the Permissions I added this Policy
The problem is that the documentation contains an image that is wrong, namely:
It should have been a Client Policy with the client admin-cli instead of the user admin.
For instance:
So, you need 2 policies/permissions:
impersonate (i.e., Policies that decide if administrator can impersonate other users), where you create a Client Policy and pass the client "admin-cli" (in your case);
user-impersonated (i.e., Policies that decide which users can be impersonated. These policies are applied to the user being impersonated), where you create a User Policy and pass the user "justin" (in your case).
Step-by-Step : KC 20.0.3 new UI
(Side note you should use other realm and client instead of the master and admin-cli at least in a production environment)
Enable the secret in the admin-cli:
go to master > clients > admin-cli
set Client authentication to ON
Create the two Policies: 1 Client Policy and 1 User Policy
go to master > clients > master-realm
click on the Authorization tab
click on the Policies sub-tab
click on Create policy, and then Client
name it something (e.g., Client-impersonator)
add admin-cli to the Client field and click Save
Repeat again the aforementioned steps, but this time create a User Policy for the user that will be impersonated (i.e., justin in your case)
Add the Policies to the corresponded scopes/permissions:
go to Users
go to the tab Permissions
set Permissions enabled to ON
click on impersonate
select the policy corresponded to the client admin-cli (e.g., policy named Client-impersonator)
click on Save
go again to Users
go to the tab Permissions
this time select user-impersonated
and select the policy for the impersonated user (i.e., justin)
Perform the request:
curl -X POST \
-d "client_id=admin-cli" \
-d "client_secret=8AEx99Ob4Hc8oricSGnii6x4Rs57g4ny" \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d "requested_subject=justin" \
http://0.0.0.0:8080/realms/master/protocol/openid-connect/token

Keycloak is it possible acess resource server from public client

I am very new to keycloak and I want to know is it possible to create public client then authorize client and get access token. Then use that access token and create UMA tickets to resource server and check if client has rights to access resoucrces using same authorization
I uses this turtorial
https://gruchalski.com/posts/2020-09-05-introduction-to-keycloak-authorization-services/
And it worked if you reauthorized to resource server directly.
But I want to use one authorisation to check rights to resources which could belong to different resource servers
I get access token using this code:
export access_token=`curl --silent -u public-client:1 \
-k -d "grant_type=password&username=${USER_NAME}&password=${USER_PASSWORD}&scope=email profile" \
-H "Content-Type:application/x-www-form-urlencoded" \
${KEYCLOAK_TOKEN_URL} | jq '.access_token' -r`
Then I try to authorise same user to different client:
curl --silent -X POST \
${KEYCLOAK_TOKEN_URL} \
-H "Authorization: Bearer ${access_token}" \
--data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
--data "audience=resource-server-1"
But I get "Client does not support permissions"
Maybe someone knows what I need to configure for this to work or even if this can work?
For what I've reading you need two clients. One public and the other confidential.
Then in your client configured as confidential set all your fine-grained authz then in your audience param you set the client id previously configured as confidential.

Getting Users and groups from Keycloak

I have a web application secured by Keycloak. Now I want to read all the security groups and users from keycloak in my application. Is it possible?
Keycloak has a very good documentation around the APIs.
I believe you are looking to get all the groups and users from the Keycloak. It could be as straightforward as calling any REST APIs.
You can follow this link to get all the groups from the Keycloak.
And this link to get the users based on the given search criteria.
But I would be wary of the performance implication it might have calling these APIs. Make sure to use pagination and appropriate filters for getting users.
Also, if you want, you can write a custom extension in Keycloak to serve your purpose. You can follow this link for it.
I could get the access token using the client secret key using the curl command from command line.
$curl -X POST -d "client_id=my_client" -d "username=username" -d "client_secret=c957b0ba-c421-4021-8433-764aa2fwes72" -d "grant_type=client_credentials" HOST/auth/realms/my_realm/protocol/openid-connect/token
I could also get the list of users after getting the access token
$curl -X GET HOST/auth/admin/realms/my_realm/users -H "Authorization: Bearer access-token" -H 'cache-control: no-cache'
Now, I'm thinking how can I do this from my web application.

Keycloak - How to request a token with a custom lifespan?

Context: We are using Keycloak to secure our APIs by usually passing tokens through Authorization Headers. However, these APIs also allow users to download files (for instance: https://api.service.io/users.xlsx).
To use these "download endpoints", our web client applications pass users' token via query strings. (e.g. https://api.service.io/users.xlsx?accessToken=${bearerToken})).
Problem: Passing tokens via query string has several security flaws (browser history, ...). Therefore we would like to pass a very short-lived token (e.g. lifespan of 15sec) instead of the normal one (lifespan of 300sec by default).
Question: How could we request a different token from Keycloak API (for instance, /realms/#{realm_id}/protocol/openid-connect/token) by:
providing the normal access token (not credentials);
and specifying a different lifespan ?
After reading Keycloak's source code, it appears this is not possible (version 3.4.2.Final) to ask for a specific lifespan at runtime.
However, I developed a Keycloak Custom REST endpoint to do that. https://github.com/looorent/keycloak-configurable-token-api
When this JAR file is deployed in Keycloak, you can ask for a given lifespan at runtime. For example:
$ curl -X POST -d '{ "tokenLifespanInSeconds": 20}' -H "Content-Type: application/json" -H "Authorization: Bearer <user-access-token>" http://auth.service.io/auth/realms/a-realm/configurable-token