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]