How to implement Feature Flags in AngularJS and Ruby on Rails? - ruby-on-rails

For an app with Rails Backend and AngularJS at the front, How to implement Feature Flags or in other words conditional features per user?
This Video gave some glimpse on how to do that, which looks quite crude to me.
I am using Rollout Gem for this authorization. In case, the feature flags are implemented totally on client-side, I feel that would be "Not So Secure and Robust way of Disabling/Enabling features"
I can't use <% if $rollout.active?(:chat, current_user) %> in the partials since they are not ERBs, but HTML pages used as angular templates.
Thank you in advance.

So you could use JWT. JWT is a token that you can use with your rails app to authenticate the users. Imagine it like a hotel card. Depending on how much you paid, you get access to some services or others. It could let you access the garage or the breakfast.
Going to technical details, when a user logs in in your app, rails will create one of those tokens and rails can put there any flag you want, so you can send a token containing:
{user_id: 3, rollout: true, admin: true}
So in the Angular side, you can parse that token and activate the sections you need, something along this lines:
<div ng-if="user.rollout"></div>
So based on what you get in the token, some sections of the page will appear.
The token cannot be tampered, so the end user can't modify it because the server will reject it.
In Angular itself you cannot do too much else, any user could create a user object and put all the flags to true, but it is the rails API who decides what the user can see, so the maximum that use could get is an empty admin page without any data, but that is not avoidable.
If you want to learn more about JWT, here is the idea and here examples (including a rails one)

Related

Post form data to Rails backend from outside app

For marketing reasons we want to a/b test some landing pages. Fairly typical but, ideally, we'd like the page to post directly into our Rails backend (creating a new user). We plan to host our landing pages on Unbounce (or whatever, doesn't really matter) but it's not clear how to post to (users#create) in Rails app from a 3rd party form without running into CSRF and other security token issues.
Perhaps there is a better (read: best practice) for how to a/b test landing pages related to a Rails application? I'm trying to minimize changes to the codebase, if possible, required to run these landing page experiments.
Any thoughts greatly appreciated.
It's good that you're using the Rails defaults for security; you're letting the framework do good work for you! However, for what you're describing, the Rails CSRF protection defaults are going to get in the way. CSRF protection exists to protect signed-in users from having their account hijacked. Since this is your signup page, there is no signed-in user, so there's really nothing to hijack.
I recommend you do two things:
Skip the authenticity token check for this controller action only (example: skip_before_action :verify_authenticity_token, on: :create).
Don't accept the signup request if there's already a signed-in user.

How to validate that a user owns the requested resource through Rails API when using devise_token_auth

