Implemented custom deserializer that uses `gcube-jackson-databind` and removes completely the dependency with `jjson-*` deserializers

This commit is contained in:
Mauro Mugnaini 2024-05-07 16:51:34 +02:00
parent e0b165c491
commit a4c5de4e9e
Signed by: mauro.mugnaini
GPG Key ID: 2440CFD0EB321EA8
3 changed files with 31 additions and 10 deletions

View File

@ -2,7 +2,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
# Changelog for "keycloak-client"
## [v2.1.0]
## [v2.1.0-SNAPSHOT]
- Added `token-exchange` support, also with `offline-token` scope, and methods to add extra headers during the OIDC token requests (#27099).
- Added custom base URL set via factory (not automatically working cross environments) [#27234].
- Added JWKS server configuration retrieval, realm's info (as `PublishedRealmRepresentation` JSON containing public key) and JWT digital signature verification by using the RSA public key of the realm on server. It uses the `jjwt` library by `io.jsonwebtoken` [#27340]

View File

@ -12,7 +12,7 @@
<groupId>org.gcube.common</groupId>
<artifactId>keycloak-client</artifactId>
<version>2.1.0</version>
<version>2.1.0-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
@ -81,13 +81,6 @@
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-gson</artifactId>
<version>${jjwt.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>

View File

@ -1,15 +1,22 @@
package org.gcube.common.keycloak.model;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.gcube.com.fasterxml.jackson.annotation.JsonInclude.Include;
import org.gcube.com.fasterxml.jackson.core.JsonProcessingException;
import org.gcube.com.fasterxml.jackson.core.type.TypeReference;
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
import org.gcube.com.fasterxml.jackson.databind.ObjectWriter;
import org.slf4j.Logger;
@ -18,6 +25,8 @@ import org.slf4j.LoggerFactory;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.DeserializationException;
import io.jsonwebtoken.io.Deserializer;
/**
* @author <a href="mailto:mauro.mugnaini@nubisware.com">Mauro Mugnaini</a>
@ -104,7 +113,7 @@ public class ModelUtils {
* @throws Exception if an error occurs constructing the verifier
*/
public static boolean isValid(String token, PublicKey publicKey, boolean checkExpiration) throws Exception {
JwtParser jwtParser = Jwts.parser().verifyWith(publicKey).build();
JwtParser jwtParser = Jwts.parser().json(new GcubeJacksonDeserializer()).verifyWith(publicKey).build();
try {
jwtParser.parse(token);
return true;
@ -231,4 +240,23 @@ public class ModelUtils {
return "";
}
}
public static class GcubeJacksonDeserializer implements Deserializer<Map<String,?>> {
@Override
public Map<String, ?> deserialize(byte[] bytes) throws DeserializationException {
return deserialize(new InputStreamReader(new ByteArrayInputStream(bytes)));
}
@Override
public Map<String, ?> deserialize(Reader reader) throws DeserializationException {
try {
return new ObjectMapper().readValue(reader, new TypeReference<HashMap<String,Object>>() {});
} catch (IOException e) {
throw new DeserializationException("Cannot deserialize JSON with GCube Jackson", e);
}
}
}
}