Day 14: #100DaysofCode - Finalized my Sinatra Project -Security
Tags: ruby, sinatra, security, womenintech
Published: 2020-06-15 01:28:20

<center><h4><b><u><a href="https://github.com/SincerelyBrittany/stockTracker"> My Sinatra Project </a></b></u> </h4>
<h1><b><u> SECURITY</b></u> </h1>
</center>

Something that became very important during the building of my Sinatra project was <i>SECURITY</i>. It is important that once your application is deployed that you ensure that you are taking proper precautions to make sure that your application is secure from cyber attacks. While building my first Sinatra project, I learned a lot about some of the most basic and simple ways to make sure that your project is secure. 

<h2> <b>1. gitignore</b> </h2>
Some may not agree, but I feel like every project on Github should have a ``.gitignore`` file. A ``.gitignore`` file allows us to "hide" certain files by preventing those files from being pushed/tracked by git. It is very simple to use, just create a file named ``.gitignore`` and then add the name of the file that you want to ignore. So for example, I had a notes file that I wanted to keep for myself and I did not want the world/github to know about. I created my <i> .gitignore</i> file and then created a file named <i> secret_notes.txt</i>.

Within my ``.gitignore`` file, I added the following: 

```
secret_notes.txt
```
It was that simple. 

If you recall from my previous <a href="https://dev.to/sincerelybrittany/day-7-100daysofcode-setting-up-a-sinatra-app-part-3-3nm9"> post </a>, when building a Sinatra project, your environment will have a "SINATRA_ENV" which defines your deployment environment, configures our database, and requires all the files in our app.require a password. My project was no different, my environment looked like this:

```
ENV['SINATRA_ENV'] ||= "development"

if ENV['SINATRA_ENV'] == "development"
  require_relative "../secrets"
end

require 'bundler/setup'
Bundler.require(:default, ENV['SINATRA_ENV'])

ActiveRecord::Base.establish_connection(
  :adapter => "sqlite3",
  :database => "db/#{ENV['SINATRA_ENV']}.sqlite"
)

```
The above requires my ``"../secrets"``, but when you go to my <a href="https://github.com/SincerelyBrittany/stockTracker"> Github repo</a> the secrets file is not available, as you may have guessed, the file was placed in my ``gitignore`` file and although you can not see it I will tell you that I placed a secure sessions password and api keys in the ``secrets.rb`` file.

<h2><b>2. Securing Users Password </b> </h2>
One way to protect the users interacting with your application is to protect their passwords. An easy way to do this is to use the <a href="https://github.com/codahale/bcrypt-ruby"> bcrypt-ruby </a> gem. The gem essentially takes a users password and encrypts it by using a hash algorithm. 

I used <a href="https://github.com/codahale/bcrypt-ruby"> bcrypt </a> in my application by adding the gem to my gemfile by running: ``bundle add bcrypt``

The bcypt Ruby gem provides you with ``has_secure_password`` method. The <a href="https://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html#method-i-has_secure_password"> has_secure_password method</a> encrypts passwords by hashing and salting the passwords and generating a ``password_digest``. <a href="https://github.com/codahale/bcrypt-ruby"> bcrypt </a> requires that you use ``password_digest`` as your attribute name in your user migrations table. I did that in my <a href="https://github.com/SincerelyBrittany/stockTracker/blob/master/db/migrate/20200606205655_create_users.rb"> users table</a>, like this:

```
class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :username
      t.string :email
      t.string :location
      t.integer :age
      t.string :password_digest
      t.timestamps
    end
  end
end
```
Then within my <a href="https://github.com/SincerelyBrittany/stockTracker/blob/master/app/models/user.rb"> users model</a>, I made sure add the ``has_secure_password`` macro inside of my User class, like this:

```

class User < ActiveRecord::Base 

has_secure_password
has_many :watchlists
has_many :stocks, through: :watchlists
validates :username, uniqueness: true
validates :username, presence: true
validates :email, presence: true

end
```

