Synchronising client DB with Keycloak users - keycloak

We are currently in the process of migrating our user authentication to Keycloak, using an OIDC server. The issue is that the architecture of some of our client applications rely on existing user tables, linked to numerous other tables throughout the services.
How can we go about keeping Keycloak users in sync with the client user, so that if a customer deletes or creates a user on Keycloak, it's reflected in that client DB? Is this generally done through overwriting OIDC methods?
Similarly, when a user logs in through Keycloak, we will require a lookup on the client DB to get additional attributes for the access token, such as the client userId and accountId for that user. Can this be done via overwriting thetransformAccessToken method and making a request to the client BE?

Related

Keycloak users security

I am using Keycloak 18.0 for Angular 13 + Spring Boot App. The solution utilizes Microservices architecture pattern for this app so basically Keycloak already guards access to other solution resources. I am using only Keycloak REST API.
The problem is Keycloak security itself:
I want to restrict Keycloak client token only to user creation.
Any user has to be able:
1. Fully access and manage ONLY his own profile.
2. Has restricted access to profiles of other users.
3. Any other operation of viewing other users, adjusting
roles etc. should be enabled only if authenticated user
has some kind of permission to do it.
For example:
Anybody can create user (signup).
After user is verified, some role is assigned to that user.
User logs in and acquire its token that has permissions to fully manage only his own resources including user itself and has restricted access to other users and user resources.
I am not sure I want to integrate Keycloak as resource security manager (i am considering that option but for now, only Spring Boot Adapter was implemented to control corresponding resources security) but at least i would like to prevent e.g. reading full list of users using Keycloak client token.
I have basic understanding of Keycloak Resource/Policy/Permission Feature but I am not sure i understand how can i apply it to Keycloak users itself.
Thanks a lot in advance for your help.

Does Keycloak need a database

I have setup Keycloak as a SAML broker, and authentication is done by an external IdP provided by the authorities. Users logging in using this IdP are all accepted and all we need from Keycloak is an OAuth token to access our system.
I have tried both the default setup using H2 and running with an external MariaDB.
The external IdP provides us with a full name of the user and a personal ID. Both data are covered by GDPR and I really do not like the sound of storing that data in a database running in the DMZ. Opening up for Keycloak to access a database in the backend is also not a good solution, especially when I do not need users to be stored.
The benefit of running without a database is that I have a simpler DMZ setup as I really do not need to store anything about the users but on the backend.
Do I need a database, and if not how do I run Keycloak without it?
Do I need a database, and if not how do I run Keycloak without it?
Yes, however, out-of-the-box Keycloak runs without having to deploy any external DB. From the Keycloak official documentation section Relational Database Setup one can read:
Keycloak comes with its own embedded Java-based relational database
called H2. This is the default database that Keycloak will use to
persist data and really only exists so that you can run the
authentication server out of the box.
So out-of-the-box you cannot run Keycloak without a DB.
That being said from the same documentation on can read:
We highly recommend that you replace it with a more production ready external database. The H2 database is not very viable in high concurrency situations and should not be used in a cluster either.
So regarding this:
The benefit running without a database is that I have a simpler DMZ
setup as I really do not need to store anything about the users but
on the backend.
You would still be better offer deploying another DB, because Keycloak stores more than just the users information in DB (e.g., realm information, groups, roles and so on).
The external IdP provides us with a full name of the user and a
personal ID. Both data are covered by GDPR and I really do not like
the sound of storing that data in a database running in the DMZ.
Opening up for Keycloak to access a database in the backend is also
not a good solution, especially when I do not need users to be stored.
You can configured that IDP and Keycloak in a manner that the users are not imported to the Keycloak whenever those user authenticate.

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

WSO2 IS and WSO2 APIM - Role change

I followed the steps mentioned in the below WSO2 documentation to use WSO2 IS as an Identity Server with WSO2 APIM.
I use WSO2 IS 5.3.0 and WSO2 APIM 2.1.0.
https://docs.wso2.com/display/AM210/Configuring+WSO2+Identity+Server+as+a+Key+Manager
I am able to access the carbon admin console in both the WSO2 IS and WSO2 APIM (in two ports)
https://localhost:9443/carbon/admin/login.jsp
https://localhost:9444/carbon/admin/login.jsp
When I use WSO2 IS console (9443) to change the user roles, most of the times it is getting reflected immediately, using the same access token. How can it be possible ? An access token is provided by WSO2 with some pre configured scopes. Within the same login session, even before the access token expires, If we change the roles of the logged in user, the roles changes are applied immediately and my access rights are changed ? Is it a valid ?
Assume a user "USER1" got an access token with privileged rights and he/she is able to access privileged APIs. Suddenly if the roles are changed and user "USER1" is assigned a normal user rights, and the user is not able to access the privileged APIs within the same login session. Is this how OAuth works ?
Please help me understand.
If I change the roles in WSO2 APIM (9444), the roles are not getting reflected immediately. Some times, it wait for the access token to expire and the gets a new access token. Sometimes, role changes are getting applied even before the access token expire.
What is the synchronization interval between WSO2 IS and WSO2 APIM, to sync the roles?
I couldn't find these roles in mysql db or ldap. Where are they stored in the backend ?
There are differences in IS as a key manager and the inbuilt key manager of API Manager. The key manager comes with API Manager is not a full fledged Identity solution. Hence its role to scope mapping, access control, etc. are somewhat limited in the point of view of Identity Management aspects.
Identity server acting as a key manager provides the full access control mechanism, hence the change in the role should affect fast as possible, even for issues keys. This is one of the reasons of using IS as a key manager.
Question 1
Ans:
Lets say a user has an admin right when he got the access token. The enterprise may decide the user has no longer needs this right and changes that on their LDAP. It should be reflected on key validation as fast as possible. Otherwise the user has continued access to the service as privileged user until key expires, which is undesirable. So the behavior is valid.
Question 2
Ans: Yes, API Manager is strong on managing APIs. However, it is not a use/role management system. Hence there will be considerable delay in reflecting the role change. So, make sure you use IS to manage the user/roles, etc. when your API Manager is configured with IS.
Where is your configured roles
It should be in WSO2UM_DB configured (UM_ROLE table), if JDBC user store is your primary UserStore.

SSO with keycloak

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.