Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSRF protection for web forms #570

Merged
merged 1 commit into from
Oct 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 21 additions & 11 deletions app/Global.scala
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import scala.concurrent.Future

import play.api.Application
import play.api.GlobalSettings
import play.api.Logger
import play.api.Mode
import play.api.Play
import play.api.mvc.Handler
import play.api.mvc.RequestHeader
import play.api.mvc.Result
import play.api.mvc.Results

import play.api.mvc._
import collins.callbacks.Callback
import collins.controllers.ApiResponse
import collins.db.DB
Expand All @@ -30,8 +25,9 @@ import collins.util.config.Registry
import collins.util.security.AuthenticationAccessor
import collins.util.security.AuthenticationProvider
import collins.util.security.AuthenticationProviderConfig
import play.filters.csrf._

object Global extends GlobalSettings with AuthenticationAccessor with CryptoAccessor {
object Global extends WithFilters(new OptionalCSRFFilter(CSRFFilter())) with GlobalSettings with AuthenticationAccessor with CryptoAccessor {
private[this] val logger = Logger.logger

override def beforeStart(app: Application) {
Expand Down Expand Up @@ -78,11 +74,12 @@ object Global extends GlobalSettings with AuthenticationAccessor with CryptoAcce

override def onError(request: RequestHeader, ex: Throwable): Future[Result] = {
logger.warn("Unhandled exception", ex)
val debugOutput = Play.maybeApplication.map {
case app if app.mode == Mode.Dev => true
case app if app.mode == Mode.Test => true
val debugOutput = Play.maybeApplication match {
case Some(Mode.Dev) => true
case Some(Mode.Test) => true
case _ => false
}.getOrElse(true)
}

val status = Results.InternalServerError
val err = if (debugOutput) Some(ex) else None
OutputType(request) match {
Expand Down Expand Up @@ -154,3 +151,16 @@ object Global extends GlobalSettings with AuthenticationAccessor with CryptoAcce
authen
}
}

class OptionalCSRFFilter(filter: CSRFFilter) extends EssentialFilter {

override def apply(nextFilter: EssentialAction): EssentialAction = new EssentialAction {

//thanks to dominik dorn for the writeup on exlusion filters
//more here: https://dominikdorn.com/2014/07/playframework-2-3-global-csrf-protection-disable-csrf-selectively/
override def apply(rh: RequestHeader) = {
val chainedFilter = filter.apply(nextFilter)
if (rh.path.startsWith("/api/")) nextFilter(rh) else chainedFilter(rh)
}
}
}
1 change: 1 addition & 0 deletions app/views/login.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ <h1>Login <small>Enter your credentials.</small></h1>
@loginForm("location").value.map { value =>
<input type="hidden" name="location" value="@value">
}
@helper.CSRF.formField
}
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions app/views/main.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
<input class="input-medium form-control" type="text" name="username" placeholder="Username">
<input class="input-medium form-control" type="password" name="password" placeholder="Password">
<button class="btn btn-default" type="submit">Sign in</button>
@helper.CSRF.formField
</form>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions app/views/resources/create.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ <h1>Create <small>Make a new @atype.label.</small></h1>
<button type="submit" class="btn btn-primary">Create @atype.label</button>
</div>
</div>
@helper.CSRF.formField
</form>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,4 @@ libraryDependencies ++= Seq(
"org.webjars" % "jquery" % "2.1.4",
"com.hazelcast" % "hazelcast" % "3.5.2",
ws
)
) :+ filters
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ resolvers ++= Seq(
"Sontype Releases" at "https://oss.sonatype.org/content/repositories/releases/"
)

addSbtPlugin("com.typesafe.play" % "sbt-plugin" % Option(System.getProperty("play.version")).getOrElse("2.3.9"))
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % Option(System.getProperty("play.version")).getOrElse("2.3.10"))

addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "0.6.0")

Expand Down