{"id":21517829,"url":"https://github.com/brokenhandsio/vapor-csrf","last_synced_at":"2025-07-03T17:32:59.845Z","repository":{"id":63906627,"uuid":"292248097","full_name":"brokenhandsio/vapor-csrf","owner":"brokenhandsio","description":"Easy CSRF protection for your Vapor websites","archived":false,"fork":false,"pushed_at":"2020-09-05T07:35:34.000Z","size":38,"stargazers_count":20,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-06-30T02:09:55.613Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/brokenhandsio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-09-02T10:08:57.000Z","updated_at":"2025-06-27T19:19:41.000Z","dependencies_parsed_at":"2022-11-28T22:45:11.379Z","dependency_job_id":null,"html_url":"https://github.com/brokenhandsio/vapor-csrf","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/brokenhandsio/vapor-csrf","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brokenhandsio%2Fvapor-csrf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brokenhandsio%2Fvapor-csrf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brokenhandsio%2Fvapor-csrf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brokenhandsio%2Fvapor-csrf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brokenhandsio","download_url":"https://codeload.github.com/brokenhandsio/vapor-csrf/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brokenhandsio%2Fvapor-csrf/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263369764,"owners_count":23456357,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-24T00:45:30.146Z","updated_at":"2025-07-03T17:32:59.801Z","avatar_url":"https://github.com/brokenhandsio.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Vapor CSRF\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://user-images.githubusercontent.com/9938337/92254623-14060f00-eec9-11ea-90e4-f6a52136aa67.png\" alt=\"Vapor CSRF\"\u003e\n    \u003cbr\u003e\n    \u003cbr\u003e\n    \u003ca href=\"https://vapor.codes\"\u003e\n        \u003cimg src=\"http://img.shields.io/badge/Vapor-4-brightgreen.svg\" alt=\"Language\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://swift.org\"\u003e\n        \u003cimg src=\"http://img.shields.io/badge/Swift-5.2-brightgreen.svg\" alt=\"Language\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/brokenhandsio/vapor-csrf/actions\"\u003e\n         \u003cimg src=\"https://github.com/brokenhandsio/vapor-csrf/workflows/CI/badge.svg?branch=main\" alt=\"Build Status\"\u003e\n    \u003ca href=\"https://codecov.io/gh/brokenhandsio/vapor-csrf\"\u003e\n        \u003cimg src=\"https://codecov.io/gh/brokenhandsio/vapor-csrf/branch/main/graph/badge.svg\" alt=\"Code Coverage\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://raw.githubusercontent.com/brokenhandsio/vapor-csrf/main/LICENSE\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"MIT License\"\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\nA simple library for protecting POST requests from CSRF (cross-site request forgery) attacks.\n\n## What is CSRF?\n\nIn simple terms it's tricking a user into making requests that a web application accepts. Imagine a bank website that has a POST request to transfer money into an account. If a malicious site can force the user to send that POST request (when they're logged in) then an attacker could trick a user into transferring money. \n\nCSRF tokens protect against this by ensuring the POST request is legitimate. The website provides a token to the GET request which it then checks when handling the POST request to ensure it matches.\n\nModern solutions such as [SameSite cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) provide a similar protection but aren't supported on all browsers.\n\n## Installation\n\nAdd the CSRF library in your dependencies array in **Package.swift**:\n\n```swift\ndependencies: [\n    // ...,\n    .package(name: \"VaporCSRF\", url: \"https://github.com/brokenhandsio/vapor-csrf.git\", from: \"1.0.0\")\n],\n```\n\nAlso ensure you add it as a dependency to your target:\n\n```swift\ntargets: [\n    .target(name: \"App\", dependencies: [\n        .product(name: \"Vapor\", package: \"vapor\"), \n        // ..., \n        \"VaporCSRF\"]),\n    // ...\n]\n```\n\n## Usage\n\nYou must be using the `SessionsMiddleware` on all routes you interact with CSRF with. You can enable this globally in **configure.swift** with:\n\n```swift\napp.middleware.use(app.sessions.middleware)\n```\n\nFor more information on sessions, [see the documentation](https://docs.vapor.codes/4.0/sessions/).\n\n### GET routes\n\nIn GET routes that could return a POST request you want to protect, store a CSRF token in the session:\n\n```swift\nlet csrfToken = req.csrf.storeToken()\n```\n\nThis function returns a token you can then pass to your HTML page. For example, with Leaf this would look like:\n\n```swift\nlet csrfToken = req.csrf.storeToken()\nlet context = MyPageContext(csrfToken: csrfToken)\nreturn req.view.render(\"myPage\", context)\n```\n\nYou then need to return the token when the form is submitted. With Leaf, this would look something like:\n\n```html\n\u003cform method=\"post\"\u003e\n    \u003cinput type=\"hidden\" name=\"csrfToken\" value=\"#(csrfToken)\"\u003e\n    \u003cinput type=\"submit\" value=\"Submit\"\u003e\n\u003c/form\u003e\n```\n\n### POST routes\n\nYou can protect your POST routes either with Middleware or manually verifying the token.\n\n#### Middleware\n\nVaporCSRF provides a middleware that checks the token for you. You can apply this to your routes with:\n\n```swift\nlet csrfTokenPotectedRoutes = app.grouped(CSRFMiddleware())\n```\n\n#### Manual Verification\n\nIf you want to control when you verify the CSRF token, you can do this manually in your route handler with `try req.csrf.verifyToken()`. E.g.:\n\n```swift\napp.post(\"myForm\") { req -\u003e EventLoopFuture\u003cResponse\u003e in\n    try req.csrf.verifyToken()\n    // ...\n}\n```\n\n### Configuration\n\nBy default, VaporCSRF looks for a value with the key `csrfToken` in the POST body. You can change the key with:\n\n```swift\napp.csrf.setTokenContentKey(\"aDifferentKey\")\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrokenhandsio%2Fvapor-csrf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrokenhandsio%2Fvapor-csrf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrokenhandsio%2Fvapor-csrf/lists"}