diff --git a/src/test/java/sirius/web/http/CSRFTokenSpec.groovy b/src/test/java/sirius/web/http/CSRFTokenSpec.groovy deleted file mode 100644 index 07876d6ca..000000000 --- a/src/test/java/sirius/web/http/CSRFTokenSpec.groovy +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Made with all the love in the world - * by scireum in Remshalden, Germany - * - * Copyright by scireum GmbH - * http://www.scireum.de - info@scireum.de - */ - -package sirius.web.http - -import io.netty.handler.codec.http.HttpHeaderNames -import io.netty.handler.codec.http.HttpResponseStatus -import sirius.kernel.BaseSpecification -import sirius.kernel.commons.Streams - -import java.nio.charset.StandardCharsets - -class CSRFTokenSpec extends BaseSpecification { - - def "safePOST() works correctly if token is missing via GET"() { - when: - def result = TestRequest.GET("/test/fake-delete-data").execute() - then: - result.getStatus() == HttpResponseStatus.INTERNAL_SERVER_ERROR - } - - def "safePOST() works correctly if token is present via GET"() { - given: - HttpURLConnection c = new URL("http://localhost:9999/test/provide-security-token").openConnection() - c.setRequestMethod("GET") - c.connect() - def token = new String(Streams.toByteArray(c.getInputStream()), StandardCharsets.UTF_8) - - when: - def result = TestRequest.GET("/test/fake-delete-data?CSRFToken=" + token).execute() - then: - result.getStatus() == HttpResponseStatus.INTERNAL_SERVER_ERROR - } - - def "safePOST() works correctly if token is missing via POST"() { - when: - def result = TestRequest.POST("/test/fake-delete-data").execute() - then: - result.getStatus() == HttpResponseStatus.INTERNAL_SERVER_ERROR - } - - def "safePOST() works correctly if correct token is present via SAFEPOST"() { - when: - def result = TestRequest.SAFEPOST("/test/fake-delete-data").execute() - then: - result.getStatus() == HttpResponseStatus.OK - } - - def "safePOST() works correctly if correct token is present via POST"() { - given: - HttpURLConnection c = new URL("http://localhost:9999/test/provide-security-token").openConnection() - c.setRequestMethod("GET") - c.connect() - def token = new String(Streams.toByteArray(c.getInputStream()), StandardCharsets.UTF_8) - - when: - HttpURLConnection c2 = new URL( - "http://localhost:9999/test/fake-delete-data?CSRFToken=" + token).openConnection() - c2.setRequestMethod("POST") - c2.setRequestProperty(HttpHeaderNames.COOKIE.toString(), c.getHeaderFields().get("set-cookie").get(0)) - c2.connect() - then: - c2.getResponseCode() == 200 - } - - def "safePOST() works correctly if expired token is present via POST"() { - given: - HttpURLConnection c = new URL("http://localhost:9999/test/provide-security-token").openConnection() - c.setRequestMethod("GET") - c.connect() - def token = new String(Streams.toByteArray(c.getInputStream()), StandardCharsets.UTF_8) - TestRequest.GET("/test/expire-security-token").execute() - - when: - HttpURLConnection c2 = new URL( - "http://localhost:9999/test/fake-delete-data?CSRFToken=" + token).openConnection() - c2.setRequestMethod("POST") - c2.setRequestProperty(HttpHeaderNames.COOKIE.toString(), c.getHeaderFields().get("set-cookie").get(0)) - c2.connect() - then: - c2.getResponseCode() == 200 - } - - def "safePOST() works correctly if wrong token is present via POST"() { - given: - HttpURLConnection c = new URL("http://localhost:9999/test/provide-security-token").openConnection() - c.setRequestMethod("GET") - c.connect() - def token = new String(Streams.toByteArray(c.getInputStream()), StandardCharsets.UTF_8) - - when: - HttpURLConnection c2 = new URL("http://localhost:9999/test/fake-delete-data?CSRFToken=w-r-o-n-g-t-o-k-e-n"). - openConnection() - c2.setRequestMethod("POST") - c2.setRequestProperty(HttpHeaderNames.COOKIE.toString(), c.getHeaderFields().get("set-cookie").get(0)) - c2.connect() - then: - c2.getResponseCode() == 500 - } - - def "unsafePOST() works correctly if token is missing via POST"() { - when: - def result = TestRequest.POST("/test/fake-delete-data-unsafe").execute() - then: - result.getStatus() == HttpResponseStatus.OK - } - - def "unsafePOST() works correctly if token is missing via GET"() { - when: - def result = TestRequest.GET("/test/fake-delete-data-unsafe").execute() - then: - result.getStatus() == HttpResponseStatus.INTERNAL_SERVER_ERROR - } - - def "ensureSafePOST() works correctly if token is missing via GET"() { - when: - def result = TestRequest.GET("/test/fake-delete-data-ensure-safe").execute() - then: - result.getStatus() == HttpResponseStatus.INTERNAL_SERVER_ERROR - } - - def "ensureSafePOST() works correctly if wrong token is present via POST"() { - when: - HttpURLConnection c = new URL( - "http://localhost:9999/test/fake-delete-data-ensure-safe?CSRFToken=w-r-o-n-g-t-o-k-e-n").openConnection() - c.setRequestMethod("POST") - c.connect() - then: - c.getResponseCode() == 401 - } - - def "ensureSafePOST() works correctly if correct token is present via POST"() { - given: - HttpURLConnection c = new URL("http://localhost:9999/test/provide-security-token").openConnection() - c.setRequestMethod("GET") - c.connect() - def token = new String(Streams.toByteArray(c.getInputStream()), StandardCharsets.UTF_8) - - when: - HttpURLConnection c2 = new URL("http://localhost:9999/test/fake-delete-data-ensure-safe?CSRFToken=" + token). - openConnection() - c2.setRequestMethod("POST") - c2.setRequestProperty(HttpHeaderNames.COOKIE.toString(), c.getHeaderFields().get("set-cookie").get(0)) - c2.connect() - then: - c2.getResponseCode() == 200 - } -} diff --git a/src/test/kotlin/sirius/web/http/CSRFTokenTest.kt b/src/test/kotlin/sirius/web/http/CSRFTokenTest.kt new file mode 100644 index 000000000..d2234fdc6 --- /dev/null +++ b/src/test/kotlin/sirius/web/http/CSRFTokenTest.kt @@ -0,0 +1,181 @@ +/* + * Made with all the love in the world + * by scireum in Remshalden, Germany + * + * Copyright by scireum GmbH + * http://www.scireum.de - info@scireum.de + */ + +package sirius.web.http + +import io.netty.handler.codec.http.HttpHeaderNames +import io.netty.handler.codec.http.HttpResponseStatus +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import sirius.kernel.SiriusExtension +import sirius.kernel.commons.Streams +import java.net.HttpURLConnection +import java.net.URL + +import java.nio.charset.StandardCharsets +import kotlin.test.assertEquals + +@ExtendWith(SiriusExtension::class) +class CSRFTokenTest { + + @Test + fun `safePOST() fails if token is missing via GET`() { + + val result = TestRequest.GET("/test/fake-delete-data").execute() + + assertEquals(HttpResponseStatus.INTERNAL_SERVER_ERROR, result.status) + } + + @Test + fun `safePOST() works if the token is present via GET`() { + + val connection = URL("http://localhost:9999/test/provide-security-token").openConnection() as HttpURLConnection + connection.setRequestMethod("GET") + connection.connect() + val token = String(Streams.toByteArray(connection.inputStream), StandardCharsets.UTF_8) + + val result = TestRequest.GET("/test/fake-delete-data?CSRFToken=$token").execute() + + assertEquals(HttpResponseStatus.INTERNAL_SERVER_ERROR, result.status) + } + + @Test + fun `safePOST() fails if token is missing via POST`() { + + val result = TestRequest.POST("/test/fake-delete-data").execute() + + assertEquals(HttpResponseStatus.INTERNAL_SERVER_ERROR, result.status) + } + + @Test + fun `safePOST() works on SAFEPOST if correct token is provided`() { + + val result = TestRequest.SAFEPOST("/test/fake-delete-data").execute() + + assertEquals(HttpResponseStatus.OK, result.status) + } + + @Test + fun `safePOST() works if correct token is present via POST`() { + + val connection = URL("http://localhost:9999/test/provide-security-token").openConnection() as HttpURLConnection + connection.setRequestMethod("GET") + connection.connect() + val token = String(Streams.toByteArray(connection.inputStream), StandardCharsets.UTF_8) + + + val connection2 = URL( + "http://localhost:9999/test/fake-delete-data?CSRFToken=$token" + ).openConnection() as HttpURLConnection + connection2.setRequestMethod("POST") + connection2.setRequestProperty( + HttpHeaderNames.COOKIE.toString(), + connection.headerFields["set-cookie"]?.get(0) + ) + connection2.connect() + + assertEquals(200, connection2.getResponseCode()) + } + + @Test + fun `safePOST() success on POST if expired token is provided`() { + + val connection = URL("http://localhost:9999/test/provide-security-token").openConnection() as HttpURLConnection + connection.setRequestMethod("GET") + connection.connect() + val token = String(Streams.toByteArray(connection.inputStream), StandardCharsets.UTF_8) + TestRequest.GET("/test/expire-security-token").execute() + + val connection2 = URL( + "http://localhost:9999/test/fake-delete-data?CSRFToken=$token" + ).openConnection() as HttpURLConnection + connection2.setRequestMethod("POST") + connection2.setRequestProperty( + HttpHeaderNames.COOKIE.toString(), + connection.headerFields["set-cookie"]?.get(0) + ) + connection2.connect() + + assertEquals(200,connection2.getResponseCode()) + } + + @Test + fun `safePOST() works if false token is given via POST`() { + + val connection = URL("http://localhost:9999/test/provide-security-token").openConnection() as HttpURLConnection + connection.setRequestMethod("GET") + connection.connect() + + val connection2 = + URL("http://localhost:9999/test/fake-delete-data?CSRFToken=w-r-o-n-g-t-o-k-e-n").openConnection() as HttpURLConnection + connection2.setRequestMethod("POST") + connection2.setRequestProperty( + HttpHeaderNames.COOKIE.toString(), + connection.headerFields["set-cookie"]?.get(0) + ) + connection2.connect() + + assertEquals(500,connection2.getResponseCode()) + } + + @Test + fun `unsafePOST() if token is missing via POST it works as intended`() { + + val result = TestRequest.POST("/test/fake-delete-data-unsafe").execute() + + assertEquals(HttpResponseStatus.OK,result.status) + } + + @Test + fun `unsafePOST() fails on GET if token is not provided`() { + + val result = TestRequest.GET("/test/fake-delete-data-unsafe").execute() + + assertEquals(HttpResponseStatus.INTERNAL_SERVER_ERROR,result.status) + } + + @Test + fun `ensureSafePOST() fails if token is missing via GET`() { + + val result = TestRequest.GET("/test/fake-delete-data-ensure-safe").execute() + + assertEquals(HttpResponseStatus.INTERNAL_SERVER_ERROR, result.status) + } + + @Test + fun `ensureSafePOST() goes wrong on POST if false token is given`() { + + val connection = URL( + "http://localhost:9999/test/fake-delete-data-ensure-safe?CSRFToken=w-r-o-n-g-t-o-k-e-n" + ).openConnection() as HttpURLConnection + connection.setRequestMethod("POST") + connection.connect() + + assertEquals(401,connection.responseCode ) + } + + @Test + fun `ensureSafePOST() works as intended if correct token is given via POST`() { + + val connection = URL("http://localhost:9999/test/provide-security-token").openConnection() as HttpURLConnection + connection.setRequestMethod("GET") + connection.connect() + val token = String(Streams.toByteArray(connection.getInputStream()), StandardCharsets.UTF_8) + + val connection2 = + URL("http://localhost:9999/test/fake-delete-data-ensure-safe?CSRFToken=$token").openConnection() as HttpURLConnection + connection2.setRequestMethod("POST") + connection2.setRequestProperty( + HttpHeaderNames.COOKIE.toString(), + connection.headerFields["set-cookie"]?.get(0) + ) + connection2.connect() + + assertEquals(200,connection2.getResponseCode()) + } +}