Skip to content

Commit

Permalink
Merge pull request #60 from italia/keycloak-24-compatibility
Browse files Browse the repository at this point in the history
Keycloak 24 compatibility
  • Loading branch information
nicolabeghin committed Mar 6, 2024
2 parents ba5c42b + 8bb04dc commit 6fa8095
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 38 deletions.
49 changes: 20 additions & 29 deletions README.md
Expand Up @@ -23,25 +23,35 @@ sure to read it and understand the config steps and the open issues and
limitations before planning your Production environment.

## Status
This project is still at a beta stage. It has been successfully tested for SPID validation and
This project is still at a development stage but it has been successfully tested for SPID validation and
**it's currently used in Production**.

Until the project gets to a stable release, it will be targeting the most recent release
of Keycloak as published on the website (see property `version.keycloak` in file `pom.xml`).
Currently the main branch is targeting Keycloak 23.0.6. **Do not use the latest release with previous
versions of Keycloak, it won't work!**
**Do not use the latest release with previous versions of Keycloak, it won't work!**

Since this plugin uses some Keycloak internal modules, versions of this plugin
are coupled to Keycloak versions. After (major) Keycloak upgrades, you will almost
certainly have also to update this provider.

## Compatibility
* Keycloak 23.x.x: Release 1.0.17
* Keycloak 19.x.x: Release 1.0.16
* Keycloak 24.x.x: Release `24.0.1`
* Keycloak 23.x.x: Release `1.0.17`
* Keycloak 19.x.x: Release `1.0.16`

