36 Commits

Author SHA1 Message Date
9412957e89 Merge branch 'develop' into stable 2025-05-09 19:02:43 -04:00
9c67dad207 v2.0.2 pom 2025-05-05 18:19:10 -04:00
55619d6b4a Merge branch 'develop' into stable 2025-05-05 18:18:53 -04:00
0b032f1f7f Merge branch 'develop' into stable 2025-05-05 11:18:56 -04:00
3d3a7433c5 Merge branch 'develop' into stable 2025-05-04 20:16:17 -04:00
9c7641b858 v1.4.3 pom 2025-04-19 18:19:07 -04:00
0e34f589c3 Merge branch 'develop' into stable 2025-04-19 18:18:49 -04:00
a73543d2a6 v1.4.1 pom 2025-02-12 14:35:41 -05:00
cd472b9269 Merge branch 'develop' into stable 2025-02-12 14:34:10 -05:00
bf848b009c v1.4.0 pom 2024-10-15 15:56:54 -04:00
52b86c0de4 Merge branch 'develop' into stable 2024-10-15 15:56:38 -04:00
8bc0a7e520 Merge branch 'develop' into stable 2024-06-21 13:17:16 -04:00
0601b2b2b2 Merge branch 'develop' into stable 2024-06-21 13:11:04 -04:00
93af3639cc Merge branch 'develop' into stable 2022-07-28 15:25:32 -04:00
0d402f6014 Merge branch 'develop' into stable 2022-07-01 12:15:48 -04:00
e7b6bd644e Merge branch 'develop' into stable 2022-07-01 12:14:32 -04:00
343e1b65b9 added password resetter 2022-01-24 15:29:17 -05:00
14487b62eb v1.2.1 pom 2021-08-31 19:55:19 -04:00
e87a6b68a7 Merge branch 'develop' into stable 2021-08-31 19:54:53 -04:00
5ecb627dbf Merge branch 'develop' into stable 2021-08-27 00:23:17 -04:00
ea487fee31 v1.1.4 pom 2021-08-25 15:54:37 -04:00
9f9ededab2 Merge branch 'develop' into stable 2021-08-25 15:53:50 -04:00
f76105b979 Merge branch 'develop' into stable 2021-08-24 21:22:46 -04:00
a3cb17e402 v1.1.3 pom 2021-08-24 21:15:19 -04:00
c6d0977b2f Merge branch 'develop' into stable 2021-08-24 21:13:44 -04:00
2405a8a313 v1.1.2 pom 2021-08-24 10:00:03 -04:00
173bfed44f Merge branch 'develop' into stable 2021-08-19 18:54:55 -04:00
dc5a7dad39 Merge branch 'develop' into stable 2021-08-19 17:50:01 -04:00
10ed99b0a2 v1.1.1 pom 2021-08-19 17:38:10 -04:00
4e4a6aca8d Merge branch 'develop' into stable 2021-08-19 17:24:24 -04:00
44d0bf533d Merge branch 'develop' into stable 2021-08-18 23:31:20 -04:00
807294881b v1.0.1 pom 2021-08-11 09:17:20 -04:00
a42c754a09 Merge branch 'develop' into stable 2021-08-11 09:08:26 -04:00
8b05c51ef6 Merge branch 'develop' into stable 2021-07-30 15:42:30 -04:00
8bc03e0ea9 Merge branch 'develop' into stable 2021-07-30 15:40:28 -04:00
d32e3c7051 v1.0.0 pom 2021-07-30 15:38:00 -04:00
5 changed files with 190 additions and 156 deletions

178
dependency-reduced-pom.xml Normal file
View File