I am building an API-only (for now) Rails app to serve as the back end for an Android app I'm building. I was previously using Firebase but wanted to do more processing on application data and I didn't want to bloat the mobile client with all the logic, so I am moving away from Firebase's real-time database and backing the application data using Rails. I was also using Firebase's authentication which is very straightforward. But it seems less complex for the overall system to keep all of this functionality in one place, so I'd like to perform auth and user management in the Rails app as well.
I have installed devise_token_auth (seen here) and finished the basic configuration. The /auth route works correctly if params are provided and creates a user. sign_in and sign_out both successfully create sessions and return some header information. The important parts returned are client, access-token, and uid, which I need to use in future calls to the API. I believe these are invalidated and replaced with each subsequent call. At this part of the flow is where I'm not sure how to proceed. I don't understand how the data in these headers is associated with the user who signed in and how I can validate that they own a resource they request. To summarize the question another way:
How can I sign a user into the API and then validate which user is making subsequent API calls?
My Android app is a task manager, so I need to be able to validate for example that if user 1 requests task 3, that they own that resource. I'm also unsure how to direct index calls using the API. That is, when the index endpoint is hit (/tasks), how can I identify from the data in the API headers which user's tasks I should retrieve.
I haven't been able to find any solid tutorials or samples using devise_token_auth so I'm having trouble stitching together the interaction between the pieces I have now. I know this is a meaty question - thanks in advance for any guidance.
How can I [...] validate which user is making subsequent API calls?
With the current_user method. This is a built-in feature to the devise_token_auth gem.
I need to be able to validate for example that if user 1 requests task 3, that they own that resource
There are many different approaches you could take. You could just write some custom logic in each controller action, using the current_user method (and return 403 forbidden if necessary).
Or, you could use a popular "framework" solution for this such as CanCanCan or Pundit. I, and probably most of the modern community, would recommend Pundit.
I highly advise you to read that library's README, as it's extremely helpful. But for the example above, you could write something like this:
class TasksController
def show
task = Task.find(params[:id])
authorize(task) # !!!
render task
end
end
# app/policies/task_policy.rb
class TaskPolicy
def show?
record.user == user
end
end
(Note that by default, the "user" in Pundit policies calls the method: current_user. This is all explained in the project's README.)
when the index endpoint is hit (/tasks), how can I identify from the data in the API headers which user's tasks I should retrieve
Again, this is all handled as part of Pundit's standard features. You just need to define a TaskPolicy::Scope and call policy_scope(Task) in the controller - as explained here.

Evercookie for rails

I'm finding a solution to detect cheaters creating many accounts at my website.
I have found permanent cross-browser cookies: http://samy.pl/evercookie/
But it written on JS, and I need something to use in rails controller. Is there any gem or plugin like evercookie?
Once I was searching for Evercookie solution for Rails, didn't find and wrote a gem 'evercookie'. You can try it.
Documentation is available on github
Email token (Devise, Sorcery)
Can you send an email to a new user?
A simple solution that many websites use is sending the user an email with a security token. A good Rails gem for this is Devise, and another is Sorcery which makes it simple to build your own custom authentication.
Third-party sign in (OmniAuth, OpenId, Facebook Connect, Twitter, etc.)
Can you authenticate the user with a third-party service?
The OmniAuth gem can connect to many third-party services and let the user authenticate using an existing account on Google, Yahoo, Facebook, Twitter, LinkedIn, and open services including LDAP and Shibboleth.
The OpenId gem works well with Google, Yahoo, and many other large providers; you can also use OpenId within OmniAuth.
In all these cases you would track the sending, so that a user can't apply again too quickly by using the same phone number, postal address, credit card, etc.
Phone Message (Twilio)
Can you send your user a text message?
The Twilio gem enables sending text messages to phone numbers. The concept is that your
app sends them a text message with a verification code.
Snail mail (postalmethods)
The postalmethods gem lets you send real, physical postcards in the postal mail. You can send a postcard with a verification code. This may take a few days, so some sites use this in conjunction with a "probationary period" for new users where they are somewhat sandboxed from causing any trouble. (for example, they can read info, but not post info).
Credit card (BrainTree)
Related ideas are to have the user send you something that requires a credit card, such as using a payment gateway like BrainTree or ActiveMerchant.
You can verify the card is open and valid without charging any money to it. Or you could require a tiny minimum payment, such as requiring the user to send you one dollar via PayPal, Google Payments, Amazon Dev Pay, etc.
Credit card numbers have internal structure (like a checksum) so you could verify that the number is the right format and checksum. A simple script is flame.org
Image Captchas (recaptcha)
To block bots, captchas such as Ruby recaptcha work very well.
Ruby has other captcha solutions and any of these are likely fine.
Karma (hypothes.is)
This isn't a gem, but it's a concept. Give new users limited privileges, such as read-only access. Let users earn new privileges by being a member for a certain amount of time, or by contributing content, or by connecting with friends and peers within your site, etc.
This is how sites like StackOverflow work, and there's a lot of good information about these approaches at http://hypothes.is
Combos
The most powerful approach is combinations of these techniques.
Perhaps give a new user some basic capabilities, such as reading information, and then let him earn new capabilities by doing one or more of the authentications above. This is how Google and Facebook add some features: you can sign up easily, then authenticate other emails, then authenticate your phone number, then authenticate your postal address.
No, there is no Rail drop-in solution and it wouldn't make much sense.
evercookie is written in JavaScript and additionally uses a SWF (Flash) object for the Local Shared Objects and PHPs for the server-side generation of cached PNGs and ETags.
Almost all of the Evercookie techniques rely on special Javascript APIs to the browser, so there's no way of porting them to a server-side technology (except for the small PHP part).
A gem might make integration and updates easier, but it would still be Javascript for the client side.
Please consider the ethical implications of Evercookie. It is a proof of concept, not a tool to be widely used, in my opinion.
If you want to roll out your own solution, a good starting point (with cookies) would be:
def create
if cookies[:xyz]
render :text => 'cheater!'
else
# save the user first (you may need to display the form again), and then set the cookie
cookies[:xyz] = { :value => "1", :expires => 1.day.from_now }
end
end
EDIT: this is not comparable to evercookie, just a simple alternative.
EDIT 2: I already said that captchas are what the author should probably use, so am I being downvoted for showing what a starting point would be if he still wants to use cookies?

Building an api as a service

I am building an api for others to use. This is a simple enough Json request the user passes as some data and we pass some back.
What I would love is to secure our api and have some sort of user system where we can turn users on and off and we can log how many requests each user makes.
What would be the best way to do this in Rails? I don't want it to slow down the request. I can see ways of doing it using devise maybe but would be great to hear other people's opinions.
Thanks
Another way is to use 3scale (http://www.3scale.net) - it's free up to a traffic cap but handles all the key management, users, documentation etc. and there's a ruby library which you can drop into your code if you're using rails. (other libs are here: https://support.3scale.net/libraries).
I've done this before using the Token Authentication capabilities of devise (see https://github.com/plataformatec/devise ).
I found the following setup works:
Create a user account for each api user.
Configure devise for token authentication
Set the Token Authentication configuration to require the token to be submitted with each request.
This will allow you to enable and disable individual users as well as to track every request back to the api user that made the call.
If you're really interested in tracking usage you may want to consider also creating a database table where you track all api requests. This can be setup to belong_to the users table so that you easily find all requests from different users (e.g., #user.api_requests).
The count of all requests made by a user would be:
#user.api_requests.count
# or use a where clause to find how many of each type
#user.api_requests.where("api_request_type = ?", 'SomeAPICallType').count
One final note -- I recently used the Grape library for building out an API. I thought it was pretty well done and it worked great for our needs. I especially like the ability it provided to version APIs. Details are here: https://github.com/intridea/grape/wiki

Rails authorization necessary for post actions?

I have an app I'm writing in rails 3 w/ cancan and devise. I'm curious if authorizing post actions on your controllers is necessary or helpful from a security standpoint? Assuming all my controller actions require authentication w/ devise (ie user must be logged in).
I can see why I need authorization through cancan on my controller actions that use GET's since a user can simply input the url they wish to visit freely and this must be locked down. However, with posts the user must post the data from a form, which is protected against an xss attack with a token.
In this case would it be safe to assume that if i limit the visibility of, say, a button in my view with cancan that the user wouldn't be able to submit a form maliciously?
Thanks alot
EDIT:
Thanks for the quick answer guys. As it has been pointed out below a malicious user can forge a form post using tools such as firebug and thus authorization is necessary.
What would be the best way to simulate this type of interaction (a user posting to an url with a form they've hacked) using capybara / cucumber?
Thanks again.
A user can submit a POST request regardless of whether they are on your website or not. You're correct in thinking that the security token will help prevent XSS, but I would add authentication in for other methods of attacks.
A good (free) ebook to read if you're concerned about security is the Ruby on Rails Security Guide. It outlines all common forms of malicious attacks and even explores some of the lesser used (but just as effective) methods. It also gives great solutions on how to make your application more secure.
You should validate a users authorization in the controller.
With simple tools like FireBug, you can edit the content of a form manually and even add more text fields or similar. The XSS protection won't help you with that.
The user would still be able to generate the button (any method from using Firebug to changing browser code would do) on client side and send the form. If I remember correctly tokens are sent in HTML header co it wouldn't be a problem to forge the form.

Resources