You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ad...@apache.org on 2016/07/08 07:55:21 UTC

[1/4] james-project git commit: JAMES-1784 Authentication strategy should be responsible of extracting the authentication part from the request

Repository: james-project
Updated Branches:
  refs/heads/master d59881815 -> 85aeb1e45


JAMES-1784 Authentication strategy should be responsible of extracting the authentication part from the request


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/3c7cc854
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/3c7cc854
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/3c7cc854

Branch: refs/heads/master
Commit: 3c7cc854c42acc897d51828b590399320de32681
Parents: d598818
Author: Antoine Duprat <ad...@linagora.com>
Authored: Fri Jul 1 14:22:56 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Jul 8 09:53:56 2016 +0200

----------------------------------------------------------------------
 .../org/apache/james/jmap/JMAPCommonModule.java |  2 +
 .../jmap/AccessTokenAuthenticationStrategy.java | 15 +++--
 .../apache/james/jmap/AuthenticationFilter.java | 18 ++---
 .../james/jmap/AuthenticationStrategy.java      |  6 +-
 .../james/jmap/JWTAuthenticationStrategy.java   | 14 ++--
 .../utils/HeadersAuthenticationExtractor.java   | 41 ++++++++++++
 .../AccessTokenAuthenticationStrategyTest.java  | 54 ++++++++++++---
 .../james/jmap/AuthenticationFilterTest.java    |  5 +-
 .../jmap/JWTAuthenticationStrategyTest.java     | 54 +++++++++++----
 .../HeadersAuthenticationExtractorTest.java     | 69 ++++++++++++++++++++
 10 files changed, 225 insertions(+), 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/3c7cc854/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPCommonModule.java b/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
index 049f3b3..0d5362f 100644
--- a/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
+++ b/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
@@ -34,6 +34,7 @@ import org.apache.james.jmap.model.MessageFactory;
 import org.apache.james.jmap.model.MessagePreviewGenerator;
 import org.apache.james.jmap.send.MailFactory;
 import org.apache.james.jmap.send.MailSpool;
+import org.apache.james.jmap.utils.HeadersAuthenticationExtractor;
 import org.apache.james.util.date.DefaultZonedDateTimeProvider;
 import org.apache.james.util.date.ZonedDateTimeProvider;
 import org.apache.mailet.base.AutomaticallySentMailDetector;
@@ -60,6 +61,7 @@ public class JMAPCommonModule extends AbstractModule {
         bind(AutomaticallySentMailDetectorImpl.class).in(Scopes.SINGLETON);
         bind(MessageFactory.class).in(Scopes.SINGLETON);
         bind(MessagePreviewGenerator.class).in(Scopes.SINGLETON);
+        bind(HeadersAuthenticationExtractor.class).in(Scopes.SINGLETON);
 
         bind(SignatureHandler.class).to(JamesSignatureHandler.class);
         bind(ZonedDateTimeProvider.class).to(DefaultZonedDateTimeProvider.class);

http://git-wip-us.apache.org/repos/asf/james-project/blob/3c7cc854/server/protocols/jmap/src/main/java/org/apache/james/jmap/AccessTokenAuthenticationStrategy.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/AccessTokenAuthenticationStrategy.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/AccessTokenAuthenticationStrategy.java
index 62043b5..d190ebd 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/AccessTokenAuthenticationStrategy.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/AccessTokenAuthenticationStrategy.java
@@ -19,15 +19,16 @@
 package org.apache.james.jmap;
 
 import java.util.Optional;
-import java.util.stream.Stream;
 
 import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
 
 import org.apache.james.jmap.api.AccessTokenManager;
 import org.apache.james.jmap.api.access.AccessToken;
 import org.apache.james.jmap.api.access.exceptions.NotAnAccessTokenException;
 import org.apache.james.jmap.exceptions.MailboxSessionCreationException;
 import org.apache.james.jmap.exceptions.NoValidAuthHeaderException;
+import org.apache.james.jmap.utils.HeadersAuthenticationExtractor;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.exception.MailboxException;
@@ -42,18 +43,20 @@ public class AccessTokenAuthenticationStrategy implements AuthenticationStrategy
 
     private final AccessTokenManager accessTokenManager;
     private final MailboxManager mailboxManager;
+    private final HeadersAuthenticationExtractor authenticationExtractor;
 
     @Inject
     @VisibleForTesting
-    AccessTokenAuthenticationStrategy(AccessTokenManager accessTokenManager, MailboxManager mailboxManager) {
+    AccessTokenAuthenticationStrategy(AccessTokenManager accessTokenManager, MailboxManager mailboxManager, HeadersAuthenticationExtractor authenticationExtractor) {
         this.accessTokenManager = accessTokenManager;
         this.mailboxManager = mailboxManager;
+        this.authenticationExtractor = authenticationExtractor;
     }
 
     @Override
-    public MailboxSession createMailboxSession(Stream<String> authHeaders) throws MailboxSessionCreationException, NoValidAuthHeaderException {
+    public MailboxSession createMailboxSession(HttpServletRequest httpRequest) throws MailboxSessionCreationException, NoValidAuthHeaderException {
 
-        Optional<String> username = authHeaders
+        Optional<String> username = authenticationExtractor.authHeaders(httpRequest)
             .map(AccessToken::fromString)
             .map(accessTokenManager::getUsernameFromToken)
             .findFirst();
@@ -69,8 +72,8 @@ public class AccessTokenAuthenticationStrategy implements AuthenticationStrategy
     }
 
     @Override
-    public boolean checkAuthorizationHeader(Stream<String> authHeaders) {
-        return authHeaders
+    public boolean checkAuthorizationHeader(HttpServletRequest httpRequest) {
+        return authenticationExtractor.authHeaders(httpRequest)
                 .map(this::accessTokenFrom)
                 .anyMatch(this::isValid);
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/3c7cc854/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationFilter.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationFilter.java
index a9ce14d..d62c1c2 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationFilter.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationFilter.java
@@ -19,10 +19,7 @@
 package org.apache.james.jmap;
 
 import java.io.IOException;
-import java.util.Collections;
-import java.util.Enumeration;
 import java.util.List;
-import java.util.stream.Stream;
 
 import javax.inject.Inject;
 import javax.servlet.Filter;
@@ -50,7 +47,6 @@ public class AuthenticationFilter implements Filter {
     private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticationFilter.class);
 
     public static final String MAILBOX_SESSION = "mailboxSession";
-    private static final String AUTHORIZATION_HEADERS = "Authorization";
 
     private final List<AuthenticationStrategy> authMethods;
 
@@ -71,9 +67,9 @@ public class AuthenticationFilter implements Filter {
 
         try {
             HttpServletRequest requestWithSession = authMethods.stream()
-                    .filter(auth -> auth.checkAuthorizationHeader(getAuthHeaders(httpRequest)))
+                    .filter(auth -> auth.checkAuthorizationHeader(httpRequest))
                     .findFirst()
-                    .map(auth -> addSessionToRequest(httpRequest, createSession(auth, getAuthHeaders(httpRequest))))
+                    .map(auth -> addSessionToRequest(httpRequest, createSession(auth, httpRequest)))
                     .orElseThrow(UnauthorizedException::new);
             chain.doFilter(requestWithSession, response);
 
@@ -84,19 +80,13 @@ public class AuthenticationFilter implements Filter {
 
     }
 
-    private Stream<String> getAuthHeaders(HttpServletRequest httpRequest) {
-        Enumeration<String> authHeaders = httpRequest.getHeaders(AUTHORIZATION_HEADERS);
-
-        return authHeaders != null ? Collections.list(authHeaders).stream() : Stream.of();
-    }
-
     private HttpServletRequest addSessionToRequest(HttpServletRequest httpRequest, MailboxSession mailboxSession) {
         httpRequest.setAttribute(MAILBOX_SESSION, mailboxSession);
         return httpRequest;
     }
 
-    private MailboxSession createSession(AuthenticationStrategy authenticationMethod, Stream<String> authorizationHeaders) {
-        return authenticationMethod.createMailboxSession(authorizationHeaders);
+    private MailboxSession createSession(AuthenticationStrategy authenticationMethod, HttpServletRequest httpRequest) {
+        return authenticationMethod.createMailboxSession(httpRequest);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/3c7cc854/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationStrategy.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationStrategy.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationStrategy.java
index 57ace0c..d75247a 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationStrategy.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationStrategy.java
@@ -18,13 +18,13 @@
  ****************************************************************/
 package org.apache.james.jmap;
 
-import java.util.stream.Stream;
+import javax.servlet.http.HttpServletRequest;
 
 import org.apache.james.mailbox.MailboxSession;
 
 public interface AuthenticationStrategy {
 
-    MailboxSession createMailboxSession(Stream<String> requestHeaders);
+    MailboxSession createMailboxSession(HttpServletRequest httpRequest);
 
-    boolean checkAuthorizationHeader(Stream<String> requestHeaders);
+    boolean checkAuthorizationHeader(HttpServletRequest httpRequest);
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/3c7cc854/server/protocols/jmap/src/main/java/org/apache/james/jmap/JWTAuthenticationStrategy.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JWTAuthenticationStrategy.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JWTAuthenticationStrategy.java
index f6564b9..9d9c659 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JWTAuthenticationStrategy.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JWTAuthenticationStrategy.java
@@ -21,10 +21,12 @@ package org.apache.james.jmap;
 import java.util.stream.Stream;
 
 import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
 
 import org.apache.james.jmap.crypto.JwtTokenVerifier;
 import org.apache.james.jmap.exceptions.MailboxSessionCreationException;
 import org.apache.james.jmap.exceptions.NoValidAuthHeaderException;
+import org.apache.james.jmap.utils.HeadersAuthenticationExtractor;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.exception.MailboxException;
@@ -39,18 +41,20 @@ public class JWTAuthenticationStrategy implements AuthenticationStrategy {
     @VisibleForTesting static final String AUTHORIZATION_HEADER_PREFIX = "Bearer ";
     private final JwtTokenVerifier tokenManager;
     private final MailboxManager mailboxManager;
+    private final HeadersAuthenticationExtractor authenticationExtractor;
 
     @Inject
     @VisibleForTesting
-    JWTAuthenticationStrategy(JwtTokenVerifier tokenManager, MailboxManager mailboxManager) {
+    JWTAuthenticationStrategy(JwtTokenVerifier tokenManager, MailboxManager mailboxManager, HeadersAuthenticationExtractor authenticationExtractor) {
         this.tokenManager = tokenManager;
         this.mailboxManager = mailboxManager;
+        this.authenticationExtractor = authenticationExtractor;
     }
 
     @Override
-    public MailboxSession createMailboxSession(Stream<String> authHeaders) throws MailboxSessionCreationException, NoValidAuthHeaderException {
+    public MailboxSession createMailboxSession(HttpServletRequest httpRequest) throws MailboxSessionCreationException, NoValidAuthHeaderException {
 
-        Stream<String> userLoginStream = extractTokensFromAuthHeaders(authHeaders)
+        Stream<String> userLoginStream = extractTokensFromAuthHeaders(authenticationExtractor.authHeaders(httpRequest))
                 .filter(tokenManager::verify)
                 .map(tokenManager::extractLogin);
 
@@ -69,8 +73,8 @@ public class JWTAuthenticationStrategy implements AuthenticationStrategy {
     }
 
     @Override
-    public boolean checkAuthorizationHeader(Stream<String> authHeaders) {
-        return extractTokensFromAuthHeaders(authHeaders)
+    public boolean checkAuthorizationHeader(HttpServletRequest httpRequest) {
+        return extractTokensFromAuthHeaders(authenticationExtractor.authHeaders(httpRequest))
                 .anyMatch(tokenManager::verify);
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/3c7cc854/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/HeadersAuthenticationExtractor.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/HeadersAuthenticationExtractor.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/HeadersAuthenticationExtractor.java
new file mode 100644
index 0000000..3bfb091
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/utils/HeadersAuthenticationExtractor.java
@@ -0,0 +1,41 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jmap.utils;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.stream.Stream;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.google.common.base.Preconditions;
+
+public class HeadersAuthenticationExtractor {
+
+    private static final String AUTHORIZATION_HEADERS = "Authorization";
+
+    public Stream<String> authHeaders(HttpServletRequest httpRequest) {
+        Preconditions.checkArgument(httpRequest != null, "'httpRequest' is mandatory");
+        Enumeration<String> authHeaders = httpRequest.getHeaders(AUTHORIZATION_HEADERS);
+
+        return authHeaders != null ? Collections.list(authHeaders).stream() : Stream.of();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3c7cc854/server/protocols/jmap/src/test/java/org/apache/james/jmap/AccessTokenAuthenticationStrategyTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/AccessTokenAuthenticationStrategyTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/AccessTokenAuthenticationStrategyTest.java
index 83cae4b..91e18e2 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/AccessTokenAuthenticationStrategyTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/AccessTokenAuthenticationStrategyTest.java
@@ -28,11 +28,14 @@ import static org.mockito.Mockito.when;
 import java.util.UUID;
 import java.util.stream.Stream;
 
+import javax.servlet.http.HttpServletRequest;
+
 import org.apache.james.jmap.api.access.AccessToken;
 import org.apache.james.jmap.api.access.exceptions.NotAnAccessTokenException;
 import org.apache.james.jmap.crypto.AccessTokenManagerImpl;
 import org.apache.james.jmap.exceptions.MailboxSessionCreationException;
 import org.apache.james.jmap.exceptions.NoValidAuthHeaderException;
+import org.apache.james.jmap.utils.HeadersAuthenticationExtractor;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.exception.MailboxException;
@@ -45,24 +48,34 @@ public class AccessTokenAuthenticationStrategyTest {
     private AccessTokenManagerImpl mockedAccessTokenManager;
     private MailboxManager mockedMailboxManager;
     private AccessTokenAuthenticationStrategy testee;
+    private HttpServletRequest request;
+    private HeadersAuthenticationExtractor mockAuthenticationExtractor;
 
     @Before
     public void setup() {
         mockedAccessTokenManager = mock(AccessTokenManagerImpl.class);
         mockedMailboxManager = mock(MailboxManager.class);
+        mockAuthenticationExtractor = mock(HeadersAuthenticationExtractor.class);
+        request = mock(HttpServletRequest.class);
 
-        testee = new AccessTokenAuthenticationStrategy(mockedAccessTokenManager, mockedMailboxManager);
+        testee = new AccessTokenAuthenticationStrategy(mockedAccessTokenManager, mockedMailboxManager, mockAuthenticationExtractor);
     }
 
     @Test
     public void createMailboxSessionShouldThrowWhenNoAuthProvided() {
-        assertThatThrownBy(() -> testee.createMailboxSession(Stream.empty()))
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.empty());
+
+        assertThatThrownBy(() -> testee.createMailboxSession(request))
             .isExactlyInstanceOf(NoValidAuthHeaderException.class);
     }
 
     @Test
     public void createMailboxSessionShouldThrowWhenAuthHeaderIsNotAnUUID() {
-        assertThatThrownBy(() -> testee.createMailboxSession(Stream.of("bad")))
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.of("bad"));
+
+        assertThatThrownBy(() -> testee.createMailboxSession(request))
                 .isExactlyInstanceOf(NotAnAccessTokenException.class);
     }
 
@@ -75,8 +88,11 @@ public class AccessTokenAuthenticationStrategyTest {
         UUID authHeader = UUID.randomUUID();
         when(mockedAccessTokenManager.getUsernameFromToken(AccessToken.fromString(authHeader.toString())))
                 .thenReturn(username);
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.of(authHeader.toString()));
 
-        assertThatThrownBy(() -> testee.createMailboxSession(Stream.of(authHeader.toString())))
+
+        assertThatThrownBy(() -> testee.createMailboxSession(request))
                 .isExactlyInstanceOf(MailboxSessionCreationException.class);
     }
 
@@ -91,24 +107,36 @@ public class AccessTokenAuthenticationStrategyTest {
         UUID authHeader = UUID.randomUUID();
         when(mockedAccessTokenManager.getUsernameFromToken(AccessToken.fromString(authHeader.toString())))
                 .thenReturn(username);
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.of(authHeader.toString()));
+
 
-        MailboxSession result = testee.createMailboxSession(Stream.of(authHeader.toString()));
+        MailboxSession result = testee.createMailboxSession(request);
         assertThat(result).isEqualTo(fakeMailboxSession);
     }
 
     @Test
     public void checkAuthorizationHeaderShouldReturnFalseWhenAuthHeaderIsEmpty() {
-        assertThat(testee.checkAuthorizationHeader(Stream.empty())).isFalse();
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.empty());
+
+        assertThat(testee.checkAuthorizationHeader(request)).isFalse();
     }
 
     @Test
     public void checkAuthorizationHeaderShouldReturnFalseWhenAuthHeaderIsInvalid() {
-        assertThat(testee.checkAuthorizationHeader(Stream.of("bad"))).isFalse();
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.of("bad"));
+
+        assertThat(testee.checkAuthorizationHeader(request)).isFalse();
     }
 
     @Test
     public void checkAuthorizationHeaderShouldReturnFalseWhenAuthHeadersAreInvalid() {
-        assertThat(testee.checkAuthorizationHeader(Stream.of("bad", "alsobad"))).isFalse();
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.of("bad", "alsobad"));
+
+        assertThat(testee.checkAuthorizationHeader(request)).isFalse();
     }
 
     @Test
@@ -117,8 +145,11 @@ public class AccessTokenAuthenticationStrategyTest {
         String validToken = UUID.randomUUID().toString();
         when(mockedAccessTokenManager.isValid(AccessToken.fromString(validToken)))
                 .thenReturn(true);
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.of(validToken));
 
-        assertThat(testee.checkAuthorizationHeader(Stream.of(validToken))).isTrue();
+
+        assertThat(testee.checkAuthorizationHeader(request)).isTrue();
     }
 
     @Test
@@ -127,7 +158,10 @@ public class AccessTokenAuthenticationStrategyTest {
         String validToken = UUID.randomUUID().toString();
         when(mockedAccessTokenManager.isValid(AccessToken.fromString(validToken)))
                 .thenReturn(true);
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.of("bad", validToken));
+
 
-        assertThat(testee.checkAuthorizationHeader(Stream.of("bad", validToken))).isTrue();
+        assertThat(testee.checkAuthorizationHeader(request)).isTrue();
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/3c7cc854/server/protocols/jmap/src/test/java/org/apache/james/jmap/AuthenticationFilterTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/AuthenticationFilterTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/AuthenticationFilterTest.java
index 6da6ea1..837ff9f 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/AuthenticationFilterTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/AuthenticationFilterTest.java
@@ -26,7 +26,6 @@ import static org.mockito.Mockito.when;
 
 import java.util.List;
 import java.util.concurrent.TimeUnit;
-import java.util.stream.Stream;
 
 import javax.servlet.FilterChain;
 import javax.servlet.ServletRequest;
@@ -129,12 +128,12 @@ public class AuthenticationFilterTest {
         }
 
         @Override
-        public MailboxSession createMailboxSession(Stream<String> requestHeaders) {
+        public MailboxSession createMailboxSession(HttpServletRequest httpRequest) {
             return null;
         }
 
         @Override
-        public boolean checkAuthorizationHeader(Stream<String> requestHeaders) {
+        public boolean checkAuthorizationHeader(HttpServletRequest httpRequest) {
             return isAuthorized;
         }
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/3c7cc854/server/protocols/jmap/src/test/java/org/apache/james/jmap/JWTAuthenticationStrategyTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/JWTAuthenticationStrategyTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/JWTAuthenticationStrategyTest.java
index f4c8459..c96b7a8 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/JWTAuthenticationStrategyTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/JWTAuthenticationStrategyTest.java
@@ -27,9 +27,12 @@ import static org.mockito.Mockito.when;
 
 import java.util.stream.Stream;
 
+import javax.servlet.http.HttpServletRequest;
+
 import org.apache.james.jmap.crypto.JwtTokenVerifier;
 import org.apache.james.jmap.exceptions.MailboxSessionCreationException;
 import org.apache.james.jmap.exceptions.NoValidAuthHeaderException;
+import org.apache.james.jmap.utils.HeadersAuthenticationExtractor;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.exception.MailboxException;
@@ -43,26 +46,35 @@ public class JWTAuthenticationStrategyTest {
     private JWTAuthenticationStrategy testee;
     private MailboxManager mockedMailboxManager;
     private JwtTokenVerifier stubTokenVerifier;
+    private HttpServletRequest request;
+    private HeadersAuthenticationExtractor mockAuthenticationExtractor;
 
     @Before
     public void setup() {
-        mockedMailboxManager = mock(MailboxManager.class);
-
         stubTokenVerifier = mock(JwtTokenVerifier.class);
+        mockedMailboxManager = mock(MailboxManager.class);
+        mockAuthenticationExtractor = mock(HeadersAuthenticationExtractor.class);
+        request = mock(HttpServletRequest.class);
 
-        testee = new JWTAuthenticationStrategy(stubTokenVerifier, mockedMailboxManager);
+        testee = new JWTAuthenticationStrategy(stubTokenVerifier, mockedMailboxManager, mockAuthenticationExtractor);
     }
 
 
     @Test
     public void createMailboxSessionShouldThrowWhenAuthHeaderIsEmpty() throws Exception {
-        assertThatThrownBy(() -> testee.createMailboxSession(Stream.empty()))
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.empty());
+
+        assertThatThrownBy(() -> testee.createMailboxSession(request))
             .isExactlyInstanceOf(NoValidAuthHeaderException.class);
     }
 
     @Test
     public void createMailboxSessionShouldReturnEmptyWhenAuthHeaderIsInvalid() throws Exception {
-        assertThatThrownBy(() -> testee.createMailboxSession(Stream.of("bad")))
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.of("bad"));
+
+        assertThatThrownBy(() -> testee.createMailboxSession(request))
             .isExactlyInstanceOf(NoValidAuthHeaderException.class);
     }
 
@@ -76,8 +88,10 @@ public class JWTAuthenticationStrategyTest {
         when(stubTokenVerifier.extractLogin(validAuthHeader)).thenReturn(username);
         when(mockedMailboxManager.createSystemSession(eq(username), any(Logger.class)))
                 .thenThrow(new MailboxException());
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.of(fakeAuthHeaderWithPrefix));
 
-        assertThatThrownBy(() -> testee.createMailboxSession(Stream.of(fakeAuthHeaderWithPrefix)))
+        assertThatThrownBy(() -> testee.createMailboxSession(request))
                 .isExactlyInstanceOf(MailboxSessionCreationException.class);
     }
 
@@ -92,14 +106,20 @@ public class JWTAuthenticationStrategyTest {
         when(stubTokenVerifier.extractLogin(validAuthHeader)).thenReturn(username);
         when(mockedMailboxManager.createSystemSession(eq(username), any(Logger.class)))
                 .thenReturn(fakeMailboxSession);
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.of(fakeAuthHeaderWithPrefix));
+
 
-        MailboxSession result = testee.createMailboxSession(Stream.of(fakeAuthHeaderWithPrefix));
+        MailboxSession result = testee.createMailboxSession(request);
         assertThat(result).isEqualTo(fakeMailboxSession);
     }
 
     @Test
     public void checkAuthorizationHeaderShouldReturnFalsewWhenAuthHeaderIsEmpty() {
-        assertThat(testee.checkAuthorizationHeader(Stream.empty())).isFalse();
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.empty());
+
+        assertThat(testee.checkAuthorizationHeader(request)).isFalse();
     }
 
     @Test
@@ -108,8 +128,10 @@ public class JWTAuthenticationStrategyTest {
         String fakeAuthHeaderWithPrefix = JWTAuthenticationStrategy.AUTHORIZATION_HEADER_PREFIX + wrongAuthHeader;
 
         when(stubTokenVerifier.verify(wrongAuthHeader)).thenReturn(false);
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.of(fakeAuthHeaderWithPrefix));
 
-        assertThat(testee.checkAuthorizationHeader(Stream.of(fakeAuthHeaderWithPrefix))).isFalse();
+        assertThat(testee.checkAuthorizationHeader(request)).isFalse();
     }
 
     @Test
@@ -122,7 +144,10 @@ public class JWTAuthenticationStrategyTest {
 
         Stream<String> authHeadersStream = Stream.of(wrongAuthHeader, invalidAuthHeader)
                 .map(h -> JWTAuthenticationStrategy.AUTHORIZATION_HEADER_PREFIX + h);
-        assertThat(testee.checkAuthorizationHeader(authHeadersStream)).isFalse();
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(authHeadersStream);
+
+        assertThat(testee.checkAuthorizationHeader(request)).isFalse();
     }
 
     @Test
@@ -131,8 +156,10 @@ public class JWTAuthenticationStrategyTest {
         String validAuthHeaderWithPrefix = JWTAuthenticationStrategy.AUTHORIZATION_HEADER_PREFIX + validAuthHeader;
 
         when(stubTokenVerifier.verify(validAuthHeader)).thenReturn(true);
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.of(validAuthHeaderWithPrefix));
 
-        assertThat(testee.checkAuthorizationHeader(Stream.of(validAuthHeaderWithPrefix))).isTrue();
+        assertThat(testee.checkAuthorizationHeader(request)).isTrue();
     }
 
     @Test
@@ -145,7 +172,10 @@ public class JWTAuthenticationStrategyTest {
 
         Stream<String> authHeadersStream = Stream.of(dummyAuthHeader, validAuthHeader)
                 .map(h -> JWTAuthenticationStrategy.AUTHORIZATION_HEADER_PREFIX + h);
-        assertThat(testee.checkAuthorizationHeader(authHeadersStream)).isTrue();
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(authHeadersStream);
+
+        assertThat(testee.checkAuthorizationHeader(request)).isTrue();
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/3c7cc854/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/HeadersAuthenticationExtractorTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/HeadersAuthenticationExtractorTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/HeadersAuthenticationExtractorTest.java
new file mode 100644
index 0000000..e995cff
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/utils/HeadersAuthenticationExtractorTest.java
@@ -0,0 +1,69 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jmap.utils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class HeadersAuthenticationExtractorTest {
+
+    private HeadersAuthenticationExtractor testee;
+
+    @Before
+    public void setup() {
+        testee = new HeadersAuthenticationExtractor();
+    }
+
+    @Test
+    public void authHeadersShouldThrowWhenRequestIsNull() {
+        assertThatThrownBy(() -> testee.authHeaders(null))
+            .isExactlyInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void authHeadersShouldReturnEmptyStreamWhenNoAuthorizationHeader() {
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        when(request.getHeaders("Authorization"))
+            .thenReturn(Collections.emptyEnumeration());
+
+        assertThat(testee.authHeaders(request)).isEmpty();
+    }
+
+    @Test
+    public void authHeadersShouldReturnStreamOfHeadersWhenSome() {
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        ImmutableList<String> expectedHeaders = ImmutableList.of("header", "otherHeader");
+        when(request.getHeaders("Authorization"))
+            .thenReturn(Collections.enumeration(expectedHeaders));
+
+        assertThat(testee.authHeaders(request)).containsOnlyElementsOf(expectedHeaders);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[4/4] james-project git commit: JAMES-1784 Add integration tests when downloading attachment with access token

Posted by ad...@apache.org.
JAMES-1784 Add integration tests when downloading attachment with access token


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/85aeb1e4
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/85aeb1e4
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/85aeb1e4

Branch: refs/heads/master
Commit: 85aeb1e45b5d5cbffbe40b7c71f7ed264e57b5a6
Parents: b6f6ac9
Author: Antoine Duprat <ad...@linagora.com>
Authored: Fri Jul 1 14:56:30 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Jul 8 09:54:07 2016 +0200

----------------------------------------------------------------------
 .../integration/cucumber/DownloadStepdefs.java  | 170 ++++++++++++++++---
 .../resources/cucumber/DownloadEndpoint.feature |  51 ++++--
 .../test/resources/cucumber/DownloadGet.feature |   5 +-
 .../java/org/apache/james/jmap/JMAPServer.java  |   2 +-
 .../james/jmap/crypto/SignedTokenFactory.java   |   4 +-
 .../james/jmap/model/AttachmentAccessToken.java |  20 ++-
 .../jmap/crypto/SignedTokenFactoryTest.java     |   3 +-
 .../jmap/crypto/SignedTokenManagerTest.java     |  10 ++
 8 files changed, 220 insertions(+), 45 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/85aeb1e4/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/DownloadStepdefs.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/DownloadStepdefs.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/DownloadStepdefs.java
index b414de9..53fe11d 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/DownloadStepdefs.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/cucumber/DownloadStepdefs.java
@@ -20,7 +20,7 @@
 package org.apache.james.jmap.methods.integration.cucumber;
 
 import static com.jayway.restassured.RestAssured.with;
-import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.isIn;
 import static org.hamcrest.Matchers.notNullValue;
 
 import java.util.Date;
@@ -31,10 +31,14 @@ import javax.inject.Inject;
 import javax.mail.Flags;
 
 import org.apache.james.jmap.api.access.AccessToken;
+import org.apache.james.jmap.model.AttachmentAccessToken;
 import org.apache.james.mailbox.model.MailboxConstants;
 import org.apache.james.mailbox.model.MailboxPath;
 
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
 import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Multimap;
 import com.jayway.restassured.http.ContentType;
 import com.jayway.restassured.response.Response;
@@ -49,12 +53,21 @@ import cucumber.runtime.java.guice.ScenarioScoped;
 @ScenarioScoped
 public class DownloadStepdefs {
 
+    private static final String ONE_ATTACHMENT_EML_ATTACHEMENT_BLOB_ID = "4000c5145f633410b80be368c44e1c394bff9437";
+    private static final String EXPIRED_ATTACHMENT_TOKEN = "usera@domain.tld_"
+            + "2016-06-29T13:41:22.124Z_"
+            + "DiZa0O14MjLWrAA8P6MG35Gt5CBp7mt5U1EH/M++rIoZK7nlGJ4dPW0dvZD7h4m3o5b/Yd8DXU5x2x4+s0HOOKzD7X0RMlsU7JHJMNLvTvRGWF/C+MUyC8Zce7DtnRVPEQX2uAZhL2PBABV07Vpa8kH+NxoS9CL955Bc1Obr4G+KN2JorADlocFQA6ElXryF5YS/HPZSvq1MTC6aJIP0ku8WRpRnbwgwJnn26YpcHXcJjbkCBtd9/BhlMV6xNd2hTBkfZmYdoNo+UKBaXWzLxAlbLuxjpxwvDNJfOEyWFPgHDoRvzP+G7KzhVWjanHAHrhF0GilEa/MKpOI1qHBSwA==";
+    private static final String INVALID_ATTACHMENT_TOKEN = "usera@domain.tld_"
+            + "2015-06-29T13:41:22.124Z_"
+            + "DiZa0O14MjLWrAA8P6MG35Gt5CBp7mt5U1EH/M++rIoZK7nlGJ4dPW0dvZD7h4m3o5b/Yd8DXU5x2x4+s0HOOKzD7X0RMlsU7JHJMNLvTvRGWF/C+MUyC8Zce7DtnRVPEQX2uAZhL2PBABV07Vpa8kH+NxoS9CL955Bc1Obr4G+KN2JorADlocFQA6ElXryF5YS/HPZSvq1MTC6aJIP0ku8WRpRnbwgwJnn26YpcHXcJjbkCBtd9/BhlMV6xNd2hTBkfZmYdoNo+UKBaXWzLxAlbLuxjpxwvDNJfOEyWFPgHDoRvzP+G7KzhVWjanHAHrhF0GilEa/MKpOI1qHBSwA==";
+
     private final UserStepdefs userStepdefs;
     private final MainStepdefs mainStepdefs;
     private Response response;
     private Multimap<String, String> attachmentsByMessageId;
     private Map<String, String> blobIdByAttachmentId;
     private ValidatableResponse validatableResponse;
+    private Map<AttachmentAccessTokenKey, AttachmentAccessToken> attachmentAccessTokens;
 
     @Inject
     private DownloadStepdefs(MainStepdefs mainStepdefs, UserStepdefs userStepdefs) {
@@ -62,6 +75,7 @@ public class DownloadStepdefs {
         this.userStepdefs = userStepdefs;
         this.attachmentsByMessageId = ArrayListMultimap.create();
         this.blobIdByAttachmentId = new HashMap<>();
+        this.attachmentAccessTokens = new HashMap<>();
     }
 
     @Given("^\"([^\"]*)\" mailbox \"([^\"]*)\" contains a message \"([^\"]*)\" with an attachment \"([^\"]*)\"$")
@@ -95,38 +109,144 @@ public class DownloadStepdefs {
             with.header("Authorization", accessToken.serialize());
         }
 
-        response = with.options("/download/myBlob");
+        response = with
+                .options("/download/" + ONE_ATTACHMENT_EML_ATTACHEMENT_BLOB_ID);
     }
 
     @When("^\"([^\"]*)\" downloads \"([^\"]*)\"$")
     public void downloads(String username, String attachmentId) throws Throwable {
         String blobId = blobIdByAttachmentId.get(attachmentId);
+        response = authenticatedDownloadRequest(blobId, username)
+                .get("/download/" + blobId);
+    }
+
+    private RequestSpecification authenticatedDownloadRequest(String blobId, String username) {
         AccessToken accessToken = userStepdefs.tokenByUser.get(username);
-        RequestSpecification with = with();
+        AttachmentAccessTokenKey key = new AttachmentAccessTokenKey(username, blobId);
+        if (attachmentAccessTokens.containsKey(key)) {
+            return with().param("access_token", attachmentAccessTokens.get(key).serialize());
+        }
         if (accessToken != null) {
-            with.header("Authorization", accessToken.serialize());
+            return with().header("Authorization", accessToken.serialize());
         }
-        response = with.get("/download/" + blobId);
+        return with();
     }
-    
 
-    @When("^\"([^\"]*)\" asks for an attachment without blobId parameter$")
-    public void getDownloadWithoutBlobId(String username) throws Throwable {
-        AccessToken accessToken = userStepdefs.tokenByUser.get(username);
+    @When("^\"([^\"]*)\" is trusted for attachment \"([^\"]*)\"$")
+    public void attachmentAccessTokenFor(String username, String attachmentId) throws Throwable {
+        userStepdefs.connectUser(username);
+        trustForBlobId(blobIdByAttachmentId.get(attachmentId), username);
+    }
+
+    private static class AttachmentAccessTokenKey {
+
+        private String username;
+        private String blobId;
+
+        public AttachmentAccessTokenKey(String username, String blobId) {
+            this.username = username;
+            this.blobId = blobId;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof AttachmentAccessTokenKey) {
+                AttachmentAccessTokenKey other = (AttachmentAccessTokenKey) obj;
+                return Objects.equal(username, other.username)
+                    && Objects.equal(blobId, other.blobId);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hashCode(username, blobId);
+        }
+
+        @Override
+        public String toString() {
+            return MoreObjects
+                    .toStringHelper(this)
+                    .add("username", username)
+                    .add("blobId", blobId)
+                    .toString();
+        }
+    }
+
+    private void trustForBlobId(String blobId, String username) {
+        String serializedAttachmentAccessToken = 
+            with()
+                .header("Authorization", userStepdefs.tokenByUser.get(username).serialize())
+            .post("/download/" + blobId)
+            .then()
+                .extract()
+                .asString();
+        attachmentAccessTokens.put(
+                new AttachmentAccessTokenKey(username, blobId),
+                AttachmentAccessToken.from(
+                    serializedAttachmentAccessToken,
+                    blobId));
+    }
+
+    @When("^\"([^\"]*)\" downloads \"([^\"]*)\" with a valid authentication token$")
+    public void downloadsWithValidToken(String username, String attachmentId) throws Throwable {
+        String blobId = blobIdByAttachmentId.get(attachmentId);
+
+        response = requestWithQueryParameterAuthentication(username, blobId)
+                .get("/download/" + attachmentId);
+    }
+
+    @When("^\"([^\"]*)\" downloads \"([^\"]*)\" without any authentication token$")
+    public void getDownloadWithoutToken(String username, String attachmentId) {
+        String blobId = blobIdByAttachmentId.get(attachmentId);
+        response = with().get("/download/" + blobId);
+    }
+
+    @When("^\"([^\"]*)\" downloads \"([^\"]*)\" with an empty authentication token$")
+    public void getDownloadWithEmptyToken(String username, String attachmentId) {
+        String blobId = blobIdByAttachmentId.get(attachmentId);
         response = with()
-            .header("Authorization", accessToken.serialize())
-            .get("/download/");
+                .param("access_token", "")
+                .get("/download/" + blobId);
     }
-    
 
-    @When("^\"([^\"]*)\" asks for an attachment with wrong blobId$")
-    public void getDownloadWithWrongBlobId(String username) throws Throwable {
-        AccessToken accessToken = userStepdefs.tokenByUser.get(username);
+    @When("^\"([^\"]*)\" downloads \"([^\"]*)\" with a bad authentication token$")
+    public void getDownloadWithBadToken(String username, String attachmentId) {
+        String blobId = blobIdByAttachmentId.get(attachmentId);
         response = with()
-                .header("Authorization", accessToken.serialize())
+                .param("access_token", "bad")
+                .get("/download/" + blobId);
+    }
+
+    @When("^\"([^\"]*)\" downloads \"([^\"]*)\" with an invalid authentication token$")
+    public void getDownloadWithUnknownToken(String username, String attachmentId) {
+        String blobId = blobIdByAttachmentId.get(attachmentId);
+        response = with()
+                .param("access_token", INVALID_ATTACHMENT_TOKEN)
+                .get("/download/" + blobId);
+    }
+
+    @When("^\"([^\"]*)\" downloads \"([^\"]*)\" without blobId parameter$")
+    public void getDownloadWithoutBlobId(String username, String attachmentId) throws Throwable {
+        String blobId = blobIdByAttachmentId.get(attachmentId);
+
+        response = requestWithQueryParameterAuthentication(username, blobId)
+            .get("/download/");
+    }
+
+    @When("^\"([^\"]*)\" downloads \"([^\"]*)\" with wrong blobId$")
+    public void getDownloadWithWrongBlobId(String username, String attachmentId) throws Throwable {
+        String blobId = blobIdByAttachmentId.get(attachmentId);
+
+        response = requestWithQueryParameterAuthentication(username, blobId)
                 .get("/download/badbadbadbadbadbadbadbadbadbadbadbadbadb");
     }
 
+    private RequestSpecification requestWithQueryParameterAuthentication(String username, String blobId) {
+        trustForBlobId(blobId, username);
+        return authenticatedDownloadRequest(blobId, username);
+    }
+
     @When("^\"([^\"]*)\" asks for a token for attachment \"([^\"]*)\"$")
     public void postDownload(String username, String attachmentId) throws Throwable {
         String blobId = blobIdByAttachmentId.get(attachmentId);
@@ -142,18 +262,22 @@ public class DownloadStepdefs {
     @When("^\"([^\"]*)\" downloads \"([^\"]*)\" with \"([^\"]*)\" name$")
     public void downloadsWithName(String username, String attachmentId, String name) {
         String blobId = blobIdByAttachmentId.get(attachmentId);
-        AccessToken accessToken = userStepdefs.tokenByUser.get(username);
-        RequestSpecification with = with();
-        if (accessToken != null) {
-            with.header("Authorization", accessToken.serialize());
-        }
-        response = with.get("/download/" + blobId + "/" + name);
+        response = authenticatedDownloadRequest(blobId, username)
+                .get("/download/" + blobId + "/" + name);
+    }
+
+    @When("^\"([^\"]*)\" downloads \"([^\"]*)\" with an expired token$")
+    public void getDownloadWithExpiredToken(String username, String attachmentId) {
+        String blobId = blobIdByAttachmentId.get(attachmentId);
+        response = with()
+                .param("access_token", EXPIRED_ATTACHMENT_TOKEN)
+                .get("/download/" + blobId);
     }
 
     @Then("^the user should be authorized$")
     public void httpStatusDifferentFromUnauthorized() {
         response.then()
-            .statusCode(not(401));
+            .statusCode(isIn(ImmutableList.of(200, 404)));
     }
 
     @Then("^the user should not be authorized$")

http://git-wip-us.apache.org/repos/asf/james-project/blob/85aeb1e4/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadEndpoint.feature
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadEndpoint.feature b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadEndpoint.feature
index d059572..e46a4fe 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadEndpoint.feature
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadEndpoint.feature
@@ -17,35 +17,58 @@ Feature: Download endpoint
     When "usera@domain.tld" checks for the availability of the attachment endpoint
     Then the user should be authorized
 
-  Scenario: An authenticated user should have access to the download endpoint
-    Given "usera@domain.tld" is connected
-    When "usera@domain.tld" downloads "a1"
-    Then the user should be authorized
-
-  @Ignore
   Scenario: An unauthenticated user should not have access to the download endpoint
     When "usera@domain.tld" downloads "a1"
     Then the user should not be authorized
 
-  Scenario: A authenticated user should not have access to the download endpoint without a blobId
-    Given "usera@domain.tld" is connected
-    When "usera@domain.tld" asks for an attachment without blobId parameter
-    Then the user should receive a bad request response
+  Scenario: A user should not have access to the download endpoint without the authentication token
+    When "usera@domain.tld" downloads "a1" without any authentication token
+    Then the user should not be authorized
+
+  Scenario: A user should not have access to the download endpoint with an empty authentication token
+    When "usera@domain.tld" downloads "a1" with an empty authentication token
+    Then the user should not be authorized
+
+  Scenario: A user should not have access to the download endpoint with a bad authentication token
+    When "usera@domain.tld" downloads "a1" with a bad authentication token
+    Then the user should not be authorized
+
+  Scenario: A user should not have access to the download endpoint with an unknown authentication token
+    When "usera@domain.tld" downloads "a1" with an invalid authentication token
+    Then the user should not be authorized
+
+  Scenario: A user should not have access to the download endpoint when an authentication token has expired
+    When "usera@domain.tld" downloads "a1" with an expired token
+    Then the user should not be authorized
 
+  Scenario: A user should not have access to the download endpoint without a blobId
+    Given "usera@domain.tld" is trusted for attachment "a1"
+    When "usera@domain.tld" downloads "a1" without blobId parameter
+    Then the user should not be authorized
 
   Scenario: A user should not retrieve anything when using wrong blobId
+    Given "usera@domain.tld" is trusted for attachment "a1"
+    When "usera@domain.tld" downloads "a1" with wrong blobId
+    Then the user should not be authorized
+
+  Scenario: A user should have access to the download endpoint when an authentication token is valid
+    Given "usera@domain.tld" is trusted for attachment "a1"
+    When "usera@domain.tld" downloads "a1"
+    Then the user should be authorized
+
+  Scenario: An authenticated user should have access to the download endpoint
     Given "usera@domain.tld" is connected
-    When "usera@domain.tld" asks for an attachment with wrong blobId
-    Then the user should receive a not found response
+    When "usera@domain.tld" downloads "a1"
+    Then the user should be authorized
 
   @Ignore
-  Scenario: A user should not have access to someone else attachment
+  Scenario: An authenticated user should not have access to someone else attachment
     Given "userb@domain.tld" is connected
     When "userb@domain.tld" downloads "a1"
     Then the user should receive a not found response
 
   @Ignore
-  Scenario: A user should have access to a shared attachment
+  Scenario: An authenticated user should have access to a shared attachment
     Given "usera@domain.tld" shares its mailbox "INBOX" with "userb@domain.tld"
     And "userb@domain.tld" is connected
     When "userb@domain.tld" downloads "a1"

http://git-wip-us.apache.org/repos/asf/james-project/blob/85aeb1e4/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadGet.feature
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadGet.feature b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadGet.feature
index bf3d21a..ccd7eef 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadGet.feature
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/resources/cucumber/DownloadGet.feature
@@ -13,8 +13,9 @@ Feature: Download GET
     Then the user should receive that attachment
 
   Scenario: Getting an attachment with an unknown blobId
-    When "username@domain.tld" downloads "123"
-    Then the user should receive a not found response
+    Given "username@domain.tld" mailbox "inbox" contains a message "1" with an attachment "2"
+    When "username@domain.tld" downloads "2" with a valid authentication token
+    Then the user should not be authorized
 
   Scenario: Getting an attachment previously stored with a desired name
     Given "username@domain.tld" mailbox "inbox" contains a message "1" with an attachment "2"

http://git-wip-us.apache.org/repos/asf/james-project/blob/85aeb1e4/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServer.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServer.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServer.java
index 7d235a4..e1c3ba5 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServer.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServer.java
@@ -58,7 +58,7 @@ public class JMAPServer implements Configurable {
                         .serveAsOneLevelTemplate(JMAPUrls.DOWNLOAD)
                             .with(downloadServlet)
                         .filterAsOneLevelTemplate(JMAPUrls.DOWNLOAD)
-                            .with(new AllowAllCrossOriginRequests(bypass(authenticationFilter).on("GET").and("OPTIONS").only()))
+                            .with(new AllowAllCrossOriginRequests(bypass(authenticationFilter).on("OPTIONS").only()))
                             .only()
                         .serve(JMAPUrls.UPLOAD)
                             .with(uploadServlet)

http://git-wip-us.apache.org/repos/asf/james-project/blob/85aeb1e4/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SignedTokenFactory.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SignedTokenFactory.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SignedTokenFactory.java
index 7154a32..594bff3 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SignedTokenFactory.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SignedTokenFactory.java
@@ -65,8 +65,8 @@ public class SignedTokenFactory implements SimpleTokenFactory {
                 .blobId(blobId)
                 .expirationDate(expirationTime)
                 .signature(signatureHandler.sign(Joiner.on(AttachmentAccessToken.SEPARATOR)
-                                                    .join(username, 
-                                                            blobId,
+                                                    .join(blobId,
+                                                            username, 
                                                             DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(expirationTime))))
                 .build();
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/85aeb1e4/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AttachmentAccessToken.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AttachmentAccessToken.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AttachmentAccessToken.java
index 4d13c75..2188b1e 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AttachmentAccessToken.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AttachmentAccessToken.java
@@ -21,11 +21,15 @@ package org.apache.james.jmap.model;
 
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
+import java.util.List;
 import java.util.Objects;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterables;
 
 public class AttachmentAccessToken implements SignedExpiringToken {
 
@@ -34,7 +38,21 @@ public class AttachmentAccessToken implements SignedExpiringToken {
     public static Builder builder() {
         return new Builder();
     }
-    
+
+    public static AttachmentAccessToken from(String serializedAttachmentAccessToken, String blobId) {
+        Preconditions.checkArgument(!Strings.isNullOrEmpty(serializedAttachmentAccessToken), "'AttachmentAccessToken' is mandatory");
+        List<String> split = Splitter.on(SEPARATOR).splitToList(serializedAttachmentAccessToken);
+        Preconditions.checkArgument(split.size() == 3, "Wrong 'AttachmentAccessToken'");
+
+        String defaultValue = null;
+        return builder()
+                .blobId(blobId)
+                .username(Iterables.get(split, 0, defaultValue))
+                .expirationDate(ZonedDateTime.parse(Iterables.get(split, 1, defaultValue)))
+                .signature(Iterables.get(split, 2, defaultValue))
+                .build();
+    }
+
     public static class Builder {
         private String username;
         private String blobId;

http://git-wip-us.apache.org/repos/asf/james-project/blob/85aeb1e4/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenFactoryTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenFactoryTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenFactoryTest.java
index 371083f..dfe8c18 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenFactoryTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenFactoryTest.java
@@ -73,7 +73,6 @@ public class SignedTokenFactoryTest {
     public void generateAttachmentAccessTokenShouldHaveTheRightOutPut() throws Exception {
         zonedDateTimeProvider.setFixedDateTime(DATE);
         assertThat(toKenFactory.generateAttachmentAccessToken("user", "blobId").serialize())
-            .isEqualTo("user_2011-12-03T10:20:30+01:00_UAmjTzvmmIwvE1Yw54tE7jC1Q2nCJ1l3XX1703kYmLIeOZe7fNSLM6V8CzPFEvZ+Y4H+UD4UTkNHbmgcPbxesITnby+UfT/tIiTppJhXJvtTxSoTy9vuAJrW9/kJh6CruqtSM+BUEkLKuuzJySmvDkaHSaXwot4egGXaJ9yHgjEh2PT3uA0O0JjRNB2x8oa370fFSZsT2QgXrqeqHWWO1j6IrAf4UcyhvjNkJBK9TVNubfqGKuCZ4dz2Rm/CUvp13CpzUoVqBS1nJ1VaIw94L2rX8RkAMTlV7AXKB3kPiBX7MdGp2NBiAUlYlOLjflYl8plnv/QrRCmfGxnsvv4WVQ==");
+            .isEqualTo("user_2011-12-03T10:20:30+01:00_eSg1mVxMpqw5/u6wsTAatP7hoHDoI7blEW0hxGPrRMMj3hECT+YhbUCdhz9Lb4U+jsYPgNLDuAHwxin79xXfLoq0nVsogEE32svRYVvbaDpro+EOtkAHhYnYxWnAGxB/70u7Zyw0oYGmWOwkCkLDFsWKglMp9IUpOJQP50zbzbdW+4dKlAi/8VmN8jFyZx40envRbgEn4Q2QQbnUH/7F9+vdLIl+bAfcj6QlevqFRsUkmTZelkv1rtGUAvnPSBQL4TeBx5Qk/eEiw8IbB2lbCIAoIFZC6Vl8QOO5Y6LFzmqHL9i0BjvuoiZ8FKQS0pGd5CU6pwc7sv0xD82Vx1eFiw==");
     }
-
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/85aeb1e4/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenManagerTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenManagerTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenManagerTest.java
index c371f0b..b31f0df 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenManagerTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenManagerTest.java
@@ -27,6 +27,7 @@ import java.time.format.DateTimeFormatter;
 
 import org.apache.james.jmap.FixedDateZonedDateTimeProvider;
 import org.apache.james.jmap.api.SimpleTokenManager.TokenStatus;
+import org.apache.james.jmap.model.AttachmentAccessToken;
 import org.apache.james.jmap.model.ContinuationToken;
 import org.junit.Before;
 import org.junit.Test;
@@ -168,4 +169,13 @@ public class SignedTokenManagerTest {
         ContinuationToken pirateContinuationToken = new ContinuationToken("user", DATE.plusMinutes(15), "fake");
         assertThat(tokenManager.getValidity(pirateContinuationToken)).isEqualTo(TokenStatus.INVALID);
     }
+
+    @Test
+    public void signedAttachmentAccessTokenShouldBeValidated() {
+        String blobId = "blobId";
+        zonedDateTimeProvider.setFixedDateTime(DATE);
+        String serializedToken = tokenFactory.generateAttachmentAccessToken("user", blobId).serialize();
+
+        assertThat(tokenManager.isValid(AttachmentAccessToken.from(serializedToken, blobId))).isTrue();
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[3/4] james-project git commit: JAMES-1784 Add QueryParameterAccessTokenAuthenticationStrategy

Posted by ad...@apache.org.
JAMES-1784 Add QueryParameterAccessTokenAuthenticationStrategy


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/b6f6ac9a
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/b6f6ac9a
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/b6f6ac9a

Branch: refs/heads/master
Commit: b6f6ac9af0961f425395896773c2d4f1e82d328f
Parents: 6262735
Author: Antoine Duprat <ad...@linagora.com>
Authored: Fri Jul 1 14:55:51 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Jul 8 09:54:06 2016 +0200

----------------------------------------------------------------------
 .../org/apache/james/jmap/JMAPCommonModule.java |  6 +-
 ...ameterAccessTokenAuthenticationStrategy.java | 85 ++++++++++++++++++
 ...erAccessTokenAuthenticationStrategyTest.java | 94 ++++++++++++++++++++
 3 files changed, 183 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/b6f6ac9a/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPCommonModule.java b/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
index 0d5362f..5a9b6a4 100644
--- a/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
+++ b/server/container/guice/guice-common/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
@@ -76,10 +76,12 @@ public class JMAPCommonModule extends AbstractModule {
     @Provides
     public List<AuthenticationStrategy> authStrategies(
             AccessTokenAuthenticationStrategy accessTokenAuthenticationStrategy,
-            JWTAuthenticationStrategy jwtAuthenticationStrategy) {
+            JWTAuthenticationStrategy jwtAuthenticationStrategy,
+            QueryParameterAccessTokenAuthenticationStrategy queryParameterAuthenticationStrategy) {
 
         return ImmutableList.of(
                 jwtAuthenticationStrategy,
-                accessTokenAuthenticationStrategy);
+                accessTokenAuthenticationStrategy,
+                queryParameterAuthenticationStrategy);
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/b6f6ac9a/server/protocols/jmap/src/main/java/org/apache/james/jmap/QueryParameterAccessTokenAuthenticationStrategy.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/QueryParameterAccessTokenAuthenticationStrategy.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/QueryParameterAccessTokenAuthenticationStrategy.java
new file mode 100644
index 0000000..498ba91
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/QueryParameterAccessTokenAuthenticationStrategy.java
@@ -0,0 +1,85 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+package org.apache.james.jmap;
+
+import java.util.Optional;
+
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.james.jmap.api.SimpleTokenManager;
+import org.apache.james.jmap.exceptions.MailboxSessionCreationException;
+import org.apache.james.jmap.exceptions.NoValidAuthHeaderException;
+import org.apache.james.jmap.exceptions.UnauthorizedException;
+import org.apache.james.jmap.model.AttachmentAccessToken;
+import org.apache.james.jmap.utils.DownloadPath;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+
+public class QueryParameterAccessTokenAuthenticationStrategy implements AuthenticationStrategy {
+
+    private static final Logger LOG = LoggerFactory.getLogger(QueryParameterAccessTokenAuthenticationStrategy.class);
+    private static final String AUTHENTICATION_PARAMETER = "access_token";
+
+    private final SimpleTokenManager tokenManager;
+    private final MailboxManager mailboxManager;
+
+    @Inject
+    @VisibleForTesting
+    QueryParameterAccessTokenAuthenticationStrategy(SimpleTokenManager tokenManager, MailboxManager mailboxManager) {
+        this.tokenManager = tokenManager;
+        this.mailboxManager = mailboxManager;
+    }
+
+    @Override
+    public MailboxSession createMailboxSession(HttpServletRequest httpRequest) throws MailboxSessionCreationException, NoValidAuthHeaderException {
+
+        return getAccessToken(httpRequest)
+            .filter(tokenManager::isValid)
+            .map(AttachmentAccessToken::getUsername)
+            .map(this::createSystemSession)
+            .orElseThrow(() -> new UnauthorizedException());
+    }
+
+    private MailboxSession createSystemSession(String username) {
+        try {
+            return mailboxManager.createSystemSession(username, LOG);
+        } catch (MailboxException e) {
+            throw new MailboxSessionCreationException(e);
+        }
+    }
+
+    private Optional<AttachmentAccessToken> getAccessToken(HttpServletRequest httpRequest) {
+        try {
+            return Optional.of(AttachmentAccessToken.from(httpRequest.getParameter(AUTHENTICATION_PARAMETER), getBlobId(httpRequest)));
+        } catch (IllegalArgumentException e) {
+            return Optional.empty();
+        }
+    }
+
+    private String getBlobId(HttpServletRequest httpRequest) {
+        String pathInfo = httpRequest.getPathInfo();
+        return DownloadPath.from(pathInfo).getBlobId();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/b6f6ac9a/server/protocols/jmap/src/test/java/org/apache/james/jmap/QueryParameterAccessTokenAuthenticationStrategyTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/QueryParameterAccessTokenAuthenticationStrategyTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/QueryParameterAccessTokenAuthenticationStrategyTest.java
new file mode 100644
index 0000000..a04d75d
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/QueryParameterAccessTokenAuthenticationStrategyTest.java
@@ -0,0 +1,94 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+package org.apache.james.jmap;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.james.jmap.api.SimpleTokenManager;
+import org.apache.james.jmap.exceptions.MailboxSessionCreationException;
+import org.apache.james.jmap.exceptions.UnauthorizedException;
+import org.apache.james.jmap.model.AttachmentAccessToken;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+
+public class QueryParameterAccessTokenAuthenticationStrategyTest {
+
+    private static final String USERNAME = "usera@domain.tld";
+    private static final String VALID_ATTACHMENT_TOKEN = "usera@domain.tld_"
+            + "2016-06-29T13:41:22.124Z_"
+            + "DiZa0O14MjLWrAA8P6MG35Gt5CBp7mt5U1EH/M++rIoZK7nlGJ4dPW0dvZD7h4m3o5b/Yd8DXU5x2x4+s0HOOKzD7X0RMlsU7JHJMNLvTvRGWF/C+MUyC8Zce7DtnRVPEQX2uAZhL2PBABV07Vpa8kH+NxoS9CL955Bc1Obr4G+KN2JorADlocFQA6ElXryF5YS/HPZSvq1MTC6aJIP0ku8WRpRnbwgwJnn26YpcHXcJjbkCBtd9/BhlMV6xNd2hTBkfZmYdoNo+UKBaXWzLxAlbLuxjpxwvDNJfOEyWFPgHDoRvzP+G7KzhVWjanHAHrhF0GilEa/MKpOI1qHBSwA==";
+
+    private SimpleTokenManager mockedSimpleTokenManager;
+    private MailboxManager mockedMailboxManager;
+    private QueryParameterAccessTokenAuthenticationStrategy testee;
+    private HttpServletRequest request;
+
+    @Before
+    public void setup() {
+        mockedSimpleTokenManager = mock(SimpleTokenManager.class);
+        mockedMailboxManager = mock(MailboxManager.class);
+        request = mock(HttpServletRequest.class);
+
+        testee = new QueryParameterAccessTokenAuthenticationStrategy(mockedSimpleTokenManager, mockedMailboxManager);
+    }
+
+    @Test
+    public void createMailboxSessionShouldThrowWhenNoAccessTokenProvided() {
+        when(request.getParameter("access_token"))
+            .thenReturn(null);
+
+        assertThatThrownBy(() -> testee.createMailboxSession(request))
+            .isExactlyInstanceOf(UnauthorizedException.class);
+    }
+
+    @Test
+    public void createMailboxSessionShouldThrowWhenAccessTokenIsNotValid() {
+        when(request.getParameter("access_token"))
+            .thenReturn("bad");
+
+        assertThatThrownBy(() -> testee.createMailboxSession(request))
+                .isExactlyInstanceOf(UnauthorizedException.class);
+    }
+
+    @Test
+    public void createMailboxSessionShouldThrowWhenMailboxExceptionHasOccurred() throws Exception {
+        when(mockedMailboxManager.createSystemSession(eq(USERNAME), any(Logger.class)))
+                .thenThrow(new MailboxException());
+
+        when(request.getParameter("access_token"))
+            .thenReturn(VALID_ATTACHMENT_TOKEN);
+        when(request.getPathInfo())
+            .thenReturn("/blobId");
+
+        when(mockedSimpleTokenManager.isValid(AttachmentAccessToken.from(VALID_ATTACHMENT_TOKEN, "blobId")))
+            .thenReturn(true);
+
+        assertThatThrownBy(() -> testee.createMailboxSession(request))
+                .isExactlyInstanceOf(MailboxSessionCreationException.class);
+    }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[2/4] james-project git commit: JAMES-1784 Remove checkAuthorizationHeader in AuthenticationStrategy

Posted by ad...@apache.org.
JAMES-1784 Remove checkAuthorizationHeader in AuthenticationStrategy


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/62627357
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/62627357
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/62627357

Branch: refs/heads/master
Commit: 62627357717844ed0630b68fb5541836639763af
Parents: 3c7cc85
Author: Antoine Duprat <ad...@linagora.com>
Authored: Mon Jul 4 13:48:31 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Fri Jul 8 09:54:06 2016 +0200

----------------------------------------------------------------------
 .../jmap/AccessTokenAuthenticationStrategy.java | 22 +----
 .../apache/james/jmap/AuthenticationFilter.java | 13 ++-
 .../james/jmap/AuthenticationStrategy.java      |  2 -
 .../james/jmap/JWTAuthenticationStrategy.java   |  6 --
 .../AccessTokenAuthenticationStrategyTest.java  | 80 +++++++------------
 .../james/jmap/AuthenticationFilterTest.java    | 27 +++++--
 .../jmap/JWTAuthenticationStrategyTest.java     | 84 +++++---------------
 7 files changed, 76 insertions(+), 158 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/62627357/server/protocols/jmap/src/main/java/org/apache/james/jmap/AccessTokenAuthenticationStrategy.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/AccessTokenAuthenticationStrategy.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/AccessTokenAuthenticationStrategy.java
index d190ebd..57d903a 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/AccessTokenAuthenticationStrategy.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/AccessTokenAuthenticationStrategy.java
@@ -25,7 +25,6 @@ import javax.servlet.http.HttpServletRequest;
 
 import org.apache.james.jmap.api.AccessTokenManager;
 import org.apache.james.jmap.api.access.AccessToken;
-import org.apache.james.jmap.api.access.exceptions.NotAnAccessTokenException;
 import org.apache.james.jmap.exceptions.MailboxSessionCreationException;
 import org.apache.james.jmap.exceptions.NoValidAuthHeaderException;
 import org.apache.james.jmap.utils.HeadersAuthenticationExtractor;
@@ -58,6 +57,7 @@ public class AccessTokenAuthenticationStrategy implements AuthenticationStrategy
 
         Optional<String> username = authenticationExtractor.authHeaders(httpRequest)
             .map(AccessToken::fromString)
+            .filter(accessTokenManager::isValid)
             .map(accessTokenManager::getUsernameFromToken)
             .findFirst();
 
@@ -70,24 +70,4 @@ public class AccessTokenAuthenticationStrategy implements AuthenticationStrategy
         }
         throw new NoValidAuthHeaderException();
     }
-
-    @Override
-    public boolean checkAuthorizationHeader(HttpServletRequest httpRequest) {
-        return authenticationExtractor.authHeaders(httpRequest)
-                .map(this::accessTokenFrom)
-                .anyMatch(this::isValid);
-    }
-
-    private Optional<AccessToken> accessTokenFrom(String header) {
-        try {
-            return Optional.of(AccessToken.fromString(header));
-        } catch (NotAnAccessTokenException e) {
-            return Optional.empty();
-        }
-    }
-
-    private boolean isValid(Optional<AccessToken> token) {
-        return token.map(accessTokenManager::isValid)
-            .orElse(false);
-    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/62627357/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationFilter.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationFilter.java
index d62c1c2..14823a5 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationFilter.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationFilter.java
@@ -20,6 +20,7 @@ package org.apache.james.jmap;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.stream.Stream;
 
 import javax.inject.Inject;
 import javax.servlet.Filter;
@@ -67,9 +68,9 @@ public class AuthenticationFilter implements Filter {
 
         try {
             HttpServletRequest requestWithSession = authMethods.stream()
-                    .filter(auth -> auth.checkAuthorizationHeader(httpRequest))
+                    .flatMap(auth -> createSession(auth, httpRequest))
                     .findFirst()
-                    .map(auth -> addSessionToRequest(httpRequest, createSession(auth, httpRequest)))
+                    .map(mailboxSession -> addSessionToRequest(httpRequest, mailboxSession))
                     .orElseThrow(UnauthorizedException::new);
             chain.doFilter(requestWithSession, response);
 
@@ -85,8 +86,12 @@ public class AuthenticationFilter implements Filter {
         return httpRequest;
     }
 
-    private MailboxSession createSession(AuthenticationStrategy authenticationMethod, HttpServletRequest httpRequest) {
-        return authenticationMethod.createMailboxSession(httpRequest);
+    private Stream<MailboxSession> createSession(AuthenticationStrategy authenticationMethod, HttpServletRequest httpRequest) {
+        try {
+            return Stream.of(authenticationMethod.createMailboxSession(httpRequest));
+        } catch (Exception e) {
+            return Stream.empty();
+        }
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/62627357/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationStrategy.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationStrategy.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationStrategy.java
index d75247a..aab2286 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationStrategy.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationStrategy.java
@@ -25,6 +25,4 @@ import org.apache.james.mailbox.MailboxSession;
 public interface AuthenticationStrategy {
 
     MailboxSession createMailboxSession(HttpServletRequest httpRequest);
-
-    boolean checkAuthorizationHeader(HttpServletRequest httpRequest);
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/62627357/server/protocols/jmap/src/main/java/org/apache/james/jmap/JWTAuthenticationStrategy.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JWTAuthenticationStrategy.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JWTAuthenticationStrategy.java
index 9d9c659..a7e91be 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JWTAuthenticationStrategy.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JWTAuthenticationStrategy.java
@@ -72,12 +72,6 @@ public class JWTAuthenticationStrategy implements AuthenticationStrategy {
                 .orElseThrow(() -> new NoValidAuthHeaderException());
     }
 
-    @Override
-    public boolean checkAuthorizationHeader(HttpServletRequest httpRequest) {
-        return extractTokensFromAuthHeaders(authenticationExtractor.authHeaders(httpRequest))
-                .anyMatch(tokenManager::verify);
-    }
-
     private Stream<String> extractTokensFromAuthHeaders(Stream<String> authHeaders) {
         return authHeaders
                 .filter(h -> h.startsWith(AUTHORIZATION_HEADER_PREFIX))

http://git-wip-us.apache.org/repos/asf/james-project/blob/62627357/server/protocols/jmap/src/test/java/org/apache/james/jmap/AccessTokenAuthenticationStrategyTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/AccessTokenAuthenticationStrategyTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/AccessTokenAuthenticationStrategyTest.java
index 91e18e2..b1c71b6 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/AccessTokenAuthenticationStrategyTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/AccessTokenAuthenticationStrategyTest.java
@@ -80,17 +80,38 @@ public class AccessTokenAuthenticationStrategyTest {
     }
 
     @Test
+    public void createMailboxSessionShouldThrowWhenAuthHeaderIsInvalid() throws Exception {
+        String username = "123456789";
+        MailboxSession fakeMailboxSession = mock(MailboxSession.class);
+
+        when(mockedMailboxManager.createSystemSession(eq(username), any(Logger.class)))
+                .thenReturn(fakeMailboxSession);
+
+        UUID authHeader = UUID.randomUUID();
+        when(mockedAccessTokenManager.getUsernameFromToken(AccessToken.fromString(authHeader.toString())))
+                .thenReturn(username);
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.of(authHeader.toString()));
+
+
+        assertThatThrownBy(() -> testee.createMailboxSession(request))
+            .isExactlyInstanceOf(NoValidAuthHeaderException.class);
+    }
+
+    @Test
     public void createMailboxSessionShouldThrowWhenMailboxExceptionHasOccurred() throws Exception {
         String username = "username";
         when(mockedMailboxManager.createSystemSession(eq(username), any(Logger.class)))
                 .thenThrow(new MailboxException());
 
         UUID authHeader = UUID.randomUUID();
-        when(mockedAccessTokenManager.getUsernameFromToken(AccessToken.fromString(authHeader.toString())))
+        AccessToken accessToken = AccessToken.fromString(authHeader.toString());
+        when(mockedAccessTokenManager.getUsernameFromToken(accessToken))
                 .thenReturn(username);
         when(mockAuthenticationExtractor.authHeaders(request))
             .thenReturn(Stream.of(authHeader.toString()));
-
+        when(mockedAccessTokenManager.isValid(accessToken))
+            .thenReturn(true);
 
         assertThatThrownBy(() -> testee.createMailboxSession(request))
                 .isExactlyInstanceOf(MailboxSessionCreationException.class);
@@ -105,63 +126,16 @@ public class AccessTokenAuthenticationStrategyTest {
                 .thenReturn(fakeMailboxSession);
 
         UUID authHeader = UUID.randomUUID();
-        when(mockedAccessTokenManager.getUsernameFromToken(AccessToken.fromString(authHeader.toString())))
+        AccessToken accessToken = AccessToken.fromString(authHeader.toString());
+        when(mockedAccessTokenManager.getUsernameFromToken(accessToken))
                 .thenReturn(username);
         when(mockAuthenticationExtractor.authHeaders(request))
             .thenReturn(Stream.of(authHeader.toString()));
+        when(mockedAccessTokenManager.isValid(accessToken))
+            .thenReturn(true);
 
 
         MailboxSession result = testee.createMailboxSession(request);
         assertThat(result).isEqualTo(fakeMailboxSession);
     }
-
-    @Test
-    public void checkAuthorizationHeaderShouldReturnFalseWhenAuthHeaderIsEmpty() {
-        when(mockAuthenticationExtractor.authHeaders(request))
-            .thenReturn(Stream.empty());
-
-        assertThat(testee.checkAuthorizationHeader(request)).isFalse();
-    }
-
-    @Test
-    public void checkAuthorizationHeaderShouldReturnFalseWhenAuthHeaderIsInvalid() {
-        when(mockAuthenticationExtractor.authHeaders(request))
-            .thenReturn(Stream.of("bad"));
-
-        assertThat(testee.checkAuthorizationHeader(request)).isFalse();
-    }
-
-    @Test
-    public void checkAuthorizationHeaderShouldReturnFalseWhenAuthHeadersAreInvalid() {
-        when(mockAuthenticationExtractor.authHeaders(request))
-            .thenReturn(Stream.of("bad", "alsobad"));
-
-        assertThat(testee.checkAuthorizationHeader(request)).isFalse();
-    }
-
-    @Test
-    public void checkAuthorizationHeaderShouldReturnTrueWhenAuthHeaderIsValid() {
-
-        String validToken = UUID.randomUUID().toString();
-        when(mockedAccessTokenManager.isValid(AccessToken.fromString(validToken)))
-                .thenReturn(true);
-        when(mockAuthenticationExtractor.authHeaders(request))
-            .thenReturn(Stream.of(validToken));
-
-
-        assertThat(testee.checkAuthorizationHeader(request)).isTrue();
-    }
-
-    @Test
-    public void checkAuthorizationHeaderShouldReturnTrueWhenOneAuthHeaderIsValid() {
-
-        String validToken = UUID.randomUUID().toString();
-        when(mockedAccessTokenManager.isValid(AccessToken.fromString(validToken)))
-                .thenReturn(true);
-        when(mockAuthenticationExtractor.authHeaders(request))
-            .thenReturn(Stream.of("bad", validToken));
-
-
-        assertThat(testee.checkAuthorizationHeader(request)).isTrue();
-    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/62627357/server/protocols/jmap/src/test/java/org/apache/james/jmap/AuthenticationFilterTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/AuthenticationFilterTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/AuthenticationFilterTest.java
index 837ff9f..8a189b7 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/AuthenticationFilterTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/AuthenticationFilterTest.java
@@ -34,6 +34,7 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.apache.james.jmap.api.access.AccessToken;
 import org.apache.james.jmap.api.access.AccessTokenRepository;
+import org.apache.james.jmap.exceptions.MailboxSessionCreationException;
 import org.apache.james.jmap.memory.access.MemoryAccessTokenRepository;
 import org.apache.james.mailbox.MailboxSession;
 import org.junit.Before;
@@ -99,6 +100,20 @@ public class AuthenticationFilterTest {
     }
 
     @Test
+    public void filterShouldChainAuthorizationStrategy() throws Exception {
+        AccessToken token = AccessToken.fromString(TOKEN);
+        when(mockedRequest.getHeader("Authorization"))
+            .thenReturn(TOKEN);
+
+        accessTokenRepository.addToken("user@domain.tld", token);
+
+        AuthenticationFilter sut = new AuthenticationFilter(ImmutableList.of(new FakeAuthenticationStrategy(false), new FakeAuthenticationStrategy(true)));
+        sut.doFilter(mockedRequest, mockedResponse, filterChain);
+
+        verify(filterChain).doFilter(any(ServletRequest.class), eq(mockedResponse));
+    }
+
+    @Test
     public void filterShouldReturnUnauthorizedOnBadAuthorizationHeader() throws Exception {
         when(mockedRequest.getHeader("Authorization"))
             .thenReturn("bad");
@@ -119,7 +134,7 @@ public class AuthenticationFilterTest {
         verify(mockedResponse).sendError(HttpServletResponse.SC_UNAUTHORIZED);
     }
 
-    private class FakeAuthenticationStrategy implements AuthenticationStrategy {
+    private static class FakeAuthenticationStrategy implements AuthenticationStrategy {
 
         private final boolean isAuthorized;
 
@@ -129,12 +144,10 @@ public class AuthenticationFilterTest {
 
         @Override
         public MailboxSession createMailboxSession(HttpServletRequest httpRequest) {
-            return null;
-        }
-
-        @Override
-        public boolean checkAuthorizationHeader(HttpServletRequest httpRequest) {
-            return isAuthorized;
+            if (!isAuthorized) {
+                throw new MailboxSessionCreationException(null);
+            }
+            return mock(MailboxSession.class);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/62627357/server/protocols/jmap/src/test/java/org/apache/james/jmap/JWTAuthenticationStrategyTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/JWTAuthenticationStrategyTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/JWTAuthenticationStrategyTest.java
index c96b7a8..4a60578 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/JWTAuthenticationStrategyTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/JWTAuthenticationStrategyTest.java
@@ -70,6 +70,25 @@ public class JWTAuthenticationStrategyTest {
     }
 
     @Test
+    public void createMailboxSessionShouldThrownWhenAuthHeadersIsInvalid() throws Exception {
+        String username = "123456789";
+        String validAuthHeader = "valid";
+        String fakeAuthHeaderWithPrefix = JWTAuthenticationStrategy.AUTHORIZATION_HEADER_PREFIX + validAuthHeader;
+        MailboxSession fakeMailboxSession = mock(MailboxSession.class);
+
+        when(stubTokenVerifier.verify(validAuthHeader)).thenReturn(false);
+        when(stubTokenVerifier.extractLogin(validAuthHeader)).thenReturn(username);
+        when(mockedMailboxManager.createSystemSession(eq(username), any(Logger.class)))
+                .thenReturn(fakeMailboxSession);
+        when(mockAuthenticationExtractor.authHeaders(request))
+            .thenReturn(Stream.of(fakeAuthHeaderWithPrefix));
+
+
+        assertThatThrownBy(() -> testee.createMailboxSession(request))
+            .isExactlyInstanceOf(NoValidAuthHeaderException.class);
+    }
+
+    @Test
     public void createMailboxSessionShouldReturnEmptyWhenAuthHeaderIsInvalid() throws Exception {
         when(mockAuthenticationExtractor.authHeaders(request))
             .thenReturn(Stream.of("bad"));
@@ -113,69 +132,4 @@ public class JWTAuthenticationStrategyTest {
         MailboxSession result = testee.createMailboxSession(request);
         assertThat(result).isEqualTo(fakeMailboxSession);
     }
-
-    @Test
-    public void checkAuthorizationHeaderShouldReturnFalsewWhenAuthHeaderIsEmpty() {
-        when(mockAuthenticationExtractor.authHeaders(request))
-            .thenReturn(Stream.empty());
-
-        assertThat(testee.checkAuthorizationHeader(request)).isFalse();
-    }
-
-    @Test
-    public void checkAuthorizationHeaderShouldReturnFalseWhenAuthHeaderIsInvalid() {
-        String wrongAuthHeader = "invalid";
-        String fakeAuthHeaderWithPrefix = JWTAuthenticationStrategy.AUTHORIZATION_HEADER_PREFIX + wrongAuthHeader;
-
-        when(stubTokenVerifier.verify(wrongAuthHeader)).thenReturn(false);
-        when(mockAuthenticationExtractor.authHeaders(request))
-            .thenReturn(Stream.of(fakeAuthHeaderWithPrefix));
-
-        assertThat(testee.checkAuthorizationHeader(request)).isFalse();
-    }
-
-    @Test
-    public void checkAuthorizationHeaderShouldReturnFalseWhenAuthHeadersAreInvalid() {
-        String wrongAuthHeader = "invalid";
-        String invalidAuthHeader = "INVALID";
-
-        when(stubTokenVerifier.verify(wrongAuthHeader)).thenReturn(false);
-        when(stubTokenVerifier.verify(invalidAuthHeader)).thenReturn(false);
-
-        Stream<String> authHeadersStream = Stream.of(wrongAuthHeader, invalidAuthHeader)
-                .map(h -> JWTAuthenticationStrategy.AUTHORIZATION_HEADER_PREFIX + h);
-        when(mockAuthenticationExtractor.authHeaders(request))
-            .thenReturn(authHeadersStream);
-
-        assertThat(testee.checkAuthorizationHeader(request)).isFalse();
-    }
-
-    @Test
-    public void checkAuthorizationHeaderShouldReturnTrueWhenAuthHeaderIsValid() {
-        String validAuthHeader = "valid";
-        String validAuthHeaderWithPrefix = JWTAuthenticationStrategy.AUTHORIZATION_HEADER_PREFIX + validAuthHeader;
-
-        when(stubTokenVerifier.verify(validAuthHeader)).thenReturn(true);
-        when(mockAuthenticationExtractor.authHeaders(request))
-            .thenReturn(Stream.of(validAuthHeaderWithPrefix));
-
-        assertThat(testee.checkAuthorizationHeader(request)).isTrue();
-    }
-
-    @Test
-    public void checkAuthorizationHeaderShouldReturnTrueWhenOneAuthHeaderIsValid() {
-        String dummyAuthHeader = "invalid";
-        String validAuthHeader = "correct";
-
-        when(stubTokenVerifier.verify(dummyAuthHeader)).thenReturn(false);
-        when(stubTokenVerifier.verify(validAuthHeader)).thenReturn(true);
-
-        Stream<String> authHeadersStream = Stream.of(dummyAuthHeader, validAuthHeader)
-                .map(h -> JWTAuthenticationStrategy.AUTHORIZATION_HEADER_PREFIX + h);
-        when(mockAuthenticationExtractor.authHeaders(request))
-            .thenReturn(authHeadersStream);
-
-        assertThat(testee.checkAuthorizationHeader(request)).isTrue();
-    }
-
 }
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org