diff options
author | vlad <vlad@drivergrp.com> | 2016-10-03 14:25:24 -0700 |
---|---|---|
committer | vlad <vlad@drivergrp.com> | 2016-10-03 14:25:24 -0700 |
commit | 94c324e249ab3e5848191602c3549cef350e83b1 (patch) | |
tree | 01ef6a4da7d3638e160fd2d25b4c621c3b793fe0 /src/main/scala/com/drivergrp/core | |
parent | d53f8227eea53871b08829909760b9e37e22a817 (diff) | |
download | driver-core-0.9.0.tar.gz driver-core-0.9.0.tar.bz2 driver-core-0.9.0.zip |
Auth service providing directive and using external source of token-to-user resolutionv0.9.0
Diffstat (limited to 'src/main/scala/com/drivergrp/core')
-rw-r--r-- | src/main/scala/com/drivergrp/core/auth.scala | 68 | ||||
-rw-r--r-- | src/main/scala/com/drivergrp/core/rest.scala | 4 |
2 files changed, 46 insertions, 26 deletions
diff --git a/src/main/scala/com/drivergrp/core/auth.scala b/src/main/scala/com/drivergrp/core/auth.scala index 2d61cbf..6b8cdaa 100644 --- a/src/main/scala/com/drivergrp/core/auth.scala +++ b/src/main/scala/com/drivergrp/core/auth.scala @@ -3,6 +3,10 @@ package com.drivergrp.core import akka.http.scaladsl.model.headers.HttpChallenges import akka.http.scaladsl.server.AuthenticationFailedRejection.CredentialsRejected +import scala.concurrent.Future +import scala.util.{Failure, Success, Try} +import scalaz.OptionT + object auth { sealed trait Permission @@ -79,39 +83,55 @@ object auth { final case class PasswordHash(value: String) - def extractUser(authToken: AuthToken): User = { - new User() { - override def id: Id[User] = Id[User](1L) - override def roles: Set[Role] = Set(PathologistRole) - } - - // TODO: or reject(ValidationRejection(s"Wasn't able to extract user for the token provided")) if none + object AuthService { + val AuthenticationTokenHeader = "WWW-Authenticate" } - object directives { + trait AuthService[U <: User] { + import akka.http.scaladsl.server._ import Directives._ - val AuthenticationTokenHeader = "WWW-Authenticate" + protected def authStatus(authToken: AuthToken): OptionT[Future, U] - def authorize(permission: Permission): Directive1[AuthToken] = { + def authorize(permission: Permission): Directive1[(AuthToken, U)] = { parameters('authToken.?).flatMap { parameterTokenValue => - optionalHeaderValueByName(AuthenticationTokenHeader).flatMap { headerTokenValue => - headerTokenValue.orElse(parameterTokenValue) match { - case Some(tokenValue) => - val token = AuthToken(Base64[Macaroon](tokenValue)) - - if (extractUser(token).roles.exists(_.hasPermission(permission))) provide(token) - else { - val challenge = HttpChallenges.basic(s"User does not have the required permission $permission") - reject(AuthenticationFailedRejection(CredentialsRejected, challenge)) - } - - case None => - reject(MissingHeaderRejection("WWW-Authenticate")) - } + optionalHeaderValueByName(AuthService.AuthenticationTokenHeader).flatMap { headerTokenValue => + verifyAuthToken(headerTokenValue.orElse(parameterTokenValue), permission) } } } + + private def verifyAuthToken(tokenOption: Option[String], permission: Permission): Directive1[(AuthToken, U)] = + tokenOption match { + case Some(tokenValue) => + val token = AuthToken(Base64[Macaroon](tokenValue)) + + onComplete(authStatus(token).run).flatMap { tokenUserResult => + checkPermissions(tokenUserResult, permission, token) + } + + case None => + reject(MissingHeaderRejection(AuthService.AuthenticationTokenHeader)) + } + + private def checkPermissions(userResult: Try[Option[U]], + permission: Permission, + token: AuthToken): Directive1[(AuthToken, U)] = { + userResult match { + case Success(Some(user)) => + if (user.roles.exists(_.hasPermission(permission))) provide(token -> user) + else { + val challenge = HttpChallenges.basic(s"User does not have the required permission $permission") + reject(AuthenticationFailedRejection(CredentialsRejected, challenge)) + } + + case Success(None) => + reject(ValidationRejection(s"Wasn't able to find authenticated user for the token provided")) + + case Failure(t) => + reject(ValidationRejection(s"Wasn't able to verify token for authenticated user", Some(t))) + } + } } } diff --git a/src/main/scala/com/drivergrp/core/rest.scala b/src/main/scala/com/drivergrp/core/rest.scala index 0d718c9..d97e13e 100644 --- a/src/main/scala/com/drivergrp/core/rest.scala +++ b/src/main/scala/com/drivergrp/core/rest.scala @@ -8,7 +8,7 @@ import akka.http.scaladsl.unmarshalling.Unmarshal import akka.stream.ActorMaterializer import akka.stream.scaladsl.Flow import akka.util.ByteString -import com.drivergrp.core.auth.AuthToken +import com.drivergrp.core.auth.{AuthService, AuthToken} import com.drivergrp.core.crypto.Crypto import com.drivergrp.core.logging.Logger import com.drivergrp.core.stats.Stats @@ -55,7 +55,7 @@ object rest { val request = requestStub .withEntity(requestStub.entity.transformDataBytes(encryptionFlow)) .withHeaders( - RawHeader(auth.directives.AuthenticationTokenHeader, s"Macaroon ${authToken.value.value}")) + RawHeader(AuthService.AuthenticationTokenHeader, authToken.value.value)) log.audit(s"Sending to ${request.uri} request $request") |