Skip to content

Commit

Permalink
add query param extraction and tests for AuthenticatorServiceLive
Browse files Browse the repository at this point in the history
  • Loading branch information
seakayone committed Dec 27, 2022
1 parent 0f0c5f6 commit b16f9cc
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 25 deletions.
Expand Up @@ -5,6 +5,7 @@ import akka.actor.ActorSystem
import zhttp.http._
import zio.Task
import zio.ZIO

import scala.concurrent.ExecutionContext

import org.knora.webapi.config.AppConfig
Expand All @@ -16,7 +17,7 @@ import org.knora.webapi.messages.v2.routing.authenticationmessages.KnoraCredenti
import org.knora.webapi.messages.v2.routing.authenticationmessages.KnoraCredentialsV2.KnoraSessionCredentialsV2
import org.knora.webapi.responders.ActorDeps
import org.knora.webapi.routing.Authenticator
import org.knora.webapi.routing.admin.AuthenticatorServiceLive.extractCredentialsFromHeader
import org.knora.webapi.routing.admin.AuthenticatorServiceLive.extractCredentialsFromRequest

case class AuthenticatorServiceLive(actorDeps: ActorDeps, appConfig: AppConfig, stringFormatter: StringFormatter)
extends AuthenticatorService {
Expand All @@ -28,14 +29,45 @@ case class AuthenticatorServiceLive(actorDeps: ActorDeps, appConfig: AppConfig,
private val authCookieName = Authenticator.calculateCookieName(appConfig)
override def getUser(request: Request): Task[UserADM] =
ZIO
.succeed(extractCredentialsFromHeader(request, authCookieName))
.succeed(extractCredentialsFromRequest(request, authCookieName))
.flatMap(credentials => ZIO.fromFuture(_ => Authenticator.getUserADMThroughCredentialsV2(credentials, appConfig)))
}

object AuthenticatorServiceLive {

// visible for testing
def extractCredentialsFromHeader(request: Request, cookieName: String)(implicit
def extractCredentialsFromRequest(request: Request, cookieName: String)(implicit
sf: StringFormatter
): Option[KnoraCredentialsV2] =
extractCredentialsFromParameters(request).orElse(extractCredentialsFromHeader(request, cookieName))

private def extractCredentialsFromParameters(request: Request)(implicit
sf: StringFormatter
): Option[KnoraCredentialsV2] =
extractUserPasswordFromParameters(request).orElse(extractTokenFromParameters(request))

private def getFirstValueFromParamKey(key: String, request: Request): Option[String] = {
val url = request.url
val params = url.queryParams
params.get(key).map(_.head)
}

private def extractUserPasswordFromParameters(request: Request)(implicit sf: StringFormatter) = {
val maybeIri = getFirstValueFromParamKey("iri", request)
val maybeEmail = getFirstValueFromParamKey("email", request)
val maybeUsername = getFirstValueFromParamKey("username", request)
val maybePassword = getFirstValueFromParamKey("password", request)
for {
_ <- List(maybeIri, maybeEmail, maybeUsername).flatten.headOption // given at least one of the following
password <- maybePassword
identifier = UserIdentifierADM(maybeIri, maybeEmail, maybeUsername)
} yield KnoraPasswordCredentialsV2(identifier, password)
}

private def extractTokenFromParameters(request: Request) =
getFirstValueFromParamKey("token", request).map(KnoraJWTTokenCredentialsV2)

private def extractCredentialsFromHeader(request: Request, cookieName: String)(implicit
sf: StringFormatter
): Option[KnoraCredentialsV2] =
extractBasicAuthEmail(request)
Expand Down
Expand Up @@ -2,6 +2,7 @@ package org.knora.webapi.routing.admin
import zhttp.http.Cookie
import zhttp.http.Headers
import zhttp.http.Request
import zhttp.http.URL
import zio.test._

import org.knora.webapi.messages.StringFormatter
Expand All @@ -16,27 +17,65 @@ object AuthenticatorServiceLiveSpec extends ZIOSpecDefault {

private implicit val sf = { StringFormatter.initForTest(); StringFormatter.getGeneralInstance }

val spec = suite("AuthenticatorServiceLiveSpec header extraction")(
test("should extract user email (basic auth)") {
val userMail: String = "user@example.com"
val req = Request().setHeaders(Headers.basicAuthorizationHeader(userMail, "pass"))
val actual = AuthenticatorServiceLive.extractCredentialsFromHeader(req, cookieName)
val expected = Some(KnoraPasswordCredentialsV2(UserIdentifierADM(maybeEmail = Some(userMail)), "pass"))
assertTrue(actual == expected)
},
test("should extract jwt token (bearer token)") {
val jwtToken = "someToken"
val req = Request().setHeaders(Headers.bearerAuthorizationHeader(jwtToken))
val actual = AuthenticatorServiceLive.extractCredentialsFromHeader(req, cookieName)
val expected = Some(KnoraJWTTokenCredentialsV2(jwtToken))
assertTrue(actual == expected)
},
test("should extract session cookie") {
val sessionCookieValue = "session"
val req = Request().setHeaders(Headers.cookie(Cookie(cookieName, sessionCookieValue)))
val actual = AuthenticatorServiceLive.extractCredentialsFromHeader(req, cookieName)
val expected = Some(KnoraSessionCredentialsV2(sessionCookieValue))
assertTrue(actual == expected)
}
val spec = suite("AuthenticatorServiceLiveSpec")(
suite("header extraction")(
test("should extract user email (basic auth)") {
val userMail: String = "user@example.com"
val req = Request().setHeaders(Headers.basicAuthorizationHeader(userMail, "pass"))
val actual = AuthenticatorServiceLive.extractCredentialsFromRequest(req, cookieName)
val expected = Some(KnoraPasswordCredentialsV2(UserIdentifierADM(maybeEmail = Some(userMail)), "pass"))
assertTrue(actual == expected)
},
test("should extract jwt token (bearer token)") {
val jwtToken = "someToken"
val req = Request().setHeaders(Headers.bearerAuthorizationHeader(jwtToken))
val actual = AuthenticatorServiceLive.extractCredentialsFromRequest(req, cookieName)
val expected = Some(KnoraJWTTokenCredentialsV2(jwtToken))
assertTrue(actual == expected)
},
test("should extract session cookie") {
val sessionCookieValue = "session"
val req = Request().setHeaders(Headers.cookie(Cookie(cookieName, sessionCookieValue)))
val actual = AuthenticatorServiceLive.extractCredentialsFromRequest(req, cookieName)
val expected = Some(KnoraSessionCredentialsV2(sessionCookieValue))
assertTrue(actual == expected)
}
),
suite("query parameter extraction")(
test("token") {
val jwtToken = "someToken"
val req = Request().setUrl(URL.empty.setQueryParams(Map("token" -> List(jwtToken))))
val actual = AuthenticatorServiceLive.extractCredentialsFromRequest(req, cookieName)
val expected = Some(KnoraJWTTokenCredentialsV2(jwtToken))
assertTrue(actual == expected)
},
test("username and password") {
val username = "someUsername"
val password = "somePassword"
val req =
Request().setUrl(URL.empty.setQueryParams(Map("username" -> List(username), "password" -> List(password))))
val actual = AuthenticatorServiceLive.extractCredentialsFromRequest(req, cookieName)
val expected = Some(KnoraPasswordCredentialsV2(UserIdentifierADM(maybeUsername = Some(username)), password))
assertTrue(actual == expected)
},
test("email and password") {
val email = "user@example.com"
val password = "somePassword"
val req =
Request().setUrl(URL.empty.setQueryParams(Map("email" -> List(email), "password" -> List(password))))
val actual = AuthenticatorServiceLive.extractCredentialsFromRequest(req, cookieName)
val expected = Some(KnoraPasswordCredentialsV2(UserIdentifierADM(maybeEmail = Some(email)), password))
assertTrue(actual == expected)
},
test("iri and password") {
val userIri = "http://rdfh.ch/users/someUser"
val password = "somePassword"
val req =
Request().setUrl(URL.empty.setQueryParams(Map("iri" -> List(userIri), "password" -> List(password))))
val actual = AuthenticatorServiceLive.extractCredentialsFromRequest(req, cookieName)
val expected = Some(KnoraPasswordCredentialsV2(UserIdentifierADM(maybeIri = Some(userIri)), password))
assertTrue(actual == expected)
}
)
)
}

0 comments on commit b16f9cc

Please sign in to comment.