Product Engineer, CTO & a Beer Enthusiast
Experiments, thoughts and scripts documented for posterity.
package object authentication {
type ContextAuthenticator[T] = RequestContext => Future[Authentication[T]]
type Authentication[T] = Either[Rejection, T]
//. . . .
}
import com.typesafe.config.ConfigFactory
import scala.concurrent.ExecutionContext.Implicits.global
import spray.routing.AuthenticationFailedRejection
case class User(userName: String, token: String) {}
trait UserAuthentication {
val conf = ConfigFactory.load()
lazy val configusername = conf.getString("security.username")
lazy val configpassword = conf.getString("security.password")
def authenticateUser: ContextAuthenticator[User] = { ctx =>
{
//get username and password from the url
val usr = ctx.request.uri.query.get("usr").get
val pwd = ctx.request.uri.query.get("pwd").get
doAuth(usr, pwd)
}
}
private def doAuth(
userName: String,
password: String
): Future[Authentication[User]] = {
//here you can call database or a web service to authenticate the user
Future {
Either.cond(
password == configpassword && userName == configusername,
User(userName = userName, token = java.util.UUID.randomUUID.toString),
AuthenticationFailedRejection("CredentialsRejected")
)
}
}
}
Note that I am importing "scala.concurrent.ExecutionContext.Implicits.global", this is because futures require an ExecutionContext and I letting spray to use the default actor ExecutingContext. //implicit val system = ActorSystem("on-spray-can")
trait CustomerService
extends HttpService
with Json4sSupport
with UserAuthentication {
val customerRoutes =
path("addCustomer") {
post {
authenticate(authenticateUser) { user =>
entity(as[JObject]) { customerObj =>
complete {
//. . . .
}
}
}
}
} ~
path("getCustomer" / Segment) { customerId =>
get {
authenticate(authenticateUser) { user =>
{
complete {
//. . .
}
}
}
}
}
}
[Success GET] http://localhost:8080/getCustomer/520ed44941f19472d5f?usr=karthik&pwd=kufli
[Failed GET] http://localhost:8080/getCustomer/520ed44941f19472d5f9?usr=fail&pwd=wrong