diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/auth/OpenIdAuthService.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/auth/OpenIdAuthService.scala index 050be8b544..cea4eeabed 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/auth/OpenIdAuthService.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/auth/OpenIdAuthService.scala @@ -9,9 +9,11 @@ import ch.epfl.bluebrain.nexus.delta.kernel.Secret import ch.epfl.bluebrain.nexus.delta.kernel.effect.migration.MigrateEffectSyntax import ch.epfl.bluebrain.nexus.delta.kernel.utils.IOUtils import ch.epfl.bluebrain.nexus.delta.sdk.auth.Credentials.ClientCredentials -import ch.epfl.bluebrain.nexus.delta.sdk.error.AuthTokenError.{AuthTokenHttpError, AuthTokenNotFoundInResponse, ExpiryNotFoundInResponse} +import ch.epfl.bluebrain.nexus.delta.sdk.error.AuthTokenError.{AuthTokenHttpError, AuthTokenNotFoundInResponse, ExpiryNotFoundInResponse, RealmIsDeprecated} import ch.epfl.bluebrain.nexus.delta.sdk.http.HttpClient import ch.epfl.bluebrain.nexus.delta.sdk.realms.Realms +import ch.epfl.bluebrain.nexus.delta.sdk.realms.model.Realm +import ch.epfl.bluebrain.nexus.delta.sourcing.model.Label import io.circe.Json import monix.bio.{IO, UIO} @@ -22,8 +24,8 @@ class OpenIdAuthService(httpClient: HttpClient, realms: Realms)(implicit clock: def auth(credentials: ClientCredentials): UIO[AccessTokenWithMetadata] = { for { - realm <- realms.fetch(credentials.realm).toUIO - response <- requestToken(realm.value.tokenEndpoint, credentials.user, credentials.password) + realm <- findRealm(credentials.realm) + response <- requestToken(realm.tokenEndpoint, credentials.user, credentials.password) (token, validDuration) <- parseResponse(response) now <- IOUtils.instant } yield { @@ -31,6 +33,13 @@ class OpenIdAuthService(httpClient: HttpClient, realms: Realms)(implicit clock: } } + private def findRealm(id: Label): UIO[Realm] = { + for { + realm <- realms.fetch(id).toUIO + _ <- UIO.when(realm.deprecated)(UIO.terminate(RealmIsDeprecated(realm.value))) + } yield realm.value + } + private def requestToken(tokenEndpoint: Uri, user: String, password: Secret[String]): UIO[Json] = { httpClient .toJson( diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/error/AuthTokenError.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/error/AuthTokenError.scala index a37dc7593a..2f1bd3e3f8 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/error/AuthTokenError.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/error/AuthTokenError.scala @@ -5,6 +5,7 @@ import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.ContextValue import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.JsonLdContext.keywords import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.encoder.JsonLdEncoder import ch.epfl.bluebrain.nexus.delta.sdk.http.HttpClientError +import ch.epfl.bluebrain.nexus.delta.sdk.realms.model.Realm import io.circe.syntax.{EncoderOps, KeyOps} import io.circe.{DecodingFailure, Encoder, JsonObject} @@ -32,6 +33,12 @@ object AuthTokenError { final case class ExpiryNotFoundInResponse(failure: DecodingFailure) extends AuthTokenError(s"Expiry not found in auth response: ${failure.reason}") + /** + * Signals that the realm specified for authentication is deprecated + */ + final case class RealmIsDeprecated(realm: Realm) + extends AuthTokenError(s"Realm for authentication is deprecated: ${realm.label}") + implicit val identityErrorEncoder: Encoder.AsObject[AuthTokenError] = { Encoder.AsObject.instance[AuthTokenError] { case AuthTokenHttpError(r) => @@ -40,6 +47,8 @@ object AuthTokenError { JsonObject(keywords.tpe -> "AuthTokenNotFoundInResponse".asJson, "reason" := r.message) case ExpiryNotFoundInResponse(r) => JsonObject(keywords.tpe -> "ExpiryNotFoundInResponse".asJson, "reason" := r.message) + case r: RealmIsDeprecated => + JsonObject(keywords.tpe := "RealmIsDeprecated", "reason" := r.getMessage) } }