Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.Sign up
Amazing post that aroused me a question. #10
After I read this amazing post: https://github.com/equivalent/scrapbook2/blob/master/archive/blogs/2017-10-12-csrf-protection-on-single-page-app-api.md I'm wondering this: https://stackoverflow.com/questions/50159847/single-page-application-and-csrf-token.
Can you answer that?
Hey @johnunclesam thank you for you post. I'm glad you like my article.
Sorry that I didn't answer the question earlier but I was hammered with work and unfortunately I'll not have time to fully answer it this weekend either (I'm on a trip)
I'm bit rusty on CSRF topic and need to remind myself on the topic before I can give valuable answer (as security answers are always complicated)
In short I would say just this: I'm using
I'll fully explain myself once I'm back but here are some random resources that may help:
Ah ok my bad now I understand what you are asking
it really depends on how the SPA is being rendered.
scenario 1 - Rails rendering the SPA
e.g. angular-rails gem rendered via sprockets
So rails render application.html.erb with angular template and then the Angular JS just communicates with Rails via API
Scenario 2 -SPA that is rendered outside Rails
(e.g. GitubPages Angualar JS App that is just communicating with pure Rails API, so Rails has nothing to do with redering the SPA)
For scenario 1
I kind-of remember that one old project I use to work for had similar solution like you are proposing https://stackoverflow.com/questions/50159847/single-page-application-and-csrf-token :
So I guess that's fine +
For scenario 2
Let me check something will reply back on Monday,
I would consider returning the CSRF token in the response header rather than setting it to cookie
@johnunclesam sorry for the 2 week delay. I forgot about this.
I've formed my answer into this article :) https://blog.eq8.eu/article/rails-api-authentication-with-spa-csrf-tokens.html
Thx for the inspiration
Great article. But anyway I would like to ask something.
Many times I see this:
class ApplicationController < ActionController::Base after_action :set_csrf_cookie def set_csrf_cookie if current_user && protect_against_forgery? cookies["my_csrf_token"] = form_authenticity_token end end end
It makes sense to have the code below?
if current_user && protect_against_forgery?
@johnunclesam I've never used it like that so I cannot make statement that I would be 100% sure of.
In principle I cannot think about scenario where your code would be problem
But at the same time I don't see a problem to set the CSRF cookie on every request like this:
honestly don't know. I definitely see what you are trying to archive but both solution (your and my code sample ) looks equally fine to me (but I may be wrong on this)
but just to be sure
and honestly there is no case I can think of where would developer need to do skip it with
well yes and no. CSRF Breach attack happens when attacker manage to figure out CSRF token from website compression (and yes even if the trafic is HTTPs)
That means that yes not exposing the CSRF token for every request (only for logged in users) is little bit helpful but still doesn't solve the issue (as attacker can still figure out CSRF token of the current_user)
Therefore if your website is dealing with this level of concern around security you will have to rotate CSRF tokens. Quoting same articles:
Therefore you are doing something like that (CSRF rotation) with:
So you are actually implementing 2 security steps here:
So in conclusion
If you really need to bulletproof the security I would recommend investigating Rails source code around what CSRF token https://github.com/rails/rails/blob/e7feaff70f13b56a0507e9f4dfaf3ebc361cb8e6/actionpack/lib/action_controller/metal/request_forgery_protection.rb#L263
It's not as sophisticated as Facebook is proposing but still provides some good tricks to prevent BREACH yet if I was a Bank and had to have bulletproof CSRF I would investigate a way how to add one more CSRF like token that is generated per user base + md5 stored in DB for individual users so I can keep track of individual tokens and if user signs out (or system detect a breach) I delete those from DB (so Rails CSRF + my custom user tracked CSRF just to be sure so I'm super paranoid)
If this CSRF protection is for my personal Blog website I wouldn't bother with that paranoid solution and just use Rails native CSRF.
But still your solution make sense. But one think you need to be extra careful is not to implement public forms without CSRF token that may be turned into protected one some day => you or your colleagues may forgot to remove