Author: matthieu
Date: Fri Dec 11 10:08:01 2015
New Revision: 1719320

URL: http://svn.apache.org/viewvc?rev=1719320&view=rev
Log:
JAMES-1644 revoking access token on DELETE

Modified:
    
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationServlet.java
    
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/api/AccessTokenManager.java
    
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/AccessTokenManagerImpl.java
    
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPAuthenticationTest.java
    
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/AccessTokenManagerImplTest.java

Modified: 
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationServlet.java
URL: 
http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationServlet.java?rev=1719320&r1=1719319&r2=1719320&view=diff
==============================================================================
--- 
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationServlet.java
 (original)
+++ 
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/AuthenticationServlet.java
 Fri Dec 11 10:08:01 2015
@@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRes
 
 import org.apache.james.jmap.api.AccessTokenManager;
 import org.apache.james.jmap.api.ContinuationTokenManager;
+import org.apache.james.jmap.api.access.AccessToken;
 import org.apache.james.jmap.exceptions.BadRequestException;
 import org.apache.james.jmap.exceptions.InternalErrorException;
 import org.apache.james.jmap.json.MultipleObjectMapperBuilder;
@@ -93,6 +94,12 @@ public class AuthenticationServlet exten
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
throws ServletException, IOException {
         returnEndPointsResponse(resp);
     }
+    
+    @Override
+    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) 
throws ServletException, IOException {
+        
accessTokenManager.revoke(AccessToken.fromString(req.getHeader("Authorization")));
+        resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
+    }
 
     private Object deserialize(HttpServletRequest req) throws 
BadRequestException {
         Object request;

Modified: 
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/api/AccessTokenManager.java
URL: 
http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/api/AccessTokenManager.java?rev=1719320&r1=1719319&r2=1719320&view=diff
==============================================================================
--- 
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/api/AccessTokenManager.java
 (original)
+++ 
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/api/AccessTokenManager.java
 Fri Dec 11 10:08:01 2015
@@ -29,5 +29,7 @@ public interface AccessTokenManager {
     String getUsernameFromToken(AccessToken token) throws InvalidAccessToken;
     
     boolean isValid(AccessToken token);
+    
+    void revoke(AccessToken token);
 
 }

Modified: 
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/AccessTokenManagerImpl.java
URL: 
http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/AccessTokenManagerImpl.java?rev=1719320&r1=1719319&r2=1719320&view=diff
==============================================================================
--- 
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/AccessTokenManagerImpl.java
 (original)
+++ 
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/AccessTokenManagerImpl.java
 Fri Dec 11 10:08:01 2015
@@ -57,4 +57,9 @@ public class AccessTokenManagerImpl impl
         }
     }
 
+    @Override
+    public void revoke(AccessToken token) {
+        accessTokenRepository.removeToken(token);
+    }
+
 }

Modified: 
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPAuthenticationTest.java
URL: 
http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPAuthenticationTest.java?rev=1719320&r1=1719319&r2=1719320&view=diff
==============================================================================
--- 
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPAuthenticationTest.java
 (original)
+++ 
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPAuthenticationTest.java
 Fri Dec 11 10:08:01 2015
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.james.jmap;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static com.jayway.restassured.RestAssured.given;
 import static com.jayway.restassured.RestAssured.with;
 import static com.jayway.restassured.config.EncoderConfig.encoderConfig;
@@ -30,6 +31,7 @@ import static org.mockito.Mockito.when;
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.UUID;
+import java.util.concurrent.TimeUnit;
 
 import javax.servlet.Filter;
 