## Configuration
### Release 1.0.17 (latest, Keycloak 23.x.x compatibility)
With the latest release targeting latest Keycloak 23.x.x it's not possible to configure the plugin through the Keycloak web UI,
### Release 24.0.1 (latest, Keycloak 24.0.1 compatibility)
With this release targeting latest Keycloak 24.0.1 it was restored the possibility of configuring the plugin through
the Keycloak web UI, detailed instructions on how to install and configure this component are
available in the project wiki (https://github.com/italia/spid-keycloak-provider/wiki/Installing-the-SPID-provider).
To avoid errors, it's suggested to use anyway https://github.com/nicolabeghin/keycloak-spid-provider-configuration-client
#### IMPORTANT if upgrading from release 1.0.17
Provider ID was changed from `spid` to `spid-saml` in order to account for [hardcoded Keycloak 24.x behavior](https://github.com/keycloak/keycloak/blob/a228b6c7c9ec7a54ee91bb547b42cc4097ae38e2/js/apps/admin-ui/src/identity-providers/add/DetailSettings.tsx#L396). Before upgrading the plugin make sure to run this SQL query against Keycloak database:

UPDATE IDENTITY_PROVIDER SET PROVIDER_ID="spid-saml" WHERE PROVIDER_ID="spid"

### Release 1.0.17 (Keycloak 23.x.x compatibility)
With the latest release targeting Keycloak 23.x.x it's not possible to configure the plugin through the Keycloak web UI,
but only through REST services. Suggested to use https://github.com/nicolabeghin/keycloak-spid-provider-configuration-client

### Release 1.0.6
Expand Down Expand Up @@ -71,9 +81,10 @@ Requirements:
Just run:
```
git clone https://github.com/italia/spid-keycloak-provider.git
docker run --rm -v $(pwd)/spid-keycloak-provider:/opt/spid-keycloak-provider -w /opt/spid-keycloak-provider maven:3.8.6-openjdk-18-slim bash -c "mvn clean package"
cd spid-keycloak-provider
docker run --rm -v $(pwd):/opt/spid-keycloak-provider -w /opt/spid-keycloak-provider maven:3.8.6-openjdk-18-slim bash -c "mvn clean package"
```
The output package will be generated under `spid-keycloak-provider/target/spid-provider.jar`.
The output package will be generated under `target/spid-provider.jar`.

## Deployment
This provider should be deployed as a module, i.e. copied under
Expand All @@ -91,26 +102,6 @@ If successful you will find a new provider type called `SPID` in the

## Upgrading from previous versions
Upgrades are usually seamless, just repeat the deployment command.
Sometimes Keycloak caches don't get flushed when a new deployment occurs; in that case you will need
to edit the file `{$KEYCLOAK_PATH}/standalone/configuration/standalone.xml`, find the following section
```
<theme>
<staticMaxAge>2592000</staticMaxAge>
<cacheThemes>true</cacheThemes>
<cacheTemplates>true</cacheTemplates>
<dir>${jboss.home.dir}/themes</dir>
</theme>
```
and change it to:
```
<theme>
<staticMaxAge>-1</staticMaxAge>
<cacheThemes>false</cacheThemes>
<cacheTemplates>false</cacheTemplates>
<dir>${jboss.home.dir}/themes</dir>
</theme>
```

Then restart Keycloak and it will reload the resources from the packages. Make sure you also clear
your browser caches or use incognito mode when verifying the correct deployment.
After the first reload you can turn back on the caches and restart Keycloak again.
Expand Down
10 changes: 8 additions & 2 deletions pom.xml
Expand Up @@ -8,7 +8,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.lscorcia</groupId>
<artifactId>keycloak-spid-provider</artifactId>
<version>1.0.17-SNAPSHOT</version>
<version>24.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Keycloak SPID Service Provider</name>
Expand All @@ -19,7 +19,7 @@
<failOnMissingWebXml>false</failOnMissingWebXml>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<version.keycloak>23.0.6</version.keycloak>
<version.keycloak>24.0.1</version.keycloak>
<slf4j-api.version>1.7.30</slf4j-api.version>
<junit-jupiter.version>5.8.2</junit-jupiter.version>
<mockito.version>4.3.1</mockito.version>
Expand Down Expand Up @@ -107,6 +107,12 @@
<version>2.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>3.1.5</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Expand Up @@ -49,7 +49,7 @@
*/
public class SpidIdentityProviderFactory extends AbstractIdentityProviderFactory<SpidIdentityProvider> implements ConfiguredProvider {

public static final String PROVIDER_ID = "spid";
public static final String PROVIDER_ID = "spid-saml";

private static final String MACEDIR_ENTITY_CATEGORY = "http://macedir.org/entity-category";
private static final String REFEDS_HIDE_FROM_DISCOVERY = "http://refeds.org/category/hide-from-discovery";
Expand Down
6 changes: 2 additions & 4 deletions src/main/java/org/keycloak/broker/spid/SpidSAMLEndpoint.java
Expand Up @@ -132,8 +132,6 @@
import org.keycloak.dom.saml.v2.protocol.AuthnContextComparisonType;
import org.keycloak.util.JsonSerialization;

import static org.keycloak.utils.LockObjectsForModification.lockUserSessionsForModification;

/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
Expand Down Expand Up @@ -350,7 +348,7 @@ protected Response logoutRequest(LogoutRequestType request, String relayState) {
} else {
for (String sessionIndex : request.getSessionIndex()) {
String brokerSessionId = config.getAlias() + "." + sessionIndex;
UserSessionModel userSession = lockUserSessionsForModification(session, () -> session.sessions().getUserSessionByBrokerSessionId(realm, brokerSessionId));
UserSessionModel userSession = session.sessions().getUserSessionByBrokerSessionId(realm, brokerSessionId);
if (userSession != null) {
if (userSession.getState() == UserSessionModel.State.LOGGING_OUT || userSession.getState() == UserSessionModel.State.LOGGED_OUT) {
continue;
Expand Down Expand Up @@ -720,7 +718,7 @@ protected Response handleLogoutResponse(SAMLDocumentHolder holder, StatusRespons
event.error(Errors.USER_SESSION_NOT_FOUND);
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
}
UserSessionModel userSession = lockUserSessionsForModification(session, () -> session.sessions().getUserSession(realm, relayState));
UserSessionModel userSession = session.sessions().getUserSession(realm, relayState);
if (userSession == null) {
logger.error("no valid user session");
event.event(EventType.LOGOUT);
Expand Down
Expand Up @@ -164,7 +164,7 @@ void get_withPublicSPConfiguration_shouldReturnExpectXml() {

Response response = invitationResourceProvider.get();
assertEquals(200, response.getStatus());
assertMetaData(response.readEntity(String.class), "/metadata/expected_metadata_public_SP.xml");
assertMetaData(response.getEntity().toString(), "/metadata/expected_metadata_public_SP.xml");
}

@Test
Expand All @@ -173,7 +173,7 @@ void get_withPrivateSPConfiguration_shouldReturnExpectXml() {

Response response = invitationResourceProvider.get();
assertEquals(200, response.getStatus());
assertMetaData(response.readEntity(String.class), "/metadata/expected_metadata_private_SP.xml");
assertMetaData(response.getEntity().toString(), "/metadata/expected_metadata_private_SP.xml");
}

private Map<String, String> mockPublicSPConfig() {
Expand Down

0 comments on commit 6fa8095

Please sign in to comment.