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

commit 452414b4486de0e0a6ce28da388ec560e4c428ae
Author: LanKhuat <[email protected]>
AuthorDate: Tue Jul 28 14:23:11 2020 +0700

    JAMES-3351 JWT authentication strategy
---
 .../apache/james/jmap/JMAPAuthenticationTest.java  | 36 +++++++++---------
 .../jmap/http/JWTAuthenticationStrategyTest.java   | 44 ++++++++++++++--------
 .../james/jmap/jwt/JWTAuthenticationStrategy.java  | 36 ++++++++----------
 3 files changed, 61 insertions(+), 55 deletions(-)

diff --git 
a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/JMAPAuthenticationTest.java
 
b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/JMAPAuthenticationTest.java
index 184bc13..280d1b6 100644
--- 
a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/JMAPAuthenticationTest.java
+++ 
b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/JMAPAuthenticationTest.java
@@ -192,7 +192,7 @@ public abstract class JMAPAuthenticationTest {
     }
 
     @Test
-    public void methodShouldContainPasswordWhenValidResquest() throws 
Exception {
+    public void methodShouldContainPasswordWhenValidRequest() {
         given()
             .contentType(ContentType.JSON)
             .accept(ContentType.JSON)
@@ -206,7 +206,7 @@ public abstract class JMAPAuthenticationTest {
 
     @Category(BasicFeature.class)
     @Test
-    public void mustReturnContinuationTokenWhenValidResquest() throws 
Exception {
+    public void mustReturnContinuationTokenWhenValidRequest() {
         given()
             .contentType(ContentType.JSON)
             .accept(ContentType.JSON)
@@ -220,7 +220,7 @@ public abstract class JMAPAuthenticationTest {
 
     @Category(BasicFeature.class)
     @Test
-    public void mustReturnAuthenticationFailedWhenBadPassword() throws 
Exception {
+    public void mustReturnAuthenticationFailedWhenBadPassword() {
         String continuationToken = fromGoodContinuationTokenRequest();
 
         given()
@@ -248,7 +248,7 @@ public abstract class JMAPAuthenticationTest {
     }
 
     @Test
-    public void 
mustReturnRestartAuthenticationWhenContinuationTokenIsExpired() throws 
Exception {
+    public void 
mustReturnRestartAuthenticationWhenContinuationTokenIsExpired() {
         String continuationToken = fromGoodContinuationTokenRequest();
         zonedDateTimeProvider.setFixedDateTime(afterExpirationDate);
 
@@ -263,7 +263,7 @@ public abstract class JMAPAuthenticationTest {
     }
 
     @Test
-    public void mustReturnAuthenticationFailedWhenUsersRepositoryException() 
throws Exception {
+    public void mustReturnAuthenticationFailedWhenUsersRepositoryException() {
         String continuationToken = fromGoodContinuationTokenRequest();
 
         given()
@@ -277,7 +277,7 @@ public abstract class JMAPAuthenticationTest {
     }
 
     @Test
-    public void mustReturnCreatedWhenGoodPassword() throws Exception {
+    public void mustReturnCreatedWhenGoodPassword() {
         String continuationToken = fromGoodContinuationTokenRequest();
         zonedDateTimeProvider.setFixedDateTime(newDate);
 
@@ -293,7 +293,7 @@ public abstract class JMAPAuthenticationTest {
 
     @Category(BasicFeature.class)
     @Test
-    public void 
mustSendJsonContainingAccessTokenAndEndpointsWhenGoodPassword() throws 
Exception {
+    public void 
mustSendJsonContainingAccessTokenAndEndpointsWhenGoodPassword() {
         String continuationToken = fromGoodContinuationTokenRequest();
         zonedDateTimeProvider.setFixedDateTime(newDate);
 
@@ -312,7 +312,7 @@ public abstract class JMAPAuthenticationTest {
     }
     
     @Test
-    public void getMustReturnUnauthorizedWithoutAuthorizationHeader() throws 
Exception {
+    public void getMustReturnUnauthorizedWithoutAuthorizationHeader() {
         given()
         .when()
             .get("/authentication")
@@ -321,7 +321,7 @@ public abstract class JMAPAuthenticationTest {
     }
 
     @Test
-    public void getMustReturnUnauthorizedWithoutAValidAuthorizationHeader() 
throws Exception {
+    public void getMustReturnUnauthorizedWithoutAValidAuthorizationHeader() {
         given()
             .header("Authorization", UUID.randomUUID())
         .when()
@@ -332,7 +332,7 @@ public abstract class JMAPAuthenticationTest {
 
     @Category(BasicFeature.class)
     @Test
-    public void getMustReturnEndpointsWhenValidAuthorizationHeader() throws 
Exception {
+    public void getMustReturnEndpointsWhenValidAuthorizationHeader() {
         String continuationToken = fromGoodContinuationTokenRequest();
         String token = fromGoodAccessTokenRequest(continuationToken);
 
@@ -350,7 +350,7 @@ public abstract class JMAPAuthenticationTest {
 
     @Category(BasicFeature.class)
     @Test
-    public void getMustReturnEndpointsWhenValidJwtAuthorizationHeader() throws 
Exception {
+    public void getMustReturnEndpointsWhenValidJwtAuthorizationHeader() {
         String token = 
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyQGRvbWFpbi50bGQifQ.U-dUPv6OU6KO5N7CooHUfMkCd"
 +
             
"FJHx2F3H4fm7Q79g1BPfBSkifPj5xyVlZ0JwEGXypC4zBw9ay3l4DxzX7D_6p1Hx_ihXsoLx1Ca-WUo44x-XRSpPfgxiZjHCJkGBLMV3RZlA"
 +
             
"jip-d18mxkcX3JGplX_sCQkFisduAOAHuKSUg9wI6VBgUQi_0B35FYv6tP_bD6eFtvaAUN9QyXXh8UQjEp8CO12lRz6enfLx_V6BG_fEMkee"
 +
@@ -365,7 +365,7 @@ public abstract class JMAPAuthenticationTest {
     }
 
     @Test
-    public void 
getMustReturnEndpointsWhenValidUnkwnonUserJwtAuthorizationHeader() throws 
Exception {
+    public void 
getMustReturnEndpointsWhenValidUnknownUserJwtAuthorizationHeader() {
         String token = 
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1bmtub3duQGRvbWFpbi50bGQifQ.hr8AhlNIpiA3Mv_A5ZLyL"
 +
             
"f1BHeBSaRDfdR_GLV_hlPdIrWv1xtwjBH86E1YnTPx2tTpr_NWTbHcR1OCkuVCpgloEnUNbE3U2l0WrGOX2Eh9dWCXOCtrNvCeSHQuvx5_8W"
 +
             
"nSVENYidk7o2icE8_gz_Giwf0Z3bHJJYXfAxupv__tCkmhqt3E888VZPjs26AsqxQ29YyX0Fjx8UwKbPrH5-tnyftX-kLjjZNtahVIVtbW4v"
 +
@@ -380,7 +380,7 @@ public abstract class JMAPAuthenticationTest {
     }
 
     @Test
-    public void getMustReturnBadCredentialsWhenInvalidJwtAuthorizationHeader() 
throws Exception {
+    public void getMustReturnBadCredentialsWhenInvalidJwtAuthorizationHeader() 
{
         String token = 
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.T04BTk"
 +
                 
"LXkJj24coSZkK13RfG25lpvmSl2MJ7N10KpBk9_-95EGYZdog-BDAn3PJzqVw52z-Bwjh4VOj1-j7cURu0cT4jXehhUrlCxS4n7QHZ"
 +
                 
"EN_bsEYGu7KzjWTpTsUiHe-rN7izXVFxDGG1TGwlmBCBnPW-EFCf9ylUsJi0r2BKNdaaPRfMIrHptH1zJBkkUziWpBN1RNLjmvlAUf"
 +
@@ -405,7 +405,7 @@ public abstract class JMAPAuthenticationTest {
     }
 
     @Test
-    public void getMustReturnEndpointsWhenCorrectAuthentication() throws 
Exception {
+    public void getMustReturnEndpointsWhenCorrectAuthentication() {
         String continuationToken = fromGoodContinuationTokenRequest();
         zonedDateTimeProvider.setFixedDateTime(newDate);
     
@@ -421,7 +421,7 @@ public abstract class JMAPAuthenticationTest {
     }
     
     @Test
-    public void deleteMustReturnUnauthenticatedWithoutAuthorizationHeader() 
throws Exception {
+    public void deleteMustReturnUnauthenticatedWithoutAuthorizationHeader() {
         given()
         .when()
             .delete("/authentication")
@@ -430,7 +430,7 @@ public abstract class JMAPAuthenticationTest {
     }
 
     @Test
-    public void 
deleteMustReturnUnauthenticatedWithoutAValidAuthroizationHeader() throws 
Exception {
+    public void 
deleteMustReturnUnauthenticatedWithoutAValidAuthroizationHeader() {
         given()
             .header("Authorization", UUID.randomUUID())
         .when()
@@ -440,7 +440,7 @@ public abstract class JMAPAuthenticationTest {
     }
 
     @Test
-    public void deleteMustReturnOKNoContentOnValidAuthorizationToken() throws 
Exception {
+    public void deleteMustReturnOKNoContentOnValidAuthorizationToken() {
         String continuationToken = fromGoodContinuationTokenRequest();
         String token = fromGoodAccessTokenRequest(continuationToken);
         given()
@@ -453,7 +453,7 @@ public abstract class JMAPAuthenticationTest {
 
     @Category(BasicFeature.class)
     @Test
-    public void deleteMustInvalidAuthorizationOnCorrectAuthorization() throws 
Exception {
+    public void deleteMustInvalidAuthorizationOnCorrectAuthorization() {
         String continuationToken = fromGoodContinuationTokenRequest();
         zonedDateTimeProvider.setFixedDateTime(newDate);
     
diff --git 
a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JWTAuthenticationStrategyTest.java
 
b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JWTAuthenticationStrategyTest.java
index 5c8b3dd..78b57ad 100644
--- 
a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JWTAuthenticationStrategyTest.java
+++ 
b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JWTAuthenticationStrategyTest.java
@@ -26,7 +26,7 @@ import static org.mockito.Mockito.when;
 
 import org.apache.james.core.Username;
 import org.apache.james.domainlist.api.DomainList;
-import org.apache.james.jmap.exceptions.MailboxSessionCreationException;
+import org.apache.james.jmap.exceptions.UnauthorizedException;
 import org.apache.james.jmap.jwt.JWTAuthenticationStrategy;
 import org.apache.james.jwt.JwtTokenVerifier;
 import org.apache.james.mailbox.MailboxManager;
@@ -66,16 +66,16 @@ public class JWTAuthenticationStrategyTest {
 
 
     @Test
-    public void createMailboxSessionShouldThrowWhenAuthHeaderIsEmpty() {
-        when(mockedHeaders.getAll(AUTHORIZATION_HEADERS))
-            .thenReturn(ImmutableList.of());
+    public void createMailboxSessionShouldReturnEmptyWhenAuthHeaderIsEmpty() {
+        when(mockedHeaders.get(AUTHORIZATION_HEADERS))
+            .thenReturn("");
 
         assertThat(testee.createMailboxSession(mockedRequest).blockOptional())
             .isEmpty();
     }
 
     @Test
-    public void createMailboxSessionShouldThrownWhenAuthHeadersIsInvalid() {
+    public void createMailboxSessionShouldThrowWhenAuthHeadersIsInvalid() {
         String username = "123456789";
         String validAuthHeader = "valid";
         String fakeAuthHeaderWithPrefix = 
JWTAuthenticationStrategy.AUTHORIZATION_HEADER_PREFIX + validAuthHeader;
@@ -86,20 +86,32 @@ public class JWTAuthenticationStrategyTest {
         
when(mockedMailboxManager.createSystemSession(eq(Username.of(username))))
                 .thenReturn(fakeMailboxSession);
 
-        when(mockedHeaders.getAll(AUTHORIZATION_HEADERS))
-            .thenReturn(ImmutableList.of(fakeAuthHeaderWithPrefix));
+        when(mockedHeaders.get(AUTHORIZATION_HEADERS))
+            .thenReturn(fakeAuthHeaderWithPrefix);
+
+        assertThatThrownBy(() -> 
testee.createMailboxSession(mockedRequest).blockOptional())
+            .isInstanceOf(UnauthorizedException.class);
+    }
+
+    @Test
+    public void createMailboxSessionShouldReturnEmptyWhenAuthHeaderIsInvalid() 
{
+        when(mockedHeaders.get(AUTHORIZATION_HEADERS))
+            .thenReturn("bad");
 
         assertThat(testee.createMailboxSession(mockedRequest).blockOptional())
             .isEmpty();
     }
 
     @Test
-    public void createMailboxSessionShouldThrowWhenAuthHeaderIsInvalid() {
+    public void createMailboxSessionShouldThrowWhenMultipleHeaders() {
+        String authHeader1 = 
JWTAuthenticationStrategy.AUTHORIZATION_HEADER_PREFIX + "token1";
+        String authHeader2 = 
JWTAuthenticationStrategy.AUTHORIZATION_HEADER_PREFIX + "token2";
+
         when(mockedHeaders.getAll(AUTHORIZATION_HEADERS))
-            .thenReturn(ImmutableList.of("bad"));
+            .thenReturn(ImmutableList.of(authHeader1, authHeader2));
 
-        assertThat(testee.createMailboxSession(mockedRequest).blockOptional())
-            .isEmpty();
+        assertThatThrownBy(() -> 
testee.createMailboxSession(mockedRequest).blockOptional())
+            .isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
@@ -113,8 +125,8 @@ public class JWTAuthenticationStrategyTest {
         
when(stubTokenVerifier.extractLogin(validAuthHeader)).thenReturn(username);
         
when(mockedMailboxManager.createSystemSession(eq(Username.of(username))))
                 .thenReturn(fakeMailboxSession);
-        when(mockedHeaders.getAll(AUTHORIZATION_HEADERS))
-            .thenReturn(ImmutableList.of(fakeAuthHeaderWithPrefix));
+        when(mockedHeaders.get(AUTHORIZATION_HEADERS))
+            .thenReturn(fakeAuthHeaderWithPrefix);
 
         MailboxSession result = 
testee.createMailboxSession(mockedRequest).block();
         assertThat(result).isEqualTo(fakeMailboxSession);
@@ -131,11 +143,11 @@ public class JWTAuthenticationStrategyTest {
         
when(stubTokenVerifier.extractLogin(validAuthHeader)).thenReturn(username);
         
when(mockedMailboxManager.createSystemSession(eq(Username.of(username))))
                 .thenReturn(fakeMailboxSession);
-        when(mockedHeaders.getAll(AUTHORIZATION_HEADERS))
-            .thenReturn(ImmutableList.of(fakeAuthHeaderWithPrefix));
+        when(mockedHeaders.get(AUTHORIZATION_HEADERS))
+            .thenReturn(fakeAuthHeaderWithPrefix);
 
 
         assertThatThrownBy(() -> 
testee.createMailboxSession(mockedRequest).block())
-            .isInstanceOf(MailboxSessionCreationException.class);
+            .isInstanceOf(UnauthorizedException.class);
     }
 }
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/jwt/JWTAuthenticationStrategy.java
 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/jwt/JWTAuthenticationStrategy.java
index 41566a7..5ffbec0 100644
--- 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/jwt/JWTAuthenticationStrategy.java
+++ 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/jwt/JWTAuthenticationStrategy.java
@@ -18,12 +18,10 @@
  ****************************************************************/
 package org.apache.james.jmap.jwt;
 
-import java.util.stream.Stream;
-
 import javax.inject.Inject;
 
 import org.apache.james.core.Username;
-import org.apache.james.jmap.exceptions.MailboxSessionCreationException;
+import org.apache.james.jmap.exceptions.UnauthorizedException;
 import org.apache.james.jmap.http.AuthenticationStrategy;
 import org.apache.james.jwt.JwtTokenVerifier;
 import org.apache.james.mailbox.MailboxManager;
@@ -53,28 +51,24 @@ public class JWTAuthenticationStrategy implements 
AuthenticationStrategy {
     }
 
     @Override
-    public Mono<MailboxSession> createMailboxSession(HttpServerRequest 
httpRequest) throws MailboxSessionCreationException {
-        Stream<Username> userLoginStream = 
extractTokensFromAuthHeaders(authHeaders(httpRequest))
-            .filter(tokenManager::verify)
-            .map(tokenManager::extractLogin)
-            .map(Username::of)
-            .peek(username -> {
+    public Mono<MailboxSession> createMailboxSession(HttpServerRequest 
httpRequest) {
+        return Mono.fromCallable(() -> authHeaders(httpRequest))
+            .filter(header -> header.startsWith(AUTHORIZATION_HEADER_PREFIX))
+            .map(header -> 
header.substring(AUTHORIZATION_HEADER_PREFIX.length()))
+            .map(userJWTToken -> {
+                if (!tokenManager.verify(userJWTToken)) {
+                    throw new UnauthorizedException("Failed Jwt verification");
+                }
+
+                Username username = 
Username.of(tokenManager.extractLogin(userJWTToken));
                 try {
                     usersRepository.assertValid(username);
                 } catch (UsersRepositoryException e) {
-                    throw new MailboxSessionCreationException(e);
+                    throw new UnauthorizedException("Invalid username", e);
                 }
-            });
-
-        Stream<MailboxSession> mailboxSessionStream = userLoginStream
-                .map(mailboxManager::createSystemSession);
-
-        return Mono.justOrEmpty(mailboxSessionStream.findFirst());
-    }
 
-    private Stream<String> extractTokensFromAuthHeaders(Stream<String> 
authHeaders) {
-        return authHeaders
-                .filter(h -> h.startsWith(AUTHORIZATION_HEADER_PREFIX))
-                .map(h -> h.substring(AUTHORIZATION_HEADER_PREFIX.length()));
+                return username;
+            })
+            .map(mailboxManager::createSystemSession);
     }
 }


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

Reply via email to