<h2><b> 2. Sessions & User Authentication </b> </h2>
A great way to ensure that someone is who they claim to be when they sign up and login is to use cookie and session based authentication.

What is cookie and session based authentication?
<a href="https://www.tutorialspoint.com/What-is-the-difference-between-session-and-cookies#:~:text=Cookies%20and%20Sessions%20are%20used,and%20their%20values%20are%20stored"> Cookies and Sessions are used to store information. Cookies are only stored on the client-side machine, while sessions get stored on the client as well as a server. </a>

What that means is that once you sign up a cookie is saved on the browser and a session is stored on the server. From then on every time you you log in or make future request, some of data stating that it is you gets sent with your HTTP request, confirming that you are an authenticated user. 

To set up my sessions I enabled sessions and created a sessions secret to my <a href="https://github.com/SincerelyBrittany/stockTracker/blob/master/app/controllers/application_controller.rb"> applications_controller</a>.  

```
  enable :sessions
  set :session_secret, ENV['SESSION_PASSWORD']
```

<h2><b>3. Secure password </b> </h2>

How did I create a secure sessions password for my environment? I generated a secured random number by using the <a href="https://rubygems.org/gems/sysrandom/versions/1.0.5"> sysrandom </a> gem. It is recommended that everyone use a gem similar to this to generate secure passwords. Simply do the following in your terminal to get a secure password: 

First install the sysrandom:
```
gem install sysrandom
``` 
Then run the following, which will generate a random string of  hexadecimals:
```
ruby -e "require 'sysrandom/securerandom'; puts SecureRandom.hex(64)"
```
It should return something similar to this:

```
5ac1ac3c2ec64ef76ac91018059f541b7e8f437fbda1ccddb4f2c56a9ccf1e75
```
I used that number to require it in my environment, I also required my api numbers provided by the <a href="https://iexcloud.io/"> IEX CLOUD </a> api. 

My ``secrets.rb`` file looked like this: 
```
ENV['SECRET_TOKEN_ID'] = "sk_oiherbnbdlfoiuhejkwbf9ubkjdhfuihf"
ENV['PUBLISHABLE_TOKEN_ID'] = "pk_kjdhfewuohjwni23yhuijkebiwr"
ENV['SESSION_PASSWORD'] = "5ac1ac3c2ec64ef76ac91018059f541b7e8f437fbda1ccddb4f2c56a9ccf1e75"
```
<h2> <b>3. Sanitizing User Input </b> </h2>
<q><i> <a href="https://www.esecurityplanet.com/browser-security/prevent-web-attacks-using-input-sanitization.html#:~:text=Input%20sanitization%20describes%20cleansing%20and,a%20false%20sense%20of%20security."> Input sanitization describes cleansing and scrubbing user input to prevent it from jumping the fence and exploiting security holes. But thorough input sanitization is hard. While some vulnerable sites simply don’t sanitize at all, others do so incompletely, lending their owners a false sense of security. </a>

Simply put, when a user is going to your website, they may not have the best intentions. For me, I wanted a user to come to my website and create a Watchlist name through a form like this: 

```
<h3>Create a New Watchlist</h3>

<form action="/watchlists" method="POST">
  <input type="text" name="watchlist[name]" id="watchlist_name" placeholder="Watchlist Name"><br>
  <input type="submit" value="Create Watchlist">
</form>
```

But what if instead of the user inputting text, they inserted a piece of javascript that generated a pop up box on the application, something like this:

```
<script>
function myFunction() {
  alert("Hello! I am an alert box!");
}
</script>
```
What if the user created a script that jeopardized my entire application and created a pop up box for all users using my application. There are ways to prevent this and I learned two different ways to avoid this kind of attack while building this project. 