@@ -0,0 +1,178 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.inteligr8.activiti</groupId>
<artifactId>keycloak-activiti-app-ext</artifactId>
<name>Keycloak Authentication &amp; Authorization for APS</name>
<version>1.4-SNAPSHOT</version>
<description>An Alfresco Process Service App extension providing improved Keycloak/AIS support.</description>
<url>https://bitbucket.org/inteligr8/keycloak-activiti-app-ext</url>
<developers>
<developer>
<id>brian.long</id>
<name>Brian Long</name>
<email>brian@inteligr8.com</email>
<url>https://twitter.com/brianmlong</url>
</developer>
</developers>
<licenses>
<license>
<name>GNU GENERAL PUBLIC LICENSE, Version 3, 29 June 2007</name>
<url>https://www.gnu.org/licenses/lgpl-3.0.txt</url>
</license>
</licenses>
<scm>
<connection>scm:git:https://bitbucket.org/inteligr8/keycloak-activiti-app-ext.git</connection>
<developerConnection>scm:git:git@bitbucket.org:inteligr8/keycloak-activiti-app-ext.git</developerConnection>
<url>https://bitbucket.org/inteligr8/keycloak-activiti-app-ext</url>
</scm>
<organization>
<name>Inteligr8</name>
<url>https://www.inteligr8.com</url>
</organization>
<build>
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<id>shade-jar</id>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<relocations>
<relocation>
<pattern />
<shadedPattern>shaded.keycloak.</shadedPattern>
<excludes>
<exclude>com.activiti.conf.*</exclude>
<exclude>com.activiti.extension.conf.*</exclude>
<exclude>com.inteligr8.activiti.**</exclude>
<exclude>META-INF/**/*</exclude>
</excludes>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>ossrh-release</id>
<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>
<executions>
<execution>
<id>ossrh-deploy</id>
<phase>deploy</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://s01.oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<maven.deploy.skip>true</maven.deploy.skip>
</properties>
</profile>
</profiles>
<repositories>
<repository>
<id>alfresco-private</id>
<url>https://artifacts.alfresco.com/nexus/content/groups/private</url>
</repository>
<repository>
<id>activiti-releases</id>
<url>https://artifacts.alfresco.com/nexus/content/repositories/activiti-enterprise-releases</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
<version>6.3.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.activiti</groupId>
<artifactId>activiti-app</artifactId>
<version>24.3.0</version>
<classifier>classes</classifier>
<scope>provided</scope>
<exclusions>
<exclusion>
<artifactId>aspose-transformation</artifactId>
<groupId>com.activiti</groupId>
</exclusion>
<exclusion>
<artifactId>aoservices</artifactId>
<groupId>org.alfresco.officeservices</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<properties>
<maven.compiler.release>17</maven.compiler.release>
<maven.compiler.source>17</maven.compiler.source>
<keycloak.version>23.0.7</keycloak.version>
<maven.compiler.target>17</maven.compiler.target>
<slf4j.version>1.7.36</slf4j.version>
<spring-security-oauth2.version>6.3.2</spring-security-oauth2.version>
<aps.version>24.3.0</aps.version>
</properties>
</project>

View File

@@ -5,7 +5,7 @@
<groupId>com.inteligr8.activiti</groupId>
<artifactId>auth-activiti-app-ext</artifactId>
<version>2.1-SNAPSHOT</version>
<version>2.1.0</version>
<name>Authentication &amp; Authorization for APS</name>
<description>An Alfresco Process Service App extension providing improved authentication and authorization support.</description>

View File

