Author: matthieu
Date: Fri Dec 11 10:07:38 2015
New Revision: 1719318
URL: http://svn.apache.org/viewvc?rev=1719318&view=rev
Log:
JAMES-1644 use AccessTokenRepository
Added:
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/exceptions/InvalidAccessToken.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/crypto/AccessTokenManagerImplTest.java
Modified:
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/AccessToken.java
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/AccessTokenRepository.java
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/exceptions/AccessTokenAlreadyStored.java
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/access/MemoryAccessTokenRepository.java
james/project/trunk/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/access/MemoryAccessTokenRepositoryTest.java
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/model/AccessTokenResponse.java
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPAuthenticationTest.java
Modified:
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/AccessToken.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/AccessToken.java?rev=1719318&r1=1719317&r2=1719318&view=diff
==============================================================================
---
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/AccessToken.java
(original)
+++
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/AccessToken.java
Fri Dec 11 10:07:38 2015
@@ -20,21 +20,26 @@
package org.apache.james.jmap.api.access;
import java.util.Objects;
+import java.util.UUID;
public class AccessToken {
public static AccessToken fromString(String tokenString) {
- return new AccessToken(tokenString);
+ return new AccessToken(UUID.fromString(tokenString));
}
- private final String token;
+ private final UUID token;
- private AccessToken(String token) {
+ private AccessToken(UUID token) {
this.token = token;
}
+
+ public static AccessToken generate() {
+ return new AccessToken(UUID.randomUUID());
+ }
public String serialize() {
- return token;
+ return token.toString();
}
@Override
Modified:
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/AccessTokenRepository.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/AccessTokenRepository.java?rev=1719318&r1=1719317&r2=1719318&view=diff
==============================================================================
---
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/AccessTokenRepository.java
(original)
+++
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/AccessTokenRepository.java
Fri Dec 11 10:07:38 2015
@@ -20,13 +20,14 @@
package org.apache.james.jmap.api.access;
import org.apache.james.jmap.api.access.exceptions.AccessTokenAlreadyStored;
+import org.apache.james.jmap.api.access.exceptions.InvalidAccessToken;
public interface AccessTokenRepository {
- void addToken(AccessToken accessToken) throws AccessTokenAlreadyStored;
+ void addToken(String username, AccessToken accessToken) throws
AccessTokenAlreadyStored;
void removeToken(AccessToken accessToken);
- boolean verifyToken(AccessToken accessToken);
+ String getUsernameFromToken(AccessToken accessToken) throws
InvalidAccessToken;
}
Modified:
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/exceptions/AccessTokenAlreadyStored.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/exceptions/AccessTokenAlreadyStored.java?rev=1719318&r1=1719317&r2=1719318&view=diff
==============================================================================
---
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/exceptions/AccessTokenAlreadyStored.java
(original)
+++
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/exceptions/AccessTokenAlreadyStored.java
Fri Dec 11 10:07:38 2015
@@ -21,7 +21,7 @@ package org.apache.james.jmap.api.access
import org.apache.james.jmap.api.access.AccessToken;
-public class AccessTokenAlreadyStored extends Exception {
+public class AccessTokenAlreadyStored extends RuntimeException {
public AccessTokenAlreadyStored(AccessToken token) {
super(token.serialize() + " is already stored");
Added:
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/exceptions/InvalidAccessToken.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/exceptions/InvalidAccessToken.java?rev=1719318&view=auto
==============================================================================
---
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/exceptions/InvalidAccessToken.java
(added)
+++
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/access/exceptions/InvalidAccessToken.java
Fri Dec 11 10:07:38 2015
@@ -0,0 +1,29 @@
+/****************************************************************
+ * 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.api.access.exceptions;
+
+import org.apache.james.jmap.api.access.AccessToken;
+
+public class InvalidAccessToken extends RuntimeException {
+
+ public InvalidAccessToken(AccessToken token) {
+ super(token.serialize() + " is missing");
+ }
+}
Modified:
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/access/MemoryAccessTokenRepository.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/access/MemoryAccessTokenRepository.java?rev=1719318&r1=1719317&r2=1719318&view=diff
==============================================================================
---
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/access/MemoryAccessTokenRepository.java
(original)
+++
james/project/trunk/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/access/MemoryAccessTokenRepository.java
Fri Dec 11 10:07:38 2015
@@ -19,19 +19,23 @@
package org.apache.james.jmap.memory.access;
-import com.google.common.base.Preconditions;
+import java.util.Optional;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
import org.apache.commons.collections4.map.PassiveExpiringMap;
import org.apache.james.jmap.api.access.AccessToken;
import org.apache.james.jmap.api.access.AccessTokenRepository;
import org.apache.james.jmap.api.access.exceptions.AccessTokenAlreadyStored;
+import org.apache.james.jmap.api.access.exceptions.InvalidAccessToken;
-import javax.inject.Inject;
-import javax.inject.Singleton;
+import com.google.common.base.Preconditions;
@Singleton
public class MemoryAccessTokenRepository implements AccessTokenRepository {
- private final PassiveExpiringMap<AccessToken, Boolean>
tokensExpirationDates;
+ private final PassiveExpiringMap<AccessToken, String>
tokensExpirationDates;
@Inject
public MemoryAccessTokenRepository(long durationInMilliseconds) {
@@ -39,10 +43,12 @@ public class MemoryAccessTokenRepository
}
@Override
- public void addToken(AccessToken accessToken) throws
AccessTokenAlreadyStored{
+ public void addToken(String username, AccessToken accessToken) throws
AccessTokenAlreadyStored{
+ Preconditions.checkNotNull(username);
+ Preconditions.checkArgument(! username.isEmpty(), "Username should not
be empty");
Preconditions.checkNotNull(accessToken);
synchronized (tokensExpirationDates) {
- if (tokensExpirationDates.putIfAbsent(accessToken, true) != null) {
+ if (tokensExpirationDates.putIfAbsent(accessToken, username) !=
null) {
throw new AccessTokenAlreadyStored(accessToken);
}
}
@@ -57,10 +63,12 @@ public class MemoryAccessTokenRepository
}
@Override
- public boolean verifyToken(AccessToken accessToken) {
+ public String getUsernameFromToken(AccessToken accessToken) throws
InvalidAccessToken {
Preconditions.checkNotNull(accessToken);
synchronized (tokensExpirationDates) {
- return tokensExpirationDates.containsKey(accessToken);
+ return Optional
+ .ofNullable(tokensExpirationDates.get(accessToken))
+ .orElseThrow(() -> new InvalidAccessToken(accessToken));
}
}
Modified:
james/project/trunk/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/access/MemoryAccessTokenRepositoryTest.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/access/MemoryAccessTokenRepositoryTest.java?rev=1719318&r1=1719317&r2=1719318&view=diff
==============================================================================
---
james/project/trunk/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/access/MemoryAccessTokenRepositoryTest.java
(original)
+++
james/project/trunk/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/access/MemoryAccessTokenRepositoryTest.java
Fri Dec 11 10:07:38 2015
@@ -24,12 +24,14 @@ import static org.assertj.core.api.Asser
import org.apache.james.jmap.api.access.AccessToken;
import org.apache.james.jmap.api.access.exceptions.AccessTokenAlreadyStored;
+import org.apache.james.jmap.api.access.exceptions.InvalidAccessToken;
import org.junit.Before;
import org.junit.Test;
public class MemoryAccessTokenRepositoryTest {
- private static final AccessToken TOKEN = AccessToken.fromString("TOKEN");
+ private static final AccessToken TOKEN = AccessToken.generate();
+ private static final String USERNAME = "username";
private static final int TTL_IN_MS = 100;
private MemoryAccessTokenRepository accessTokenRepository;
@@ -41,42 +43,52 @@ public class MemoryAccessTokenRepository
@Test
public void validTokenMustWork() throws Exception {
- accessTokenRepository.addToken(TOKEN);
- assertThat(accessTokenRepository.verifyToken(TOKEN)).isTrue();
+ accessTokenRepository.addToken(USERNAME, TOKEN);
+
assertThat(accessTokenRepository.getUsernameFromToken(TOKEN)).isEqualTo(USERNAME);
}
- @Test
+ @Test(expected=InvalidAccessToken.class)
public void nonStoredTokensMustBeInvalid() throws Exception {
- assertThat(accessTokenRepository.verifyToken(TOKEN)).isFalse();
+ accessTokenRepository.getUsernameFromToken(TOKEN);
}
- @Test
+ @Test(expected=InvalidAccessToken.class)
public void removedTokensMustBeInvalid() throws Exception {
- accessTokenRepository.addToken(TOKEN);
+ accessTokenRepository.addToken(USERNAME, TOKEN);
accessTokenRepository.removeToken(TOKEN);
- assertThat(accessTokenRepository.verifyToken(TOKEN)).isFalse();
+ accessTokenRepository.getUsernameFromToken(TOKEN);
}
@Test(expected = AccessTokenAlreadyStored.class)
public void addTokenMustThrowWhenTokenIsAlreadyStored() throws Exception {
try {
- accessTokenRepository.addToken(TOKEN);
+ accessTokenRepository.addToken(USERNAME, TOKEN);
} catch(Exception e) {
fail("Exception caught", e);
}
- accessTokenRepository.addToken(TOKEN);
+ accessTokenRepository.addToken(USERNAME, TOKEN);
}
- @Test
+ @Test(expected=InvalidAccessToken.class)
public void outDatedTokenMustBeInvalid() throws Exception {
- accessTokenRepository.addToken(TOKEN);
+ accessTokenRepository.addToken(USERNAME, TOKEN);
Thread.sleep(200);
- assertThat(accessTokenRepository.verifyToken(TOKEN)).isFalse();
+ accessTokenRepository.getUsernameFromToken(TOKEN);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void addTokenMustThrowWhenUsernameIsNull() throws Exception {
+ accessTokenRepository.addToken(null, TOKEN);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void addTokenMustThrowWhenUsernameIsEmpty() throws Exception {
+ accessTokenRepository.addToken("", TOKEN);
}
@Test(expected = NullPointerException.class)
public void addTokenMustThrowWhenTokenIsNull() throws Exception {
- accessTokenRepository.addToken(null);
+ accessTokenRepository.addToken(USERNAME, null);
}
@Test(expected = NullPointerException.class)
@@ -85,8 +97,8 @@ public class MemoryAccessTokenRepository
}
@Test(expected = NullPointerException.class)
- public void verifyTokenTokenMustThrowWhenTokenIsNull() throws Exception {
- accessTokenRepository.verifyToken(null);
+ public void getUsernameFromTokenMustThrowWhenTokenIsNull() throws
Exception {
+ accessTokenRepository.getUsernameFromToken(null);
}
}
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=1719318&r1=1719317&r2=1719318&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:07:38 2015
@@ -26,6 +26,7 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.james.jmap.api.AccessTokenManager;
import org.apache.james.jmap.api.ContinuationTokenManager;
import org.apache.james.jmap.exceptions.BadRequestException;
import org.apache.james.jmap.exceptions.InternalErrorException;
@@ -52,18 +53,19 @@ public class AuthenticationServlet exten
private final ObjectMapper mapper;
private final UsersRepository usersRepository;
private final ContinuationTokenManager continuationTokenManager;
-
+ private final AccessTokenManager accessTokenManager;
+
@Inject
- @VisibleForTesting AuthenticationServlet(UsersRepository usersRepository,
ContinuationTokenManager continuationTokenManager) {
+ @VisibleForTesting AuthenticationServlet(UsersRepository usersRepository,
ContinuationTokenManager continuationTokenManager, AccessTokenManager
accessTokenManager) {
this.usersRepository = usersRepository;
this.continuationTokenManager = continuationTokenManager;
+ this.accessTokenManager = accessTokenManager;
this.mapper = new MultipleObjectMapperBuilder()
.registerClass(ContinuationTokenRequest.UNIQUE_JSON_PATH,
ContinuationTokenRequest.class)
.registerClass(AccessTokenRequest.UNIQUE_JSON_PATH,
AccessTokenRequest.class)
.build();
}
-
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
try {
@@ -119,7 +121,7 @@ public class AuthenticationServlet exten
.build();
mapper.writeValue(resp.getOutputStream(),
continuationTokenResponse);
} catch (Exception e) {
- throw new InternalErrorException("Error while responding to
continuation token");
+ throw new InternalErrorException("Error while responding to
continuation token", e);
}
}
@@ -139,7 +141,7 @@ public class AuthenticationServlet exten
private void manageAuthenticationResponse(AccessTokenRequest request,
HttpServletResponse resp) throws IOException {
String username = request.getToken().getUsername();
if (authenticate(request, username)) {
- returnAccessTokenResponse(resp);
+ returnAccessTokenResponse(resp, username);
} else {
LOG.info("Authentication failure for " + username);
returnUnauthorizedResponse(resp);
@@ -156,15 +158,14 @@ public class AuthenticationServlet exten
return authenticated;
}
- private void returnAccessTokenResponse(HttpServletResponse resp) throws
IOException {
+ private void returnAccessTokenResponse(HttpServletResponse resp, String
username) throws IOException {
resp.setContentType(JSON_CONTENT_TYPE_UTF8);
resp.setStatus(HttpServletResponse.SC_CREATED);
AccessTokenResponse response = AccessTokenResponse
- .builder()
- // TODO Answer a real token
- .accessToken("token")
- // TODO Send API endpoints
- .build();
+ .builder()
+ .accessToken(accessTokenManager.grantAccessToken(username))
+ // TODO Send API endpoints
+ .build();
mapper.writeValue(resp.getOutputStream(), response);
}
Added:
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=1719318&view=auto
==============================================================================
---
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/api/AccessTokenManager.java
(added)
+++
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/api/AccessTokenManager.java
Fri Dec 11 10:07:38 2015
@@ -0,0 +1,31 @@
+/****************************************************************
+ * 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.api;
+
+import org.apache.james.jmap.api.access.AccessToken;
+import org.apache.james.jmap.api.access.exceptions.InvalidAccessToken;
+
+public interface AccessTokenManager {
+
+ AccessToken grantAccessToken(String username);
+
+ String getUsernameFromToken(AccessToken token) throws InvalidAccessToken;
+
+}
Added:
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=1719318&view=auto
==============================================================================
---
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/AccessTokenManagerImpl.java
(added)
+++
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/AccessTokenManagerImpl.java
Fri Dec 11 10:07:38 2015
@@ -0,0 +1,50 @@
+/****************************************************************
+ * 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.crypto;
+
+import org.apache.james.jmap.api.AccessTokenManager;
+import org.apache.james.jmap.api.access.AccessToken;
+import org.apache.james.jmap.api.access.AccessTokenRepository;
+import org.apache.james.jmap.api.access.exceptions.InvalidAccessToken;
+
+import com.google.common.base.Preconditions;
+
+public class AccessTokenManagerImpl implements AccessTokenManager {
+
+ private final AccessTokenRepository accessTokenRepository;
+
+ public AccessTokenManagerImpl(AccessTokenRepository accessTokenRepository)
{
+ this.accessTokenRepository = accessTokenRepository;
+ }
+
+ @Override
+ public AccessToken grantAccessToken(String username) {
+ Preconditions.checkNotNull(username);
+ AccessToken accessToken = AccessToken.generate();
+ accessTokenRepository.addToken(username, accessToken);
+ return accessToken;
+ }
+
+ @Override
+ public String getUsernameFromToken(AccessToken token) throws
InvalidAccessToken {
+ return accessTokenRepository.getUsernameFromToken(token);
+ }
+
+}
Modified:
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AccessTokenResponse.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AccessTokenResponse.java?rev=1719318&r1=1719317&r2=1719318&view=diff
==============================================================================
---
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AccessTokenResponse.java
(original)
+++
james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/model/AccessTokenResponse.java
Fri Dec 11 10:07:38 2015
@@ -18,6 +18,8 @@
****************************************************************/
package org.apache.james.jmap.model;
+import org.apache.james.jmap.api.access.AccessToken;
+
public class AccessTokenResponse {
public static Builder builder() {
@@ -25,7 +27,7 @@ public class AccessTokenResponse {
}
public static class Builder {
- private String accessToken;
+ private AccessToken accessToken;
private String api;
private String eventSource;
private String upload;
@@ -33,7 +35,7 @@ public class AccessTokenResponse {
private Builder() {}
- public Builder accessToken(String accessToken) {
+ public Builder accessToken(AccessToken accessToken) {
this.accessToken = accessToken;
return this;
}
@@ -63,13 +65,13 @@ public class AccessTokenResponse {
}
}
- private final String accessToken;
+ private final AccessToken accessToken;
private final String api;
private final String eventSource;
private final String upload;
private final String download;
- private AccessTokenResponse(String accessToken, String api, String
eventSource, String upload, String download) {
+ private AccessTokenResponse(AccessToken accessToken, String api, String
eventSource, String upload, String download) {
this.accessToken = accessToken;
this.api = api;
this.eventSource = eventSource;
@@ -78,7 +80,7 @@ public class AccessTokenResponse {
}
public String getAccessToken() {
- return accessToken;
+ return accessToken.serialize();
}
public String getApi() {
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=1719318&r1=1719317&r2=1719318&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:07:38 2015
@@ -22,18 +22,22 @@ import static com.jayway.restassured.Res
import static com.jayway.restassured.RestAssured.with;
import static com.jayway.restassured.config.EncoderConfig.encoderConfig;
import static com.jayway.restassured.config.RestAssuredConfig.newConfig;
-import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.isA;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+
import org.apache.james.http.jetty.Configuration;
import org.apache.james.http.jetty.JettyHttpServer;
+import org.apache.james.jmap.api.AccessTokenManager;
import org.apache.james.jmap.api.ContinuationTokenManager;
-import org.apache.james.jmap.model.ContinuationToken;
+import org.apache.james.jmap.crypto.AccessTokenManagerImpl;
+import org.apache.james.jmap.crypto.JamesSignatureHandlerProvider;
+import org.apache.james.jmap.crypto.SignedContinuationTokenManager;
+import org.apache.james.jmap.memory.access.MemoryAccessTokenRepository;
import org.apache.james.jmap.utils.ZonedDateTimeProvider;
import org.apache.james.user.api.UsersRepository;
import org.apache.james.user.api.UsersRepositoryException;
@@ -45,26 +49,27 @@ import com.google.common.base.Charsets;
import com.jayway.restassured.RestAssured;
import com.jayway.restassured.http.ContentType;
-import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
-
public class JMAPAuthenticationTest {
-
- private static final ZonedDateTime oldDate =
ZonedDateTime.parse("2011-12-03T10:15:30+01:00",
DateTimeFormatter.ISO_OFFSET_DATE_TIME);
- private static final ZonedDateTime newDate =
ZonedDateTime.parse("2011-12-03T10:16:30+01:00",
DateTimeFormatter.ISO_OFFSET_DATE_TIME);
-
+
+ private static final ZonedDateTime oldDate =
ZonedDateTime.parse("2011-12-03T10:15:30+01:00",
DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+ private static final ZonedDateTime newDate =
ZonedDateTime.parse("2011-12-03T10:16:30+01:00",
DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+ private static final ZonedDateTime afterExpirationDate =
ZonedDateTime.parse("2011-12-03T10:30:31+01:00",
DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+
private JettyHttpServer server;
+
private UsersRepository mockedUsersRepository;
- private ContinuationTokenManager mockedContinuationTokenManager;
+ private ContinuationTokenManager continuationTokenManager;
private ZonedDateTimeProvider mockedZonedDateTimeProvider;
-
+ private AccessTokenManager accessTokenManager;
+
@Before
public void setup() throws Exception {
mockedUsersRepository = mock(UsersRepository.class);
- mockedContinuationTokenManager = mock(ContinuationTokenManager.class);
mockedZonedDateTimeProvider = mock(ZonedDateTimeProvider.class);
+ accessTokenManager = new AccessTokenManagerImpl(new
MemoryAccessTokenRepository(100));
+ continuationTokenManager = new SignedContinuationTokenManager(new
JamesSignatureHandlerProvider().provide(), mockedZonedDateTimeProvider);
- AuthenticationServlet authenticationServlet = new
AuthenticationServlet(mockedUsersRepository, mockedContinuationTokenManager);
+ AuthenticationServlet authenticationServlet = new
AuthenticationServlet(mockedUsersRepository, continuationTokenManager,
accessTokenManager);
server = JettyHttpServer.create(
Configuration.builder()
@@ -82,17 +87,7 @@ public class JMAPAuthenticationTest {
public void teardown() throws Exception {
server.stop();
}
-
- @Test
- public void shouldReturnMalformedRequestWhenXMLContentType() {
- given()
- .contentType(ContentType.XML)
- .when()
- .post("/authentication")
- .then()
- .statusCode(400);
- }
-
+
@Test
public void mustReturnMalformedRequestWhenContentTypeIsMissing() {
given()
@@ -158,41 +153,37 @@ public class JMAPAuthenticationTest {
}
@Test
- public void mustReturnJsonResponse() throws Exception {
-
when(mockedContinuationTokenManager.generateToken(eq("[email protected]")))
- .thenAnswer(invocationOnMock -> new
ContinuationToken("[email protected]", newDate, "signature"));
-
when(mockedContinuationTokenManager.isValid(any())).thenAnswer(invocationOnMock
-> true);
-
+ public void mustReturnMalformedRequestWhenBodyIsNotAcceptable() {
given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
- .body("{\"username\": \"[email protected]\", \"clientName\":
\"Mozilla Thunderbird\", \"clientVersion\": \"42.0\", \"deviceName\": \"Joe
Bloggâs iPhone\"}")
+ .body("{\"badAttributeName\": \"value\"}")
.when()
.post("/authentication")
.then()
- .statusCode(200)
- .contentType(ContentType.JSON);
+ .statusCode(400);
}
-
-
@Test
- public void mustReturnMalformedRequestWhenBodyIsNotAcceptable() {
+ public void mustReturnJsonResponse() throws Exception {
+ when(mockedZonedDateTimeProvider.provide())
+ .thenReturn(oldDate);
+
given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
- .body("{\"badAttributeName\": \"value\"}")
+ .body("{\"username\": \"[email protected]\", \"clientName\":
\"Mozilla Thunderbird\", \"clientVersion\": \"42.0\", \"deviceName\": \"Joe
Bloggâs iPhone\"}")
.when()
.post("/authentication")
.then()
- .statusCode(400);
+ .statusCode(200)
+ .contentType(ContentType.JSON);
}
@Test
public void methodShouldContainPasswordWhenValidResquest() throws
Exception {
-
when(mockedZonedDateTimeProvider.provide()).thenAnswer(invocationOnMock ->
oldDate);
-
when(mockedContinuationTokenManager.generateToken(eq("[email protected]")))
- .thenAnswer(invocationOnMock -> new
ContinuationToken("[email protected]", newDate, "signature"));
+ when(mockedZonedDateTimeProvider.provide())
+ .thenReturn(oldDate);
given()
.contentType(ContentType.JSON)
@@ -207,9 +198,8 @@ public class JMAPAuthenticationTest {
@Test
public void mustReturnContinuationTokenWhenValidResquest() throws
Exception {
-
when(mockedZonedDateTimeProvider.provide()).thenAnswer(invocationOnMock ->
oldDate);
-
when(mockedContinuationTokenManager.generateToken(eq("[email protected]")))
- .thenAnswer(invocationOnMock -> new
ContinuationToken("[email protected]", newDate, "signature"));
+ when(mockedZonedDateTimeProvider.provide())
+ .thenReturn(oldDate);
given()
.contentType(ContentType.JSON)
@@ -224,25 +214,53 @@ public class JMAPAuthenticationTest {
@Test
public void mustReturnAuthenticationFailedWhenBadPassword() throws
Exception {
-
when(mockedZonedDateTimeProvider.provide()).thenAnswer(invocationOnMock ->
oldDate);
-
when(mockedContinuationTokenManager.generateToken(eq("[email protected]")))
- .thenAnswer(invocationOnMock -> new
ContinuationToken("[email protected]", newDate, "signature"));
-
when(mockedContinuationTokenManager.isValid(any())).thenAnswer(invocationOnMock
-> true);
+ when(mockedZonedDateTimeProvider.provide())
+ .thenReturn(oldDate);
String continuationToken =
- with()
+ with()
+ .contentType(ContentType.JSON)
+ .accept(ContentType.JSON)
+ .body("{\"username\": \"[email protected]\", \"clientName\":
\"Mozilla Thunderbird\", \"clientVersion\": \"42.0\", \"deviceName\": \"Joe
Bloggâs iPhone\"}")
+ .post("/authentication")
+ .body()
+ .path("continuationToken")
+ .toString();
+
+ given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
- .body("{\"username\": \"[email protected]\", \"clientName\":
\"Mozilla Thunderbird\", \"clientVersion\": \"42.0\", \"deviceName\": \"Joe
Bloggâs iPhone\"}")
- .post("/authentication")
- .body()
- .path("continuationToken")
- .toString();
+ .body("{\"token\": \"" + continuationToken + "\", \"method\":
\"password\", \"password\": \"badpassword\"}")
+ .when()
+ .post("/authentication")
+ .then()
+ .statusCode(401);
+ }
+
+ @Test
+ public void
mustReturnAuthenticationFailedWhenContinuationTokenIsRejectedByTheContinuationTokenManager()
throws Exception {
+ when(mockedZonedDateTimeProvider.provide())
+ .thenReturn(oldDate);
+
+ String continuationToken =
+ with()
+ .contentType(ContentType.JSON)
+ .accept(ContentType.JSON)
+ .body("{\"username\": \"[email protected]\", \"clientName\":
\"Mozilla Thunderbird\", \"clientVersion\": \"42.0\", \"deviceName\": \"Joe
Bloggâs iPhone\"}")
+ .post("/authentication")
+ .body()
+ .path("continuationToken")
+ .toString();
+ when(mockedUsersRepository.test("[email protected]", "password"))
+ .thenReturn(true);
+ when(mockedZonedDateTimeProvider.provide())
+ .thenReturn(afterExpirationDate);
+
given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
- .body("{\"token\": \"" + continuationToken + "\", \"method\":
\"password\", \"password\": \"badpassword\"}")
+ .body("{\"token\": \"" + continuationToken + "\", \"method\":
\"password\", \"password\": \"password\"}")
.when()
.post("/authentication")
.then()
@@ -251,24 +269,22 @@ public class JMAPAuthenticationTest {
@Test
public void mustReturnAuthenticationFailedWhenUsersRepositoryException()
throws Exception {
-
when(mockedZonedDateTimeProvider.provide()).thenAnswer(invocationOnMock ->
oldDate);
-
when(mockedContinuationTokenManager.generateToken(eq("[email protected]")))
- .thenAnswer(invocationOnMock -> new
ContinuationToken("[email protected]", newDate, "signature"));
-
when(mockedContinuationTokenManager.isValid(any())).thenAnswer(invocationOnMock
-> true);
+ when(mockedZonedDateTimeProvider.provide())
+ .thenReturn(oldDate);
String continuationToken =
- with()
- .contentType(ContentType.JSON)
- .accept(ContentType.JSON)
- .body("{\"username\": \"[email protected]\", \"clientName\":
\"Mozilla Thunderbird\", \"clientVersion\": \"42.0\", \"deviceName\": \"Joe
Bloggâs iPhone\"}")
- .post("/authentication")
- .body()
- .path("continuationToken")
- .toString();
-
- when(mockedUsersRepository.test("username", "password"))
+ with()
+ .contentType(ContentType.JSON)
+ .accept(ContentType.JSON)
+ .body("{\"username\": \"[email protected]\", \"clientName\":
\"Mozilla Thunderbird\", \"clientVersion\": \"42.0\", \"deviceName\": \"Joe
Bloggâs iPhone\"}")
+ .post("/authentication")
+ .body()
+ .path("continuationToken")
+ .toString();
+
+ when(mockedUsersRepository.test("[email protected]", "password"))
.thenThrow(new UsersRepositoryException("test"));
-
+
given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
@@ -281,24 +297,24 @@ public class JMAPAuthenticationTest {
@Test
public void mustReturnCreatedWhenGoodPassword() throws Exception {
-
when(mockedZonedDateTimeProvider.provide()).thenAnswer(invocationOnMock ->
oldDate);
-
when(mockedContinuationTokenManager.generateToken(eq("[email protected]")))
- .thenAnswer(invocationOnMock -> new ContinuationToken("username",
newDate, "signature"));
-
when(mockedContinuationTokenManager.isValid(any())).thenAnswer(invocationOnMock
-> true);
+ when(mockedZonedDateTimeProvider.provide())
+ .thenReturn(oldDate);
String continuationToken =
- with()
- .contentType(ContentType.JSON)
- .accept(ContentType.JSON)
- .body("{\"username\": \"[email protected]\", \"clientName\":
\"Mozilla Thunderbird\", \"clientVersion\": \"42.0\", \"deviceName\": \"Joe
Bloggâs iPhone\"}")
- .post("/authentication")
- .body()
- .path("continuationToken")
- .toString();
-
- when(mockedUsersRepository.test("username", "password"))
+ with()
+ .contentType(ContentType.JSON)
+ .accept(ContentType.JSON)
+ .body("{\"username\": \"[email protected]\", \"clientName\":
\"Mozilla Thunderbird\", \"clientVersion\": \"42.0\", \"deviceName\": \"Joe
Bloggâs iPhone\"}")
+ .post("/authentication")
+ .body()
+ .path("continuationToken")
+ .toString();
+
+ when(mockedUsersRepository.test("[email protected]", "password"))
.thenReturn(true);
-
+ when(mockedZonedDateTimeProvider.provide())
+ .thenReturn(newDate);
+
given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
@@ -311,51 +327,32 @@ public class JMAPAuthenticationTest {
@Test
public void mustSendJsonContainingAccessTokenWhenGoodPassword() throws
Exception {
-
when(mockedZonedDateTimeProvider.provide()).thenAnswer(invocationOnMock ->
oldDate);
- ContinuationToken sentContinuationToken = new
ContinuationToken("[email protected]", newDate, "signature");
-
when(mockedContinuationTokenManager.generateToken(eq("[email protected]")))
- .thenAnswer(invocationOnMock -> sentContinuationToken);
-
when(mockedContinuationTokenManager.isValid(any())).thenAnswer(invocationOnMock
-> true);
-
- ContinuationToken receivedContinuationToken =
ContinuationToken.fromString(
- with()
- .contentType(ContentType.JSON)
- .accept(ContentType.JSON)
- .body("{\"username\": \"[email protected]\", \"clientName\":
\"Mozilla Thunderbird\", \"clientVersion\": \"42.0\", \"deviceName\": \"Joe
Bloggâs iPhone\"}")
- .post("/authentication")
- .body()
- .path("continuationToken")
- .toString());
-
- assertThat(receivedContinuationToken).isEqualTo(sentContinuationToken);
- }
-
-
- @Test
- public void
mustReturnAuthenticationFailedWhenContinuationTokenIsRejectedByTheContinuationTokenManager()
throws Exception {
-
when(mockedZonedDateTimeProvider.provide()).thenAnswer(invocationOnMock ->
oldDate);
-
when(mockedContinuationTokenManager.generateToken(eq("[email protected]")))
- .thenAnswer(invocationOnMock -> new
ContinuationToken("[email protected]", newDate, "signature"));
-
when(mockedContinuationTokenManager.isValid(any())).thenAnswer(invocationOnMock
-> false);
+ when(mockedZonedDateTimeProvider.provide())
+ .thenReturn(oldDate);
String continuationToken =
with()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
.body("{\"username\": \"[email protected]\", \"clientName\":
\"Mozilla Thunderbird\", \"clientVersion\": \"42.0\", \"deviceName\": \"Joe
Bloggâs iPhone\"}")
- .post("/authentication")
+ .post("/authentication")
.body()
.path("continuationToken")
- .toString();
+ .toString();
+
+ when(mockedUsersRepository.test("[email protected]", "password"))
+ .thenReturn(true);
+ when(mockedZonedDateTimeProvider.provide())
+ .thenReturn(newDate);
given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
- .body("{\"token\": \"" + continuationToken + "\", \"method\":
\"password\", \"password\": \"badpassword\"}")
+ .body("{\"token\": \"" + continuationToken + "\", \"method\":
\"password\", \"password\": \"password\"}")
.when()
.post("/authentication")
.then()
- .statusCode(401);
+ .body("accessToken", isA(String.class));
}
}
Added:
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=1719318&view=auto
==============================================================================
---
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/AccessTokenManagerImplTest.java
(added)
+++
james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/AccessTokenManagerImplTest.java
Fri Dec 11 10:07:38 2015
@@ -0,0 +1,75 @@
+/****************************************************************
+ * 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.crypto;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.james.jmap.api.AccessTokenManager;
+import org.apache.james.jmap.api.access.AccessToken;
+import org.apache.james.jmap.api.access.AccessTokenRepository;
+import org.apache.james.jmap.api.access.exceptions.InvalidAccessToken;
+import org.apache.james.jmap.memory.access.MemoryAccessTokenRepository;
+import org.junit.Before;
+import org.junit.Test;
+
+public class AccessTokenManagerImplTest {
+
+ private AccessTokenManager accessTokenManager;
+ private AccessTokenRepository accessTokenRepository;
+
+ @Before
+ public void setUp() throws Exception {
+ accessTokenRepository = new MemoryAccessTokenRepository(100);
+ accessTokenManager = new AccessTokenManagerImpl(accessTokenRepository);
+ }
+
+ @Test(expected=NullPointerException.class)
+ public void grantShouldThrowOnNullUsername() throws Exception {
+ accessTokenManager.grantAccessToken(null);
+ }
+
+ @Test
+ public void grantShouldGenerateATokenOnUsername() throws Exception {
+
assertThat(accessTokenManager.grantAccessToken("username")).isNotNull();
+ }
+
+ @Test
+ public void grantShouldStoreATokenOnUsername() throws Exception {
+ AccessToken token = accessTokenManager.grantAccessToken("username");
+
assertThat(accessTokenRepository.getUsernameFromToken(token)).isEqualTo("username");
+ }
+
+ @Test(expected=InvalidAccessToken.class)
+ public void getUsernameShouldThrowWhenUnknownToken() throws Exception {
+ accessTokenManager.getUsernameFromToken(AccessToken.generate());
+ }
+
+ @Test(expected=InvalidAccessToken.class)
+ public void getUsernameShouldThrowWhenOtherToken() throws Exception {
+ accessTokenManager.grantAccessToken("username");
+ accessTokenManager.getUsernameFromToken(AccessToken.generate());
+ }
+
+ @Test
+ public void getUsernameShouldReturnUsernameWhenExistingUsername() throws
Exception {
+ AccessToken token = accessTokenManager.grantAccessToken("username");
+
assertThat(accessTokenManager.getUsernameFromToken(token)).isEqualTo("username");
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]