<h3> Using The Sanitize Gem </h3>
The first way I learned was to use the <a href="https://github.com/rgrove/sanitize"> sanitize gem </a> to avoid <a href="https://www.esecurityplanet.com/threats/how-to-prevent-sql-injection-attacks.html">SQL injection</a>, <a href="https://www.esecurityplanet.com/browser-security/how-to-prevent-cross-site-scripting-xss-attacks.html">cross-site scripting</a> (XSS), and <a href="https://www.esecurityplanet.com/browser-security/how-to-prevent-remote-file-inclusion-rfi-attacks.html">remote file inclusion</a> (RFI). 

The gem allows us to ``Sanitize.fragment(html)`` to 

I chose to use ``Sanitize.fragment(html)`` which uses its strictest settings by default, which means it will strip all HTML and leave only safe text behind. This gem is helpful because you can personalize it to allow certain html elements in the input from users. Feel free to look at the <a href="https://github.com/rgrove/sanitize"> gem docs</a> for more examples. 

Personally, I used the gem in my ``post '/watchlists'`` within my <a href="https://github.com/SincerelyBrittany/stockTracker/blob/master/app/controllers/watchlists_controller.rb">watchlist_controller</a> after a user creates a new name for a watchlist, it will Sanitize the user input and save it after it is Sanitized, like this --
```
   post '/watchlists' do
     authenticate
    if params[:watchlist][:stock] == nil
     @watchlist = current_user.watchlists.new(name: Sanitize.fragment(params[:watchlist][:name]), user_id: params[:user_id])
      if @watchlist.save
        flash[:message] = "You have successfully created a watchlists."
      redirect "/watchlists"
```
<h3> Using .Gsub </h3>

When you google grep and gsub you'll see something like this:
<a href="https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/grep"> Grep search for matches to argument pattern within each element of a character vector: they differ in the format of and amount of detail in the result and .gsub replaces all occurrences. If replacement contains backreferences which are not defined in pattern the result is undefined (but most often the backreference is taken to be "")</a>

To grasp a better understanding, I collaborated with some of my classmates and learned how to prevent a user from inputting inappropriate data into my application while signing up. One way is by using grep, regex and .gsub. 

Within my <a href="https://github.com/SincerelyBrittany/stockTracker/blob/master/app/controllers/users_controller.rb"> signup controller</a> you will see that the ``post signup`` has the following information:

```
  post '/signup' do
      @u = User.new(:username => params[:username].gsub(/[\<\>\/]/, ""),
                          :password => params[:password],
                          :email => params[:email].gsub(/[\<\>\/]/, ""),
                          :location => params[:location].gsub(/[\<\>\/]/, ""),
                          :age => params[:age].gsub(/[\<\>\/]/, ""))
      if @u.save
          session[:user_id] = @u.id
          redirect "/watchlists"
      else
          erb :'sessions/signup'
      end
  end
```

The ``.gsub`` searches for matches in my argument pattern ``(/[\<\>\/]/, "")`` and if it matches it will result in an undefined/blank answer. So if someone signs up and puts ``<h1> Hello</h1>`` as there username. It will result in a username of ``h1helloh1`` removing the ``<>`` tags and essentially not effecting the application at all, but instead gives the user a ridiculous username. 

I learned a lot about how to protect my application and the individuals using my application while building this application and look forward to learning more ways to protect future projects that I build. 

Resources
<a href="https://medium.com/@tpstar/password-digest-column-in-user-migration-table-871ff9120a5"> Password_digest column in User migration table </a>

<a href="https://medium.com/@ashleymcolletti/add-authentication-to-your-rails-app-with-bcrypt-a53917252159"> Add Authentication to Your Rails App With bcrypt </a>

Feel free to use my<b><u><a href="https://github.com/SincerelyBrittany/stockTracker"> Sinatra Project </a></b></u> and contribute to it. 

<a href="https://soundcloud.com/spotlightfirst/eryn-allen-kane-her-pain-bj-the-chicago-kid-kendrick-lamar-remix"> Song of the day</a>