Keycloak security with Soteria (JEE 8)
This project is a library to add security to servlets and JaxRS endpoints using the new security specification JSR-375.
Getting started
Dependency
Maven central
Add below dependency to your pom.
<dependency>
<groupId>io.github.pablobastidasv</groupId>
<artifactId>kc_security</artifactId>
<version>{version}</version>
</dependency>
Jitpack
To older versions use jitpack. Add the dependency in your pom as below.
NOTE: Last version published on Jetpack.io is 1.2.1
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependency>
<groupId>com.github.pablobastidasv</groupId>
<artifactId>kc_security</artifactId>
<version>{version}</version>
</dependency>
Configuration
Keycloak security library could be configured through keycloak.json
file or define main values as environment variable.
With specified keycloak.json
file
NOTE: This approach supports full capabilities of keycloak-servlet-filter-adapter
, the keycloak configuration file is defined and used in total.
Create a file called microprofile-config.properties
inside META-INF
folder and add below property, this value should be the full path to keycloak
file location.
security.kc.file-path=/opt/keycloak.json
With keycloak.json
file in default location
keycloak.json
file could be also created in resource folder inside war file to be used as configuration in case security.kc.file-path
is not specified.
With environment variables
NOTE: This approach just define basic values to work in development environment or to test applications.
Create a file called microprofile-config.properties
inside META-INF
folder and add below properties with values corresponding to your configuration.
security.kc.realm=my-realm
security.kc.authServerUrl=https://my-auth-server/auth
security.kc.clientId=my-client-id
NOTE: As this project use MP-Config to set the Keycloak configuration.
JwtPrincipal
As a Principal
, is provided an extension with JwtPrincipal
which can be injected in your beans via CDI.
@Inject
private JwtPrincipal principal;
The JwtPrincipal
provides util information about the logged user. Bellow this class' attributes:
String userName;
String fullName;
String givenName;
String familyName;
String email;
String picture;
String token;
String realm;
Map<String, Object> claims;
Key | Description |
---|---|
userName | Keycloak JWT value of: preferred_username |
fullName | Keycloak JWT value of: name |
givenName | Keycloak JWT value of: given_name |
familyName | Keycloak JWT value of: family_name |
Keycloak JWT value of: email | |
picture | Keycloak JWT value of: picture |
token | The JWT token |
realm | The realm where authentication was performed |
claims | Map of any other claims and data that might be in the IDToken. Could be custom claims set up by the auth server |
Multi-tenant support
Since version 2.x.x
the library provide an alternative to handle multi-tenant environments.
To enable the multi-tenant capabilities must be perform the 2 steps described below:
- Define environment variable
SECURITY_KC_MULTITENANT_ENABLED
to true. - Implement interface
co.pablob.security.kc.control.MultiTenantProducer
.
NOTE: The property also can be set as security.kc.multiTenant.enabled
.
The MultiTenantProducer
interface
This interface requires the user to implement the method adapterConfigFromRequest
, this method receives an String
parameter which is the realm Key and thi will identify what tenant information must be loaded.
Additionally, this method must return and InputStream
created based on the information that the keycloak.json
file contains.
Below an example about how to implement this interface.
public class MultiTenantAdapterConfigProducer implements MultiTenantProducer {
@Override
public InputStream adapterConfigFromRequest(String realmKey) {
byte[] keycloakConfig = Optional.ofNullable(getKeycloakJsonString(realmKey))
.map(String::getBytes)
.orElseGet(this::defaultConfig);
return new ByteArrayInputStream(keycloakConfig);
}
}
NOTE: By default the value of realmKey
is the server name returned by HttpServletRequest::getServerName
, if this value is not enough for you, you can always overwrite the method String obtainRealmNameKey(HttpServletRequest request)
and define the key string that fits better to you.
Tested platforms
This library has been tested in: