11 Commits

13 changed files with 110 additions and 133 deletions

View File

@@ -25,7 +25,8 @@ Notice the use of `PostResources` instead of `PreResources`. This library needs
| Keycloak Activiti App Extension | Activiti App | | Keycloak Activiti App Extension | Activiti App |
| ------------------------------- | --------------- | | ------------------------------- | --------------- |
| v1.0 - v1.2 | v1.11.x | | v1.0 - v1.2 | v1.11.x |
| v1.3+ | v1.11.x - v2.3+ | | v1.3 | v1.11.x - v2.x |
| v1.4+ | v24.x+ |
## Configuration ## Configuration
@@ -35,7 +36,7 @@ The library is highly configurable. You configure it with properties specified
| Property | Default | Description | | Property | Default | Description |
| ---------------------------------------------- | --------- | ----------- | | ---------------------------------------------- | --------- | ----------- |
| `keycloak-ext.ais.enabled` | `false` | Enable AIS integration, overriding and extending the OOTB AIS provider. | | `keycloak-ext.keycloak.enabled` | `false` | Enable Keycloak integration, overriding and extending the OOTB OAuth provider. |
| `keycloak-ext.ootbSecurityConfig.enabled` | `true` | Enable OOTB functionality as if this module were not installed. This adapter operates at priority `0`. This means it only works if other adapters are disabled (default). | | `keycloak-ext.ootbSecurityConfig.enabled` | `true` | Enable OOTB functionality as if this module were not installed. This adapter operates at priority `0`. This means it only works if other adapters are disabled (default). |
| `keycloak-ext.default.admins.users` | | A default set of administrators to add to the administration role on application startup. | | `keycloak-ext.default.admins.users` | | A default set of administrators to add to the administration role on application startup. |
| `keycloak-ext.clearNewUserDefaultGroups` | `true` | When creating a new user, clear any default groups added to that user. This will not impact existing users. | | `keycloak-ext.clearNewUserDefaultGroups` | `true` | When creating a new user, clear any default groups added to that user. This will not impact existing users. |
@@ -57,8 +58,8 @@ The library is highly configurable. You configure it with properties specified
| Property | Default | Description | | Property | Default | Description |
| ----------------------------------------- | --------------- | ----------- | | ----------------------------------------- | --------------- | ----------- |
| `keycloak-ext.ais.priority` | `-10` | The order of configurable adapters to use with the application. Only the lowest priority enabled adapter will be used. Values of `1`+ will only load if the OOTB adapter is disabled. | | `keycloak-ext.keycloak.priority` | `-5` | The order of configurable adapters to use with the application. Only the lowest priority enabled adapter will be used. Values of `1`+ will only load if the OOTB adapter is disabled. |
| `keycloak-ext.group.admins.validate` | `false` | Whether or not to validate the existence and capabilities of an administrators group on appliation startup. This is only applicable for when one is accidently removed and no one has the rights to create one. | | `keycloak-ext.group.admins.validate` | `false` | Whether or not to validate the existence and capabilities of an administrators group on application startup. This is only applicable for when one is accidently removed and no one has the rights to create one. |
| `keycloak-ext.group.admins.name` | `admins` | The name of an administrators group to potentially add and default users on application startup. | | `keycloak-ext.group.admins.name` | `admins` | The name of an administrators group to potentially add and default users on application startup. |
| `keycloak-ext.group.admins.externalId` | `admins` | The name of an administrators group to potentially add and default users on application startup. | | `keycloak-ext.group.admins.externalId` | `admins` | The name of an administrators group to potentially add and default users on application startup. |
| `keycloak-ext.createMissingUser` | `true` | Before authentication, check to make sure the user exists as an APS user; if they don't, create the user. | | `keycloak-ext.createMissingUser` | `true` | Before authentication, check to make sure the user exists as an APS user; if they don't, create the user. |
@@ -66,9 +67,8 @@ The library is highly configurable. You configure it with properties specified
| `keycloak-ext.syncGroupAdd` | `true` | If the user belongs to a role but not its corresponding group, add the user to the group. | | `keycloak-ext.syncGroupAdd` | `true` | If the user belongs to a role but not its corresponding group, add the user to the group. |
| `keycloak-ext.syncGroupRemove` | `true` | If the user belongs to a group but does not have the corresponding role, remove the user from the group. | | `keycloak-ext.syncGroupRemove` | `true` | If the user belongs to a group but does not have the corresponding role, remove the user from the group. |
### Untested ### Deprecated
| Property | Default | Description | | Property | Since | Description |
| ----------------------------------------- | --------------- | ----------- | | ---------------------------------------------- | ----- | ----------- |
| `keycloak-ext.keycloak.enabled` | `false` | Enable Keycloak integration, overriding and extending the OOTB Keycloak provider (*untested*). | | `keycloak-ext.ais.*` | v24.x | AIS integration was removed. The `keycloak-ext.keycloak.*` properties must be used instead. |
| `keycloak-ext.keycloak.priority` | `-5` | The order of configurable adapters to use with the application. Only the lowest priority enabled adapter will be used. Values of `1`+ will only load if the OOTB adapter is disabled. |

80
pom.xml
View File

@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.inteligr8.activiti</groupId> <groupId>com.inteligr8.activiti</groupId>
<artifactId>keycloak-activiti-app-ext</artifactId> <artifactId>keycloak-activiti-app-ext</artifactId>
<version>1.3.1</version> <version>1.4.2</version>
<name>Keycloak Authentication &amp; Authorization for APS</name> <name>Keycloak Authentication &amp; Authorization for APS</name>
<description>An Alfresco Process Service App extension providing improved Keycloak/AIS support.</description> <description>An Alfresco Process Service App extension providing improved Keycloak/AIS support.</description>
<url>https://bitbucket.org/inteligr8/keycloak-activiti-app-ext</url> <url>https://bitbucket.org/inteligr8/keycloak-activiti-app-ext</url>
@@ -39,9 +39,9 @@
<maven.compiler.target>17</maven.compiler.target> <maven.compiler.target>17</maven.compiler.target>
<maven.compiler.release>17</maven.compiler.release> <maven.compiler.release>17</maven.compiler.release>
<aps.version>2.4.4</aps.version> <aps.version>24.3.0</aps.version>
<keycloak.version>18.0.2</keycloak.version> <keycloak.version>18.0.2</keycloak.version>
<spring-security-oauth2.version>5.8.5</spring-security-oauth2.version> <spring-security-oauth2.version>6.3.2</spring-security-oauth2.version>
<slf4j.version>1.7.36</slf4j.version> <slf4j.version>1.7.36</slf4j.version>
</properties> </properties>
@@ -85,6 +85,69 @@
</dependency> </dependency>
</dependencies> </dependencies>
<profiles>
<profile>
<id>ossrh-release</id>
<properties>
<maven.deploy.skip>true</maven.deploy.skip>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>source</id>
<phase>package</phase>
<goals><goal>jar-no-fork</goal></goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>javadoc</id>
<phase>package</phase>
<goals><goal>jar</goal></goals>
<configuration>
<show>public</show>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-gpg-plugin</artifactId>
<executions>
<execution>
<id>sign</id>
<phase>verify</phase>
<goals><goal>sign</goal></goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.7.0</version>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://s01.oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
<executions>
<execution>
<id>ossrh-deploy</id>
<phase>deploy</phase>
<goals><goal>deploy</goal></goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<repositories> <repositories>
<repository> <repository>
<id>alfresco-private</id> <id>alfresco-private</id>
@@ -96,15 +159,4 @@
</repository> </repository>
</repositories> </repositories>
<distributionManagement>
<repository>
<id>inteligr8-releases</id>
<url>https://repos.inteligr8.com/nexus/repository/inteligr8-public</url>
</repository>
<snapshotRepository>
<id>inteligr8-snapshots</id>
<url>https://repos.inteligr8.com/nexus/repository/inteligr8-snapshots</url>
</snapshotRepository>
</distributionManagement>
</project> </project>

View File

