All Downloads are FREE. Search and download functionalities are using the official Maven repository.

pl.touk.nussknacker.ui.security.oidc.GenericOidcService.scala Maven / Gradle / Ivy

The newest version!
package pl.touk.nussknacker.ui.security.oidc

import com.typesafe.scalalogging.LazyLogging
import io.circe.Decoder
import io.circe.generic.extras.{Configuration, ConfiguredJsonCodec, JsonKey}
import pl.touk.nussknacker.ui.security.oauth2._
import sttp.client3.SttpBackend

import scala.concurrent.duration.FiniteDuration
import scala.concurrent.{ExecutionContext, Future}

trait OidcAuthorizationData extends OAuth2AuthorizationData {
  val idToken: Option[String]
}

/** Apart from backward compatibility of the configuration, this class is not intended for direct instantiation.
  * There is a concrete subclass [[pl.touk.nussknacker.ui.security.oidc.OidcService]] in the Oidc authentication
  * provider for OIDC compliant authorization servers.
  */
class GenericOidcService[
    UserData <: JwtStandardClaims: Decoder,
    AuthorizationData <: OidcAuthorizationData
](clientApi: OAuth2ClientApi[UserData, AuthorizationData], configuration: OAuth2Configuration)(
    implicit ec: ExecutionContext
) extends JwtOAuth2Service[UserData, AuthorizationData, UserData](clientApi, configuration)
    with LazyLogging {

  protected val useIdToken: Boolean = configuration.jwt.exists(_.userinfoFromIdToken)

  override protected def authenticateUser(authorization: AuthorizationData): Future[UserData] = {
    if (useIdToken) {
      val idToken = authorization.idToken.get
      introspectJwtToken[UserData](idToken)
        .filter(_.audienceAsList == List(configuration.clientId))
    } else {
      super.authenticateUser(authorization)
    }
  }

}

@ConfiguredJsonCodec final case class DefaultOidcAuthorizationData(
    @JsonKey("access_token") accessToken: String,
    @JsonKey("token_type") tokenType: String,
    @JsonKey("refresh_token") refreshToken: Option[String] = None,
    @JsonKey("expires_in") expirationPeriod: Option[FiniteDuration] = None,
    @JsonKey("id_token") idToken: Option[String] = None
) extends OidcAuthorizationData

object DefaultOidcAuthorizationData extends RelativeSecondsCodecs {
  implicit val config: Configuration = Configuration.default
}

object GenericOidcService {

  def apply(configuration: OAuth2Configuration)(
      implicit ec: ExecutionContext,
      backend: SttpBackend[Future, Any]
  ): GenericOidcService[OidcUserInfo, DefaultOidcAuthorizationData] =
    new GenericOidcService(
      OAuth2ClientApi[OidcUserInfo, DefaultOidcAuthorizationData](configuration),
      configuration
    ) {

      override protected def toIntrospectedData(claims: OidcUserInfo): IntrospectedAccessTokenData = {
        super.toIntrospectedData(claims).copy(roles = claims.roles)
      }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy