- All rest services except login should be secured
- Login service returns JWT token as part of the header
- Before to access any other services we have to validate JWT token in the header of a request
Our route without security has next view:
lazy val routes: Route =
pathPrefix("api") {
pathPrefix("login") {
post {
parameter("email", "password") { (email, password) =>
val loginResult: Future[Boolean] = loginService.login(email, password)
onSuccess(loginResult) { result =>
if(result) {
respondWithHeader(RawHeader("TOKEN", createJwtToken(email))) {
complete(StatusCodes.OK)
}else{
complete(StatusCodes.Unauthorized)
}
}
}
}
}
} ~
pathPrefix("myService") {
val data = myService.search()
complite(data)
}
}
Now let's write a method which will wrap invocation of all services which we want to secure:def authenticated: Directive1[String] =
Directives.optionalHeaderValueByName("TOKEN").flatMap {
case Some(jwt) if !isJwtTokenValid(jwt) =>
Directives.complete(StatusCodes.Unauthorized -> "Invalid token.")
case Some(jwt) if isJwtTokenExpired(jwt) =>
Directives.complete(StatusCodes.Unauthorized -> "Token expired.")
case Some(jwt) if !isJwtTokenExpired(jwt) => decodeJwtToken(jwt) match {
case Some(email) =>
Directives.provide(email)
case None =>
Directives.complete(StatusCodes.Unauthorized)
}
case _ => Directives.complete(StatusCodes.Unauthorized)
}
And the last step is to invoke it before our services:
pathPrefix("api") {
pathPrefix("login") {
...
} ~
authenticated{email =>
pathPrefix("myService") {
val data = myService.search()
complite(data)
}
}
}
No comments:
Post a Comment