Get User Profile in Keycloak using REST Api - keycloak

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.

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

Keycloak: cannot get token from a custom spi

I have to create two rest services via keycloak.
The first one sends a verification code to a phone number. The second one grant a token to a user if the verification code is correct for a given phone number.
I have created a module with a custom SPI following the guide in https://github.com/FX-HAO/keycloak-phone-authenticator. The provider can be found. I have also created the Direct grant flow copy and made it the default direct grant flow for the realm.
I can send the verification code with a request to http://{host}//auth/realms/{my_realm}/{my_provider}/send_sms
However, I cannot get the token using the following request:
curl -X POST http://{host}/auth/realms/{my realm}/protocol/openid-connect/token
-H 'authorization: Basic {my keycloak admin username and password}'
-H 'content-type: application/x-www-form-urlencoded' -d 'grant_type=password&phone_number={phone number}&code={code}'
I keep getting the invalid_client_credentials error and it seems that my provider is not called because there is nothing in its logs.
What am I doing wrong?
As #sventorben said, the problem was in specifying wrong credentials for the client

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

OpenId via Curl

How can I do OpenId based authentication using Curl?
At first place can I do it?
Regards,
Allahbaksh
I suppose you are talking about the curl command line, not the library. I have not tried, but according to what I know of OpenID and curl, it should be possible. However, not fully automated. You'll have to "parse" the content of the identity provider and of the content provider login pages if you want to be realy restful and generic. If you know where you're going and don't mind to couple your service and client (no hateoas), you can first authenticate with the identity provider, e.g.:
curl -iSsL --user-agent 'Mozilla/5.0' --cookie cookies --cookie-jar cookies \
--data login=$mylogin \
--data passwd=$mypasswd \
https://identprovider.example.com/login
and then post your OpenID to the content provider:
curl -iSsL --user-agent 'Mozilla/5.0' --cookie cookies --cookie-jar cookies \
--data openid="$myopenidurl" \
http://contentprovider.example.com/login
This suppose that the content provider is already authorised to use the identity provider.
Then get your content:
curl -iSsL --user-agent 'Mozilla/5.0' --cookie cookies --cookie-jar cookies \
http://contentprovider.example.com/interesting/content
Note that this approach is not restful, since I hard encoded the POST uris and fields in the code. To decouple the client and the server, the uris and field names must be extracted from responses. In a bash script, you can use sed for example.
I think is should work, but if not, then you'll have to realy follow the redirects and extract URIs and forms, since some params can be passed in the redirect URIs or in hidden form fields.