This is an automated email from the ASF dual-hosted git repository. rcordier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit c3965277428a9ffdef6bdf997163a66290d7a139 Author: duc91 <[email protected]> AuthorDate: Fri May 22 11:51:44 2020 +0700 JAMES-3093 Add JWT Authentication, integration test for JMAP RFC 8621 --- .../james/jmap/draft/DraftMethodsModule.java | 2 +- .../james/jmap/rfc8621/RFC8621MethodsModule.java | 10 +- .../apache/james/jmap/http/AuthenticatorTest.java | 2 +- .../jmap/http/JWTAuthenticationStrategyTest.java | 3 +- .../DistributedBasicAuthenticationTest.java | 4 +- .../distributed/DistributedEchoMethodTest.java | 1 - ....java => DistributedJWTAuthenticationTest.java} | 6 +- ...act.scala => BasicAuthenticationContract.scala} | 46 ++------- .../james/jmap/rfc8621/contract/Fixture.scala | 35 ++++++- .../contract/JWTAuthenticationContract.scala | 107 +++++++++++++++++++++ .../rfc8621/memory/MemoryAuthenticationTest.java | 4 +- server/protocols/jmap-rfc-8621/pom.xml | 4 + server/protocols/jmap/pom.xml | 18 +++- .../MailboxSessionCreationException.java | 2 +- .../james/jmap/jwt}/JWTAuthenticationStrategy.java | 10 +- 15 files changed, 192 insertions(+), 62 deletions(-) diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/DraftMethodsModule.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/DraftMethodsModule.java index 72488fd..d95d95c 100644 --- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/DraftMethodsModule.java +++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/DraftMethodsModule.java @@ -46,8 +46,8 @@ import org.apache.james.jmap.draft.methods.SetVacationResponseMethod; import org.apache.james.jmap.http.AccessTokenAuthenticationStrategy; import org.apache.james.jmap.http.Authenticator; import org.apache.james.jmap.http.InjectionKeys; -import org.apache.james.jmap.http.JWTAuthenticationStrategy; import org.apache.james.jmap.http.QueryParameterAccessTokenAuthenticationStrategy; +import org.apache.james.jmap.jwt.JWTAuthenticationStrategy; import org.apache.james.metrics.api.MetricFactory; import com.google.inject.AbstractModule; diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java index adffa45..f085137 100644 --- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java +++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java @@ -26,6 +26,7 @@ import org.apache.james.jmap.http.Authenticator; import org.apache.james.jmap.http.BasicAuthenticationStrategy; import org.apache.james.jmap.http.rfc8621.InjectionKeys; import org.apache.james.jmap.json.Serializer; +import org.apache.james.jmap.jwt.JWTAuthenticationStrategy; import org.apache.james.jmap.method.CoreEcho; import org.apache.james.jmap.method.Method; import org.apache.james.jmap.routes.JMAPApiRoutes; @@ -57,7 +58,12 @@ public class RFC8621MethodsModule extends AbstractModule { @Provides @Singleton @Named(InjectionKeys.RFC_8621) - Authenticator provideAuthenticator(MetricFactory metricFactory, BasicAuthenticationStrategy basicAuthenticationStrategy) { - return Authenticator.of(metricFactory, basicAuthenticationStrategy); + Authenticator provideAuthenticator(MetricFactory metricFactory, + BasicAuthenticationStrategy basicAuthenticationStrategy, + JWTAuthenticationStrategy jwtAuthenticationStrategy) { + return Authenticator.of( + metricFactory, + basicAuthenticationStrategy, + jwtAuthenticationStrategy); } } diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/AuthenticatorTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/AuthenticatorTest.java index 59c3816..f009783 100644 --- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/AuthenticatorTest.java +++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/AuthenticatorTest.java @@ -30,7 +30,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.apache.james.core.Username; import org.apache.james.jmap.api.access.AccessToken; import org.apache.james.jmap.api.access.AccessTokenRepository; -import org.apache.james.jmap.draft.exceptions.MailboxSessionCreationException; +import org.apache.james.jmap.exceptions.MailboxSessionCreationException; import org.apache.james.jmap.exceptions.UnauthorizedException; import org.apache.james.jmap.memory.access.MemoryAccessTokenRepository; import org.apache.james.mailbox.MailboxSession; diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JWTAuthenticationStrategyTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JWTAuthenticationStrategyTest.java index 49d5144..ac5169d 100644 --- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JWTAuthenticationStrategyTest.java +++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JWTAuthenticationStrategyTest.java @@ -26,7 +26,8 @@ import static org.mockito.Mockito.when; import org.apache.james.core.Username; import org.apache.james.domainlist.api.DomainList; -import org.apache.james.jmap.draft.exceptions.MailboxSessionCreationException; +import org.apache.james.jmap.exceptions.MailboxSessionCreationException; +import org.apache.james.jmap.jwt.JWTAuthenticationStrategy; import org.apache.james.jwt.JwtTokenVerifier; import org.apache.james.mailbox.MailboxManager; import org.apache.james.mailbox.MailboxSession; diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedBasicAuthenticationTest.java b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedBasicAuthenticationTest.java index 1d7932b..d4f2151 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedBasicAuthenticationTest.java +++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedBasicAuthenticationTest.java @@ -26,14 +26,14 @@ import org.apache.james.DockerElasticSearchExtension; import org.apache.james.GuiceJamesServer; import org.apache.james.JamesServerBuilder; import org.apache.james.JamesServerExtension; -import org.apache.james.jmap.rfc8621.contract.AuthenticationContract; +import org.apache.james.jmap.rfc8621.contract.BasicAuthenticationContract; import org.apache.james.modules.AwsS3BlobStoreExtension; import org.apache.james.modules.RabbitMQExtension; import org.apache.james.modules.TestJMAPServerModule; import org.apache.james.modules.blobstore.BlobStoreConfiguration; import org.junit.jupiter.api.extension.RegisterExtension; -public class DistributedBasicAuthenticationTest implements AuthenticationContract { +public class DistributedBasicAuthenticationTest implements BasicAuthenticationContract { @RegisterExtension static JamesServerExtension testExtension = new JamesServerBuilder<CassandraRabbitMQJamesConfiguration>(tmpDir -> CassandraRabbitMQJamesConfiguration.builder() diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java index c55787b..1e504db 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java +++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java @@ -23,7 +23,6 @@ import org.apache.james.CassandraExtension; import org.apache.james.CassandraRabbitMQJamesConfiguration; import org.apache.james.CassandraRabbitMQJamesServerMain; import org.apache.james.DockerElasticSearchExtension; -import org.apache.james.GuiceJamesServer; import org.apache.james.JamesServerBuilder; import org.apache.james.JamesServerExtension; import org.apache.james.jmap.rfc8621.contract.EchoMethodContract; diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedJWTAuthenticationTest.java similarity index 93% copy from server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java copy to server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedJWTAuthenticationTest.java index c55787b..0a8787b 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java +++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedJWTAuthenticationTest.java @@ -23,18 +23,16 @@ import org.apache.james.CassandraExtension; import org.apache.james.CassandraRabbitMQJamesConfiguration; import org.apache.james.CassandraRabbitMQJamesServerMain; import org.apache.james.DockerElasticSearchExtension; -import org.apache.james.GuiceJamesServer; import org.apache.james.JamesServerBuilder; import org.apache.james.JamesServerExtension; -import org.apache.james.jmap.rfc8621.contract.EchoMethodContract; +import org.apache.james.jmap.rfc8621.contract.JWTAuthenticationContract; import org.apache.james.modules.AwsS3BlobStoreExtension; import org.apache.james.modules.RabbitMQExtension; import org.apache.james.modules.TestJMAPServerModule; import org.apache.james.modules.blobstore.BlobStoreConfiguration; import org.junit.jupiter.api.extension.RegisterExtension; -public class DistributedEchoMethodTest implements EchoMethodContract { - +public class DistributedJWTAuthenticationTest implements JWTAuthenticationContract { @RegisterExtension static JamesServerExtension testExtension = new JamesServerBuilder<CassandraRabbitMQJamesConfiguration>(tmpDir -> CassandraRabbitMQJamesConfiguration.builder() diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/AuthenticationContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/BasicAuthenticationContract.scala similarity index 68% rename from server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/AuthenticationContract.scala rename to server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/BasicAuthenticationContract.scala index 6716c1a..f257bbf 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/AuthenticationContract.scala +++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/BasicAuthenticationContract.scala @@ -1,44 +1,27 @@ -/**************************************************************** - * 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.rfc8621.contract import java.nio.charset.StandardCharsets.UTF_8 import java.util.Base64 import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT -import io.restassured.RestAssured._ +import io.restassured.RestAssured.{`given`, requestSpecification} import io.restassured.authentication.NoAuthScheme -import io.restassured.http.{Header, Headers} +import io.restassured.http.Header import org.apache.http.HttpStatus.{SC_OK, SC_UNAUTHORIZED} import org.apache.james.GuiceJamesServer -import org.apache.james.jmap.rfc8621.contract.AuthenticationContract._ +import org.apache.james.jmap.rfc8621.contract.BasicAuthenticationContract._ import org.apache.james.jmap.rfc8621.contract.Fixture._ import org.apache.james.jmap.rfc8621.contract.tags.CategoryTags import org.apache.james.utils.DataProbeImpl import org.junit.jupiter.api.{BeforeEach, Tag, Test} -object AuthenticationContract { - private val AUTHORIZATION_HEADER: String = "Authorization" +object BasicAuthenticationContract { + private def toBase64(stringValue: String): String = { + Base64.getEncoder.encodeToString(stringValue.getBytes(UTF_8)) + } } -trait AuthenticationContract { +trait BasicAuthenticationContract { @BeforeEach def setUp(server: GuiceJamesServer): Unit = { server.getProbe(classOf[DataProbeImpl]) @@ -55,7 +38,7 @@ trait AuthenticationContract { @Test def postShouldRespondUnauthorizedWhenNoAuthorizationHeader(): Unit = { - `given`() + given() .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) .body(ECHO_REQUEST_OBJECT) .when() @@ -137,15 +120,4 @@ trait AuthenticationContract { .then .statusCode(SC_UNAUTHORIZED) } - - private def getHeadersWith(authHeader: Header): Headers = { - new Headers( - new Header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER), - authHeader - ) - } - - private def toBase64(stringValue: String): String = { - Base64.getEncoder.encodeToString(stringValue.getBytes(UTF_8)) - } } diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/Fixture.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/Fixture.scala index 56be582..be44b77 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/Fixture.scala +++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/Fixture.scala @@ -21,11 +21,12 @@ package org.apache.james.jmap.rfc8621.contract import java.nio.charset.StandardCharsets +import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT import io.restassured.authentication.PreemptiveBasicAuthScheme import io.restassured.builder.RequestSpecBuilder import io.restassured.config.EncoderConfig.encoderConfig import io.restassured.config.RestAssuredConfig.newConfig -import io.restassured.http.ContentType +import io.restassured.http.{ContentType, Header, Headers} import org.apache.james.GuiceJamesServer import org.apache.james.core.{Domain, Username} import org.apache.james.jmap.JMAPUrls.JMAP @@ -50,6 +51,14 @@ object Fixture { authScheme } + def getHeadersWith(authHeader: Header): Headers = { + new Headers( + new Header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER), + authHeader + ) + } + + val AUTHORIZATION_HEADER: String = "Authorization" val DOMAIN: Domain = Domain.of("domain.tld") val DOMAIN_WITH_SPACE: Domain = Domain.of("dom ain.tld") val _2_DOT_DOMAIN: Domain = Domain.of("do.main.tld") @@ -91,4 +100,28 @@ object Fixture { |}""".stripMargin val ACCEPT_RFC8621_VERSION_HEADER: String = "application/json; jmapVersion=rfc-8621" + + val USER: Username = Username.fromLocalPartWithDomain("user", DOMAIN) + val USER_PASSWORD: String = "user" + + // These tokens copied from class JwtTokenVerifierTest + val USER_TOKEN: String = + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyQGRvbWFpbi50bGQifQ.U-dUPv6OU6KO5N7CooHUfMkCd" + + "FJHx2F3H4fm7Q79g1BPfBSkifPj5xyVlZ0JwEGXypC4zBw9ay3l4DxzX7D_6p1Hx_ihXsoLx1Ca-WUo44x-XRSpPfgxiZjHCJkGBLMV3RZlA" + + "jip-d18mxkcX3JGplX_sCQkFisduAOAHuKSUg9wI6VBgUQi_0B35FYv6tP_bD6eFtvaAUN9QyXXh8UQjEp8CO12lRz6enfLx_V6BG_fEMkee" + + "6vRqdEqx_F9OF3eWTe1giMp_JhQ7_l1OXXtbd4TndVvTeuVy4irPbsRc-M8x_-qTDpFp6saRRsyOcFspxPp5n3yIhEK7B3UZiseXw" + + val UNKNOWN_USER_TOKEN: String = + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.T04BTk" + + "LXkJj24coSZkK13RfG25lpvmSl2MJ7N10KpBk9_-95EGYZdog-BDAn3PJzqVw52z-Bwjh4VOj1-j7cURu0cT4jXehhUrlCxS4n7QHZD" + + "N_bsEYGu7KzjWTpTsUiHe-rN7izXVFxDGG1TGwlmBCBnPW-EFCf9ylUsJi0r2BKNdaaPRfMIrHptH1zJBkkUziWpBN1RNLjmvlAUf49" + + "t1Tbv21ZqYM5Ht2vrhJWczFbuC-TD-8zJkXhjTmA1GVgomIX5dx1cH-dZX1wANNmshUJGHgepWlPU-5VIYxPEhb219RMLJIELMY2qN" + + "OR8Q31ydinyqzXvCSzVJOf6T60-w" + + val INVALID_JWT_TOKEN: String = + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbkBvcGVu" + + "thispartiscompletelywrong.reQc3DiVvbQHF08oW1qOUyDJyv3tfzDNk8jhVZequiCdOI9vXnRlOe" + + "-yDYktd4WT8MYhqY7MgS-wR0vO9jZFv8ZCgd_MkKCvCO0HmMjP5iQPZ0kqGkgWUH7X123tfR38MfbCVAdPDba-K3MfkogV1xvDhlkPScFr_6MxE" + + "xtedOK2JnQZn7t9sUzSrcyjWverm7gZkPptkIVoS8TsEeMMME5vFXe_nqkEG69q3kuBUm_33tbR5oNS0ZGZKlG9r41lHBjyf9J1xN4UYV8n866d" + + "a7RPPCzshIWUtO0q9T2umWTnp-6OnOdBCkndrZmRR6pPxsD5YL0_77Wq8KT_5__fGA" } diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/JWTAuthenticationContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/JWTAuthenticationContract.scala new file mode 100644 index 0000000..5fbad90 --- /dev/null +++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/JWTAuthenticationContract.scala @@ -0,0 +1,107 @@ +/**************************************************************** + * 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.rfc8621.contract + +import io.restassured.RestAssured.{`given`, requestSpecification} +import io.restassured.authentication.NoAuthScheme +import io.restassured.http.Header +import org.apache.http.HttpStatus._ +import org.apache.james.GuiceJamesServer +import org.apache.james.core.Username +import org.apache.james.jmap.rfc8621.contract.Fixture._ +import org.apache.james.jmap.rfc8621.contract.JWTAuthenticationContract._ +import org.apache.james.jmap.rfc8621.contract.tags.CategoryTags +import org.apache.james.utils.DataProbeImpl +import org.junit.jupiter.api.{BeforeEach, Tag, Test} + +object JWTAuthenticationContract { + private val USER_TOKEN: String = + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyQGRvbWFpbi50bGQifQ.U-dUPv6OU6KO5N7CooHUfMkCd" + + "FJHx2F3H4fm7Q79g1BPfBSkifPj5xyVlZ0JwEGXypC4zBw9ay3l4DxzX7D_6p1Hx_ihXsoLx1Ca-WUo44x-XRSpPfgxiZjHCJkGBLMV3RZlA" + + "jip-d18mxkcX3JGplX_sCQkFisduAOAHuKSUg9wI6VBgUQi_0B35FYv6tP_bD6eFtvaAUN9QyXXh8UQjEp8CO12lRz6enfLx_V6BG_fEMkee" + + "6vRqdEqx_F9OF3eWTe1giMp_JhQ7_l1OXXtbd4TndVvTeuVy4irPbsRc-M8x_-qTDpFp6saRRsyOcFspxPp5n3yIhEK7B3UZiseXw" + + private val UNKNOWN_USER_TOKEN: String = + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.T04BTk" + + "LXkJj24coSZkK13RfG25lpvmSl2MJ7N10KpBk9_-95EGYZdog-BDAn3PJzqVw52z-Bwjh4VOj1-j7cURu0cT4jXehhUrlCxS4n7QHZD" + + "N_bsEYGu7KzjWTpTsUiHe-rN7izXVFxDGG1TGwlmBCBnPW-EFCf9ylUsJi0r2BKNdaaPRfMIrHptH1zJBkkUziWpBN1RNLjmvlAUf49" + + "t1Tbv21ZqYM5Ht2vrhJWczFbuC-TD-8zJkXhjTmA1GVgomIX5dx1cH-dZX1wANNmshUJGHgepWlPU-5VIYxPEhb219RMLJIELMY2qN" + + "OR8Q31ydinyqzXvCSzVJOf6T60-w" + + private val INVALID_JWT_TOKEN: String = + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbkBvcGVu" + + "thispartiscompletelywrong.reQc3DiVvbQHF08oW1qOUyDJyv3tfzDNk8jhVZequiCdOI9vXnRlOe" + + "-yDYktd4WT8MYhqY7MgS-wR0vO9jZFv8ZCgd_MkKCvCO0HmMjP5iQPZ0kqGkgWUH7X123tfR38MfbCVAdPDba-K3MfkogV1xvDhlkPScFr_6MxE" + + "xtedOK2JnQZn7t9sUzSrcyjWverm7gZkPptkIVoS8TsEeMMME5vFXe_nqkEG69q3kuBUm_33tbR5oNS0ZGZKlG9r41lHBjyf9J1xN4UYV8n866d" + + "a7RPPCzshIWUtO0q9T2umWTnp-6OnOdBCkndrZmRR6pPxsD5YL0_77Wq8KT_5__fGA" + + private val USER: Username = Username.fromLocalPartWithDomain("user", DOMAIN) + private val USER_PASSWORD: String = "user" +} + +trait JWTAuthenticationContract { + @BeforeEach + def setUp(server: GuiceJamesServer): Unit = { + server.getProbe(classOf[DataProbeImpl]) + .fluent() + .addDomain(DOMAIN.asString()) + .addUser(USER.asString(), USER_PASSWORD) + + requestSpecification = baseRequestSpecBuilder(server) + .setAuth(new NoAuthScheme) + .build + } + + @Tag(CategoryTags.BASIC_FEATURE) + @Test + def getMustReturnEndpointsWhenValidJwtAuthorizationHeader(): Unit = { + `given` + .headers(getHeadersWith(new Header(AUTHORIZATION_HEADER, s"Bearer $USER_TOKEN"))) + .body(ECHO_REQUEST_OBJECT) + .when + .post() + .`then` + .statusCode(SC_OK) + } + + @Test + @Tag(CategoryTags.BASIC_FEATURE) + def getMustReturnOKWhenValidUnknownUserJwtAuthorizationHeader(): Unit = { + val authHeader: Header = new Header(AUTHORIZATION_HEADER, s"Bearer $UNKNOWN_USER_TOKEN") + `given`() + .headers(getHeadersWith(authHeader)) + .body(ECHO_REQUEST_OBJECT) + .when() + .post() + .then + .statusCode(SC_UNAUTHORIZED) + } + + @Test + @Tag(CategoryTags.BASIC_FEATURE) + def getMustReturnBadCredentialsWhenInvalidJwtAuthorizationHeader(): Unit = { + `given` + .headers(getHeadersWith(new Header(AUTHORIZATION_HEADER, s"Bearer $INVALID_JWT_TOKEN"))) + .body(ECHO_REQUEST_OBJECT) + .when + .post() + .`then` + .statusCode(SC_UNAUTHORIZED) + } +} diff --git a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryAuthenticationTest.java b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryAuthenticationTest.java index c99bf0f..5fd5b42 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryAuthenticationTest.java +++ b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryAuthenticationTest.java @@ -24,11 +24,11 @@ import static org.apache.james.MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_ import org.apache.james.GuiceJamesServer; import org.apache.james.JamesServerBuilder; import org.apache.james.JamesServerExtension; -import org.apache.james.jmap.rfc8621.contract.AuthenticationContract; +import org.apache.james.jmap.rfc8621.contract.BasicAuthenticationContract; import org.apache.james.modules.TestJMAPServerModule; import org.junit.jupiter.api.extension.RegisterExtension; -public class MemoryAuthenticationTest implements AuthenticationContract { +public class MemoryAuthenticationTest implements BasicAuthenticationContract { @RegisterExtension static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider()) .server(configuration -> GuiceJamesServer.forConfiguration(configuration) diff --git a/server/protocols/jmap-rfc-8621/pom.xml b/server/protocols/jmap-rfc-8621/pom.xml index feccb0c..0cf4eae 100644 --- a/server/protocols/jmap-rfc-8621/pom.xml +++ b/server/protocols/jmap-rfc-8621/pom.xml @@ -73,6 +73,10 @@ </dependency> <dependency> <groupId>${james.groupId}</groupId> + <artifactId>james-server-jwt</artifactId> + </dependency> + <dependency> + <groupId>${james.groupId}</groupId> <artifactId>metrics-tests</artifactId> <scope>test</scope> </dependency> diff --git a/server/protocols/jmap/pom.xml b/server/protocols/jmap/pom.xml index a052b80..37cc3db 100644 --- a/server/protocols/jmap/pom.xml +++ b/server/protocols/jmap/pom.xml @@ -32,11 +32,19 @@ <dependencies> <dependency> <groupId>${james.groupId}</groupId> + <artifactId>james-core</artifactId> + </dependency> + <dependency> + <groupId>${james.groupId}</groupId> <artifactId>apache-james-mailbox-api</artifactId> </dependency> <dependency> <groupId>${james.groupId}</groupId> - <artifactId>james-core</artifactId> + <artifactId>james-server-data-api</artifactId> + </dependency> + <dependency> + <groupId>${james.groupId}</groupId> + <artifactId>james-server-jwt</artifactId> </dependency> <dependency> <groupId>${james.groupId}</groupId> @@ -73,15 +81,15 @@ <artifactId>javax.annotation-api</artifactId> </dependency> <dependency> + <groupId>javax.annotation</groupId> + <artifactId>javax.annotation-api</artifactId> + </dependency> + <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.4.13</version> </dependency> <dependency> - <groupId>javax.annotation</groupId> - <artifactId>javax.annotation-api</artifactId> - </dependency> - <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <scope>test</scope> diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/exceptions/MailboxSessionCreationException.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxSessionCreationException.java similarity index 96% rename from server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/exceptions/MailboxSessionCreationException.java rename to server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxSessionCreationException.java index 8865c15..a1971c2 100644 --- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/exceptions/MailboxSessionCreationException.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxSessionCreationException.java @@ -17,7 +17,7 @@ * under the License. * ****************************************************************/ -package org.apache.james.jmap.draft.exceptions; +package org.apache.james.jmap.exceptions; public class MailboxSessionCreationException extends RuntimeException { diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/JWTAuthenticationStrategy.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/jwt/JWTAuthenticationStrategy.java similarity index 88% rename from server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/JWTAuthenticationStrategy.java rename to server/protocols/jmap/src/main/java/org/apache/james/jmap/jwt/JWTAuthenticationStrategy.java index 6f4a275..41566a7 100644 --- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/JWTAuthenticationStrategy.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/jwt/JWTAuthenticationStrategy.java @@ -16,14 +16,15 @@ * specific language governing permissions and limitations * * under the License. * ****************************************************************/ -package org.apache.james.jmap.http; +package org.apache.james.jmap.jwt; import java.util.stream.Stream; import javax.inject.Inject; import org.apache.james.core.Username; -import org.apache.james.jmap.draft.exceptions.MailboxSessionCreationException; +import org.apache.james.jmap.exceptions.MailboxSessionCreationException; +import org.apache.james.jmap.http.AuthenticationStrategy; import org.apache.james.jwt.JwtTokenVerifier; import org.apache.james.mailbox.MailboxManager; import org.apache.james.mailbox.MailboxSession; @@ -37,14 +38,15 @@ import reactor.netty.http.server.HttpServerRequest; public class JWTAuthenticationStrategy implements AuthenticationStrategy { - @VisibleForTesting static final String AUTHORIZATION_HEADER_PREFIX = "Bearer "; + @VisibleForTesting + public static final String AUTHORIZATION_HEADER_PREFIX = "Bearer "; private final JwtTokenVerifier tokenManager; private final MailboxManager mailboxManager; private final UsersRepository usersRepository; @Inject @VisibleForTesting - JWTAuthenticationStrategy(JwtTokenVerifier tokenManager, MailboxManager mailboxManager, UsersRepository usersRepository) { + public JWTAuthenticationStrategy(JwtTokenVerifier tokenManager, MailboxManager mailboxManager, UsersRepository usersRepository) { this.tokenManager = tokenManager; this.mailboxManager = mailboxManager; this.usersRepository = usersRepository; --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
