This paper describes how to leverage Keycloak/RH-SSO in a microservice SAAS Architecture.
1) SAAS: Software as a Service with KeyCloak
- All Saas Applications are registered within keycloak as client service using confidential mode.
- A Saas application can be registered using client_id/client secret or client_id/signed jwt
2) Multitenancy architecture with Saas application
- A Saas architecture is able to deal with multiple tenant.
- A tenant corresponds to domain such as foo1.com (for compagny foo1), foo2.com (for compagny foo2) … foo.com (for compagny foon)
One of the key concept of multitenancy architecture is the concept of complete isolation from one tenant to the other.
With keycloak, this concept is leveraged using a realm per tenant basis. It means that there will be a specific realm per tenant
3) How keycloak address concept multi tenancy with Saas
Multi Tenancy, in our context, means that a single target application (WAR) can be secured with multiple Keycloak realms.
In practice, this means that the application needs to have multiple keycloak.json adapter configuration files (one per realm). Keycloak is implementing a config resolver path to detect from which tenant it has been called
org.keycloak.adapters.KeycloakConfigResolver. For example: package example; import org.keycloak.adapters.KeycloakConfigResolver; import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.adapters.KeycloakDeploymentBuilder; public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver { @Override public KeycloakDeployment resolve(OIDCHttpFacade.Request request) { if (path.startsWith("alternative")) { KeycloakDeployment deployment = cache.get(realm); if (null == deployment) { InputStream is = getClass().getResourceAsStream("/tenant1-keycloak.json"); return KeycloakDeploymentBuilder.build(is); } } else { InputStream is = getClass().getResourceAsStream("/default-keycloak.json"); return KeycloakDeploymentBuilder.build(is); } } }
As a consequence, it means that the Sass application needs to be registered within all tenants (i.e realms, using and sharing same client_id/client_secret or client_id/signed jwt) for all tenants
Further information on this section are available at:
- https://github.com/keycloak/keycloak/tree/master/examples/multi-tenant (keycloak demo example)
5) LDAP Identity Store – Keycloak
It is possible to use a single LDAP identity store.
At LDAP level, each tenant is going to be mapped in a different organizational unit
Example
Top level=dc=example,dc=dcom Tenant 1: ou=foo1,dc=example,dc=com Tenant 2: ou=foo2,dc=example,dc=com ....... Tenant n: ou=foon,dc=example,dc=com
As all the different tenants are mapped on different ou branches, it is possible to have a single LDAP backend (which is containing all the different branches suffixes)
Each realm teant is mapped on a specific branch, as the tenant filtering is specified in the realm/tenant mapping
(example filter ou=foo1 for realm 1)
The LDAP database is able to achieve scalability with million of entries.
6) Integrating Saas with other IDP Providers
It is also possible to integrate with other IDP providers such as OKTA, OneLogin using SAML or opendid protocol. In this case keycloak is considered as a Service Provider (SP).
Most often, mappers have to be set in order to retrieve the mandatory attributes expzcted by keycloak such as username/email/firtsname/lastname
Accoung linking has also to be specified, as there are also various ways to deal with account linking
7) Saas presentation Login Panel with external IDP
By default, when nothing is done, a specific button is added to the usual username/login page with keycloak web page. To be redirected to the specific external IDP, the customer needs to click on this specific button.
It is possible to bypass the Keycloak panel, and being redirect immediately to the external IDP from keycloak. This provides a feeling that the Saas application is direcly hosted on the external IDP, although behind the scene it is redirected through keycloak used as SP.
The configuration of this is described at:
12.2. Default Identity Provider
It’s possible to automatically redirect to a identity provider instead of displaying the login form. To enable this go to Authentication select the Browser flow. Then click on config for the Identity Provider Redirector authenticator. Set Default Identity Provider to the alias of the identity provider you want to automatically redirect users to.
If the configured default identity provider is not found the login form will be displayed instead.
This authenticator is also responsible for dealing with the kc_idp_hint query parameter. See client suggested identity provider section for more details.
8) Saas – High availibility
In order to provide High Availability for Saas solution you need to consider to implement
Keycloak High Availibility:
- It is done using Keycloak being deployed in a cluster
LDAP high availibility
- done through LDAP replication with 2 LDAP instances as well
9) Deploying a microservice architecture with a Saas Authentication service using keycloak
Keycloak scales very well with micro-service architecture Saas architecture.
As already presented before, the user needs to have a dedicated service to perform authentication which is shared among all the different tenants.
9.1) Registering a microservice
Each microservice needs to registered with keycloak as an openID client the mode bearer only mode within keycloak
9.2) Accessing to the microservice from a client application directly
A client application for which is returned an id_token and access token, can access to the microservice directly using the access token. (It is assumed that the service client application has been configured to return access tokens and id_tokens)
This dedicated service is registered with keycloak as an openID client. It means that in response is returned a signed JWT id_token and access_token.
9.3 Passing a bearer token to a microservice
A beraer token to access the microservice can be done as follows
(customer-portal – keycloak examples)
HttpGet get = new HttpGet(UriUtils.getOrigin(req.getRequestURL().toString()) + "/database/customers"); get.addHeader("Authorization", "Bearer " + session.getTokenString()); try { HttpResponse response = client.execute(get); if (response.getStatusLine().getStatusCode() != 200) { throw new Failure(response.getStatusLine().getStatusCode()); }
9.4 Microservice verifying the signature
The id_token with keycloak is always signed with RSA256 realm signature.
This id_token is thus passed to the different microservices, where each microservice can validate that the token is valid.
As within keycloak, access tokens are also implemented as signed JWT. It is also possible to validate directly the signature of the access_token passed to the microservice.
For this, the microservice is getting hold of the public key of the realm to verify the access token.
An example of java code source verification is provided at:
https://gist.github.com/thomasdarimont/52152ed68486c65b50a04fcf7bd9bbde
- New Keycloak online training - 19 janvier 2022
- Sizing Keycloak or Redhat SSO projects - 8 juin 2021
- Keycloak.X Distribution - 28 janvier 2021