Can someone explain this paragraph to me from the Rails Security Guide? - ruby-on-rails

See here: http://guides.rubyonrails.org/security.html
[Rails CSRF protection] will automatically include a security token, calculated from the current session and the server-side secret, in all forms and Ajax requests generated by Rails. You won’t need the secret, if you use CookieStorage as session storage. If the security token doesn’t match what was expected, the session will be reset.
I'm really hoping that someone could explain to my why the server side secret is not needed if I store the entire session in a cookie.
The reason I ask is because I am trying to figure out if there is a way to generate CSRF tokens in a 100% client-side application (ember.js) where I won't have Rails inserting a CSRF token on all forms. I can certainly write to cookies using JavaScript, and I can certainly hash various values.
If there is some way to generate a cookie client-side using JavaScript, without a server-side secret, and being able to verify on the server please let me know!

Did you try googling this?
There is plenty of information on jQuery/ember.js/Rails CSRF out there. jQuery has an $.ajaxPrefilter which you can use to append the CSRF token from your META tags to the request headers (and having said META tags existing on page for a single page app shouldn't be a problem).
This article provides one implemenation that uses this method (the example is in Coffeescript).
$ ->
token = $('meta[name="csrf-token"]').attr('content')
$.ajaxPrefilter (options, originalOptions, xhr) ->
xhr.setRequestHeader('X-CSRF-Token', token)
Here is another implemenation extending the DS.RESTAdapter.
All Rails is doing in a 'normal' application is adding the CSRF token as a hidden input field to your forms. Whether coming this way or as an HTTP request header, it's picked up on by rails just the same.

I think it might be if using CookieSessionStore in Rails, there will be a secret token used to sign cookie. Rails may use that secret token instead to verify

Related

Invalid authenticity token when POSTing to a Rails API

I have a web application that gets & stores some data through a Rails API.
When I try to "post" to the Rails API, I get an error ActionController::InvalidAuthenticityToken. I know one option is to simply disable the authenticity token requirement on my Rails controller.
Is it possible to have my web app providing a correct authenticity token when it calls the Rails API? How can I do this?
2 Part answer for you here.
First if you are going to be using Rails as an API I would recommend you use another way of validating that the user making the request is actually the user they say they are such as creating a unique token upon account creation or login that can be returned in the initial response and provided as a HTTP header in subsequent requests. If you are worried about the security of this you could optionally base64 encode the key plus some other value and decode it server side before comparison.
If you still wish to use the CSRF method baked in to Rails you can do so as long as the user is making a request from the webapp using AJAX or whatever. If you have the csrf_meta_tags ERB in the header of your layout file you can get the value and set it in the X-CSRF-Token HTTP header. Using jQuery it may look something like:
$.ajaxPrefilter(function(options, originalOptions, xhr) {
var token = $('meta[name="csrf-token"]').attr('content');
if (token) xhr.setRequestHeader('X-CSRF-Token', token);
});
This would cause it to be added to every ajax request made using jQuery.

Store JWT token in cookie

This is my setup:
1 authentication server which gives out JWT token on successfull
authentication.
Multiple API resource servers which gives information (when the user
is authenticated).
Now I want to build my ASP.NET MVC frontend. Is it ok to take the token, which I receive after authentication, and put it in a cookie so I can access it with every secured call I need to make? I use the RestSharp DLL for doing my http calls. If it has a security flaw, then where should I store my token?
I would use this code for the cookie:
System.Web.HttpContext.Current.Response.Cookies.Add(new System.Web.HttpCookie("Token")
{
Value = token.access_token,
HttpOnly = true
});
You’re on the right path! The cookie should always have the HttpOnly flag, setting this flag will prevent the JavaScript environment (in the web browser) from accessing the cookie. This is the best way to prevent XSS attacks in the browser.
You should also use the Secure flag in production, to ensure that the cookie is only sent over HTTPS.
You also need to prevent CSRF attacks. This is typically done by setting a value in another cookie, which must be supplied on every request.
I work at Stormpath and we’ve written a lot of information about front-end security. These two posts may be useful for understanding all the facets:
Token Based Authentication for Single Page Apps (SPAs)
https://stormpath.com/blog/build-secure-user-interfaces-using-jwts/
Are you generating your own JWTs?
If yes, you should consider using a signing algorithm based on asymetric encryption, like "RS256" or "RS512" -- this way you can verify the claims in your client application without sharing the private secret.
Do you really need to pass the JWT into the Cookie?
It might be safer to just put a random id in your Cookie, which references the JWT access token, and do the de-referencing magic on the server which serves your web-app.

How to obtain the authenticity token given the session and the devise secret key?

How to obtain the authenticity token given the session and the secret key?
I'm using rails and devise.
I want to logout from a webview on a iOS app, but I get this error:
Can't verify CSRF token authenticity
So I'm planning to obtain the token from the session cookie and using the secret key. It might not be a good idea to ship the app with the secret key on the code, but I'm just planning to do it for a prototype. (How should I do it without using the secret key?)
Better solution
If you have access to the session via the cookies, you probably have access to the meta tags of the html, so you can easily retrieve the authenticity_token with this jquery:
$('meta[name=csrf-token]').attr('content')
If you have access to the session via the cookies, you probably have access to the meta tags of the html, so you can easily retrieve the authenticity_token with this jquery:
$('meta[name=csrf-token]').attr('content')
I have a couple of suggestions here.
First, if you're not using form_for or form_tag, I'd recommend using those. If you can't for some reason, it may be a better idea to just turn off CSRF protection for the controller/method by setting
protect_from_forgery except :my_method_i_dont_want_protection_on
in your controller file. Not recommended though. Any reason you can't just use the form helpers that will include it for you?
i think u r looking for this form_authenticity_token
See this

Why are Rails Authenticity Tokens session persistent and not unique to each submission?

I'm wondering why Rails form Authenticity Tokens last the entire session instead of being generated uniquely per each submission.
I'm coming from web2py, where forms are generated with unique one-time tokens called _formkey. The formkey automatically prevents duplicate submissions resulting from double-clicking, back-button caching, etc.
In Rails, you apparently have to deal with the double-submission problem yourself (See https://stackoverflow.com/a/4683161/165673). It seems to me that one-time Authenticity Tokens would solve this problem, as well as being more secure?
One token for entire session is easier to implement. Think about a case where you have two opened tabs with forms.
One token for session is as secure as one-time token solution. At least as the protection against CSRF attacks.
In Rails, you apparently have to deal with the double-submission problem yourself
There is out of the box solution for that. Read about disable_with option. Of course all requests that modify data should be sent via HTTP POST, not GET.

Rails API design without disabling CSRF protection

Back in February 2011, Rails was changed to require the CSRF token for all non-GET requests, even those for an API endpoint. I understand the explanation for why this is an important change for browser requests, but that blog post does not offer any advice for how an API should handle the change.
I am not interested in disabling CSRF protection for certain actions.
How are APIs supposed to deal with this change? Is the expectation that an API client makes a GET request to the API to get a CSRF token, then includes that token in every request during that session?
It appears that the token does not change from one POST to another. Is it safe to assume that the token will not change for the duration of the session?
I don't relish the extra error handling when the session expires, but I suppose it is better than having to GET a token before every POST/PUT/DELETE request.
Old question but security is important enough that I feel it deserves a complete answer. As discussed in this question there are still some risk of CSRF even with APIs. Yes browsers are supposed to guard against this by default, but as you don't have complete control of the browser and plugins the user has installed, it's should still be considered a best practice to protect against CSRF in your API.
The way I've seen it done sometimes is to parse the CSRF meta tag from the HTML page itself. I don't really like this though as it doesn't fit well with the way a lot of single page + API apps work today and I feel the CSRF token should be sent in every request regardless of whether it's HTML, JSON or XML.
So I'd suggest instead passing a CSRF token as a cookie or header value via an after filter for all requests. The API can simply re-submit that back as a header value of X-CSRF-Token which Rails already checks.
This is how I did it with AngularJS:
# In my ApplicationController
after_filter :set_csrf_cookie
def set_csrf_cookie
if protect_against_forgery?
cookies['XSRF-TOKEN'] = form_authenticity_token
end
end
AngularJS automatically looks for a cookie named XSRF-TOKEN but feel free to name it anything you want for your purposes. Then when you submit a POST/PUT/DELETE you should to set the header property X-CSRF-Token which Rails automatically looks for.
Unfortunately, AngualrJS already sends back the XSRF-TOKEN cookie in a header value of X-XSRF-TOKEN. It's easy to override Rails' default behaviour to accomodate this in ApplicationController like this:
protected
def verified_request?
super || form_authenticity_token == request.headers['X-XSRF-TOKEN']
end
For Rails 4.2 there is a built in helper now for validating CSRF that should be used.
protected
def verified_request?
super || valid_authenticity_token?(session, request.headers['X-XSRF-TOKEN'])
end
I hope that's helpful.
EDIT: In a discussion on this for a Rails pull-request I submitted it came out that passing the CSRF token through the API for login is a particularly bad practice (e.g., someone could create third-party login for your site that uses user credentials instead of tokens). So cavet emptor. It's up to you to decide how concerned you are about that for your application. In this case you could still use the above approach but only send back the CSRF cookie to a browser that already has an authenticated session and not for every request. This will prevent submitting a valid login without using the CSRF meta tag.
Rails works with the 'secure by default' convention. Cross-Site or Cross-Session Request Forgery requires a user to have a browser and another trusted website. This is not relevant for APIs, since they don't run in the browser and don't maintain any session. Therefore, you should disable CSRF for APIs.
Of course, you should protect your API by requiring HTTP Authentication or a custom implemented API token or OAuth solution.

Resources