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

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

Related

Get User Profile in Keycloak using REST Api

I have got a accessToken by calling the keycloak endpoint /token using REST Api as follows
curl -d 'client_id=myclient' -d 'username=username' -d 'password=password' -d 'grant_type=password' -d 'scope=openid' -d 'client_secret=xxxxxxxxxxxxxxxxxxxxxxxxx' 'http://192.168.43.29:8080/realms/aurcc/protocol/openid-connect/token'
But by using this api, when a request is made to the /userinfo endpoint, response will only contains sub,given_name,preferred_name,email_verified,family_name. But the response doesn't contain any information about the groups in which the user is added.
Next time, I used keycloak-js adapter in my Vuejs application. There the /userinfo endpoint results in a response which contains the above said attributes plus the groups attribute. I don't why this weird thing happening.
Help me to get the groups attribute in the response of /userinfo endpoint.

Personal access tokens with Keycloak

Is there way to create user-specific (aka. personal) access tokens in Keycloak?
So, our goal would be that a user creates one or more personal access tokens (like in GitHub or GitLab) and he/she uses these tokens for authentication.
Any idea how to achieve this using Keycloak?
Keycloak have no short size of personal API key
But you can use full size of JWT.
It is getting Access Token with password grant type.
This is demo
localhost:8180 – is a host and a port number on which the Keycloak server is running,
test – is a Keycloak Realm,
admin-cli – one of default client,
user: user name
1234: password
password : grand_type
The Grant Type is a way to exchange a user’s credentials for an access token.
$ curl -v -d "client_id=admin-cli" -d "username=user" -d "password=1234" -d "grant_type=password" -X POST "http://localhost:8180/auth/realms/test/protocol/openid-connect/token" | jq '.access_token'
result in terminal
"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6Q0hvYVhPX2hqbXFRTnNYOVlacnhkZmpUdk1sbWozUFNkSXpTWUJjMzRFIn0.eyJleHAiOjE2NjAzMzU4ODIsImlhdCI6MTY2MDMzNTU4MiwianRpIjoiYmFkMmFlNjktMWNiYS00NGMyLWEyZDctYzdhOWQ5YjQ4OGI4IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MTgwL2F1dGgvcmVhbG1zL3Rlc3QiLCJzdWIiOiIzOTRiNjcwOS0zOGEyLTRhYTAtYTg0OS1mZTRjODFlNDA2MjQiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJhZG1pbi1jbGkiLCJzZXNzaW9uX3N0YXRlIjoiZGM5YjI1YzEtOTRlMy00MTlhLTliOGQtMjYwZTVkMmY3MzcxIiwiYWNyIjoiMSIsInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsInNpZCI6ImRjOWIyNWMxLTk0ZTMtNDE5YS05YjhkLTI2MGU1ZDJmNzM3MSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6IlRvbSBDdXJpZXMiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ1c2VyIiwiZ2l2ZW5fbmFtZSI6IlRvbSIsImZhbWlseV9uYW1lIjoiQ3VyaWVzIiwiZW1haWwiOiJ1c2VyQHRlc3QuY29tIn0.Gnx6WwpsUxQM990H89BBYi_Kiy3BdAQcCYFRknDJ9qpkGAZSYrAAjjEeEBA5ZXKIUzu0O2trly0iWVW1r4Lb5ihiqSva1BaR42v5WWXHL9gpeS-ttsoKP6N1x74msHXssRmjN5vZG_dwXF-gpKhhJmXI0fLW3-_uuH3LZ9Ar-4zNliVLjJGmePtzq74nn7WbwhggiWDQu2_mQFBnf9vJvcxn6jY9TX5oxppn4BNcvXrChAZyDXLt7RW32ud3p1Cs7Jn360Vg6cRo4wq7-Mams8hhnonhDEaakJtcin7gLK6jwFC7f2ND8banDYL3CEsem4HpmxSRX43UBhfyO64Z8A"
API call for getting user information with this access_token
$ curl --location --request GET 'http://localhost:8180/auth/realms/test/protocol/openid-connect/userinfo' --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6Q0hvYVhPX2hqbXFRTnNYOVlacnhkZmpUdk1sbWozUFNkSXpTWUJjMzRFIn0.eyJleHAiOjE2NjAzMzU4MjMsImlhdCI6MTY2MDMzNTUyMywianRpIjoiYjc3MjMzY2ItYTI2Zi00ZGNiLWJkZTktNjRiNzhiMmQzZTM2IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MTgwL2F1dGgvcmVhbG1zL3Rlc3QiLCJzdWIiOiIzOTRiNjcwOS0zOGEyLTRhYTAtYTg0OS1mZTRjODFlNDA2MjQiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJhZG1pbi1jbGkiLCJzZXNzaW9uX3N0YXRlIjoiNjg2Y2EyNDctMzZjYS00MTNiLWE4M2YtODUyZjJmNWY3YWVmIiwiYWNyIjoiMSIsInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsInNpZCI6IjY4NmNhMjQ3LTM2Y2EtNDEzYi1hODNmLTg1MmYyZjVmN2FlZiIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6IlRvbSBDdXJpZXMiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ1c2VyIiwiZ2l2ZW5fbmFtZSI6IlRvbSIsImZhbWlseV9uYW1lIjoiQ3VyaWVzIiwiZW1haWwiOiJ1c2VyQHRlc3QuY29tIn0.KNioWAOTl7S5bYi303ZWkYRnTv4BnH9B7Q-Oe6j5nO5g_QD2RrWhMO1bUXA3uHdj5P3Y9Mk3vWYfsOlacVfYGmuYmGYhTD6LhbCILPf1r4qMBHUnAtPmWBUmLPNy1XQc-PPjVU6I0FzwW4-UoHCmrqgpDvSoarxf3PiUgwaYzPGm6IeAaHw-ndSO0vkhue2j2s8eVfiiH6TExkngq3zc8E1Y0WK3EM_LxcoDbfrRTNROYDqjK6Bi6_jIECjuRRC6E4ies1svMd8XGwS8iYuHB62hX7_rEBT4PmCwddjfE-IO6XoPy970gdWFUZfiRxbz1Orh-6SySVaeEPdskTGb2Q' | jq
result in terminal
{
"sub": "394b6709-38a2-4aa0-a849-fe4c81e40624",
"email_verified": false,
"name": "Tom Curies",
"preferred_username": "user",
"given_name": "Tom",
"family_name": "Curies",
"email": "user#test.com"
}
You can get the token end point by curl commend.
It is not necessary the access token.
curl --location --request GET 'http://localhost:8180/auth/realms/test/.well-known/openid-configuration' | jq
It will give a full list of result OIDC Discovery
{
"issuer": "http://localhost:8180/auth/realms/test",
"authorization_endpoint": "http://localhost:8180/auth/realms/test/protocol/openid-connect/auth",
"token_endpoint": "http://localhost:8180/auth/realms/test/protocol/openid-connect/token",
"introspection_endpoint": "http://localhost:8180/auth/realms/test/protocol/openid-connect/token/introspect",
"userinfo_endpoint": "http://localhost:8180/auth/realms/test/protocol/openid-connect/userinfo",
"end_session_endpoint": "http://localhost:8180/auth/realms/test/protocol/openid-connect/logout",
>>> deleted here next lines
I think you can customize the authentication flow using a custom Keycloak authentication SPI in that propagates passed personal token to the same 3-rd service that returns if the user is authenticated or not (see https://wjw465150.gitbooks.io/keycloak-documentation/content/server_development/topics/auth-spi.html for details)
Of course, you also need to create some web UI for token creation that will be then stored and verified with this custom SPI.

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.

How to specify client-specific custom attribute in access token

I have a Keycloak setup and I'm using the client_credential flow to create access tokens for thousands of back-ends.
I would like to include another custom field in the access token, so next to exp etc., I'd like to have a field publicKey. This field is specific and unique for each of the clients.
Is that possible using Keycloak?
EDIT: Clarified that I have many back-ends and each of them has a specific and unique publicKey
I assume you have a hard-coded value inside the claim publicKey. If so, this will suffice:
You create a custom scope who issues the token. So assuming you have a Client Backend, which wants to exchange a user token for a serviceaccount-token to reach out to a downstream service client_credentials_service, and this serviceaccount-token should have the publicKey attribute inside, here's one way you could do it:
In your realm, create and save a new Scope under Client Scopesin admin UI.
Go to Client Scopes -> publicKeyScope -> Mappers -> create and create a new hardcoded claim, example below:
Open your client client_credentials_service and switch to tab Client Scopes
Here you could add your new scope either as default or as optional scope to your client. optional means, in the request you make to kcs token endpoint to obtain a token via client_credentials flow, you have to add the scope=publicKeyScope param. e.g. like this:
curl --location --request POST 'http://localhost:8080/auth/realms/yourRealm/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=client_credentials_service' \
--data-urlencode 'client_secret=your-secret' \
--data-urlencode 'scope=email publicKeyScope' \
--data-urlencode 'grant_type=client_credentials'
When it's added as default, you don't have to explicitly add the desired scope to the request.
As long as you're not adding this scope (or the corresponding mapping) to another client, only your client_credentials_service token obtained via client credentials flow will include this claim.
Example for resulting token:

How to add multiple owners on single resource in 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