@@ -70,10 +72,12 @@ public class JMAPAuthenticationTest {
     public void setup() throws Exception {
         mockedUsersRepository = mock(UsersRepository.class);
         mockedZonedDateTimeProvider = mock(ZonedDateTimeProvider.class);
-        accessTokenManager = new AccessTokenManagerImpl(new 
MemoryAccessTokenRepository(100));
+        accessTokenManager = new AccessTokenManagerImpl(new 
MemoryAccessTokenRepository(TimeUnit.MILLISECONDS.convert(1, TimeUnit.HOURS)));
         continuationTokenManager = new SignedContinuationTokenManager(new 
JamesSignatureHandlerProvider().provide(), mockedZonedDateTimeProvider);
         
         AuthenticationServlet authenticationServlet = new 
AuthenticationServlet(mockedUsersRepository, continuationTokenManager, 
accessTokenManager);
+
+
         AuthenticationFilter authenticationFilter = new 
AuthenticationFilter(accessTokenManager);
         Filter getAuthenticationFilter = new 
BypassOnPostFilter(authenticationFilter);
         
@@ -367,13 +371,7 @@ public class JMAPAuthenticationTest {
         when(mockedZonedDateTimeProvider.provide())
             .thenReturn(newDate);
     
-        String accessToken = with()
-            .contentType(ContentType.JSON)
-            .accept(ContentType.JSON)
-            .body("{\"token\": \"" + continuationToken + "\", \"method\": 
\"password\", \"password\": \"password\"}")
-        .post("/authentication")
-            .path("accessToken")
-            .toString();
+        String accessToken = fromGoodAccessTokenRequest(continuationToken);
     
         given()
             .header("Authorization", accessToken)
@@ -383,6 +381,69 @@ public class JMAPAuthenticationTest {
             .statusCode(200)
             .body("api", isA(String.class));
     }
+    
+    @Test
+    public void deleteMustReturnUnauthenticatedWithoutAuthorizationHeader() 
throws Exception {
+        given()
+        .when()
+            .delete("/authentication")
+        .then()
+            .statusCode(401);
+    }
+
+    @Test
+    public void 
deleteMustReturnUnauthenticatedWithoutAValidAuthroizationHeader() throws 
Exception {
+        given()
+            .header("Authorization", UUID.randomUUID())
+        .when()
+            .delete("/authentication")
+        .then()
+            .statusCode(401);
+    }
+    
+    @Test
+    public void deleteMustReturnOKNoContentOnValidAuthorizationToken() throws 
Exception {
+        AccessToken token = accessTokenManager.grantAccessToken("username");
+        given()
+            .header("Authorization", token.serialize())
+        .when()
+            .delete("/authentication")
+        .then()
+            .statusCode(204);
+    }
+
+    @Test
+    public void deleteMustInvalidTokenOnValidAuthorizationToken() throws 
Exception {
+        AccessToken token = accessTokenManager.grantAccessToken("username");
+        with()
+            .header("Authorization", token.serialize())
+            .delete("/authentication");
+        assertThat(accessTokenManager.isValid(token)).isFalse();
+    }
+
+    @Test
+    public void deleteMustInvalidAuthorizationOnCorrectAuthorization() throws 
Exception {
+        when(mockedZonedDateTimeProvider.provide())
+            .thenReturn(oldDate);
+
+        String continuationToken = fromGoodContinuationTokenRequest();
+    
+        when(mockedUsersRepository.test("[email protected]", "password"))
+            .thenReturn(true);
+        when(mockedZonedDateTimeProvider.provide())
+            .thenReturn(newDate);
+    
+        String accessToken = fromGoodAccessTokenRequest(continuationToken);
+        
+        goodDeleteAccessTokenRequest(accessToken);
+    
+        given()
+            .header("Authorization", accessToken)
+        .when()
+            .get("/authentication")
+        .then()
+            .statusCode(401);
+    }
 
     private String fromGoodContinuationTokenRequest() {
         return with()
@@ -395,4 +456,19 @@ public class JMAPAuthenticationTest {
             .toString();
     }
 
+    private String fromGoodAccessTokenRequest(String continuationToken) {
+        return with()
+            .contentType(ContentType.JSON)
+            .accept(ContentType.JSON)
+            .body("{\"token\": \"" + continuationToken + "\", \"method\": 
\"password\", \"password\": \"password\"}")
+        .post("/authentication")
+            .path("accessToken")
+            .toString();
+    }
+
+    private void goodDeleteAccessTokenRequest(String accessToken) {
+        with()
+            .header("Authorization", accessToken)
+            .delete("/authentication");
+    }
 }

Modified: 
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/AccessTokenManagerImplTest.java
URL: 
http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/AccessTokenManagerImplTest.java?rev=1719320&r1=1719319&r2=1719320&view=diff
==============================================================================
--- 
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/AccessTokenManagerImplTest.java
 (original)
+++ 
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/AccessTokenManagerImplTest.java
 Fri Dec 11 10:08:01 2015
@@ -98,4 +98,28 @@ public class AccessTokenManagerImplTest
         AccessToken accessToken = 
accessTokenManager.grantAccessToken("username");
         assertThat(accessTokenManager.isValid(accessToken)).isTrue();
     }
+    
+    @Test(expected=NullPointerException.class)
+    public void revokeShouldThrowWhenNullToken() throws Exception {
+        accessTokenManager.revoke(null);
+    }
+    
+    @Test
+    public void revokeShouldNoopOnUnknownToken() throws Exception {
+        accessTokenManager.revoke(AccessToken.generate());
+    }
+    
+    @Test
+    public void revokeShouldNoopOnRevokingTwice() throws Exception {
+        AccessToken token = AccessToken.generate();
+        accessTokenManager.revoke(token);
+        accessTokenManager.revoke(token);
+    }
+    
+    @Test
+    public void revokeShouldInvalidExistingToken() throws Exception {
+        AccessToken token = accessTokenManager.grantAccessToken("username");
+        accessTokenManager.revoke(token);
+        assertThat(accessTokenManager.isValid(token)).isFalse();
+    }
 }



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

Reply via email to