This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git


The following commit(s) were added to refs/heads/master by this push:
     new 36c01ab  JAMES-3680 JwtTokenVerifier should allow extracting a claim 
(#779)
36c01ab is described below

commit 36c01ab93d1d2aa02965df7286dcb80210314108
Author: Benoit TELLIER <[email protected]>
AuthorDate: Mon Dec 6 21:13:22 2021 +0700

    JAMES-3680 JwtTokenVerifier should allow extracting a claim (#779)
---
 .../org/apache/james/jwt/JwtTokenVerifier.java     | 43 +++++++++-------------
 .../org/apache/james/jwt/JwtTokenVerifierTest.java | 34 +++++++++++++++++
 2 files changed, 51 insertions(+), 26 deletions(-)

diff --git 
a/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtTokenVerifier.java 
b/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtTokenVerifier.java
index 8a8feeb..cc6baba 100644
--- 
a/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtTokenVerifier.java
+++ 
b/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtTokenVerifier.java
@@ -25,8 +25,6 @@ import java.util.Optional;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Strings;
-
 import io.jsonwebtoken.Claims;
 import io.jsonwebtoken.Jws;
 import io.jsonwebtoken.JwtException;
@@ -53,44 +51,37 @@ public class JwtTokenVerifier {
     }
 
     public Optional<String> verifyAndExtractLogin(String token) {
+        return verifyAndExtractClaim(token, "sub", String.class)
+            .filter(s -> !s.isEmpty());
+    }
+
+    public <T> Optional<T> verifyAndExtractClaim(String token, String 
claimName, Class<T> returnType) {
         return publicKeys.stream()
-            .flatMap(key -> verifyAndExtractLogin(token, key).stream())
+            .flatMap(key -> verifyAndExtractClaim(token, claimName, 
returnType, key).stream())
             .findFirst();
     }
 
-    public Optional<String> verifyAndExtractLogin(String token, PublicKey key) 
{
+    private <T> Optional<T> verifyAndExtractClaim(String token, String 
claimName, Class<T> returnType, PublicKey publicKey) {
         try {
-            String subject = extractLogin(token, key);
-            if (Strings.isNullOrEmpty(subject)) {
-                throw new MalformedJwtException("'subject' field in token is 
mandatory");
+            Jws<Claims> jws = parseToken(token, publicKey);
+            T claim = jws
+                .getBody()
+                .get(claimName, returnType);
+            if (claim == null) {
+                throw new MalformedJwtException("'" + claimName + "' field in 
token is mandatory");
             }
-            return Optional.of(subject);
+            return Optional.of(claim);
         } catch (JwtException e) {
             LOGGER.info("Failed Jwt verification", e);
             return Optional.empty();
         }
     }
 
-    private String extractLogin(String token, PublicKey publicKey) throws 
JwtException {
-        Jws<Claims> jws = parseToken(token, publicKey);
-        return jws
-                .getBody()
-                .getSubject();
-    }
-
     public boolean hasAttribute(String attributeName, Object expectedValue, 
String token) {
-       return publicKeys.stream()
-           .anyMatch(key -> hasAttribute(attributeName, expectedValue, token, 
key));
-    }
-
-    private boolean hasAttribute(String attributeName, Object expectedValue, 
String token, PublicKey publicKey) {
         try {
-            Jwts
-                .parser()
-                .require(attributeName, expectedValue)
-                .setSigningKey(publicKey)
-                .parseClaimsJws(token);
-            return true;
+            return verifyAndExtractClaim(token, attributeName, Object.class)
+                .map(expectedValue::equals)
+                .orElse(false);
         } catch (JwtException e) {
             LOGGER.info("Jwt validation failed for claim {} to {}", 
attributeName, expectedValue, e);
             return false;
diff --git 
a/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
 
b/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
index 3bfe79b..3e67427 100644
--- 
a/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
+++ 
b/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
@@ -88,6 +88,40 @@ class JwtTokenVerifierTest {
     }
 
     @Test
+    void verifyAndExtractClaimShouldAllowExtractingClaim() {
+        assertThat(sut.verifyAndExtractClaim(VALID_TOKEN_WITHOUT_ADMIN, 
"name", String.class))
+            .contains("John Doe");
+    }
+
+    @Test
+    void verifyAndExtractClaimShouldReturnEmptyWhenBadDatatype() {
+        assertThat(sut.verifyAndExtractClaim(VALID_TOKEN_WITHOUT_ADMIN, 
"name", Integer.class))
+            .isEmpty();
+    }
+
+    @Test
+    void verifyAndExtractClaimShouldReturnEmptyWhenNotFound() {
+        assertThat(sut.verifyAndExtractClaim(VALID_TOKEN_WITHOUT_ADMIN, 
"notFound", String.class))
+            .isEmpty();
+    }
+
+
+    @Test
+    void verifyAndExtractClaimShouldReturnEmptyWhenNoneAlgorithm() {
+        assertThat(sut.verifyAndExtractClaim(TOKEN_NONE_ALGORITHM, "name", 
String.class))
+            .isEmpty();
+    }
+
+    @Test
+    void verifyAndExtractLoginShouldReturnEmptyOnMismatchingSigningKey() {
+        String invalidToken = 
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.Pd6t82"
 +
+            
"tPL3EZdkeYxw_DV2KimE1U2FvuLHmfR_mimJ5US3JFU4J2Gd94O7rwpSTGN1B9h-_lsTebo4ua4xHsTtmczZ9xa8a_kWKaSkqFjNFa"
 +
+            "Fp6zcoD6ivCu03SlRqsQzSRHXo6TKbnqOt9D6Y2rNa3C4igSwoS0jUE4BgpXbc0";
+
+        assertThat(sut.verifyAndExtractClaim(invalidToken, "name", 
String.class)).isEmpty();
+    }
+
+    @Test
     void shouldReturnTrueOnValidSignatureWithMultipleKeys() {
         PublicKeyProvider pubKeyProvider = new PublicKeyProvider(new 
JwtConfiguration(ImmutableList.of(PUBLIC_PEM_KEY_2, PUBLIC_PEM_KEY)), new 
PublicKeyReader());
         JwtTokenVerifier sut = new JwtTokenVerifier(pubKeyProvider);

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to