Skip to content

Instantly share code, notes, and snippets.

@tobnee
Created February 27, 2014 15:57
Show Gist options
  • Save tobnee/9252893 to your computer and use it in GitHub Desktop.
Save tobnee/9252893 to your computer and use it in GitHub Desktop.
A simple way to use Play Filters to enforce some basic authentication rules. Based on this pattern more elaborate rules can be implemented.
object Global extends WithFilters(
new OpenIdAuthFilter,
new RoleBasedPathAccessFilter(a => Some(User("user", "ADMIN")), "ADMIN", routes.Admin.index())
) {
}
case class User(mail: String, role: String)
import play.api.mvc._
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import play.api.libs.iteratee.Iteratee
import controllers.routes
/**
* Ensure that user is logged in before any call can go though.
* The only valid paths before log in are the login page and
* the OpenID callback
*/
class OpenIdAuthFilter extends EssentialFilter {
val openIdCallbackPath = routes.Application.openIDCallback
val loginPath = routes.Application.login()
val loginPaths = Set(openIdCallbackPath.url, loginPath.url)
def apply(next: EssentialAction): EssentialAction = new EssentialAction {
def apply(request: RequestHeader) = {
if (!loginPaths.contains(request.path) && request.session.get("email").isEmpty) {
Iteratee.ignore[Array[Byte]].map(_ => Results.Redirect(loginPath))
} else {
next(request)
}
}
}
}
import play.api.mvc._
import play.api.libs.iteratee.Iteratee
import scala.concurrent.ExecutionContext
import ExecutionContext.Implicits.global
/**
* If a user enters a restricted area (e.g. /admin), check if he has the appropriate role
* otherwise reject the request
*/
class RoleBasedPathAccessFilter(val userByMail: (String => Option[User]), val resRole: String, restrictedAreas: { def url: String }*) extends EssentialFilter {
private val restricted = restrictedAreas.map(_.url).toSet
def apply(next: EssentialAction): EssentialAction = new EssentialAction {
def apply(request: RequestHeader) = {
val area = request.path
if (restricted.contains(request.path)) {
if (isAuthenticated(area, request)) next(request)
else Iteratee.ignore[Array[Byte]].map(_ => Results.Forbidden(views.html.defaultpages.unauthorized()))
} else next(request)
}
}
def isAuthenticated(area: String, request: RequestHeader) = {
request.session.get("email").flatMap(userByMail)
.find(user => user.role == resRole)
.isDefined
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment