diff --git a/pan-domain-auth-core/src/main/scala/com/gu/pandomainauth/service/Google2FAGroupChecker.scala b/pan-domain-auth-core/src/main/scala/com/gu/pandomainauth/service/Google2FAGroupChecker.scala index 262577c..52a5b19 100644 --- a/pan-domain-auth-core/src/main/scala/com/gu/pandomainauth/service/Google2FAGroupChecker.scala +++ b/pan-domain-auth-core/src/main/scala/com/gu/pandomainauth/service/Google2FAGroupChecker.scala @@ -13,25 +13,32 @@ import com.google.auth.oauth2.ServiceAccountCredentials import scala.jdk.CollectionConverters._ import com.gu.pandomainauth.model.{AuthenticatedUser, Google2FAGroupSettings} -import org.slf4j.LoggerFactory +import org.slf4j.{Logger, LoggerFactory} + +import scala.util.{Failure, Success, Try} class GroupChecker(config: Google2FAGroupSettings, bucketName: String, s3Client: AmazonS3, appName: String) { - private val logger = LoggerFactory.getLogger(this.getClass) + protected val logger: Logger = LoggerFactory.getLogger(this.getClass) private val transport = GoogleNetHttpTransport.newTrustedTransport() - private val jsonFactory = GsonFactory.getDefaultInstance() + private val jsonFactory = GsonFactory.getDefaultInstance + + private val scopes = List( + DirectoryScopes.ADMIN_DIRECTORY_GROUP_READONLY, + DirectoryScopes.ADMIN_DIRECTORY_USER_READONLY + ).asJavaCollection private val credentials = ServiceAccountCredentials.newBuilder() .setClientId("not-needed-but-must-not-be-null") .setClientEmail(config.serviceAccountId) - .setScopes(List(DirectoryScopes.ADMIN_DIRECTORY_GROUP_READONLY).asJavaCollection) + .setScopes(scopes) .setServiceAccountUser(config.adminUserEmail) .setPrivateKey(loadServiceAccountPrivateKey) .build private val httpCredentialsAdapter = new HttpCredentialsAdapter(credentials) - protected val directory = new Directory.Builder(transport, jsonFactory, httpCredentialsAdapter) + protected val directory: Directory = new Directory.Builder(transport, jsonFactory, httpCredentialsAdapter) .setApplicationName(appName) .build @@ -58,6 +65,10 @@ class GroupChecker(config: Google2FAGroupSettings, bucketName: String, s3Client: } } + protected def has2fa(userEmail: String): Boolean = withGoogle4xxErrorHandling { + directory.users().get(userEmail).setFields("isEnrolledIn2Sv").execute().getIsEnrolledIn2Sv + } + protected def hasGroup(query: Directory#Groups#List, groupId: String): Boolean = withGoogle4xxErrorHandling { val groupsResponse = query.execute() @@ -72,7 +83,7 @@ class GroupChecker(config: Google2FAGroupSettings, bucketName: String, s3Client: private def hasMoreGroups(groupsResponse: Groups): Boolean = { val token = groupsResponse.getNextPageToken - token != null && token.length > 0 + token != null && token.nonEmpty } } @@ -89,6 +100,13 @@ class GoogleGroupChecker(config: Google2FAGroupSettings, bucketName: String, s3C class Google2FAGroupChecker(config: Google2FAGroupSettings, bucketName: String, s3Client: AmazonS3, appName: String) extends GroupChecker(config, bucketName, s3Client, appName) { def checkMultifactor(authenticatedUser: AuthenticatedUser): Boolean = { + val has2faEnrol = Try { has2fa(authenticatedUser.user.email) } + // currently do nothing with the result but log, to better understand how this change would affect the tools + has2faEnrol match { + case Success(true) => logger.info(s"${authenticatedUser.user.email} has 2fa enrolled") + case Success(false) => logger.error(s"${authenticatedUser.user.email} does not have 2fa enrolled") + case Failure(cause) => logger.error(s"failed to get 2fa enrolled status for ${authenticatedUser.user.email}", cause) + } hasGroup(authenticatedUser.user.email, config.multifactorGroupId) } diff --git a/pan-domain-auth-play/src/main/scala/com/gu/pandomainauth/action/Actions.scala b/pan-domain-auth-play/src/main/scala/com/gu/pandomainauth/action/Actions.scala index 7101ce0..bd89a74 100644 --- a/pan-domain-auth-play/src/main/scala/com/gu/pandomainauth/action/Actions.scala +++ b/pan-domain-auth-play/src/main/scala/com/gu/pandomainauth/action/Actions.scala @@ -131,10 +131,10 @@ trait AuthActions { /** * invoked when the user is not logged in a can't be authed - this may be when the user is not valid in yur system - * or when they have exoplicitly logged out. + * or when they have explicitly logged out. * - * Override this to add a logged out screen and display maeesages for your app. The default implementation is - * to ust return a 403 response + * Override this to add a logged out screen and display messages for your app. The default implementation is + * to just return a 403 response * * @param message * @param request