How to get Keycloak user information via REST without admin role - keycloak

I'm using keycloak as authorization server. The users send own username/password to MyWebApp and MyWebApp with grant_type: password get the token and then response token to the user. Now I want to my users be able to get their information, change their password and everything related to themselves RESTFUL. When I send a rest request to /{realm}/users/{id} to get user information, The keycloak get 403 error response. How can I get user information without admin access from keyclaok?
Note: I've seen this question, But I want to give the user edit profile too.

I think you are using Oauth with Grant type=password. If the token you mentioned is generate by Keycloak. You can request user information to Keycloak using /userinfo endpoint.
This is example of endpoint:
"http://localhost:8080/auth/realms/demo/protocol/openid-connect/userinfo"
This is how to send the parameters:
https://connect2id.com/products/server/docs/api/userinfo
GET /userinfo HTTP/1.1
Host: c2id.com
Authorization: Bearer Gp7b5hiURKpWzEXgMJP38EnYimgxlBC1PpS2zGXUqe

As far as i know in new versions of Keycloak, Account application (~/auth/realms/{realm}/account) will be implemented as REST backend so your users will be able to work with their profile data in RESTful way (check out keycloak blog).
If you can't wait too long for such feature, you could implement your own REST backend for user profile operations. It mean that you have to implement REST endpoint Service Provider, and integrate to that API your custom set of Keycloak Roles (Your also may to implement endpoint without checks for any roles, so only bearer authentication required). Check Keycloak development docs, also you could use Keycloak sources, especially org.keycloak.services.resources.admin package as implementation example.
PS. For viewing user info, consider using User Info OIDC endpoint (See Hlex answer). It also could be customized via OIDC mappers (Clients -> {client Id} -> Mappers tab)

Related

Disable Keycloak user quickly when account is disabled on identity provider

When an user account is disabled on a connected IdP, how do I ensure the account is blocked as soon as possible on Keycloak? At the moment, the “disabled” user is able to continue using my SPA because Keycloak continues to refresh the access token without speaking to the external IdP.
One of the critical features required by my partners when using SSO is that they have control over their users’ access to my application. At the moment if the user was logged into my SPA, they can continue using it for about 24 hours. I would hope to cut that time down to 5 minutes, the lifetime of the access token.
The external IdP is Google. I have tried using both Keycloak’s builtin Social provider for Google as well as setting up a SAML app in Google and user-defind SAML provider in Keycloak. I’m using Keycloak v9 but can upgrade if necessary.
Is there a recipe to achieve my goal? What options do I need to set in the Keycloak client and SAML provider?
Many thanks!
The approach could be as follows. The resource server will need to do the checking with the IDP, not Keycloak.
Enable the option to Store Tokens and Read Stored Tokens in the IDP settings.
Assign users the broker/read-tokens role.
On the resource server, decide on a frequency to check whether the user has been disabled on the IDP. Be aware of each IDP's token introspection's endpoint. Each time the API is consumed:
First of course verify the access token as usual.
If it's time to verify against the IDP, call the Keycloak API with the access token to retrieve the IDP's access token.
The Keycloak endpoint is: https://{domain}/realms/{realm}/broker/{idpid}/token
Call the IDP's token introspection endpoint to validate the IDP access token.
Act accordingly if the IDP responds that the token is not valid. Respond with 401 and ensure that the Keycloak access token can't be used again. Maybe the end_session_endpoint or revocation_endpoint, not sure.
Token validation endpoints:
Google: https://www.googleapis.com/oauth2/v3/tokeninfo?access_token={access_token}
AuthO: https://{tenant}.eu.auth0.com/userinfo
MS Azure: doesn't exist, good luck with that!

Keycloak Resource Server authorization flow

I'm new to Keycloak and trying to find out if authorization services (Resource Server) can fit my requirements.
I have the following scenario: A client app is trying to access my API endpoints which are behind the API gateway. I want to authenticate (using id and secret) the app and if it's App A allow it access to the endpoint /credits, if it's App B allow it access to the endpoint /debits.
I assume that API gateway should verify if a call should be rejected or not.
Could you please tell me what should my workflow look like and what Keycloak functionality should I use?
I'd add roles CREDITS_CLIENT and DEBITS_CLIENT to the API_SERVICE realm in keycloak.
Then, I'd create app-a-service-account and app-b-service-account in that realm, the former with CREDITS_CLIENT role and the later with DEBITS_CLIENT role.
In the gateway or API controller, endpoint /credits requires role CREDITS_CLIENT and endpoint /debits requires role DEBITS_CLIENT.
On each call, check if the details in the jwt include the role that authorizes the account/user to access the endpoint.

Keycloak REST API 401 when using custom client with service account

