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

Unexpected InvalidCSRFTokenError when submitted via AJAX with CSRF token in header #1902

Closed
imranismail opened this issue Sep 4, 2016 · 4 comments

Comments

@imranismail
Copy link
Contributor

imranismail commented Sep 4, 2016

Environment

  • Elixir version (elixir -v): 1.3.2
  • Phoenix version (mix deps): 1.2.1
  • NodeJS version (node -v): 6.4.0
  • NPM version (npm -v): 3.10.5
  • Operating system: OSX 10.11.6

Expected behavior

Set CSRF Token in app.html.slim

window.csrfToken = '<%= get_csrf_token() %>'

Set a remote link in projects/index.html.slim

a.card-footer-item href="#{project_path(@conn, :delete, project)}" data-method="delete" data-remote="true"
  | Delete

Register events in app.js

const remotes = document.querySelector('[data-remote=true]')
remotes && remotes.addEventListener('click', (ev) => {
  ev.preventDefault()
  submittedRemotely(ev)
})

function submittedRemotely ({target}) {
  const request = new window.Request(target.getAttribute('href'), {
    method: target.getAttribute('data-method'),
    headers: new window.Headers({'x-csrf-token': window.csrfToken})
  })
  window.fetch(request)
}

Click delete link, should not redirect and should delete resource with a status of 200

Actual behavior

Plug.CSRFProtection.InvalidCSRFTokenError at DELETE /projects/8

invalid CSRF (Cross Site Request Forgery) token, make sure all requests include a valid '_csrf_token' param or 'x-csrf-token' header

Params

  • id "8"

Request info

  • URI: http://localhost:4000/projects/8
  • Query string:
  • Peer:127.0.0.1:50492

Headers

  • accept */*
  • accept-encoding gzip, deflate, sdch
  • accept-language en-US,en;q=0.8,ms;q=0.6,zh-CN;q=0.4,zh;q=0.2,ar;q=0.2
  • connection keep-alive
  • host localhost:4000
  • origin http://localhost:4000
  • referer http://localhost:4000/projects
  • user-agent Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36
  • x-csrf-token XwE1PAYuMgQVQyoUSjYhQRV6MhwmAAAA4jmrGdjPA7cp/AM7Y7ARew==
@josevalim
Copy link
Member

Can you please provide a simple app that reproduces the error? It would
make it much easier to figure it out.

On Monday, September 5, 2016, Imran Ismail notifications@github.com wrote:

Environment

  • Elixir version (elixir -v): 1.3.2
  • Phoenix version (mix deps): 1.2.1
  • NodeJS version (node -v): 6.4.0
  • NPM version (npm -v): 3.10.5
  • Operating system: OSX 10.11.6

Expected behavior

Set CSRF Token in app.html.slim

window.csrfToken = '<%= get_csrf_token() %>'

Set a remote link in projects/index.html.slim

a.card-footer-item href="#{project_path(@conn, :delete, project)}" data-method="delete" data-remote="true"
| Delete

Register events in app.js

const remotes = document.querySelector('[data-remote=true]')
remotes && remotes.addEventListener('click', (ev) => {
ev.preventDefault()
submittedRemotely(ev)
})
function submittedRemotely ({target}) {
const request = new window.Request(target.getAttribute('href'), {
method: target.getAttribute('method'),
headers: new window.Headers({'x-csrf-token': window.csrfToken})
})
window.fetch(request)
}

Click delete link, should not redirect and should delete resource with a
status of 200
Actual behavior Plug.CSRFProtection.InvalidCSRFTokenError at DELETE
/projects/8

invalid CSRF (Cross Site Request Forgery) token, make sure all requests
include a valid '_csrf_token' param or 'x-csrf-token' header
Params

  • id "8"

Request info

Headers

  • accept /
  • accept-encoding gzip, deflate, sdch
  • accept-language en-US,en;q=0.8,ms;q=0.6,zh-CN;q=0.4,zh;q=0.2,ar;q=0.2
  • connection keep-alive
  • host localhost:4000
  • origin http://localhost:4000
  • referer http://localhost:4000/projects
  • user-agent Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N)
    AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile
    Safari/537.36
  • x-csrf-token XwE1PAYuMgQVQyoUSjYhQRV6MhwmAAAA4jmrGdjPA7cp/AM7Y7ARew==


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#1902, or mute the
thread
https://github.com/notifications/unsubscribe-auth/AAAlbiI2Ctq_XCkPHba2S17bgyt5HyQFks5qm0wMgaJpZM4J0pdG
.

José Valim
www.plataformatec.com.br
Skype: jv.ptec
Founder and Director of R&D

@imranismail
Copy link
Contributor Author

Sure, just stripped some stuff. Here's the app
https://github.com/imranismail/phoenix-1902

@jguyon
Copy link

jguyon commented Sep 6, 2016

I don't know if you're still having this problem, but I looked into it.

Apparently, the problem is that Plug.CSRFProtection works with the session data stored in cookies, but fetch requests don't include these by default.

To fix it, you need to give the credentials option of your request a value of 'include' or 'same-origin' (https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials), like this:

function submittedRemotely ({target}) {
  const request = new window.Request(target.getAttribute('href'), {
    method: target.getAttribute('data-method'),
    headers: new window.Headers({'x-csrf-token': window.csrfToken}),
    credentials: 'same-origin'
  })
  window.fetch(request)
}

@josevalim
Copy link
Member

Thank you @sideburnsandtie! ❤️ I am closing this unless @imranismail has more information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants