Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: migrate to sttp.client4 #416

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ val Versions = new {
val jsoniter = "2.21.4"
val monix = "3.4.1"
val scalaTest = "3.2.16"
val sttp = "3.3.18"
val sttp = "4.0.0-M3"
val refined = "0.10.3"
val scalaCache = "1.0.0-M6"
}
Expand Down Expand Up @@ -97,7 +97,7 @@ lazy val oauth2 = crossProject(JSPlatform, JVMPlatform)
.settings(
name := "sttp-oauth2",
libraryDependencies ++= Seq(
"com.softwaremill.sttp.client3" %%% "core" % Versions.sttp,
"com.softwaremill.sttp.client4" %%% "core" % Versions.sttp,
"org.typelevel" %%% "cats-core" % Versions.catsCore,
"eu.timepit" %%% "refined" % Versions.refined,
"org.scalatest" %%% "scalatest" % Versions.scalaTest % Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.ocadotechnology.sttp.oauth2.common._
import com.ocadotechnology.sttp.oauth2.common.Error.OAuth2Error
import com.ocadotechnology.sttp.oauth2.json.JsonDecoder
import eu.timepit.refined.types.string.NonEmptyString
import sttp.client3.SttpBackend
import sttp.client4.GenericBackend
import sttp.model.Uri
import sttp.monad.MonadError
import sttp.monad.syntax._
Expand All @@ -30,16 +30,18 @@ object AccessTokenProvider {
clientId: NonEmptyString,
clientSecret: Secret[String]
)(
backend: SttpBackend[F, Any]
)(implicit decoder: JsonDecoder[ClientCredentialsToken.AccessTokenResponse], oAuth2ErrorDecoder: JsonDecoder[OAuth2Error]): AccessTokenProvider[F] =
backend: GenericBackend[F, Any]
)(
implicit decoder: JsonDecoder[ClientCredentialsToken.AccessTokenResponse],
oAuth2ErrorDecoder: JsonDecoder[OAuth2Error]
): AccessTokenProvider[F] =
new AccessTokenProvider[F] {
implicit val F: MonadError[F] = backend.responseMonad
implicit val F: MonadError[F] = backend.monad

override def requestToken(scope: Option[Scope]): F[ClientCredentialsToken.AccessTokenResponse] =
ClientCredentials
.requestToken(tokenUrl, clientId, clientSecret, scope)(backend)
.map(_.leftMap(OAuth2Exception.apply))
.flatMap(_.fold(F.error, F.unit))
.flatMap(_.leftMap(OAuth2Exception.apply).fold(F.error, F.unit))

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import cats.implicits._
import com.ocadotechnology.sttp.oauth2.common._
import com.ocadotechnology.sttp.oauth2.AuthorizationCodeProvider.Config
import com.ocadotechnology.sttp.oauth2.json.JsonDecoder
import sttp.client3._
import sttp.client4._
import sttp.model.HeaderNames
import sttp.model.Uri
import sttp.monad.MonadError
Expand Down Expand Up @@ -41,9 +41,9 @@ object AuthorizationCode {
clientId: String,
clientSecret: Secret[String]
)(
backend: SttpBackend[F, Any]
backend: GenericBackend[F, Any]
): F[RT] = {
implicit val F: MonadError[F] = backend.responseMonad
implicit val F: MonadError[F] = backend.monad
backend
.send {
basicRequest
Expand Down Expand Up @@ -72,9 +72,9 @@ object AuthorizationCode {
clientSecret: Secret[String],
scopeOverride: ScopeSelection
)(
backend: SttpBackend[F, Any]
backend: GenericBackend[F, Any]
): F[RT] = {
implicit val F: MonadError[F] = backend.responseMonad
implicit val F: MonadError[F] = backend.monad
backend
.send {
basicRequest
Expand Down Expand Up @@ -111,7 +111,7 @@ object AuthorizationCode {
clientSecret: Secret[String],
authCode: String
)(
backend: SttpBackend[F, Any]
backend: GenericBackend[F, Any]
): F[RT] =
convertAuthCodeToUser[F, Uri, RT](tokenUri, authCode, redirectUri.toString, clientId, clientSecret)(backend)

Expand All @@ -131,7 +131,7 @@ object AuthorizationCode {
refreshToken: String,
scopeOverride: ScopeSelection = ScopeSelection.KeepExisting
)(
backend: SttpBackend[F, Any]
backend: GenericBackend[F, Any]
): F[RT] =
performTokenRefresh[F, Uri, RT](tokenUri, refreshToken, clientId, clientSecret, scopeOverride)(backend)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.ocadotechnology.sttp.oauth2.json.JsonDecoder
import eu.timepit.refined.api.Refined
import eu.timepit.refined.refineV
import eu.timepit.refined.string.Url
import sttp.client3._
import sttp.client4._
import sttp.model.Uri

/** Provides set of functions to simplify oauth2 identity provider integration. Use the `instance` companion object method to create
Expand Down Expand Up @@ -123,7 +123,7 @@ object AuthorizationCodeProvider {
clientSecret: Secret[String],
pathsConfig: Config = Config.default
)(
backend: SttpBackend[F, Any]
backend: GenericBackend[F, Any]
): AuthorizationCodeProvider[Refined[String, Url], F] =
new AuthorizationCodeProvider[Refined[String, Url], F] {

Expand Down Expand Up @@ -165,7 +165,7 @@ object AuthorizationCodeProvider {
clientSecret: Secret[String],
pathsConfig: Config = Config.default
)(
backend: SttpBackend[F, Any]
backend: GenericBackend[F, Any]
): AuthorizationCodeProvider[Uri, F] =
new AuthorizationCodeProvider[Uri, F] {
private val tokenUri = baseUrl.addPath(pathsConfig.tokenPath.values)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import com.ocadotechnology.sttp.oauth2.common.Error.OAuth2Error
import com.ocadotechnology.sttp.oauth2.Introspection.TokenIntrospectionResponse
import com.ocadotechnology.sttp.oauth2.json.JsonDecoder
import eu.timepit.refined.types.string.NonEmptyString
import sttp.client3.SttpBackend
import sttp.client3.basicRequest
import sttp.client4.GenericBackend
import sttp.client4.basicRequest
import sttp.model.Uri
import sttp.monad.MonadError
import sttp.monad.syntax._
Expand All @@ -24,9 +24,12 @@ object ClientCredentials {
clientSecret: Secret[String],
scope: Option[Scope]
)(
backend: SttpBackend[F, Any]
)(implicit decoder: JsonDecoder[ClientCredentialsToken.AccessTokenResponse], oAuth2ErrorDecoder: JsonDecoder[OAuth2Error]): F[ClientCredentialsToken.Response] = {
implicit val F: MonadError[F] = backend.responseMonad
backend: GenericBackend[F, Any]
)(
implicit decoder: JsonDecoder[ClientCredentialsToken.AccessTokenResponse],
oAuth2ErrorDecoder: JsonDecoder[OAuth2Error]
): F[ClientCredentialsToken.Response] = {
implicit val F: MonadError[F] = backend.monad
backend
.send {
basicRequest
Expand Down Expand Up @@ -55,9 +58,12 @@ object ClientCredentials {
clientSecret: Secret[String],
token: Secret[String]
)(
backend: SttpBackend[F, Any]
)(implicit decoder: JsonDecoder[TokenIntrospectionResponse], oAuth2ErrorDecoder: JsonDecoder[OAuth2Error]): F[Introspection.Response] = {
implicit val F: MonadError[F] = backend.responseMonad
backend: GenericBackend[F, Any]
)(
implicit decoder: JsonDecoder[TokenIntrospectionResponse],
oAuth2ErrorDecoder: JsonDecoder[OAuth2Error]
): F[Introspection.Response] = {
implicit val F: MonadError[F] = backend.monad
backend
.send {
basicRequest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.ocadotechnology.sttp.oauth2.common.Error.OAuth2Error
import com.ocadotechnology.sttp.oauth2.Introspection.TokenIntrospectionResponse
import com.ocadotechnology.sttp.oauth2.json.JsonDecoder
import eu.timepit.refined.types.string.NonEmptyString
import sttp.client3.SttpBackend
import sttp.client4.GenericBackend
import sttp.model.Uri

/** Tagless Final algebra for ClientCredentials token requests and verification.
Expand All @@ -24,7 +24,7 @@ object ClientCredentialsProvider {
clientId: NonEmptyString,
clientSecret: Secret[String]
)(
backend: SttpBackend[F, Any]
backend: GenericBackend[F, Any]
)(
implicit accessTokenResponseDecoder: JsonDecoder[ClientCredentialsToken.AccessTokenResponse],
tokenIntrospectionResponseDecoder: JsonDecoder[TokenIntrospectionResponse],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.ocadotechnology.sttp.oauth2.common.Error
import com.ocadotechnology.sttp.oauth2.common.Error.OAuth2Error
import com.ocadotechnology.sttp.oauth2.common.Scope
import com.ocadotechnology.sttp.oauth2.json.JsonDecoder
import sttp.client3.ResponseAs
import sttp.client4.ResponseAs

import scala.concurrent.duration.FiniteDuration

Expand All @@ -15,7 +15,7 @@ object ClientCredentialsToken {
def response(
implicit decoder: JsonDecoder[ClientCredentialsToken.AccessTokenResponse],
oAuth2ErrorDecoder: JsonDecoder[OAuth2Error]
): ResponseAs[Response, Any] =
): ResponseAs[Response] =
common.responseWithCommonError[ClientCredentialsToken.AccessTokenResponse]

final case class AccessTokenResponse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.ocadotechnology.sttp.oauth2
import com.ocadotechnology.sttp.oauth2.common._
import com.ocadotechnology.sttp.oauth2.common.Error.OAuth2Error
import com.ocadotechnology.sttp.oauth2.json.JsonDecoder
import sttp.client3.ResponseAs
import sttp.client4.ResponseAs

import java.time.Instant

Expand All @@ -14,7 +14,7 @@ object Introspection {
def response(
implicit decoder: JsonDecoder[TokenIntrospectionResponse],
oAuth2ErrorDecoder: JsonDecoder[OAuth2Error]
): ResponseAs[Response, Any] =
): ResponseAs[Response] =
common.responseWithCommonError[TokenIntrospectionResponse]

// Defined by https://datatracker.ietf.org/doc/html/rfc7662#section-2.2 with some extra fields
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.ocadotechnology.sttp.oauth2
import com.ocadotechnology.sttp.oauth2.common.Error
import com.ocadotechnology.sttp.oauth2.common.Error.OAuth2Error
import com.ocadotechnology.sttp.oauth2.json.JsonDecoder
import sttp.client3.ResponseAs
import sttp.client4.ResponseAs

object OAuth2Token {

Expand All @@ -13,7 +13,7 @@ object OAuth2Token {
def response(
implicit decoder: JsonDecoder[ExtendedOAuth2TokenResponse],
oAuth2ErrorDecoder: JsonDecoder[OAuth2Error]
): ResponseAs[Response, Any] =
): ResponseAs[Response] =
common.responseWithCommonError[ExtendedOAuth2TokenResponse]

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.ocadotechnology.sttp.oauth2.common._
import com.ocadotechnology.sttp.oauth2.common.Error.OAuth2Error
import com.ocadotechnology.sttp.oauth2.json.JsonDecoder
import eu.timepit.refined.types.string.NonEmptyString
import sttp.client3._
import sttp.client4._
import sttp.model.Uri
import sttp.monad.MonadError
import sttp.monad.syntax._
Expand All @@ -31,12 +31,12 @@ object PasswordGrant {
clientSecret: Secret[String],
scope: Scope
)(
backend: SttpBackend[F, Any]
backend: GenericBackend[F, Any]
)(
implicit decoder: JsonDecoder[ExtendedOAuth2TokenResponse],
oAuth2ErrorDecoder: JsonDecoder[OAuth2Error]
): F[OAuth2Token.Response] = {
implicit val F: MonadError[F] = backend.responseMonad
implicit val F: MonadError[F] = backend.monad
backend
.send {
basicRequest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.ocadotechnology.sttp.oauth2.common._
import com.ocadotechnology.sttp.oauth2.common.Error.OAuth2Error
import com.ocadotechnology.sttp.oauth2.json.JsonDecoder
import eu.timepit.refined.types.string.NonEmptyString
import sttp.client3.SttpBackend
import sttp.client4.GenericBackend
import sttp.model.Uri
import sttp.monad.MonadError
import sttp.monad.syntax._
Expand All @@ -24,12 +24,12 @@ object PasswordGrantProvider {
clientId: NonEmptyString,
clientSecret: Secret[String]
)(
backend: SttpBackend[F, Any]
backend: GenericBackend[F, Any]
)(
implicit decoder: JsonDecoder[ExtendedOAuth2TokenResponse],
oAuth2ErrorDecoder: JsonDecoder[OAuth2Error]
): PasswordGrantProvider[F] = { (user: User, scope: Scope) =>
implicit val F: MonadError[F] = backend.responseMonad
implicit val F: MonadError[F] = backend.monad
PasswordGrant
.requestToken(tokenUrl, user, clientId, clientSecret, scope)(backend)
.map(_.leftMap(OAuth2Exception.apply))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,3 @@ private[oauth2] final case class RefreshTokenResponse(
)

}

Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,22 @@ import com.ocadotechnology.sttp.oauth2.common.Scope
import com.ocadotechnology.sttp.oauth2.json.JsonDecoder
import eu.timepit.refined.types.string.NonEmptyString
import sttp.capabilities.Effect
import sttp.client3._
import sttp.client4._
import sttp.client4.wrappers.DelegateBackend
import sttp.model.Uri
import sttp.monad.MonadError
import sttp.monad.syntax._

/** SttpBackend, that adds auth bearer headers to every request.
*/
final class SttpOauth2ClientCredentialsBackend[F[_], P] private (
delegate: SttpBackend[F, P],
delegate: GenericBackend[F, P],
accessTokenProvider: AccessTokenProvider[F],
scope: Option[common.Scope]
) extends DelegateSttpBackend(delegate) {
implicit val F: MonadError[F] = delegate.responseMonad
) extends DelegateBackend(delegate) {
implicit val F: MonadError[F] = delegate.monad

override def send[T, R >: P with Effect[F]](request: Request[T, R]): F[Response[T]] = for {
override def send[T](request: GenericRequest[T, P with Effect[F]]): F[Response[T]] = for {
token <- accessTokenProvider.requestToken(scope)
response <- delegate.send(request.auth.bearer(token.accessToken.value))
} yield response
Expand All @@ -35,7 +36,7 @@ object SttpOauth2ClientCredentialsBackend {
)(
scope: Option[Scope]
)(
backend: SttpBackend[F, P]
backend: GenericBackend[F, P]
)(
implicit decoder: JsonDecoder[ClientCredentialsToken.AccessTokenResponse],
oAuth2ErrorDecoder: JsonDecoder[OAuth2Error]
Expand All @@ -49,7 +50,7 @@ object SttpOauth2ClientCredentialsBackend {
)(
scope: Option[Scope]
)(
backend: SttpBackend[F, P]
backend: GenericBackend[F, P]
) =
new SttpOauth2ClientCredentialsBackend[F, P](backend, accessTokenProvider, scope)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.ocadotechnology.sttp.oauth2.common.Error.OAuth2Error
import com.ocadotechnology.sttp.oauth2.Introspection.TokenIntrospectionResponse
import com.ocadotechnology.sttp.oauth2.json.JsonDecoder
import eu.timepit.refined.types.string.NonEmptyString
import sttp.client3.SttpBackend
import sttp.client4.GenericBackend
import sttp.model.Uri
import sttp.monad.MonadError
import sttp.monad.syntax._
Expand All @@ -32,13 +32,13 @@ object TokenIntrospection {
clientId: NonEmptyString,
clientSecret: Secret[String]
)(
backend: SttpBackend[F, Any]
backend: GenericBackend[F, Any]
)(
implicit decoder: JsonDecoder[TokenIntrospectionResponse],
oAuth2ErrorDecoder: JsonDecoder[OAuth2Error]
): TokenIntrospection[F] =
new TokenIntrospection[F] {
implicit val F: MonadError[F] = backend.responseMonad
implicit val F: MonadError[F] = backend.monad

override def introspect(token: Secret[String]): F[Introspection.TokenIntrospectionResponse] =
ClientCredentials
Expand Down
Loading