{"id":28125097,"url":"https://github.com/xing/unified_csrf_prevention","last_synced_at":"2025-10-04T23:56:18.105Z","repository":{"id":59158601,"uuid":"136153692","full_name":"xing/unified_csrf_prevention","owner":"xing","description":"Self-healing, stateless and programming language agnostic CSRF prevention library for Rails","archived":false,"fork":false,"pushed_at":"2018-07-03T22:12:52.000Z","size":18,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-09-01T00:20:32.985Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","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/xing.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-05T09:30:31.000Z","updated_at":"2020-04-14T21:56:03.000Z","dependencies_parsed_at":"2022-09-13T20:10:29.696Z","dependency_job_id":null,"html_url":"https://github.com/xing/unified_csrf_prevention","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/xing/unified_csrf_prevention","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xing%2Funified_csrf_prevention","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xing%2Funified_csrf_prevention/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xing%2Funified_csrf_prevention/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xing%2Funified_csrf_prevention/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xing","download_url":"https://codeload.github.com/xing/unified_csrf_prevention/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xing%2Funified_csrf_prevention/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278391185,"owners_count":25978945,"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","status":"online","status_checked_at":"2025-10-04T02:00:05.491Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":"2025-05-14T09:20:09.916Z","updated_at":"2025-10-04T23:56:18.090Z","avatar_url":"https://github.com/xing.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Unified CSRF Prevention for Rails\n\nThis gem is a drop-in upgrade for request forgery protection in Rails 4 and 5 with the following benefits:\n\n* It is self-healing by design. Whenever a user comes in with an invalid authenticity token, they will have a valid one sent back along with the error response so the next request will succeed. There's no need for the user to reload the page.\n* The CSRF prevention is decoupled from the users' sessions that could eventually get wiped out or overwritten, resulting in errors.\n* The approach is framework/language agnostic, so the token generated by one application will be accepted by any other, including non-Rails applications (given they implement the same CSRF prevention scheme).\n* The mechanism is stateless from the backend's perspective. The data is stored in the browser's cookies, requiring no backend storage.\n* The solution design was audited by Xing Security team and [cure53](https://cure53.de).\n* It is both React- and jQuery-friendly.\n\nPlease read the [Cross-application CSRF Prevention specification](https://github.com/xing/cross-application-csrf-prevention) for design and implementation details.\n\n## Configuring Your Application\n\n1. Add the gem to the `Gemfile`:\n\n```ruby\ngem 'unified_csrf_prevention'\n```\n\n2. Set the shared secret key configuration value for `production`, `preview` and whatever other environment your have:\n\n```ruby\nRails.application.configure do\n  # existing configuration settings\n\n  config.unified_csrf_prevention_key = '64 random characters'\nend\n```\n\n3. Replace the unobtrusive scripting adapter that adds the `X-CSRF-Token` header which comes with Rails with this one (assuming jQuery is used):\n\n```js\n$.ajaxPrefilter(function(options) {\n  var token = (document.cookie.match(/(?:^|;\\s*)csrf_token=([^;]+)/) || [])[1];\n\n  if (token) {\n    options.headers[\"X-CSRF-Token\"] = token;\n  }\n});\n```\n\nImportant note: **the token must be read from cookies for each and every frontend request the application makes. It is not acceptable to read the token once and store it in some variable, DOM node or in any other form.**\n\nIn other words, please do exactly what the provided snippet does - for any request read the token from the cookie right before the request is sent. Don't try to cache the token, transfer it from the backend, or optimize out the cookie access, otherwise your application could end up using invalid tokens.\n\nIf your application uses something different from jQuery to make AJAX calls, please adjust the snippet accordingly. The key parts are running the code before each request is sent, and setting the header with the value read from the cookie. Basically, `$.ajaxPrefilter` and `options.headers` should be replaced with something that works with the library you use instead of jQuery.\n\nIf your application for some reason has several different ways to send AJAX requests, you need to adjust all of them.\n\n## Usage\n\nThe gem is seamlessly integrated with Rails' built-in request forgery protection mechanism so there's nothing special to be done on top of the regular `protect_from_forgery` controller setting.\nAuthenticity tokens transferred in hidden inputs as well as per-form authenticity tokens introduced in Rails 5 just work out of the box.\nSee [Ruby on Rails Security Guide](http://guides.rubyonrails.org/security.html#csrf-countermeasures) for details.\n\n## Testing Controllers with Forgery Protection Enabled\n\nSometimes it's necessary to test the controller code with the actual forgery protection mechanisms enabled (`allow_forgery_protection` overwritten in tests).\nProviding the cookies for requests to make `unified_csrf_prevention` work is a bit of a hassle, so instead it's possible to mock the token validation and thus make the controller accept the supplied token:\n\n```ruby\ndescribe '#some_action' do\n  context 'when requested with valid csrf token' do\n    let(:csrf_token) { controller.send(:form_authenticity_token) }\n\n    before do\n      allow(controller).to receive(:valid_token?).with(csrf_token).and_return true\n    end\n\n    it 'executes action' do\n      post :some_action, authenticity_token: csrf_token\n      expect(response).to be_ok\n    end\n  end\nend\n```\n\n## Compatibility\n\nThe gem is compatible with Rails 4.2, 5.0, 5.1 and 5.2.\n\n## Running Specs\n\n```bash\nrubocop\nappraisal install\nappraisal rspec\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxing%2Funified_csrf_prevention","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxing%2Funified_csrf_prevention","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxing%2Funified_csrf_prevention/lists"}