@@ -1,6 +1,5 @@
package com.inteligr8.activiti.auth.oauth;
import static org.springframework.security.config.Customizer.withDefaults;
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
import org.apache.commons.lang3.StringUtils;
@@ -15,17 +14,11 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AndRequestMatcher;
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
import com.activiti.domain.idm.Capabilities;
import com.activiti.security.ActivitiAppRequestHeaderService;
import com.activiti.security.ActivitiRestAuthorizationService;
import com.activiti.security.ProtectedPaths;
import com.activiti.security.identity.service.config.IdentityServiceEnabledCondition;
import com.inteligr8.activiti.auth.service.JwtAuthenticationProvider;
@@ -50,12 +43,6 @@ public class IdentityServiceConfigurationOverride {
@Autowired
private JwtAuthenticationProvider jwtAuthenticationProvider;
@Autowired
private ActivitiAppRequestHeaderService appRequestHeaderService;
@Autowired
private ActivitiRestAuthorizationService restAuthorizationService;
@Bean("inteligr8.clientRegistrationRepository")
@Primary
public ClientRegistrationRepository clientRegistrationRepository() {
@@ -86,13 +73,11 @@ public class IdentityServiceConfigurationOverride {
}
/**
* Slightly higher priority than the one provided OOTB. This allows for
* the bean injection of the `JwtAuthenticationConverter`.
* Slightly lower priority than the one provided OOTB. This
* allows for the bean injection of the JwtAuthenticationConverter.
*
* This is basically a copy of what is provided OOTB, but:
*
* - The ability to configure the `JwtAuthenticationConverter`.
* - Allow non-UI access to `/app/rest/*`
* A lower priority means it is applied last. This means it replaces the
* JwtAuthenticationConverter provided by Alfresco OOTB.
*
* @see com.activiti.security.identity.service.config.IdentityServiceConfigurationApi#identityServiceApiWebSecurity
*/
@@ -100,44 +85,11 @@ public class IdentityServiceConfigurationOverride {
@Order(-5)
public SecurityFilterChain identityServiceApiWebSecurity(HttpSecurity http) throws Exception {
http
.securityMatchers(matchers -> {
matchers.requestMatchers(
// same as OOTB
antMatcher(ProtectedPaths.API_URL_PATH + "/**"),
// want to also allow non-UI access to the the protected API
// we do this for anything with an `Authorization` header, as the UI uses session-based authorization
new AndRequestMatcher(new RequestHeaderRequestMatcher("Authorization"), antMatcher(ProtectedPaths.APP_URL_PATH + "/rest/**"))
);
})
.csrf(csrf -> {
csrf.disable();
})
.cors(withDefaults())
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // Stores no Session for API calls
.securityMatcher(antMatcher(ProtectedPaths.API_URL_PATH + "/**"))
.oauth2ResourceServer(oauth2 ->
oauth2.jwt(jwtConfigurer -> {
// here is where we are injecting a Spring extendible `JwtAuthenticationConverter`.
jwtConfigurer.jwtAuthenticationConverter(this.jwtAuthenticationProvider.create());
})
)
.authorizeHttpRequests(request ->
request
// same as OOTB
.requestMatchers(antMatcher(ProtectedPaths.API_URL_PATH + "/enterprise/**"))
.access(this.appRequestHeaderService)
.requestMatchers(antMatcher(ProtectedPaths.API_URL_PATH + "/**"))
.access(this.restAuthorizationService)
// borrowed from OOTB /app/rest security
.requestMatchers(antMatcher(ProtectedPaths.APP_URL_PATH + "/rest/reporting/**"))
.hasAuthority(Capabilities.ACCESS_REPORTS)
.requestMatchers(
antMatcher(ProtectedPaths.API_URL_PATH + "/**"),
antMatcher(ProtectedPaths.APP_URL_PATH + "/rest/**")
)
.authenticated()
);
return http.build();

View File

@@ -101,14 +101,14 @@
"profile",
"roles",
"basic",
"email",
"microprofile-jwt"
"email"
],
"optionalClientScopes": [
"address",
"phone",
"organization",
"offline_access"
"offline_access",
"microprofile-jwt"
]
},
{
@@ -156,76 +156,15 @@
"profile",
"roles",
"basic",
"email",
"microprofile-jwt"
"email"
],
"optionalClientScopes": [
"address",
"phone",
"organization",
"offline_access"
"offline_access",
"microprofile-jwt"
]
},
{
"clientId": "cli",
"name": "Command Line Tools",
"description": "",
"rootUrl": "",
"adminUrl": "",
"baseUrl": "",
"surrogateAuthRequired": false,
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"secret": "eJa5W7bv4ohFbr7QRtaCk0eccRFoYM5x",
"redirectUris": [
"/*"
],
"webOrigins": [
"/*"
],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
"standardFlowEnabled": false,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": false,
"serviceAccountsEnabled": true,
"publicClient": false,
"frontchannelLogout": true,
"protocol": "openid-connect",
"attributes": {
"realm_client": "false",
"oidc.ciba.grant.enabled": "false",
"client.secret.creation.time": "1747506410",
"backchannel.logout.session.required": "true",
"standard.token.exchange.enabled": "true",
"oauth2.device.authorization.grant.enabled": "false",
"backchannel.logout.revoke.offline.tokens": "false"
},
"authenticationFlowBindingOverrides": {},
"fullScopeAllowed": true,
"nodeReRegistrationTimeout": -1,
"defaultClientScopes": [
"web-origins",
"acr",
"profile",
"roles",
"basic",
"email",
"microprofile-jwt"
],
"optionalClientScopes": [
"address",
"phone",
"organization",
"offline_access"
],
"access": {
"view": true,
"configure": true,
"manage": true
}
}
],
"users": [

View File

@@ -1,35 +0,0 @@
@keycloakRealm = my-app
@keycloakBaseUrl = http://localhost:8081
@oauthUrl = {{keycloakBaseUrl}}/realms/{{keycloakRealm}}
@keycloakTokenUrl = {{oauthUrl}}/protocol/openid-connect/token
@oauthClientId = cli
@oauthClientSecret = eJa5W7bv4ohFbr7QRtaCk0eccRFoYM5x
@apsBaseUrl = http://localhost:8080/activiti-app
### Token
# @name token
curl -LX POST {{keycloakTokenUrl}} \
-H 'Content-type: application/x-www-form-urlencoded' \
-d "grant_type=client_credentials" \
-d "client_id={{oauthClientId}}" \
-d "client_secret={{oauthClientSecret}}"
@accessToken = {{token.response.body.access_token}}
@auth = Bearer {{accessToken}}
### APS Version
# @name version
GET {{apsBaseUrl}}/api/enterprise/app-version
Authorization: Bearer {{accessToken}}
### APS Tenants
# @name tenants
GET {{apsBaseUrl}}/api/enterprise/admin/tenants
Authorization: Bearer {{accessToken}}
@tenantId = {{tenants.response.body.0.id}}
### APS Templates
# @name templates
GET {{apsBaseUrl}}/app/rest/document-templates?tenantId={{tenantId}}&start=0&size=10&sort=sort_by_name_asc
Authorization: Bearer {{accessToken}}