How to integrate Keycloak user data into app db - spring

I have a spring boot application and a user column in my app db. The problem is now that my user informations are divided up at the spring boot db and the Keycloak db.
I found this older posts where there synced the data manually (redundant on both dbs), isn't there a best practice way, isn't this a standard usecase, I am wondering why there is no information about this?
How to integrate or make use of KeyCloak user database in my application?
Keycloak provider and user storage

I would say that the standard use-case is you connect
Keycloak to your application's database, which contains users' information (keycloak is just a server to authenticate your users).
To be able to connect from Keycloak to your application's database, you need to implement new Service provider interface (User Storage SPI) as mentioned in the documentation.

Related

How can I implement Single Sign On (SSO) multi tenancy functionality with Keycloak and Spring Boot OAuth2 clients?

Problem
Implementing SSO login for multiple OAuth2 providers in Spring Boot.
Setup
Two Spring Boot web applications (App1 and App2) that are configured to be OAuth2 clients. Both will communicate with a Keycloak authorization server that has two realms.
Business Requirements
Implement Single Sign-On functionality (SSO).
Multi tenancy with shared user base.
Only one user can access one tenant at any time.
I have two spring boot applications which are OAuth2 clients running in docker containers. We are setting up multiple Keycloak realms that are configured for each tenant. From the Spring side of things, we include the auto configuration properties for two providers where each provider will be mapped to a different Keycloak realm. So the properties will look as follows:
spring.security.oauth2.client.provider.realm1......
spring.security.oauth2.client.provider.realm2......
Behavior
When a user logs into the first application (App1), Spring shows a generated html page. This page shows a list of each provider configured from the application.properties as an option to login to.
A user can select one and is redirected to the Keycloak login page with the realm that was mapped from Spring's provider properties. Then when successfully logged in, the user is redirected back as expected.
We use Spring Mongo session to store the session information and we also see in the Keycloak admin client the realm that shows the active session as well.
When trying to access the other application (App2), Spring does not detect the user or session and will show the same generated html page that shows the providers to select and login to.
When clicking on the same provider (realm), Spring will then find the session and will be redirected to the requested resource and all is well. This part is what I am trying to implement without asking for the provider first. The main reason is to enforce a business requirement where a user in a session can not access more than one realm at a time.
Attempted Solution
Provide a Spring Security login controller that will have a service layer to find the mongo session and then build the OAuth2 link Spring generates when you click a provider from the list.
However, I dont have the user yet. This also becomes a problem when opening a different tab as I dont believe I have any scope to the cookies that were created from the first application as well.
The only other thing I can think of is trying to get the client ip and store that in the session so I can find it later. However, when using nginx proxy configuration, this becomes a problem as I cant seem to get the actual ip and always seem to get the proxy ip instead even with the nginx headers I have seen from documentation.
Question
Is there anyway to find the session and redirect to the requested provider programmatically?
Note: I am currently aware of the keycloak starter dependencies that are available but I was trying to see if there is a more Spring oriented solution with its general OAuth2 client security configuration.
Front end solution
User navigate to app1, app1 detects no user session (need for login), app1 redirects user to app2 with some query parameters indicating purpose of redirect.
App2 receives redirect request and check if session exist (user logged in to app2). Now you can deal with it. redirect back to app1 or display some error, etc.
User not logged in to app2 , app2 redirects back to app1 with indication "show providers"
Symmetrical behavior shall be implemented on app1 too.
Depending on security requirements query parameters can be encrypted to prevent manual url hacking.
If you need further protection Keycloak authentication can be extended with functionality to check your Session storage for already logged in users.

Custom Role Based Authorization in Spring Boot

I am developing a web application where I have React as my Frontend and Spring boot as the Backend REST API. I have authentication mechanism setup where user can login with email and password. My application will be used by a group of people for a company. The admin user will login initially and sends invites to other people in the group with predefined access privileges available in the application. How can I implement this type of role based access in spring boot.
I gone across Spring security for role based access, but I didn't find how to create custom fine grained roles based on our web application. Please someone help just to give me the path I need to go.
P.S: I want to implement the way AWS or other cloud providers implement there IAM roles to assign it to different users in their organization but not as complex but a similar functionality

