diff --git a/build.sbt b/build.sbt index 0e4016ed..7dcd16fd 100644 --- a/build.sbt +++ b/build.sbt @@ -74,8 +74,22 @@ lazy val `mauth-signer-apachehttp` = javaModuleProject("mauth-signer-apachehttp" Dependencies.test(scalaMock, scalaTest).map(withExclusions) ) -lazy val `mauth-signer-akka-http` = scalaModuleProject("mauth-signer-akka-http") +lazy val `mauth-signer-scala-core` = scalaModuleProject("mauth-signer-scala-core") .dependsOn(`mauth-signer`, `mauth-test-utils` % "test") + .settings( + noPublishSettings, + moduleName := "mauth-signer-scala-core", + testFrameworks += new TestFramework("munit.Framework"), + libraryDependencies ++= + Dependencies.compile(akkaHttp, akkaStream).map(withExclusions) ++ + Dependencies.compile(scalaLogging, scalaLibCompat).map(withExclusions) ++ + //Dependencies.example(akkaHttp, akkaStream).map(withExclusions) ++ + Dependencies.test(scalaMock, scalaTest, wiremock).map(withExclusions), + mimaPreviousArtifacts := Set.empty + ) + +lazy val `mauth-signer-akka-http` = scalaModuleProject("mauth-signer-akka-http") + .dependsOn(`mauth-signer`, `mauth-signer-scala-core`, `mauth-test-utils` % "test") .configs(ExampleTests) .settings( exampleSettings, @@ -88,13 +102,26 @@ lazy val `mauth-signer-akka-http` = scalaModuleProject("mauth-signer-akka-http") ) lazy val `mauth-signer-sttp` = scalaModuleProject("mauth-signer-sttp") - .dependsOn(`mauth-signer`, `mauth-test-utils` % "test") + .dependsOn(`mauth-signer`, `mauth-signer-scala-core`, `mauth-test-utils` % "test") .settings( publishSettings, libraryDependencies ++= Dependencies.compile(scalaLibCompat, sttp, scalaLogging).map(withExclusions) ++ - Dependencies.test(scalaMock, scalaTest, wiremock, sttpAkkaHttpBackend).map(withExclusions), - // TODO remove once published + Dependencies.test(scalaMock, scalaTest, wiremock, sttpAkkaHttpBackend).map(withExclusions) + ) + +lazy val `mauth-signer-http4s` = scalaModuleProject("mauth-signer-http4s") + .dependsOn(`mauth-signer`, `mauth-signer-scala-core`, `mauth-test-utils` % "test") + .settings( + basicSettings, + moduleName := "mauth-authenticator-http4s", + publishSettings, + testFrameworks += new TestFramework("munit.Framework"), + libraryDependencies ++= + Dependencies.provided(http4sClient) ++ + Dependencies.compile(enumeratum) ++ + Dependencies.compile(log4cats) ++ + Dependencies.test(munitCatsEffect, http4sDsl), mimaPreviousArtifacts := Set.empty ) @@ -152,11 +179,10 @@ lazy val `mauth-authenticator-http4s` = (project in file("modules/mauth-authenti publishSettings, testFrameworks += new TestFramework("munit.Framework"), libraryDependencies ++= - Dependencies.provided(http4s) ++ + Dependencies.provided(http4sDsl) ++ Dependencies.compile(enumeratum) ++ Dependencies.compile(log4cats) ++ - Dependencies.test(munitCatsEffect), - mimaPreviousArtifacts := Set.empty + Dependencies.test(munitCatsEffect) ) lazy val `mauth-jvm-clients` = (project in file(".")) @@ -168,6 +194,7 @@ lazy val `mauth-jvm-clients` = (project in file(".")) `mauth-common`, `mauth-signer`, `mauth-signer-akka-http`, + `mauth-signer-http4s`, `mauth-signer-sttp`, `mauth-signer-apachehttp`, `mauth-sender-sttp-akka-http`, diff --git a/modules/mauth-authenticator-akka-http/src/test/scala/com/mdsol/mauth/akka/http/MauthPublicKeyProviderSpec.scala b/modules/mauth-authenticator-akka-http/src/test/scala/com/mdsol/mauth/akka/http/MauthPublicKeyProviderSpec.scala index 5f131858..dad3013f 100644 --- a/modules/mauth-authenticator-akka-http/src/test/scala/com/mdsol/mauth/akka/http/MauthPublicKeyProviderSpec.scala +++ b/modules/mauth-authenticator-akka-http/src/test/scala/com/mdsol/mauth/akka/http/MauthPublicKeyProviderSpec.scala @@ -2,7 +2,6 @@ package com.mdsol.mauth.akka.http import java.net.URI import java.security.Security - import akka.actor.ActorSystem import com.mdsol.mauth.models.{SignedRequest, UnsignedRequest} import com.mdsol.mauth.test.utils.{FakeMAuthServer, PortFinder} diff --git a/modules/mauth-authenticator-http4s/src/main/scala/com/mdsol/mauth/http4s/MAuthMiddleware.scala b/modules/mauth-authenticator-http4s/src/main/scala/com/mdsol/mauth/http4s/MAuthMiddleware.scala index b576a07a..dfa54d71 100644 --- a/modules/mauth-authenticator-http4s/src/main/scala/com/mdsol/mauth/http4s/MAuthMiddleware.scala +++ b/modules/mauth-authenticator-http4s/src/main/scala/com/mdsol/mauth/http4s/MAuthMiddleware.scala @@ -38,8 +38,7 @@ object HeaderVersion extends Enum[HeaderVersion] { object MAuthMiddleware { import HeaderVersion._ - def apply[G[_]: Sync, F[_]](requestValidationTimeout: Duration, fk: F ~> G)(http: Http[G, F])(implicit - authenticator: Authenticator, + def apply[G[_]: Sync, F[_]](requestValidationTimeout: Duration, authenticator: Authenticator, fk: F ~> G)(http: Http[G, F])(implicit ec: ExecutionContext, F: Async[F] ): Http[G, F] = @@ -107,13 +106,11 @@ object MAuthMiddleware { } } - def httpRoutes[F[_]: Async](requestValidationTimeout: Duration)(httpRoutes: HttpRoutes[F])(implicit - authenticator: Authenticator, + def httpRoutes[F[_]: Async](requestValidationTimeout: Duration, authenticator: Authenticator)(httpRoutes: HttpRoutes[F])(implicit ec: ExecutionContext - ): HttpRoutes[F] = apply(requestValidationTimeout, OptionT.liftK[F])(httpRoutes) + ): HttpRoutes[F] = apply(requestValidationTimeout, authenticator, OptionT.liftK[F])(httpRoutes) - def httpApp[F[_]: Async](requestValidationTimeout: Duration)(httpRoutes: HttpApp[F])(implicit - authenticator: Authenticator, + def httpApp[F[_]: Async](requestValidationTimeout: Duration, authenticator: Authenticator)(httpRoutes: HttpApp[F])(implicit ec: ExecutionContext - ): HttpApp[F] = apply(requestValidationTimeout, FunctionK.id[F])(httpRoutes) + ): HttpApp[F] = apply(requestValidationTimeout, authenticator, FunctionK.id[F])(httpRoutes) } diff --git a/modules/mauth-authenticator-http4s/src/test/scala/com/mdsol/mauth/http4s/MAuthMiddlewareSuite.scala b/modules/mauth-authenticator-http4s/src/test/scala/com/mdsol/mauth/http4s/MAuthMiddlewareSuite.scala index 8ca2edd5..c3c91be9 100644 --- a/modules/mauth-authenticator-http4s/src/test/scala/com/mdsol/mauth/http4s/MAuthMiddlewareSuite.scala +++ b/modules/mauth-authenticator-http4s/src/test/scala/com/mdsol/mauth/http4s/MAuthMiddlewareSuite.scala @@ -17,7 +17,7 @@ import org.http4s.Method._ import java.security.{PublicKey, Security} import java.util.UUID -import scala.concurrent.{ExecutionContext, Future} +import scala.concurrent.Future import scala.concurrent.duration._ class MAuthMiddlewareSuite extends CatsEffectSuite { @@ -75,11 +75,11 @@ class MAuthMiddlewareSuite extends CatsEffectSuite { private implicit val authenticator: RequestAuthenticator = new RequestAuthenticator(client, epochTimeProvider) - private val service = MAuthMiddleware.httpRoutes[IO](requestValidationTimeout)(route).orNotFound + private val service = MAuthMiddleware.httpRoutes[IO](requestValidationTimeout, authenticator)(route).orNotFound val authenticatorV2: RequestAuthenticator = new RequestAuthenticator(client, epochTimeProvider, v2OnlyAuthenticate = true) val serviceV2 = - MAuthMiddleware.httpRoutes[IO](requestValidationTimeout)(route)(implicitly[Async[IO]], authenticatorV2, implicitly[ExecutionContext]).orNotFound + MAuthMiddleware.httpRoutes[IO](requestValidationTimeout, authenticatorV2)(route).orNotFound test("allow successfully authenticated request") { val res = service( @@ -147,7 +147,7 @@ class MAuthMiddlewareSuite extends CatsEffectSuite { val localAuthenticator: RequestAuthenticator = new RequestAuthenticator(localClient, epochTimeProvider) val localService = - MAuthMiddleware.httpRoutes[IO](requestValidationTimeout)(route)(implicitly[Async[IO]], localAuthenticator, implicitly[ExecutionContext]).orNotFound + MAuthMiddleware.httpRoutes[IO](requestValidationTimeout, localAuthenticator)(route).orNotFound val res = localService( Request[IO](GET, uri"/").withHeaders( diff --git a/modules/mauth-signer-akka-http/src/example/scala/com/mdsol/mauth/MauthRequestSignerExample.scala b/modules/mauth-signer-akka-http/src/example/scala/com/mdsol/mauth/MauthRequestSignerExample.scala index 3dc330b8..b9248f1d 100644 --- a/modules/mauth-signer-akka-http/src/example/scala/com/mdsol/mauth/MauthRequestSignerExample.scala +++ b/modules/mauth-signer-akka-http/src/example/scala/com/mdsol/mauth/MauthRequestSignerExample.scala @@ -1,7 +1,6 @@ package com.mdsol.mauth import java.net.URI - import akka.actor.ActorSystem import com.mdsol.mauth.http.HttpClient import com.mdsol.mauth.http.Implicits._ @@ -26,7 +25,7 @@ object MauthRequestSignerExample { val httpMethod = "GET" val uri = URI.create("https://api.mdsol.com/v1/countries") - val signedRequest = MAuthRequestSigner(configuration).signRequest(models.UnsignedRequest(httpMethod, uri, body = Array.empty, headers = Map.empty)) + val signedRequest = MAuthRequestSigner(configuration).signRequest(UnsignedRequest(httpMethod, uri, body = Array.empty, headers = Map.empty)) Await.result( HttpClient.call(signedRequest.toAkkaHttpRequest).map(response => println(s"response code: ${response._1.value}, response: ${response._3.toString}")), 10.seconds diff --git a/modules/mauth-signer-akka-http/src/main/scala/com/mdsol/mauth/http/Implicits.scala b/modules/mauth-signer-akka-http/src/main/scala/com/mdsol/mauth/http/Implicits.scala index 9ea45b2c..b2e523ec 100644 --- a/modules/mauth-signer-akka-http/src/main/scala/com/mdsol/mauth/http/Implicits.scala +++ b/modules/mauth-signer-akka-http/src/main/scala/com/mdsol/mauth/http/Implicits.scala @@ -1,9 +1,9 @@ package com.mdsol.mauth.http import akka.http.scaladsl.model.headers.RawHeader -import akka.http.scaladsl.model.{HttpEntity, _} -import com.mdsol.mauth.SignedRequest +import akka.http.scaladsl.model._ import com.mdsol.mauth.http.HttpVerbOps._ +import com.mdsol.mauth.SignedRequest import com.mdsol.mauth.models.{SignedRequest => NewSignedRequest} import scala.annotation.nowarn @@ -29,7 +29,7 @@ object Implicits { implicit class NewSignedRequestOps(val signedRequest: NewSignedRequest) extends AnyVal { - /** Create an akka-http request from a [[com.mdsol.mauth.models.SignedRequest]] + /** Create an akka-http request from a [[models.SignedRequest]] */ def toAkkaHttpRequest: HttpRequest = { val contentType: Option[String] = extractContentTypeFromHeaders(signedRequest.req.headers) diff --git a/modules/mauth-signer-akka-http/src/test/scala/com/mdsol/mauth/MAuthRequestAkkaSignerSpec.scala b/modules/mauth-signer-akka-http/src/test/scala/com/mdsol/mauth/MAuthRequestAkkaSignerSpec.scala new file mode 100644 index 00000000..c80695b4 --- /dev/null +++ b/modules/mauth-signer-akka-http/src/test/scala/com/mdsol/mauth/MAuthRequestAkkaSignerSpec.scala @@ -0,0 +1,110 @@ +package com.mdsol.mauth + +import java.net.URI +import java.security.Security +import java.util.UUID + +import akka.actor.ActorSystem +import akka.http.scaladsl.model._ +import com.github.tomakehurst.wiremock.WireMockServer +import com.github.tomakehurst.wiremock.client.WireMock.{aResponse, equalTo, post, urlPathEqualTo} +import com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig +import com.mdsol.mauth.http.HttpClient +import com.mdsol.mauth.http.Implicits._ +import com.mdsol.mauth.models.{UnsignedRequest => NewUnsignedRequest} +import com.mdsol.mauth.test.utils.TestFixtures._ +import com.mdsol.mauth.util.EpochTimeProvider +import org.apache.http.HttpStatus +import org.bouncycastle.jce.provider.BouncyCastleProvider +import org.scalatest.BeforeAndAfterAll +import org.scalatest.concurrent.PatienceConfiguration.Timeout +import org.scalatest.concurrent.ScalaFutures +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers + +import scala.concurrent.duration._ + +class MAuthRequestAkkaSignerSpec extends AnyFlatSpec with Matchers with HttpClient with BeforeAndAfterAll with ScalaFutures { + + implicit val system: ActorSystem = ActorSystem() + var service = new WireMockServer(wireMockConfig.dynamicPort) + + Security.addProvider(new BouncyCastleProvider) + + val CONST_EPOCH_TIME_PROVIDER: EpochTimeProvider = new EpochTimeProvider() { override def inSeconds(): Long = EXPECTED_TIME_HEADER_1.toLong } + + val signer: MAuthRequestSigner = new MAuthRequestSigner( + UUID.fromString(APP_UUID_1), + PRIVATE_KEY_1, + CONST_EPOCH_TIME_PROVIDER, + SignerConfiguration.ALL_SIGN_VERSIONS + ) + + val signerV2: MAuthRequestSigner = new MAuthRequestSigner( + UUID.fromString(APP_UUID_1), + PRIVATE_KEY_1, + CONST_EPOCH_TIME_PROVIDER, + java.util.Arrays.asList[MAuthVersion](MAuthVersion.MWSV2) + ) + + val signerV1: MAuthRequestSigner = new MAuthRequestSigner( + UUID.fromString(APP_UUID_1), + PRIVATE_KEY_1, + CONST_EPOCH_TIME_PROVIDER, + java.util.Arrays.asList[MAuthVersion](MAuthVersion.MWS) + ) + + override protected def beforeAll(): Unit = + service.start() + + override protected def afterAll(): Unit = + service.stop() + + val simpleUnsignedRequest: UnsignedRequest = UnsignedRequest(uri = URI_EMPTY_PATH) + val simpleNewUnsignedRequest: NewUnsignedRequest = + NewUnsignedRequest.fromStringBodyUtf8(httpMethod = "GET", uri = URI_EMPTY_PATH, body = "", headers = Map.empty) + + val unsignedRequest: NewUnsignedRequest = + NewUnsignedRequest.fromStringBodyUtf8(httpMethod = "GET", uri = URI_EMPTY_PATH_WITH_PARAM, body = SIMPLE_REQUEST_BODY, headers = Map.empty) + "MAuthRequestSigner" should "add time header to a request for V1" in { + signer.signRequest(simpleUnsignedRequest).getOrElse(fail("signRequest unexpectedly failed")).timeHeader shouldBe EXPECTED_TIME_HEADER_1 + } + + it should "correctly send a customized content-type header" in { + service.stubFor( + post(urlPathEqualTo(s"/v1/test")) + .willReturn(aResponse().withStatus(HttpStatus.SC_OK)) + .withHeader("Content-type", equalTo("application/json")) + ) + + val simpleNewUnsignedRequest = + NewUnsignedRequest + .fromStringBodyUtf8( + httpMethod = "POST", + uri = new URI(s"${service.baseUrl()}/v1/test"), + body = "", + headers = Map("Content-Type" -> ContentTypes.`application/json`.toString()) + ) + + whenReady(HttpClient.call(signerV2.signRequest(simpleNewUnsignedRequest).toAkkaHttpRequest), timeout = Timeout(5.seconds)) { response => + response.status shouldBe StatusCodes.OK + } + } + + it should "correctly send the default content type (text/plain UTF-8) when content type not specified" in { + service.stubFor( + post(urlPathEqualTo(s"/v1/test")) + .willReturn(aResponse().withStatus(HttpStatus.SC_OK)) + .withHeader("Content-type", equalTo(ContentTypes.`text/plain(UTF-8)`.toString())) + ) + + val simpleNewUnsignedRequest = + NewUnsignedRequest + .fromStringBodyUtf8(httpMethod = "POST", uri = new URI(s"${service.baseUrl()}/v1/test"), body = "", headers = Map()) + + whenReady(HttpClient.call(signerV2.signRequest(simpleNewUnsignedRequest).toAkkaHttpRequest), timeout = Timeout(5.seconds)) { response => + response.status shouldBe StatusCodes.OK + } + } + +} diff --git a/modules/mauth-signer-http4s/src/main/scala/com/mdsol/mauth/http4s/client/MAuthSigner.scala b/modules/mauth-signer-http4s/src/main/scala/com/mdsol/mauth/http4s/client/MAuthSigner.scala new file mode 100644 index 00000000..c2b41eb6 --- /dev/null +++ b/modules/mauth-signer-http4s/src/main/scala/com/mdsol/mauth/http4s/client/MAuthSigner.scala @@ -0,0 +1,35 @@ +package com.mdsol.mauth.http4s.client + +import cats.syntax.all._ +import cats.effect.kernel.{Async, Resource} +import com.mdsol.mauth.RequestSigner +import com.mdsol.mauth.models.UnsignedRequest +import org.http4s.Request +import org.http4s.client.Client + +import java.net.URI + +object MAuthSigner { + def apply[F[_]: Async](signer: RequestSigner)(client: Client[F]): Client[F] = + Client { req => + for { + req <- Resource.eval(req.as[Array[Byte]].flatMap { byteArray => + val signedRequest = signer.signRequest( + UnsignedRequest( + req.method.name, + URI.create(req.uri.renderString), + byteArray, + req.headers.headers.view.map(h => h.name.toString -> h.value).toMap + ) + ) + Request( + method = req.method, + uri = req.uri, + headers = req.headers.put(signedRequest.mauthHeaders.toList), + body = req.body + ).pure[F] + }) + res <- client.run(req) + } yield res + } +} diff --git a/modules/mauth-signer-http4s/src/test/scala/com/mdsol/mauth/http4s/client/MAuthSignerMiddlewareSuite.scala b/modules/mauth-signer-http4s/src/test/scala/com/mdsol/mauth/http4s/client/MAuthSignerMiddlewareSuite.scala new file mode 100644 index 00000000..e9ebd7f9 --- /dev/null +++ b/modules/mauth-signer-http4s/src/test/scala/com/mdsol/mauth/http4s/client/MAuthSignerMiddlewareSuite.scala @@ -0,0 +1,99 @@ +package com.mdsol.mauth.http4s.client + +import cats.effect.IO +import cats.syntax.all._ +import com.mdsol.mauth.models.UnsignedRequest +import com.mdsol.mauth.{MAuthRequestSigner, MAuthVersion} +import munit.CatsEffectSuite +import org.http4s.client.Client +import org.http4s.{Headers, HttpRoutes, Request, Response, Status, Uri} +import org.http4s.dsl.io._ +import com.mdsol.mauth.test.utils.TestFixtures._ +import com.mdsol.mauth.util.EpochTimeProvider + +import java.net.URI +import java.util.UUID + +class MAuthSignerMiddlewareSuite extends CatsEffectSuite { + + private val CONST_EPOCH_TIME_PROVIDER: EpochTimeProvider = new EpochTimeProvider() { override def inSeconds(): Long = EXPECTED_TIME_HEADER_1.toLong } + + private val signerV2: MAuthRequestSigner = new MAuthRequestSigner( + UUID.fromString(APP_UUID_1), + PRIVATE_KEY_1, + CONST_EPOCH_TIME_PROVIDER, + java.util.Arrays.asList[MAuthVersion](MAuthVersion.MWSV2) + ) + + val signerV1: MAuthRequestSigner = new MAuthRequestSigner( + UUID.fromString(APP_UUID_1), + PRIVATE_KEY_1, + CONST_EPOCH_TIME_PROVIDER, + java.util.Arrays.asList[MAuthVersion](MAuthVersion.MWS) + ) + + private def route(headers: Map[String, String]) = HttpRoutes + .of[IO] { case req @ POST -> Root / "v1" / "test" => + if (headers.forall(h => req.headers.headers.map(h => h.name.toString -> h.value).contains(h))) + Response[IO](Status.Ok).pure[IO] + else + Response[IO](Status.InternalServerError).pure[IO] + } + .orNotFound + + test("correctly send a customized content-type header for v2") { + + val simpleNewUnsignedRequest = + UnsignedRequest + .fromStringBodyUtf8( + httpMethod = "POST", + uri = new URI(s"/v1/test"), + body = "", + headers = Map("Content-Type" -> "application/json") + ) + + val signedReq = signerV2.signRequest(simpleNewUnsignedRequest) + + val client = Client.fromHttpApp(route(signedReq.mauthHeaders ++ simpleNewUnsignedRequest.headers)) + + val mAuthedClient = MAuthSigner(signerV2)(client) + + mAuthedClient + .status( + Request[IO]( + method = POST, + uri = Uri.unsafeFromString(s"/v1/test"), + headers = Headers(signedReq.mauthHeaders.toList ++ List("Content-Type" -> "application/json")) + ) + ) + .assertEquals(Status.Ok) + } + + test("correctly send a customized content-type header for v1") { + + val simpleNewUnsignedRequest = + UnsignedRequest + .fromStringBodyUtf8( + httpMethod = "POST", + uri = new URI(s"/v1/test"), + body = "", + headers = Map("Content-Type" -> "application/json") + ) + + val signedReq = signerV1.signRequest(simpleNewUnsignedRequest) + + val client = Client.fromHttpApp(route(signedReq.mauthHeaders ++ simpleNewUnsignedRequest.headers)) + + val mAuthedClient = MAuthSigner(signerV1)(client) + + mAuthedClient + .status( + Request[IO]( + method = POST, + uri = Uri.unsafeFromString(s"/v1/test"), + headers = Headers(signedReq.mauthHeaders.toList ++ List("Content-Type" -> "application/json")) + ) + ) + .assertEquals(Status.Ok) + } +} diff --git a/modules/mauth-signer-akka-http/src/main/scala/com/mdsol/mauth/MAuthRequestSigner.scala b/modules/mauth-signer-scala-core/src/main/scala/com/mdsol/mauth/MAuthRequestSigner.scala similarity index 98% rename from modules/mauth-signer-akka-http/src/main/scala/com/mdsol/mauth/MAuthRequestSigner.scala rename to modules/mauth-signer-scala-core/src/main/scala/com/mdsol/mauth/MAuthRequestSigner.scala index 3d3ff643..009fa66f 100644 --- a/modules/mauth-signer-akka-http/src/main/scala/com/mdsol/mauth/MAuthRequestSigner.scala +++ b/modules/mauth-signer-scala-core/src/main/scala/com/mdsol/mauth/MAuthRequestSigner.scala @@ -1,13 +1,12 @@ package com.mdsol.mauth +import com.mdsol.mauth.models.{SignedRequest => NewSignedRequest, UnsignedRequest => NewUnsignedRequest} +import com.mdsol.mauth.util.{CurrentEpochTimeProvider, EpochTimeProvider, MAuthKeysHelper} + import java.net.URI import java.security.PrivateKey import java.util.{List, UUID} - import scala.jdk.CollectionConverters._ -import models.{SignedRequest => NewSignedRequest, UnsignedRequest => NewUnsignedRequest} -import com.mdsol.mauth.util.{CurrentEpochTimeProvider, EpochTimeProvider, MAuthKeysHelper} - import scala.util.{Failure, Success, Try} /** Library agnostic representation of the data required for a request signing diff --git a/modules/mauth-signer-akka-http/src/main/scala/com/mdsol/mauth/models/SignedRequest.scala b/modules/mauth-signer-scala-core/src/main/scala/com/mdsol/mauth/models/SignedRequest.scala similarity index 100% rename from modules/mauth-signer-akka-http/src/main/scala/com/mdsol/mauth/models/SignedRequest.scala rename to modules/mauth-signer-scala-core/src/main/scala/com/mdsol/mauth/models/SignedRequest.scala diff --git a/modules/mauth-signer-akka-http/src/main/scala/com/mdsol/mauth/models/UnsignedRequest.scala b/modules/mauth-signer-scala-core/src/main/scala/com/mdsol/mauth/models/UnsignedRequest.scala similarity index 100% rename from modules/mauth-signer-akka-http/src/main/scala/com/mdsol/mauth/models/UnsignedRequest.scala rename to modules/mauth-signer-scala-core/src/main/scala/com/mdsol/mauth/models/UnsignedRequest.scala diff --git a/modules/mauth-signer-akka-http/src/test/scala/com/mdsol/mauth/MAuthRequestSignerSpec.scala b/modules/mauth-signer-scala-core/src/test/scala/com/mdsol/mauth/MAuthRequestSignerSpec.scala similarity index 77% rename from modules/mauth-signer-akka-http/src/test/scala/com/mdsol/mauth/MAuthRequestSignerSpec.scala rename to modules/mauth-signer-scala-core/src/test/scala/com/mdsol/mauth/MAuthRequestSignerSpec.scala index d234d9dc..a6533f18 100644 --- a/modules/mauth-signer-akka-http/src/test/scala/com/mdsol/mauth/MAuthRequestSignerSpec.scala +++ b/modules/mauth-signer-scala-core/src/test/scala/com/mdsol/mauth/MAuthRequestSignerSpec.scala @@ -24,10 +24,7 @@ import org.scalatest.matchers.should.Matchers import scala.concurrent.duration._ -class MAuthRequestSignerSpec extends AnyFlatSpec with Matchers with HttpClient with BeforeAndAfterAll with ScalaFutures { - - implicit val system: ActorSystem = ActorSystem() - var service = new WireMockServer(wireMockConfig.dynamicPort) +class MAuthRequestSignerSpec extends AnyFlatSpec with Matchers { Security.addProvider(new BouncyCastleProvider) @@ -54,12 +51,6 @@ class MAuthRequestSignerSpec extends AnyFlatSpec with Matchers with HttpClient w java.util.Arrays.asList[MAuthVersion](MAuthVersion.MWS) ) - override protected def beforeAll(): Unit = - service.start() - - override protected def afterAll(): Unit = - service.stop() - val simpleUnsignedRequest: UnsignedRequest = UnsignedRequest(uri = URI_EMPTY_PATH) val simpleNewUnsignedRequest: NewUnsignedRequest = NewUnsignedRequest.fromStringBodyUtf8(httpMethod = "GET", uri = URI_EMPTY_PATH, body = "", headers = Map.empty) @@ -132,42 +123,6 @@ class MAuthRequestSignerSpec extends AnyFlatSpec with Matchers with HttpClient w .mauthHeaders(MAuthRequest.MCC_AUTHENTICATION_HEADER_NAME) shouldBe EXPECTED_AUTHENTICATION_HEADER } - it should "correctly send a customized content-type header" in { - service.stubFor( - post(urlPathEqualTo(s"/v1/test")) - .willReturn(aResponse().withStatus(HttpStatus.SC_OK)) - .withHeader("Content-type", equalTo("application/json")) - ) - - val simpleNewUnsignedRequest = - NewUnsignedRequest - .fromStringBodyUtf8( - httpMethod = "POST", - uri = new URI(s"${service.baseUrl()}/v1/test"), - body = "", - headers = Map("Content-Type" -> ContentTypes.`application/json`.toString()) - ) - - whenReady(HttpClient.call(signerV2.signRequest(simpleNewUnsignedRequest).toAkkaHttpRequest), timeout = Timeout(5.seconds)) { response => - response.status shouldBe StatusCodes.OK - } - } - - it should "correctly send the default content type (text/plain UTF-8) when content type not specified" in { - service.stubFor( - post(urlPathEqualTo(s"/v1/test")) - .willReturn(aResponse().withStatus(HttpStatus.SC_OK)) - .withHeader("Content-type", equalTo(ContentTypes.`text/plain(UTF-8)`.toString())) - ) - - val simpleNewUnsignedRequest = - NewUnsignedRequest - .fromStringBodyUtf8(httpMethod = "POST", uri = new URI(s"${service.baseUrl()}/v1/test"), body = "", headers = Map()) - - whenReady(HttpClient.call(signerV2.signRequest(simpleNewUnsignedRequest).toAkkaHttpRequest), timeout = Timeout(5.seconds)) { response => - response.status shouldBe StatusCodes.OK - } - } "MAuthRequestSigner with V1 only required" should "add mauth headers to a request for V1 only " in { val authHeaders = signerV1.signRequest(simpleNewUnsignedRequest).mauthHeaders diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 2a2b823a..6f4d6d31 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -31,7 +31,8 @@ object Dependencies extends DependencyUtils { val sttpAkkaHttpBackend: ModuleID = "com.softwaremill.sttp.client3" %% "akka-http-backend" % Version.sttp val scalaLibCompat: ModuleID = "org.scala-lang.modules" %% "scala-collection-compat" % "2.4.3" val caffeine: ModuleID = "com.github.ben-manes.caffeine" % "caffeine" % "3.1.1" - val http4s: ModuleID = "org.http4s" %% "http4s-dsl" % Version.http4s + val http4sDsl: ModuleID = "org.http4s" %% "http4s-dsl" % Version.http4s + val http4sClient: ModuleID = "org.http4s" %% "http4s-client" % Version.http4s val enumeratum: ModuleID = "com.beachape" %% "enumeratum" % Version.enumeratum val log4cats = "org.typelevel" %% "log4cats-slf4j" % Version.log4cats