Hi i am a bit confused as to how to secure applications through keycloak, the website shows how to secure clients. The application which i need to secure in my setup is a desktop application which uses keycloak + keycloak-gatekeeper protected endpoints.
i managed to get it working using the following library in python
https://bitbucket.org/agriness/python-keycloak/src/master/
however, it requires me to enter the client-secret and i am wondering if this is safe?
also, when i use the browser login instead, the browser doesnt need the client secret, but goes though gatekeeper, this tells me that i am doing something wrong here.
thanks
Use public access type client (Clients doc):
Public access type is for client-side clients that need to perform a browser login. With a client-side application there is no way to keep a secret safe. Instead it is very important to restrict access by configuring correct redirect URIs for the client.
You can change access type on clients - choose client - settings tab admin interface.
in your case, I would use Access type as confidential
and Authorization Enabled > on
and you should use the secrecy key to authorize your call to keylock when you want to interact with keycloak API
Keycloak keycloak = KeycloakBuilder.builder()
.serverUrl("localhost")
.realm("myRealm")
.grantType(OAuth2Constants.PASSWORD)
.clientId("myclient")
.clientSecret("xxxx-xxxxx-xxxx-xxx")
.username("foo")//the admin user
.password("password")
.build();
keycloak.realm("myRealm").users().list();
Related
As a newbie of Keycloak, I try to configure a client with a "Password" grant type. I know that this is not the preferred solution in most cases.
I created a realm 'realm2' with a client 'myclient2' and a user.
When trying to get the token with Postman, I get this error:
{
"error": "unauthorized_client",
"error_description": "Client secret not provided in request"
}
When I add the client_secret, I get the token. I tried to provide a username and password and no secret.
Via the Keycloak user interface I can also login as 'johan' in the 'realm2'.
This is my request in Postman:
In Keycloak I configured the 'realm2' with no special properties set:
The client 'myclient2' is:
I can see on the Credentials tab of the client:
I configured 1 user in the realm2 with just 'password' as a password:
How can I configure my Keycloack settings so I don't need the 'secret' but the username and password?
You could disable authentication for the client, making it public. You can do this by turning off "Client authentication" under the settings tab of your client.
EDIT: I just realized your keycloak version seems different to mine. This configuration is likely under the Access Type selector in your settings tab, by changing it from confidential to public
#Haf answer is right to the point; TL;DR: In the client Access Type dropdown menu select public instead of confidential.
Nonetheless, I want to add a bit more information behind the scenes since you stated that:
As a newbie for Keycloack I try to configure a client with a
"Password" grant type.
First, you should know that Keycloak implements OpenID Connect, which
is a simple identity layer on top of the OAuth 2.0 protocol.
According to the OAuth 2.0 protocol clients can be either confidential or public.
The main difference relates to whether or not the application is able
to hold credentials (such as a client ID and secret) securely.
Regarding the confidential clients:
Because they use a trusted backend server, confidential applications
can use grant types that require them to authenticate by specifying
their client ID and client secret when calling the Token endpoint.
Armed with this knowledge you can easily figure it out how to create a client that will not have a client secret.
I have a SPA (Vue) that communicates via REST with a Quarkus Backend. I would like to use Keycloak for Authentication/Authorization. However, I do not need the whole "Browser Flow" Keycloak feature, instead my SPA has its own Login Form to get a JWT from Keycloak (Direct Grant Flow). This token will be used to communicate with my REST Endpoints.
Frontend -> gets a JWT from Keycloak
Frontend -> gets access to protected resources with that JWT.
However I came accross this article that vehemently discourages devs from using the Direct Grant flow. So what now? Is there a way to still use my own login form with Keycloak?
Something along the lines of:
Frontend login -> Backend -> Keycloak Authentication/Authorization -> JTW
Frontend -> gets access to protected resources with that JWT.
I am slightly overwhelmed by all the different configuration possibilities in Keycloak and Quarkus. So far I managed to get a token from keycloak with a public client (direct grant), and that token is being used to access protected resources. My Quarkus backend knows the keycloak server too and communicates with it via a second client (acces type: confidential)
quarkus.oidc.auth-server-url=http://localhost:8081/auth/realms/myrealm
quarkus.oidc.client-id=backend-service
#quarkus.oidc.credentials.secret=my-secret
However, I am not sure why this works at all since the secret is commented out. Why would I need it in the first place ?
One way could be to use the authorization code flow with a custom theme for keycloak : https://www.keycloak.org/docs/latest/server_development/
As you are using react, you can take a look at https://github.com/InseeFrLab/keycloakify which allows you to reuse your react component with keycloak theming.
(Disclaimer: I belong to the organization maintening this library)
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
We are considering to use the keycloak as our SSO framework.
According to the keycloak documentation for multi-tenancy support the application server should hold all the keycloak.json authentication files, the way to acquire those files is from the keycloak admin, is there a way to get them dynamically via API ? or at least to get the realm public key ? we would like to avoid to manually add this file for each realm to the application server (to avoid downtime, etc).
Another multi-tenancy related question - according to the documentation the same clients should be created for each realm, so if I have 100 realms and 10 clients, I should define the same 10 clients 100 times ? is there an alternative ?
One of our flows is backend micro-service that should be authenticated against an application (defined as keycloak client), we would like to avoid keeping user/psw on the server for security reasons, is there a way that an admin can acquire a token and place it manually on the server file system for that micro service ? is there a option to generate this token in the keycloak UI ?
Thanks in advance.
All Keycloak functionality is available via the admin REST API, so you can automate this. The realm's public key is available via http://localhost:8080/auth/realms/{realm}/
A realm for each tenant will give a tenant-specific login page. Therefore this is the way to go - 10 clients registered 100 times. See more in the chapter Client Registration of the Keycloak documentation. If you don't need specific themes, you can opt to put everything in one realm, but you will lose a lot of flexibility on that path.
If your backend micro service should appear like one (technical) user, you can issue an offline token that doesn't expire. This is the online documentation for offline tokens. Currently there is no admin functionality to retrieve an offline token for a user by an admin. You'll need to build this yourself. An admin can later revoke offline tokens using the given admin API.
I have implemented Oauth2 using sparkl2 app. I am using spring-security as described in the sparkl2 app using java config. I can successfully get auth token using curl and i can invoke web service using curl.
My question is
How I can access my REST service within the same browser after login into my application? I am not sure what I am missing here?
Let me elaborate my question in more details. The way browser keep session after login and we can access any protected resource in the application, what is the best way to implement so that I can test my REST api from browser
spring security keeps it in session. Session id is stored in browser cookie, so its passed with each request to your service. Then spring security should take it and check if specific session(with user logged in) is allowed to hit this particular url.
I would start with configuring secure paths in your java config:
http.authorizeRequests().antMatchers().hasAnyRole(...)
or some other method instead antMatchers.
you probably have to log in user into spring security on some oauth callback, something like:
Authentication auth = new UsernamePasswordAuthenticationToken(user, null, authorities);
SecurityContextHolder.getContext().setAuthentication(auth);