@@ -22,12 +22,12 @@ import org.springframework.security.config.annotation.authentication.builders.Au
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.inteligr8.activiti.ActivitiSecurityConfigAdapter; import com.inteligr8.activiti.security.ActivitiSecurityConfigAdapter;
/** /**
* This class/bean executes the OOTB security configuration without the * This class/bean executes the OOTB security configuration without the
* override, so you can still use its OOTB features. This will allow you to * override, so you can still use its OOTB features. This will allow you to
* enable/disable features, chain them, and uset he OOTB features as a * enable/disable features, chain them, and unset the OOTB features as a
* fallback or failsafe. * fallback or failsafe.
* *
* This class must be in the com.activiti.conf package so it can use protected * This class must be in the com.activiti.conf package so it can use protected

View File

@@ -16,6 +16,7 @@ package com.activiti.extension.conf;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FullyQualifiedAnnotationBeanNameGenerator;
/** /**
* A means for injecting packages to scan for the Spring context. * A means for injecting packages to scan for the Spring context.
@@ -23,7 +24,15 @@ import org.springframework.context.annotation.Configuration;
* @author brian@inteligr8.com * @author brian@inteligr8.com
*/ */
@Configuration @Configuration
@ComponentScan(basePackages = {"com.inteligr8.activiti"}) @ComponentScan(
basePackages = {
"com.inteligr8.activiti.ais",
"com.inteligr8.activiti.idm",
"com.inteligr8.activiti.keycloak",
"com.inteligr8.activiti.security"
},
nameGenerator = FullyQualifiedAnnotationBeanNameGenerator.class
)
public class KeycloakExtSpringComponentScanner { public class KeycloakExtSpringComponentScanner {
} }

View File

@@ -1,92 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.inteligr8.activiti.ais;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import com.activiti.api.msmt.MsmtTenantResolver;
import com.activiti.conf.MsmtProperties;
import com.activiti.security.identity.service.authentication.provider.IdentityServiceAuthenticationProvider;
import com.inteligr8.activiti.ActivitiSecurityConfigAdapter;
import com.inteligr8.activiti.auth.Authenticator;
import com.inteligr8.activiti.auth.InterceptingAuthenticationProvider;
/**
* This class/bean injects a custom AIS authentication provider into the
* security configuration.
*
* @author brian@inteligr8.com
* @see com.activiti.security.identity.service.authentication.provider.IdentityServiceAuthenticationProvider
*/
@Component
public class IdentityServiceSecurityConfigurationAdapter implements ActivitiSecurityConfigAdapter {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Value("${keycloak-ext.ais.enabled:false}")
private boolean enabled;
// this assures execution before the OOTB impl (-10 < 0)
@Value("${keycloak-ext.ais.priority:-10}")
private int priority;
@Autowired
protected MsmtProperties msmtProperties;
@Autowired(required = false) // Only when multi-schema multi-tenant is enabled
protected MsmtTenantResolver tenantResolver;
@Autowired
@Qualifier("keycloak-ext.activiti-app.authenticator")
private Authenticator authenticator;
protected Authenticator getAuthenticator() {
return this.authenticator;
}
@Override
public boolean isEnabled() {
return this.enabled;
}
@Override
public int getPriority() {
return this.priority;
}
@Override
public void configureGlobal(AuthenticationManagerBuilder auth, UserDetailsService userDetailsService) {
this.logger.trace("configureGlobal()");
this.logger.info("Using AIS authentication extension, featuring creation of missing users and authority synchronization");
IdentityServiceAuthenticationProvider provider = new IdentityServiceAuthenticationProvider();
if (this.msmtProperties.isMultiSchemaMultiTenantEnabled())
provider.setTenantResolver(this.tenantResolver);
provider.setUserDetailsService(userDetailsService);
provider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(new InterceptingAuthenticationProvider(provider, this.getAuthenticator()));
}
}

View File