How to migrate users from user service database to spring boot auth server database?

I am building a micro service bases spring boot application. In order to protect my rest APIs, i have implemented spring boot authorization server to provide oauth2 tokens to users. Currently i have users in master database under the table users. Authorization server is authenticating users from the authorization database under its users table. Do i need to migrate all my users from my master database to authorization server database? or should i call an API to user service and authenticate users?
This depends on your overall architecture, but in General you do not need to migrate users, you can check the permissions of users by calling the API of the service that stores these users.
In my opinion, this is the preferred way to divide microservices into an authentication/authorization microservice and a user information storage microservice, since user information is not related to authentication/authorization and has low connectivity, so you can easily change the authentication/authorization microservice in the future.
But there are also opposite points of view, in favor of combining authentication/authorization microservices and user storage. The main advantage of this approach is the simplicity of managing and supporting a single microservice.

How to store OAuth2 session into database and share it between Spring Boot servers

I want to create a solution based on that tutorial: https://www.baeldung.com/rest-api-spring-oauth2-angular
But it's not clear for me how several Spring Boot servers behind load balanced can share the same token session.
With session cookie the session data can be stored in MySQL and of server goes offline the session will be resumed by another Spring Boot server.
Can we have with OAuth2 the same setup with shared database so that the session data can be shared and switching of severs can be completely transparent for the end users?
Can we have with OAuth2 the same setup with shared database so that
the session data can be shared and switching of severs can be
completely transparent for the end users?
Yes, You just have to define a JdbcTokenStore and use it instead of the default InMemoryStore to store your OAuth tokens. The JdbcTokenStore must use a DataSource which is pointing to a MySQL Database.
Finally if you configure your Spring Boot apps to connect to the same MySQL Database to store Tokens by defining a DataSource you can get it working.
This post could be a good starting point.

Spring Boot REST service – End User Authentication vs APP (REST client) Authentication

I have gone through many posts and articles but didn't find a straightforward solution for the case below which I have to implement.
Platform: Spring Boot 2.x.x (Spring Security 5.x.x) with embed Tomcat
Solution: REST service that consume many client apps and many end users.
I have to implement a REST end point /api/search which accessible for many client application. As an example, web application APP-X (Angular), web application APP-Y(Jquery/Bootstrap) and mobile application APP-Z (IOS). All three clients are separate entities (both technical perspective and business perspective).
So I have to authenticate above application using onetime token. Therefore I planned to go for Spring OAuth2 by enabling #EnableAuthorizationServer and #EnableResourceServer. For each app client I’ll generate a token and they can use it when they connect with my REST service. Is this approach correct?
Apart from the app clients system has capability to register and login functionality for end users. Also my end point (/api/search) can access both anonymous users and users who registered under ROLE_REGUSER role. And through the security context, I need to access the user details as usual user authentication.
This is the place I got stuck. How can I handle the following points together using Spring Security 5.x.x (Spring Boot 2.x.x).
I. Both client apps and end users authentications.
II. Allow access for anonymous users and registered users for same end point.
I have attached small diagram to elaborate the above scenario.
Thanks
I found a solution when I upgraded my spring security version to 5.2. In version 5.2, they have depreciated #EnableAuthorizationServer and #EnableResourceServer. So I had to move with an external authorization provider who supports auth2. I chose AWS Cognito, and fulfill the above requirement, using the user pool option.
In AWS Cognito
I created a user pool.
Then created two app clients in the same user pool.
One app client configured as support to the client credentials flow.
The second app client configured as support to the user authentication flow.
In client applications
Retrieve access token directly from AWS Cognito using client credentials and used to secure all API calls.
If a user login at any stage, retrieve access token directly from AWS Cognito using the authorization code and replace any existing access token.
The advantage is, the resources server can validate any access token that generated related to the same user pool.
In resources server (backend API/Spring Boot)
Validate access token.

Resources