<commit_before>---
menu: main
title: CSRF
weight: 123
---

Http4s provides [Middleware], named `CSRF`, to avoid Cross-site request forgery attacks.This middleware 
is modeled after the double submit cookie pattern: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Double_Submit_Cookie

Examples in this document have the following dependencies.

```scala
libraryDependencies ++= Seq(
  "org.http4s" %% "http4s-dsl" % http4sVersion,
  "org.http4s" %% "http4s-server" % http4sVersion
)
```

And we need some imports.

```tut:silent
  import cats.effect._
  import org.http4s._
  import org.http4s.dsl.io._
  import org.http4s.implicits._
  import org.http4s.headers.Referer
  import org.http4s.server.middleware._
```

Let's start by making a simple service.

```tut:book
val service = HttpRoutes.of[IO] {
  case _ =>
    Ok()
} 

val request = Request[IO](Method.GET, uri"/")

service.orNotFound(request).unsafeRunSync
```

Now we can build our CSRF Middleware by creating a CSRFBuilder

```tut:silent
val cookieName = "csrf-token"
val key  = CSRF.generateSigningKey[IO].unsafeRunSync
val defaultOriginCheck: Request[IO] => Boolean =
  CSRF.defaultOriginCheck[IO](_, "localhost", Uri.Scheme.http, None)
val csrfBuilder = CSRF[IO,IO](key, defaultOriginCheck)
```

More info on what is possible here: https://http4s.org/v0.21/api/org/http4s/server/middleware/csrf$$csrfbuilder but
we will create for a fairly simple CSRF Middleware in our example.

```tut:book
val csrf = csrfBuilder.withCookieName(cookieName).withCookieDomain(Some("localhost")).withCookiePath(Some("/")).build
```

Now we need to wrap this around our service!
```tut:book
val dummyRequest: Request[IO] =
    Request[IO](method = Method.GET).putHeaders(Header("Origin", "http://localhost"))
val resp = csrf.validate()(service.orNotFound)(dummyRequest).unsafeRunSync()
```

Notice how the response has the CSRF cookies added. How easy was
that? And, as described in [Middleware], services and middleware can be
composed such that only some of your endpoints are CSRF enabled. By default, 
safe methods will update the CSRF token, while unsafe methods will validate them.


As described in [Middleware], services and middleware can be composed such
that only some of your endpoints are CSRF enabled.
<commit_msg>feat: Had a repeated paragraph<commit_after>---
menu: main
title: CSRF
weight: 123
---

Http4s provides [Middleware], named `CSRF`, to avoid Cross-site request forgery attacks.This middleware 
is modeled after the double submit cookie pattern: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Double_Submit_Cookie

Examples in this document have the following dependencies.

```scala
libraryDependencies ++= Seq(
  "org.http4s" %% "http4s-dsl" % http4sVersion,
  "org.http4s" %% "http4s-server" % http4sVersion
)
```

And we need some imports.

```tut:silent
  import cats.effect._
  import org.http4s._
  import org.http4s.dsl.io._
  import org.http4s.implicits._
  import org.http4s.headers.Referer
  import org.http4s.server.middleware._
```

Let's start by making a simple service.

```tut:book
val service = HttpRoutes.of[IO] {
  case _ =>
    Ok()
} 

val request = Request[IO](Method.GET, uri"/")

service.orNotFound(request).unsafeRunSync
```

Now we can build our CSRF Middleware by creating a CSRFBuilder

```tut:silent
val cookieName = "csrf-token"
val key  = CSRF.generateSigningKey[IO].unsafeRunSync
val defaultOriginCheck: Request[IO] => Boolean =
  CSRF.defaultOriginCheck[IO](_, "localhost", Uri.Scheme.http, None)
val csrfBuilder = CSRF[IO,IO](key, defaultOriginCheck)
```

More info on what is possible here: https://http4s.org/v0.21/api/org/http4s/server/middleware/csrf$$csrfbuilder but
we will create for a fairly simple CSRF Middleware in our example.

```tut:book
val csrf = csrfBuilder.withCookieName(cookieName).withCookieDomain(Some("localhost")).withCookiePath(Some("/")).build
```

Now we need to wrap this around our service!
```tut:book
val dummyRequest: Request[IO] =
    Request[IO](method = Method.GET).putHeaders(Header("Origin", "http://localhost"))
val resp = csrf.validate()(service.orNotFound)(dummyRequest).unsafeRunSync()
```

Notice how the response has the CSRF cookies added. How easy was
that? And, as described in [Middleware], services and middleware can be
composed such that only some of your endpoints are CSRF enabled. By default, 
safe methods will update the CSRF token, while unsafe methods will validate them.

{'fraction_non_alphanumeric': 0.11617614516485948, 'fraction_numerical': 0.008851515822084531, 'mean_word_length': 5.075268817204301, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1428849', 'n_tokens_mistral': 1507, 'n_tokens_neox': 1451, 'n_words': 432}