app/controllers/DesktopLogin.scala (62 lines of code) (raw):
package controllers
import com.gu.pandomainauth.model._
import com.gu.pandomainauth.service.{CookieUtils, OAuthException}
import com.gu.pandomainauth.{PanDomain, PanDomainAuthSettingsRefresher}
import play.api.Logging
import play.api.mvc.{Action, AnyContent}
import java.net.URLEncoder
import scala.concurrent.ExecutionContext
import scala.concurrent.duration.DurationInt
class DesktopLogin(
deps: LoginControllerComponents,
panDomainSettings: PanDomainAuthSettingsRefresher
) extends LoginController(deps, panDomainSettings) with Logging {
override lazy val authCallbackUrl: String = deps.config.host + "/desktop/oauthCallback"
implicit private val ec: ExecutionContext = deps.executionContext
def clientSideRedirectToDesktopLogin = Action {
val desktopLoginUrl = controllers.routes.DesktopLogin.desktopLogin().url
Ok(views.html.clientSideRedirectToLogin(desktopLoginUrl))
}
def desktopLogin: Action[AnyContent] = Action.async { implicit request =>
val antiForgeryToken = OAuth.generateAntiForgeryToken()
OAuth.redirectToOAuthProvider(antiForgeryToken, None)(ec) map { _.withSession {
request.session + (ANTI_FORGERY_KEY -> antiForgeryToken)
}}
}
def authStatus: Action[AnyContent] = Action { request =>
request.headers.get(AUTHORIZATION) match {
case Some(s"GU-Desktop-Panda $token") =>
PanDomain.authStatus(token,
verification = panDomainSettings.settings.signingAndVerification,
validateUser = PanDomain.guardianValidation,
apiGracePeriod = 9.hours.toMillis,
system = panDomainSettings.system,
cacheValidation = false,
forceExpiry = false
) match {
case Expired(_) => new Status(419)
case GracePeriod(authedUser) => Ok(s"hello ${authedUser.user.email} - you're in a grace period")
case Authenticated(authedUser) => Ok(s"hello ${authedUser.user.email}")
case NotAuthorized(_) => Forbidden
case InvalidCookie(_) => BadRequest
case NotAuthenticated => Unauthorized
}
case _ => Unauthorized
}
}
def desktopOauthCallback(): Action[AnyContent] = Action.async { implicit request =>
val token =
request.session.get(ANTI_FORGERY_KEY).getOrElse(throw new OAuthException("missing anti forgery token"))
OAuth.validatedUserIdentity(token)(request, deps.executionContext, wsClient).map { claimedAuth =>
logger.debug("fresh user desktop login")
val authedUserData = claimedAuth.copy(authenticatingSystem = "login-desktop", multiFactor = checkMultifactor(claimedAuth))
if (validateUser(authedUserData)) {
val token = CookieUtils.generateCookieData(authedUserData, panDomainSettings.settings.signingAndVerification)
Redirect(s"gu-panda://desktop?token=${URLEncoder.encode(token, "UTF-8")}&stage=${deps.config.stage.toLowerCase}")
.withSession(session = request.session - ANTI_FORGERY_KEY - LOGIN_ORIGIN_KEY)
} else {
showUnauthedMessage(invalidUserMessage(claimedAuth))
}
}
}
}