org.camunda.bpm.extension.keycloak.KeycloakServiceBase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of camunda-bpm-identity-keycloak Show documentation
Show all versions of camunda-bpm-identity-keycloak Show documentation
A Camunda Identity Provider Plugin for Keycloak
package org.camunda.bpm.extension.keycloak;
import static org.camunda.bpm.extension.keycloak.json.JsonUtil.*;
import java.util.Arrays;
import java.util.List;
import org.camunda.bpm.engine.authorization.Permission;
import org.camunda.bpm.engine.authorization.Resource;
import org.camunda.bpm.engine.impl.persistence.entity.UserEntity;
import org.camunda.bpm.extension.keycloak.json.JsonException;
import org.camunda.bpm.extension.keycloak.rest.KeycloakRestTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestClientException;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
/**
* Base class for services implementing user / group queries against Keycloak.
* Provides general helper methods.
*/
public abstract class KeycloakServiceBase {
protected KeycloakConfiguration keycloakConfiguration;
protected KeycloakRestTemplate restTemplate;
protected KeycloakContextProvider keycloakContextProvider;
/**
* Default constructor.
*
* @param keycloakConfiguration the Keycloak configuration
* @param restTemplate REST template
* @param keycloakContextProvider Keycloak context provider
*/
public KeycloakServiceBase(KeycloakConfiguration keycloakConfiguration,
KeycloakRestTemplate restTemplate, KeycloakContextProvider keycloakContextProvider) {
this.keycloakConfiguration = keycloakConfiguration;
this.restTemplate = restTemplate;
this.keycloakContextProvider = keycloakContextProvider;
}
//-------------------------------------------------------------------------
// User and Group ID Mappings dependent on configuration settings
//-------------------------------------------------------------------------
/**
* Gets the Keycloak internal ID of an user.
* @param userId the userId as sent by the client
* @return the Keycloak internal ID
* @throws KeycloakUserNotFoundException in case the user cannot be found
* @throws RestClientException in case of technical errors
*/
protected String getKeycloakUserID(String userId) throws KeycloakUserNotFoundException, RestClientException {
String userSearch;
if (keycloakConfiguration.isUseEmailAsCamundaUserId()) {
userSearch="/users?email=" + userId;
} else if (keycloakConfiguration.isUseUsernameAsCamundaUserId()) {
userSearch="/users?username=" + userId;
} else {
return userId;
}
try {
ResponseEntity response = restTemplate.exchange(
keycloakConfiguration.getKeycloakAdminUrl() + userSearch, HttpMethod.GET, String.class);
JsonArray resultList = parseAsJsonArray(response.getBody());
JsonObject result = findFirst(resultList,
keycloakConfiguration.isUseUsernameAsCamundaUserId() ? "username" : "email",
userId);
if (result != null) {
return getJsonString(result, "id");
}
throw new KeycloakUserNotFoundException(userId +
(keycloakConfiguration.isUseEmailAsCamundaUserId()
? " not found - email unknown"
: " not found - username unknown"));
} catch (JsonException je) {
throw new KeycloakUserNotFoundException(userId +
(keycloakConfiguration.isUseEmailAsCamundaUserId()
? " not found - email unknown"
: " not found - username unknown"), je);
}
}
/**
* Gets the Keycloak internal ID of a group.
* @param groupId the userId as sent by the client
* @return the Keycloak internal ID
* @throws KeycloakGroupNotFoundException in case the group cannot be found
* @throws RestClientException in case of technical errors
*/
protected String getKeycloakGroupID(String groupId) throws KeycloakGroupNotFoundException, RestClientException {
String groupSearch;
if (keycloakConfiguration.isUseGroupPathAsCamundaGroupId()) {
groupSearch = "/group-by-path/" + groupId;
} else {
return groupId;
}
try {
ResponseEntity response = restTemplate.exchange(
keycloakConfiguration.getKeycloakAdminUrl() + groupSearch, HttpMethod.GET, String.class);
return parseAsJsonObjectAndGetMemberAsString(response.getBody(), "id");
} catch (JsonException je) {
throw new KeycloakGroupNotFoundException(groupId + " not found - path unknown", je);
}
}
//-------------------------------------------------------------------------
// General helper methods
//-------------------------------------------------------------------------
/**
* Return the maximum result size of Keycloak queries as String.
* @return maximum results for Keycloak search requests
*/
protected String getMaxQueryResultSize() {
return Integer.toString(keycloakConfiguration.getMaxResultSize());
}
/**
* Truncates a list to a given maximum size.
* @param element type of list
* @param list the original list
* @param maxSize the maximum size
* @return the truncated list
*/
protected List truncate(List list, int maxSize) {
if (list == null) return list;
int actualSize = list.size();
if (actualSize <= maxSize) return list;
return list.subList(0, maxSize);
}
/**
* Adds a single argument to search filter
* @param filter the current filter
* @param name the name of the attribute
* @param value the value to search
*/
protected void addArgument(StringBuilder filter, String name, String value) {
if (filter.length() > 0) {
filter.append("&");
}
filter.append(name).append('=').append(value);
}
/**
* Checks whether a filter applies.
* @param queryParameter the queryParameter
* @param attribute the corresponding attribute value
* @return {@code true} if the query parameter is not set at all or if both are equal.
*/
protected boolean matches(Object queryParameter, Object attribute) {
return queryParameter == null || queryParameter.equals(attribute);
}
/**
* Checks whether a filter applies.
* @param queryParameter the queryParameter list
* @param attribute the corresponding attribute value
* @return {@code true} if the query parameter is not set at all or if one of the query parameter matches the attribute.
*/
protected boolean matches(Object[] queryParameter, Object attribute) {
return queryParameter == null || queryParameter.length == 0 ||
(attribute != null && Arrays.asList(queryParameter).contains(attribute));
}
/**
* Checks whether a like filter applies.
* @param queryParameter the queryParameter
* @param attribute the corresponding attribute value
* @return {@code true} if the query parameter is not set at all or if the attribute is like the query parameters.
*/
protected boolean matchesLike(String queryParameter, String attribute) {
if (queryParameter == null) {
return true;
} else if (attribute == null) {
return queryParameter.replaceAll("[%\\*]", "").length() == 0;
}
return attribute.matches(queryParameter.replaceAll("[%\\*]", ".*"));
}
/**
* Null safe compare of two strings.
* @param str1 string 1
* @param str2 string 2
* @return 0 if both strings are equal; -1 if string 1 is less, +1 if string 1 is greater than string 2
*/
protected static int compare(final String str1, final String str2) {
if (str1 == str2) {
return 0;
}
if (str1 == null) {
return -1;
}
if (str2 == null) {
return 1;
}
return str1.compareTo(str2);
}
/**
* @return true if the passed-in user is currently authenticated
*/
protected boolean isAuthenticatedUser(UserEntity user) {
return isAuthenticatedUser(user.getId());
}
/**
* @return true if the passed-in userId matches the currently authenticated user
*/
protected boolean isAuthenticatedUser(String userId) {
if (userId == null) {
return false;
}
return userId.equalsIgnoreCase(
org.camunda.bpm.engine.impl.context.Context.getCommandContext().getAuthenticatedUserId());
}
/**
* Checks if the current is user is authorized to access a specific resource
* @param permission the permission, e.g. READ
* @param resource the resource type, e.g. GROUP
* @param resourceId the ID of the concrete resource to check
* @return {@code true} if the current user is authorized to access the given resourceId
*/
protected boolean isAuthorized(Permission permission, Resource resource, String resourceId) {
return !keycloakConfiguration.isAuthorizationCheckEnabled() || org.camunda.bpm.engine.impl.context.Context
.getCommandContext().getAuthorizationManager().isAuthorized(permission, resource, resourceId);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy