backend/app/controllers/api/Authentication.scala (57 lines of code) (raw):
package controllers.api
import pdi.jwt.JwtSession._
import pdi.jwt.JwtTime
import play.api.libs.json.Json
import play.api.mvc.{AnyContent, ControllerComponents, Request}
import services.Config
import services.users.UserManagement
import utils.{Epoch, Logging}
import utils.attempt._
import utils.auth._
import utils.auth.providers.UserProvider
import utils.controller.{AuthControllerComponents, OptionalAuthApiController}
import java.time.Clock
import play.api.Configuration
import scala.concurrent.ExecutionContext
class Authentication(override val controllerComponents: AuthControllerComponents, userAuthenticator: UserProvider, users: UserManagement, config: Config)(implicit conf: Configuration, clock: Clock)
extends OptionalAuthApiController with Logging {
def healthcheck() = noAuth.ApiAction {
Right(Ok("Ok"))
}
def token() = noAuth.ApiAction.attempt { implicit request:Request[AnyContent] =>
val time = Epoch.now
for {
user <- userAuthenticator.authenticate(request, time)
permissions <- users.getPermissions(user.username)
} yield {
val issuedAt = JwtTime.now
val loginExpiry = issuedAt + config.auth.timeouts.maxLoginAge.toMillis
val verificationExpiry = issuedAt + config.auth.timeouts.maxVerificationAge.toMillis
logger.info(s"User ${user.username} logged in. Login Expiry: $loginExpiry. Verification Expiry: $verificationExpiry")
NoContent
.addingToJwtSession(Token.USER_KEY, Json.toJson(user))
.addingToJwtSession(Token.ISSUED_AT_KEY, issuedAt)
.addingToJwtSession(Token.REFRESHED_AT_KEY, issuedAt)
.addingToJwtSession(Token.LOGIN_EXPIRY_KEY, loginExpiry)
.addingToJwtSession(Token.VERIFICATION_EXPIRY_KEY, verificationExpiry)
.addingToJwtSession(Token.PERMISSIONS, Json.toJson(permissions))
}
}
def invalidateExistingTokens() = auth.ApiAction.attempt { request: UserIdentityRequest[AnyContent] =>
for {
_ <- users.updateInvalidatedTime(request.user.username, System.currentTimeMillis())
} yield {
logger.info(s"User ${request.user.username} logged out")
NoContent
}
}
def generate2faToken(username: String) = noAuth.ApiAction.attempt { request: Request[AnyContent] =>
userAuthenticator.generate2faToken(username, config.app.label.getOrElse(request.host))
.map { token =>
Ok(Json.obj("secret" -> token.secret, "url" -> token.url))
}
}
def keepalive() = auth.ApiAction.attempt {
Attempt.Right(NoContent)
}
}