we want to access the Keycloak (Version 10) REST API from one of our backend services. To authenticate, we have setup the followings:
new clients within our realm
enabled service account for that client
assigned all [1] roles of “realm-management” to the services account
Accessing the API, e.g. fetching a selected user always results in a 401 response.
Steps to make the requests are:
Retrieve access_token from https://my-keycloak.com/auth/realms/my-realm/protocol/openid-connect/token using grant_type=client_credentials + Client ID + Client Secret
Fetch user from https://my-keycloak.com/auth/realms/my-realm/users/some-user-id-4711
using the Authorization: Bearer $ACCESS_TOKEN with the Token from step 1.
My Question: Is it even possible to use a custom client or do we have to stick to login via admin-cli? How would we need to configure the custom client, to grant access to the REST API.
Thanks,
Martin
[1] Simply setting all roles for the sake of testing, regardless that we only want to read data in the end.

Keycloak authentication: how can a external user get an token without exposing client secret

I have a query about how keycloak is supposed to be working with client without GUI access.
Basically I have:
A keycloak server configured with a realm, clients(Access type confidential) and Users
A server application with a GUI that also provide API, secure with keycloak (client, user, blablabla)
This is kind of working already as I am able to log on the GUI, have the redirect, etc..
Even accessing the APIs works well, when I have access to a GUI: I log on my UI, follow the redirect and get my UI to display the token. The the human (to differentiate the user from an application), can use the token in any API client.
In this context the user never sees the client secret, which is instinctively the right way. (note that I am very opened to people telling me my instinct is wrong!)
What I am NOT able to do so far is to find the way a server application (without GUI) can get a valid token?
The authorization_endpoint, as far as I understand it, requires both the client id and the client secret) to get a token, which I would rather avoid: I don't think giving my client secret to all my "customers" is the proper way to do it.
Alternatively I could create an API on my client that woudl ask for user credential and ask for the token in its behalf, but that would expose the clients credentials to my application, which is against the whole concept!
I tried setting my client Access type as public, but when I use the API call below I also get a error:
POST /auth/realms/realmname/protocol/openid-connect/tokenAPI
'grant_type=client_credentials'
'client_id=client_id'
'username=username'
'password=password'
{
"error": "unauthorized_client",
"error_description": "Public client not allowed to retrieve service account"
}
Would anyone know how this is supposed to be done ?
Thanks in advance.
Max
(...) A server application (without GUI) can get a valid token... typically using the Client Credentials flow.
But we would define in this case a dedicated Client for your server (client?) application to authenticate against. The returned token (not bound to a specific user) will serve for authorizations on allowed applications (i.e. your classic GUI or API clients).
So, basically you should (in very short):
define a specific confidential Client in your Keycloak
add the desired applications (or other Clients) to the Client Scope(s). Those you want to authorize transitively from this Client.
authenticate against this Client with Client Credentials flow (given the token endpoint, client id, credentials, scope)
ensure that you are authenticating through TLS and that parameters are included in request body (and not in headers - for enhanced privacy)
further harden security of your Client(s)
When you do not want anymore this particular server (client?) application to access your applications, you can change the corresponding "authentication" Client's secret/credentials or simply delete it.
"I don't think giving my client secret to all my "customers" is the proper way to do it."
You are right and the proposed method above strictly avoids that. Each customer would have its own credentials.
EDIT
(adding more details)
By performing as above, you would end up with the following scheme:
Flow Keycloak Server
C/S app. or Customer X <--- Client Creds ---> Auth. Client X
--- Access Token ---> Appl. Client <--> Appl. Server
C/S app. or Customer Y <--- Client Creds ---> Auth. Client Y
--- Access Token ---> Appl. Client <--> Appl. Server
Browser users <--- Standard ------> Appl. Client <--> Appl. Server
Note: this is not a detailed flow chart. Arrows mostly show relationships here.
Finally, please note that the terminology may differ a little here, but the proposed method is basically the same that Google uses. So you may aswell take some inpiration from there:
https://developers.google.com/identity/protocols/oauth2
I just had the same problem some weeks ago
In my case, I have a backend API and a frontend application that the users can use.
Eventually, I can't share the client_secret to the frontend application.
So here is my solution:
On keycloak, create a client (ex front_end_client) with grant type public
This client is going to be used by the frontend application to authenticate users using implicit flow (with PKCE will be more secure)
On keycloak, create a second client (On the same REALM as the first client) with grant type confidential, this client is going to be used by the backend API
Now, this is how it works:
Frontend app authenticate users and get the access token (Using the font_end_client)
The frontend app sends this token for every request to the backend
Backend app verify this token, and can retrieve permissions from it

Oauth2: how should the resource server know if the access token is valid?

I'm implementing an Ouath2 authentication with Spring for our mobile API. So far it works but I don't know how I should keep the resource server separate. So I have an auth server which gives out tokens and refresh tokens using the password grant-type. Meaning the user would log into the mobile app, which sends the auth server the client id/client secret along with the user's
credentials, which results in an access token and a refresh token for the user with the appropriate (ROLE_USER) privileges. Another web based client is for the admins who do the same and get the ROLE_ADMIN privilege etc.
This works well so far.
Now if any client sends a request to the resource server what should happen? Should the resource server check the token's validity? If so in what way? Or should the auth server copy the token into the resource-server's database?
If you #EnableResourceServer you get a filter that checks access tokens. It needs to share a TokenStore with the auth server. That's about it to get something working.