From 7ab6522e4c7da1e1ee9a6a56d479005ef25c7e0e Mon Sep 17 00:00:00 2001 From: Andreas Wuerl Date: Fri, 22 Feb 2019 20:26:55 +0100 Subject: [PATCH] hide vavr --- .gitignore | 1 + .travis.yml | 4 +- pom.xml | 112 +++++++++++++++--- .../security/JWTAuthenticationProvider.java | 65 +++++----- .../security/jwt/security/JWTPrincipal.java | 26 ++-- .../config/JWTSecurityConfiguration.java | 2 +- .../security/config/_JWTSecurityConfig.java | 9 +- .../security/jwt/token/claim/_JWTClaim.java | 4 +- .../security/jwt/token/claim/_JWTClaims.java | 5 +- .../token/extractor/InnerClaimsWrapper.java | 21 ++-- .../token/verifier/JWTVerifierFactory.java | 14 ++- .../JWTAuthenticationProviderTest.java | 12 +- .../jwt/security/JWTPrincipalTest.java | 32 +++-- ...datingHierarchicalClaimsExtractorTest.java | 2 +- 14 files changed, 192 insertions(+), 117 deletions(-) diff --git a/.gitignore b/.gitignore index 651474f..6026de7 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ /.settings/ /.classpath /.factorypath +/dependency-reduced-pom.xml diff --git a/.travis.yml b/.travis.yml index 28dd6a0..8dd21a8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,4 +3,6 @@ install: "mvn install -DskipTests=true" script: "mvn -e clean test jacoco:report coveralls:report" jdk: - oraclejdk8 - + - openjdk8 + - oraclejdk11 + - openjdk11 diff --git a/pom.xml b/pom.xml index ab1446a..f9cc03e 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 @@ -10,7 +11,7 @@ spring-security-jwt com.mercateo.spring - 1.0.6-SNAPSHOT + 1.1.0-SNAPSHOT spring-security-jwt jar @@ -64,15 +65,16 @@ scm:git:git@github.com:Mercateo/spring-security-jwt.git scm:git:git@github.com:Mercateo/spring-security-jwt.git https://github.com/Mercateo/spring-security-jwt.git - spring-security-jwt-1.0.4 + HEAD UTF-8 UTF-8 - 5.0.8.RELEASE - 5.0.9.RELEASE - 2.9.7 + 5.1.4.RELEASE + 5.1.5.RELEASE + 2.9.8 + 2.7.5 @@ -84,7 +86,7 @@ maven-compiler-plugin - 3.7.0 + 3.8.0 1.8 1.8 @@ -122,11 +124,15 @@ + + none + 8 + org.apache.maven.plugins maven-jar-plugin - 3.1.0 + 3.1.1 @@ -138,7 +144,7 @@ org.jacoco jacoco-maven-plugin - 0.8.2 + 0.8.3 prepare-agent @@ -152,11 +158,18 @@ org.eluder.coveralls coveralls-maven-plugin 4.3.0 + + + javax.xml.bind + jaxb-api + 2.3.1 + + org.apache.maven.plugins maven-surefire-plugin - 2.22.0 + 2.22.1 **/*ITest.java @@ -166,7 +179,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 2.22.0 + 2.22.1 @@ -180,6 +193,27 @@ + + org.apache.maven.plugins + maven-shade-plugin + 3.2.1 + + + package + + shade + + + + + io.vavr + com.mercateo.spring.security.jwt.relocated.io.vavr + + + + + + @@ -187,7 +221,7 @@ org.projectlombok lombok - 1.18.2 + 1.18.6 provided @@ -196,10 +230,50 @@ 3.1.0 provided + + org.immutables + value + ${immutables.version} + provided + + + org.immutables + value-annotations + ${immutables.version} + + + org.immutables.vavr + vavr-encodings + 0.6.0 + + + value + org.immutables + + + io.vavr + vavr + + + com.mercateo default-immutables - 1.2.4 + 1.2.5 + + + value + org.immutables + + + value-annotations + org.immutables + + + org.immutables.vavr + vavr-encodings + + @@ -237,17 +311,17 @@ com.auth0 java-jwt - 3.4.0 + 3.7.0 com.auth0 jwks-rsa - 0.6.0 + 0.7.0 io.vavr vavr - 0.9.2 + 0.10.0 org.slf4j @@ -264,19 +338,19 @@ org.assertj assertj-core - 3.11.1 + 3.12.0 test org.mockito mockito-core - 2.22.0 + 2.24.5 test org.bouncycastle bcprov-jdk15on - 1.60 + 1.61 test diff --git a/src/main/java/com/mercateo/spring/security/jwt/security/JWTAuthenticationProvider.java b/src/main/java/com/mercateo/spring/security/jwt/security/JWTAuthenticationProvider.java index 8e37368..e8b523a 100644 --- a/src/main/java/com/mercateo/spring/security/jwt/security/JWTAuthenticationProvider.java +++ b/src/main/java/com/mercateo/spring/security/jwt/security/JWTAuthenticationProvider.java @@ -15,25 +15,24 @@ */ package com.mercateo.spring.security.jwt.security; -import java.util.Objects; - -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; - import com.auth0.jwt.JWT; import com.mercateo.spring.security.jwt.token.claim.JWTClaim; import com.mercateo.spring.security.jwt.token.claim.JWTClaims; import com.mercateo.spring.security.jwt.token.exception.InvalidTokenException; import com.mercateo.spring.security.jwt.token.exception.TokenException; import com.mercateo.spring.security.jwt.token.extractor.ValidatingHierarchicalClaimsExtractor; - import io.vavr.collection.List; +import io.vavr.control.Option; import lombok.AllArgsConstructor; -import lombok.val; import lombok.extern.slf4j.Slf4j; +import lombok.val; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Objects; @Slf4j @AllArgsConstructor @@ -48,7 +47,7 @@ public boolean supports(Class authentication) { @Override protected void additionalAuthenticationChecks(UserDetails userDetails, - UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { + UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { // intentionally left blank } @@ -84,33 +83,33 @@ protected List retrieveAuthorities(JWTClaims claims) val scopes = extractScopes(claims); val roles = extractRoles(claims); return List // - .ofAll(scopes) - .appendAll(roles) - .map(value -> JWTAuthority.builder().authority(value).build()); + .ofAll(scopes) + .appendAll(roles) + .map(value -> JWTAuthority.builder().authority(value).build()); } private List extractScopes(JWTClaims claims) { - return claims - .claims() - .get("scope") - .map(JWTClaim::value) - .filter(Objects::nonNull) - .map(value -> ((String) value).split("\\s+")) - .map(List::of) - .getOrElse(List.empty()); + return Option.of(claims + .claims() + .get("scope")) + .map(JWTClaim::value) + .filter(Objects::nonNull) + .map(value -> ((String) value).split("\\s+")) + .map(List::of) + .getOrElse(List.empty()); } private List extractRoles(JWTClaims claims) { - return claims - .claims() - .get("roles") - .map(JWTClaim::value) - .filter(Objects::nonNull) - .map(container -> (Object[]) container) - .map(List::of) - .map(list -> list // - .map(element -> "ROLE_" + element) - .map(String::toUpperCase)) - .getOrElse(List.empty()); + return Option.of(claims + .claims() + .get("roles")) + .map(JWTClaim::value) + .filter(Objects::nonNull) + .map(container -> (Object[]) container) + .map(List::of) + .map(list -> list // + .map(element -> "ROLE_" + element) + .map(String::toUpperCase)) + .getOrElse(List.empty()); } } diff --git a/src/main/java/com/mercateo/spring/security/jwt/security/JWTPrincipal.java b/src/main/java/com/mercateo/spring/security/jwt/security/JWTPrincipal.java index ca60170..8a7cb1e 100644 --- a/src/main/java/com/mercateo/spring/security/jwt/security/JWTPrincipal.java +++ b/src/main/java/com/mercateo/spring/security/jwt/security/JWTPrincipal.java @@ -15,21 +15,19 @@ */ package com.mercateo.spring.security.jwt.security; -import static java.util.Objects.requireNonNull; - -import java.util.Collection; - +import com.fasterxml.jackson.annotation.JsonIgnore; import com.mercateo.spring.security.jwt.data.ClaimName; +import com.mercateo.spring.security.jwt.token.claim.JWTClaim; +import io.vavr.collection.List; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.mercateo.spring.security.jwt.token.claim.JWTClaim; +import java.util.Collection; +import java.util.Map; +import java.util.Optional; -import io.vavr.collection.List; -import io.vavr.collection.Map; -import io.vavr.control.Option; +import static java.util.Objects.requireNonNull; public class JWTPrincipal implements UserDetails { @@ -44,7 +42,7 @@ public class JWTPrincipal implements UserDetails { private final Map claims; public JWTPrincipal(long id, String username, String token, List authorities, - Map claims) { + Map claims) { this.id = Long.valueOf(id); this.username = username; this.token = token; @@ -97,7 +95,7 @@ public String getToken() { @Override public Collection getAuthorities() { - return authorities.toJavaList(); + return authorities.asJava(); } @Override @@ -105,11 +103,11 @@ public String getPassword() { return null; } - public Option getClaim(String key) { - return claims.get(key); + public Optional getClaim(String key) { + return Optional.ofNullable(claims.get(key)); } - public Option getClaim(ClaimName claimName) { + public Optional getClaim(ClaimName claimName) { return getClaim(claimName.getValue()); } } diff --git a/src/main/java/com/mercateo/spring/security/jwt/security/config/JWTSecurityConfiguration.java b/src/main/java/com/mercateo/spring/security/jwt/security/config/JWTSecurityConfiguration.java index c2153bf..80dc8c3 100644 --- a/src/main/java/com/mercateo/spring/security/jwt/security/config/JWTSecurityConfiguration.java +++ b/src/main/java/com/mercateo/spring/security/jwt/security/config/JWTSecurityConfiguration.java @@ -132,7 +132,7 @@ public void configure(WebSecurity web) throws Exception { } private String[] getUnauthenticatedPaths() { - return config.map(JWTSecurityConfig::anonymousPaths).map(list -> list.toJavaArray(String.class)).orElse( + return config.map(JWTSecurityConfig::anonymousPaths).map(list -> list.toJavaArray(String[]::new)).orElse( new String[0]); } } diff --git a/src/main/java/com/mercateo/spring/security/jwt/security/config/_JWTSecurityConfig.java b/src/main/java/com/mercateo/spring/security/jwt/security/config/_JWTSecurityConfig.java index 4eb097e..4171fc3 100644 --- a/src/main/java/com/mercateo/spring/security/jwt/security/config/_JWTSecurityConfig.java +++ b/src/main/java/com/mercateo/spring/security/jwt/security/config/_JWTSecurityConfig.java @@ -16,15 +16,12 @@ package com.mercateo.spring.security.jwt.security.config; import com.mercateo.immutables.ValueStyle; -import org.immutables.value.Value; -import org.springframework.http.HttpMethod; -import org.springframework.security.web.authentication.AuthenticationFailureHandler; - -import com.mercateo.immutables.DataClass; import com.mercateo.spring.security.jwt.token.config.JWTConfig; - import io.vavr.collection.Set; import io.vavr.control.Option; +import org.immutables.value.Value; +import org.springframework.http.HttpMethod; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; @Value.Immutable @ValueStyle diff --git a/src/main/java/com/mercateo/spring/security/jwt/token/claim/_JWTClaim.java b/src/main/java/com/mercateo/spring/security/jwt/token/claim/_JWTClaim.java index 7117481..8d5a5dc 100644 --- a/src/main/java/com/mercateo/spring/security/jwt/token/claim/_JWTClaim.java +++ b/src/main/java/com/mercateo/spring/security/jwt/token/claim/_JWTClaim.java @@ -21,6 +21,8 @@ import io.vavr.control.Option; +import java.util.Optional; + @Value.Immutable @ValueStyle public interface _JWTClaim { @@ -38,7 +40,7 @@ default boolean verified() { return false; } - Option innerClaim(); + Optional innerClaim(); @Value.Default default int depth() { diff --git a/src/main/java/com/mercateo/spring/security/jwt/token/claim/_JWTClaims.java b/src/main/java/com/mercateo/spring/security/jwt/token/claim/_JWTClaims.java index 0acb785..0808b04 100644 --- a/src/main/java/com/mercateo/spring/security/jwt/token/claim/_JWTClaims.java +++ b/src/main/java/com/mercateo/spring/security/jwt/token/claim/_JWTClaims.java @@ -15,13 +15,12 @@ */ package com.mercateo.spring.security.jwt.token.claim; +import com.auth0.jwt.interfaces.DecodedJWT; import com.mercateo.immutables.ValueStyle; import org.immutables.value.Value; -import com.auth0.jwt.interfaces.DecodedJWT; -import com.mercateo.immutables.DataClass; +import java.util.Map; -import io.vavr.collection.Map; @Value.Immutable @ValueStyle diff --git a/src/main/java/com/mercateo/spring/security/jwt/token/extractor/InnerClaimsWrapper.java b/src/main/java/com/mercateo/spring/security/jwt/token/extractor/InnerClaimsWrapper.java index 68ec90f..5e7b22f 100644 --- a/src/main/java/com/mercateo/spring/security/jwt/token/extractor/InnerClaimsWrapper.java +++ b/src/main/java/com/mercateo/spring/security/jwt/token/extractor/InnerClaimsWrapper.java @@ -16,31 +16,30 @@ package com.mercateo.spring.security.jwt.token.extractor; import com.mercateo.spring.security.jwt.token.claim.JWTClaim; - import io.vavr.collection.List; -import io.vavr.collection.Map; -import io.vavr.control.Option; + +import java.util.Map; +import java.util.Optional; class InnerClaimsWrapper { Map wrapInnerClaims(List claims) { - return claims.groupBy(JWTClaim::name).mapValues(this::wrapGroupedClaims); + return claims.groupBy(JWTClaim::name).mapValues(this::wrapGroupedClaims).toJavaMap(); } private JWTClaim wrapGroupedClaims(List claims) { final List reverse = claims.reverse(); - Option innerClaim = Option.none(); + Optional innerClaim = Optional.empty(); for (JWTClaim jwtClaim : reverse) { - innerClaim = Option.some(JWTClaim // - .builder() - .from(jwtClaim) - .innerClaim(innerClaim) - .build()); + innerClaim = Optional.of(JWTClaim // + .builder() + .from(jwtClaim) + .innerClaim(innerClaim) + .build()); } - // noinspection ConstantConditions return innerClaim.get(); } } diff --git a/src/main/java/com/mercateo/spring/security/jwt/token/verifier/JWTVerifierFactory.java b/src/main/java/com/mercateo/spring/security/jwt/token/verifier/JWTVerifierFactory.java index 6c121e5..e5a7afe 100644 --- a/src/main/java/com/mercateo/spring/security/jwt/token/verifier/JWTVerifierFactory.java +++ b/src/main/java/com/mercateo/spring/security/jwt/token/verifier/JWTVerifierFactory.java @@ -16,8 +16,12 @@ package com.mercateo.spring.security.jwt.token.verifier; import java.security.Key; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.X509EncodedKeySpec; import com.auth0.jwk.Jwk; import com.auth0.jwt.algorithms.Algorithm; @@ -28,7 +32,6 @@ import lombok.AllArgsConstructor; import lombok.val; import lombok.extern.slf4j.Slf4j; -import sun.security.rsa.RSAPublicKeyImpl; @AllArgsConstructor @Slf4j @@ -49,7 +52,7 @@ public RSAPublicKey getPublicKeyById(String keyId) { .getKeysetForId(keyId) .mapTry(Jwk::getPublicKey) .map(Key::getEncoded) - .mapTry(RSAPublicKeyImpl::new) + .mapTry(JWTVerifierFactory::createKey) .onFailure(e -> log.warn("Error getting public key for id " + keyId, e)) .getOrElseThrow(JWTVerifierFactory::map); } @@ -74,9 +77,14 @@ public String getPrivateKeyId() { val tokenAudiences = config.getTokenAudiences(); if (tokenAudiences.nonEmpty()) { - verification.withAudience(tokenAudiences.toJavaArray(String.class)); + verification.withAudience(tokenAudiences.toJavaArray(String[]::new)); } return verification.build(); } + + private static RSAPublicKey createKey(byte[] bytes ) throws NoSuchAlgorithmException, InvalidKeySpecException { + return (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic( + new X509EncodedKeySpec(bytes)); + } } diff --git a/src/test/java/com/mercateo/spring/security/jwt/security/JWTAuthenticationProviderTest.java b/src/test/java/com/mercateo/spring/security/jwt/security/JWTAuthenticationProviderTest.java index 8e21c3e..4cdc583 100644 --- a/src/test/java/com/mercateo/spring/security/jwt/security/JWTAuthenticationProviderTest.java +++ b/src/test/java/com/mercateo/spring/security/jwt/security/JWTAuthenticationProviderTest.java @@ -36,8 +36,8 @@ public void shouldMapExtractedClaims() throws Exception { val tokenString = JWT.create().withSubject("").sign(Algorithm.none()); val tokenContainer = new JWTAuthenticationToken(tokenString); - final Map claimsMap = HashMap.of( // - "bar", JWTClaim.builder().value("baz").name("bar").build()); + final java.util.Map claimsMap = HashMap.of( // + "bar", JWTClaim.builder().value("baz").name("bar").build()).toJavaMap(); JWTClaims claims = JWTClaims.builder().claims(claimsMap).token(JWT.decode(tokenString)).build(); @@ -56,8 +56,8 @@ public void shouldMapScopesToGrantedAuthorities() throws Exception { val tokenString = JWT.create().sign(Algorithm.none()); val tokenContainer = new JWTAuthenticationToken(tokenString); - final Map claimsMap = HashMap.of( // - "scope", JWTClaim.builder().name("scope").value("foo bar").build()); + final java.util.Map claimsMap = HashMap.of( // + "scope", JWTClaim.builder().name("scope").value("foo bar").build()).toJavaMap(); JWTClaims claims = JWTClaims.builder().claims(claimsMap).token(JWT.decode(tokenString)).build(); when(hierarchicalJWTClaimsExtractor.extractClaims(tokenString)).thenReturn(claims); @@ -76,8 +76,8 @@ public void shouldMapRolesToGrantedAuthorities() throws Exception { val tokenString = JWT.create().sign(Algorithm.none()); val tokenContainer = new JWTAuthenticationToken(tokenString); - final Map claimsMap = HashMap.of( // - "roles", JWTClaim.builder().name("roles").value(new Object[]{"foo", "bar"}).build()); + final java.util.Map claimsMap = HashMap.of( // + "roles", JWTClaim.builder().name("roles").value(new Object[]{"foo", "bar"}).build()).toJavaMap(); JWTClaims claims = JWTClaims.builder().claims(claimsMap).token(JWT.decode(tokenString)).build(); when(hierarchicalJWTClaimsExtractor.extractClaims(tokenString)).thenReturn(claims); diff --git a/src/test/java/com/mercateo/spring/security/jwt/security/JWTPrincipalTest.java b/src/test/java/com/mercateo/spring/security/jwt/security/JWTPrincipalTest.java index 30c9f52..d9e3f7f 100644 --- a/src/test/java/com/mercateo/spring/security/jwt/security/JWTPrincipalTest.java +++ b/src/test/java/com/mercateo/spring/security/jwt/security/JWTPrincipalTest.java @@ -1,16 +1,13 @@ package com.mercateo.spring.security.jwt.security; -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.Before; -import org.junit.Test; - import com.mercateo.spring.security.jwt.data.ClaimName; import com.mercateo.spring.security.jwt.token.claim.JWTClaim; - import io.vavr.collection.HashMap; import io.vavr.collection.List; -import io.vavr.collection.Map; +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; public class JWTPrincipalTest { @@ -18,14 +15,13 @@ public class JWTPrincipalTest { @Before public void setUp() throws Exception { - Map claimsStringHashMap = HashMap.empty(); - claimsStringHashMap = claimsStringHashMap.put("foo_bar", JWTClaim - .builder() - .name("foo_bar") - .value("") - .issuer("") - .build()); - uut = new JWTPrincipal(123l, "", "", List.empty(), claimsStringHashMap); + java.util.Map claimsStringMap = HashMap.of("foo_bar", JWTClaim + .builder() + .name("foo_bar") + .value("") + .issuer("") + .build()).toJavaMap(); + uut = new JWTPrincipal(123l, "", "", List.empty(), claimsStringMap); } @Test @@ -35,17 +31,17 @@ public void shouldTransportId() throws Exception { @Test public void returnsClaimValue() { - assertThat(uut.getClaim("foo_bar")).extracting(JWTClaim::value).containsExactly(""); + assertThat(uut.getClaim("foo_bar")).get().extracting(JWTClaim::value).isEqualTo(""); } @Test public void returnsClaimIssuer() { - assertThat(uut.getClaim("foo_bar")).extracting(JWTClaim::issuer).containsExactly(""); + assertThat(uut.getClaim("foo_bar")).get().extracting(JWTClaim::issuer).isEqualTo(""); } @Test public void returnsClaimByNameEnum() { - assertThat(uut.getClaim(Claims.FOO_BAR)).extracting(JWTClaim::issuer).containsExactly(""); + assertThat(uut.getClaim(Claims.FOO_BAR)).get().extracting(JWTClaim::issuer).isEqualTo(""); } enum Claims implements ClaimName { diff --git a/src/test/java/com/mercateo/spring/security/jwt/token/extractor/ValidatingHierarchicalClaimsExtractorTest.java b/src/test/java/com/mercateo/spring/security/jwt/token/extractor/ValidatingHierarchicalClaimsExtractorTest.java index 67fe8b0..73b27b5 100644 --- a/src/test/java/com/mercateo/spring/security/jwt/token/extractor/ValidatingHierarchicalClaimsExtractorTest.java +++ b/src/test/java/com/mercateo/spring/security/jwt/token/extractor/ValidatingHierarchicalClaimsExtractorTest.java @@ -77,7 +77,7 @@ private JWTCreator.Builder signedJwtBuilder() { } private JWTClaim getClaimByName(JWTClaims claims, String name) { - return claims.claims().get(name).get(); + return claims.claims().get(name); } private void assertClaimContent(JWTClaim claim, Object value, boolean verified, int depth) {