@@ -12,7 +12,7 @@
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <https://www.gnu.org/licenses/>. * with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.inteligr8.activiti; package com.inteligr8.activiti.idm;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -32,6 +32,8 @@ import com.activiti.domain.idm.Group;
import com.activiti.domain.idm.GroupCapability; import com.activiti.domain.idm.GroupCapability;
import com.activiti.domain.idm.Tenant; import com.activiti.domain.idm.Tenant;
import com.activiti.service.api.GroupService; import com.activiti.service.api.GroupService;
import com.inteligr8.activiti.DataFixer;
import com.inteligr8.activiti.keycloak.TenantFinderService;
/** /**
* This class/bean attempts to fix the administrative group in APS. This may * This class/bean attempts to fix the administrative group in APS. This may

View File

@@ -12,12 +12,12 @@
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <https://www.gnu.org/licenses/>. * with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.inteligr8.activiti; package com.inteligr8.activiti.idm;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import javax.persistence.NonUniqueResultException; import jakarta.persistence.NonUniqueResultException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -29,6 +29,8 @@ import com.activiti.domain.idm.Group;
import com.activiti.domain.idm.User; import com.activiti.domain.idm.User;
import com.activiti.service.api.GroupService; import com.activiti.service.api.GroupService;
import com.activiti.service.api.UserService; import com.activiti.service.api.UserService;
import com.inteligr8.activiti.DataFixer;
import com.inteligr8.activiti.keycloak.TenantFinderService;
/** /**
* This class/bean attempts to add administrators to the administrative group * This class/bean attempts to add administrators to the administrative group

View File

@@ -12,7 +12,7 @@
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <https://www.gnu.org/licenses/>. * with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.inteligr8.activiti; package com.inteligr8.activiti.idm;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -22,6 +22,8 @@ import org.springframework.stereotype.Component;
import com.activiti.domain.idm.User; import com.activiti.domain.idm.User;
import com.activiti.service.api.UserService; import com.activiti.service.api.UserService;
import com.inteligr8.activiti.DataFixer;
import com.inteligr8.activiti.keycloak.TenantFinderService;
/** /**
* This class/bean attempts to reset the configured user's password. * This class/bean attempts to reset the configured user's password.

View File

@@ -24,7 +24,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.OverridingMethodsMustInvokeSuper; import javax.annotation.OverridingMethodsMustInvokeSuper;
import javax.persistence.NonUniqueResultException; import jakarta.persistence.NonUniqueResultException;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessToken;
@@ -41,7 +41,6 @@ import com.activiti.domain.idm.Group;
import com.activiti.domain.idm.User; import com.activiti.domain.idm.User;
import com.activiti.service.api.GroupService; import com.activiti.service.api.GroupService;
import com.activiti.service.api.UserService; import com.activiti.service.api.UserService;
import com.inteligr8.activiti.TenantFinderService;
/** /**
* This class/bean implements an Open ID Connect authenticator for Alfresco * This class/bean implements an Open ID Connect authenticator for Alfresco
@@ -261,7 +260,8 @@ public class KeycloakActivitiAppAuthenticator extends AbstractKeycloakActivitiAu
} }
} }
if (group != null && this.syncGroupAdd) { if (group != null) {
if (this.syncGroupAdd) {
this.logger.trace("Adding user '{}' to group '{}'", user.getExternalId(), group.getName()); this.logger.trace("Adding user '{}' to group '{}'", user.getExternalId(), group.getName());
this.groupService.addUserToGroup(group, userWithGroups); this.groupService.addUserToGroup(group, userWithGroups);
} else { } else {
@@ -269,6 +269,7 @@ public class KeycloakActivitiAppAuthenticator extends AbstractKeycloakActivitiAu
} }
} }
} }
}
private String keycloakRoleToApsGroupExternalId(String role) { private String keycloakRoleToApsGroupExternalId(String role) {
return this.externalIdmSource + "_" + role; return this.externalIdmSource + "_" + role;

View File

@@ -25,9 +25,9 @@ import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.inteligr8.activiti.ActivitiSecurityConfigAdapter;
import com.inteligr8.activiti.auth.Authenticator; import com.inteligr8.activiti.auth.Authenticator;
import com.inteligr8.activiti.auth.InterceptingAuthenticationProvider; import com.inteligr8.activiti.auth.InterceptingAuthenticationProvider;
import com.inteligr8.activiti.security.ActivitiSecurityConfigAdapter;
/** /**
* This class/bean injects a custom keycloak authentication provider into the * This class/bean injects a custom keycloak authentication provider into the

View File

@@ -12,7 +12,7 @@
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <https://www.gnu.org/licenses/>. * with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.inteligr8.activiti; package com.inteligr8.activiti.keycloak;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;

View File

@@ -12,7 +12,7 @@
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <https://www.gnu.org/licenses/>. * with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.inteligr8.activiti; package com.inteligr8.activiti.security;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;

View File

@@ -12,7 +12,7 @@
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <https://www.gnu.org/licenses/>. * with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.inteligr8.activiti; package com.inteligr8.activiti.security;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@@ -25,6 +25,7 @@ import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.activiti.api.security.AlfrescoSecurityConfigOverride; import com.activiti.api.security.AlfrescoSecurityConfigOverride;
import com.inteligr8.activiti.DataFixer;
/** /**
* This class/bean overrides the APS security configuration with a collection * This class/bean overrides the APS security configuration with a collection