use single unique client for multiple realm in keycloak - keycloak

We are using keycloak in a multi-tenant micro-services application.
We have planed to use one realm per tenant.
Also there is single endpoint that all user requests (from all tenants) authenticated with JWT bearer token flow.
Is that possible to create one application client in keycloak and share it amount all realms?
Or we have to create a client (with same name) for each realms?

Is that possible to create one application client in keycloak and
share it amount all realms?
Out-of-the box this is not possible, just like users, clients are defined at the Realm level, and consequently, cannot be shared among realms.

Related

Migrate from JWT to Identity Server 4 without need to re-login website users after deployment

I have an API service that is currently secured using JWT. I'm going to replace JWT with Identity Server 4 and secure my API with Identity Server 4. I had a custom way of generating JWT tokens (JWE). How can I replace JWT with Identity Server 4 without the current signed-in users to the site need to re-login?
Specifically, I wanna use the Skoruba Identity Server 4 project template.
In IdentityServer, the access tokens are generated to authenticate users. The Access tokens have very small limited lifetime as per convention. There's a concept of refresh token which has longer lifetime and the same is used with basic auth to get new access token. This prevents the hassle to sign in again and again.
The refresh tokens are built using a hash and are persisted in a table (if configured).
JWE is a very different setup altogether. I had my users logged out even after a new deployment of IdentityServer4 (using of persistent grants is helping to solve this).
I don't think it's not technically possible to transfer sessions from one environment to another. Both use a encryption decryption strategies which are very different from each other.
You can give a try by writing a custom implementation of TokenCreationService

Flask-OIDC | How to call a specific function after the user logged in

