in backend/app/utils/auth/AuthActionBuilder.scala [36:95]
private[auth] def invokeBlockWithTime[A](request: Request[A], block: (UserIdentityRequest[A]) => Future[Result],
now: Long): Future[Either[Failure, Result]] = {
implicit val implicitReq = request
val claimData = request.jwtSession.claimData
val maybeToken = claimData.validate[Token]
maybeToken match {
case (JsSuccess(token, _)) if token.loginExpiry > now =>
val isVerificationExpired = token.verificationExpiry <= now
for {
maybeDbUser <- if (isVerificationExpired) getUser(token.user.username).asFuture else Future.successful(Left(AuthenticationFailure("Verification hasn't expired", reportAsFailure = true)))
result <- block(new AuthenticatedRequest(token.user, request))
} yield {
if (isVerificationExpired) {
maybeDbUser match {
case Right(user) if user.invalidationTime.exists(token.issuedAt < _) =>
// The user has logged out
val msg = s"Authenticated failed because token was issued before database invalidation time"
logger.warn(token.user.asLogMarker, msg)
Left(AuthenticationFailure(msg, reportAsFailure = true))
case Left(failure) =>
logger.error(token.user.asLogMarker, "Authentication failed because user was not found in DB", failure.toThrowable)
Left(failure)
case Right(_) =>
val verificationExpiry = now + maxVerificationAge.toMillis
val expiryDateTime = LocalDateTime.ofInstant(
Instant.ofEpochMilli(verificationExpiry),
ZoneId.systemDefault()
)
logger.info(token.user.asLogMarker, s"Authentication succeeded, verification expired but token renewed. New verification expiry: ${expiryDateTime}")
Right(result
.refreshJwtSession
.addingToJwtSession(Token.VERIFICATION_EXPIRY_KEY, verificationExpiry)
.addingToJwtSession(Token.REFRESHED_AT_KEY, now)
)
}
} else {
Right(result
.refreshJwtSession
.addingToJwtSession(Token.REFRESHED_AT_KEY, now)
)
}
}
case JsSuccess(token, _) => {
val msg = s"Token is older than $maxLoginAge"
logger.info(token.user.asLogMarker, msg)
Future.successful(Left(AuthenticationFailure(msg, reportAsFailure = false)))
}
case JsError(errors) => {
val msg = s"Failed to parse token: $errors"
logger.warn(msg)
// This error happens whenever the token is missing,
// as a result of vulnerability scanners and occasionally developer testing/debugging
// (e.g. just opening https://giant.pfi.gutools.co.uk/api/search in your browser will fire this alarm).
// For this reason we don't want to get an alarm.
Future.successful(Left(AuthenticationFailure(msg, reportAsFailure = false)))
}
}
}