I built a login system using Flask OIDC and Keycloak. In my system, there is some endpoints decorated with oidc.require_login() that calls the Keycloak login page.
My goal is, after the user successfully logged in, my system checks if the user name exists in a specific database.
How can I set a function to be called every time someone successfully logged in with Keycloak and do this verification at the database?
According to your needs there are several ways to create the user in the backend.
The easiest way would be to just check the JWT token on every request. OIDC is based on JWT and that token is available on any request (which should already be done to find user roles etc). So your application can check that JWT and extract the username from it (see here for details about the JWT format). With the username you can check your internal database and create the user, if it doesnt exist. But at that time you'll not have access to any user credentials any more. It is just SSO and you need to trust Keycloak and the JWT... Also - you'll never be informed, if the user will be deleted in Keycloak, which could be an issue.
There is a callback API in Keycloak in form of the Admin URL per client. But the documentation is not clear. It says: It’s used by the Keycloak server to send backend requests to the application for various tasks, like logout users or push revocation policies. But I cannot find a complete list of "tasks". I saw only logout events. see Keycloak documentation and the documentation only talks about that. If I add an admin url to a test client, I did not get any requests at login time.
a different but more complicated way would be to create your own UserStorage SPI in Keycloak. It would be Java of course, but only some classes. There is an HTTP example or have a look at the LDAP user storage SPI, which supports registration too. If you choose that for your realm and a user tries to login to Keycloak (Login form), the SPI can call your backend to check the user. It also could be "used" to create the user in the backend by checking the Keycloak local storage and only if there is a local Keycloak user, call the backend. That isn't the reason, why you should implement the UserStorage SPI, but it's possible. If you think, this is a good idea, I would prefer to use your backend storage as the one and only storage or build a different one, that then could call your real backend in case of a new user. I would use this one by not using Keycloak local stored users but, by using your own database.
next (maybe last one). You can write an EventListener SPI to read all events and only filter the login events, see here and here. I think, that would be the easiest one. But be aware. In that case, the HTTP call to your backend coming from the event itself is based on a normal HTTP request (without OIDC at that time).
The last two examples create a JAR (which is explained in the links). That JAR with the SPI must be deployed in keycloaks standalone/deployments folder. The EventListener should be active by default, the UserStorage SPI must be activated per realm.
But - be aware - Keycloak/SSO/JWT - should not be used by creating users in multiple backends. Syncing the users between all backends in a SSO environment is maybe the wrong way. Most information is located in the JWT or can be called by a backend from one central user identity management. Do not store a user more then once. If you need the user reference in your backend - link just to the username or userid (string) instead of a complete entity.
There is no direct way of doing this, other sotfware like Openam, Okta allow you to trigger specific flows in a post-login configuration.
In keycloak, you can try to create your custom authn flow(using Default Identity Provider, its the only option that allow a redirect), and then select this flow in your Identity provider in post login flow.
The idea here is that after login, the user will be redirected to a link ( an api call that will verify his presence on the external database, and sent him back to keycloak once the verification is done.
More info here

Go get access to Users Resources, Policies and Permissions in Keycloak 7.x

I am evaluating Keycloak 7.X to be used in our applications consist of approximately twelve microservices (Spring Boot) and four Angular 6.x applications. I plan to use Keycloak adapters for Angular applications as well as Spring Boot instead of OAuth 2.0 for SpringBoot. My proof of concept must demonstrate the following use cases.
(1) Single Sign-On.
(2) Role-Based access control
(3) Policy and Permission- e.g. a user with role "Supervisor" should be able to access the salary of all employees of the organization. However, he/she could give raise to only those employees who work at the same location of the supervisor. In other words, there will an attribute "location" assoicated with each user. Even if the role of the user is "Supervisor", the permssion must consider the attribute "location" to determine access to the resource.
I am planning to use JWT. The JWT will contain the list of permissions and the individual microservice will determine using the combination of "location" and "permission".
Unfortunately, I am unable to configure the client in Keycloak to assign policies and Permissions nor could I find any example on internet.
To use policies and permissions your applications should implement User-Manager Access 2.0 protocol. Read User-Managed Access documentation page for example flow.
I am planning to use JWT. The JWT will contain the list of permissions and the individual microservice will determine using the combination of "location" and "permission".
If the logic behind access definition is located in microservices then you don't need policies and permissions. You can just define roles (e.g. supervisor) and attributes (e.g. location) on Keycloak side and set them to be included in access token (JWT).

Keycloak - Limit users access per client/application

I've just setup my first Keycloak server to offer SSO between two applications. These are not Java applications, and one is connected with SAML-2 and the other with OpenID Connect.
So in Keycloak I have Realm-1, and then Client-1(application1) and Client-2(application2) and user-1 and user-2.
Now I want user-1 to only be allowed access to Client-1, and user-2 to be allowed access to both Client-1 and Client-2. Should be simple enough.
I have tried to read up on Roles and Authorization, but I find the documentation(or maybe just the topic) very confusing. I have been playing around with it with no success. I was expecting an interface to just map a group to a Client, and restrict access to the Clients by adding/removing users from groups.
If you are using SAML:
Create a new role in Keycloak.
Assign this role to the group.
Create new authentication script in Keycloak. Configure which role is allowed upon login (e.g. user.hasRole(realm.getRole("yourRoleName")) ).
In client setting, under "Authentication Flow overrides" choose the created authentication(from step 3).
If you are using openid, look at the comment in this thread

How to use authorization using tokens (Oauth, JWT, etc.) in modern web server applications

I am developing a web server application where I need to add authorization. This is the typical flow:
server issues token(Oauth/JWT) to the client after authentication
client sends token in each REST API request to server
server validates token and extracts the privileges held by the owner of this token
server accordingly fulfills client's request
Question:
Depending on the role of the client, the data from a SQL DB (mysql, oracle, etc.) needs to be returned back to the client. Let's say there are three users each with different roles:
userA
userB
userC
The DB has various tables and depending upon the role of the user the access to the data (tables as well as columns) is allowed.
How do I manage this access ? Should I put this logic of varying access in the web server or it needs to go into DB ?
Making SQL queries on the fly based on user role does not sound practical to me. I am looking for good practices to handle such a scenario.
[I am using Play+Scala for web server]