Skip to content

Instantly share code, notes, and snippets.

@jendiamond
Last active September 24, 2019 23:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jendiamond/55a2009f82331d0c5ffef3d3be21624e to your computer and use it in GitHub Desktop.
Save jendiamond/55a2009f82331d0c5ffef3d3be21624e to your computer and use it in GitHub Desktop.

Cookies Sessions and Encryption

chrome://settings/siteData

  • We send a token in a post request triggered by the button to EMEL
  • Then EMEL authenticates the User
  • Then EMEL sends back a GET request which returns the token in a redirect which follows the callback URL back to our SinaiPOC
  • Then WE verify the token by checking to see if it is stored in the database

NEXT

  • Set a cookie with the domain: sinai2.library.ucla.edu
  • when UV tries to request the images the browser will send the cookie along with that request
  • Then Cantaloupe will verify the cookie through the Rails delegate script
  • Then Cantaloupe sends the image to the UV
  • Set an ENV variable for Sinai domain name (this will be the domain to test on. (For now SET it to http://localhost:3000)

Cookies are read and written through ActionController#cookies.

https://api.rubyonrails.org/v5.2.1/classes/ActionDispatch/Cookies.html
https://stackoverflow.com/questions/6244402/how-to-set-cookies-in-applicationcontroller
The cookies being read are the ones received along with the request,
the cookies being written will be sent out with the response.
Reading a cookie does not get the cookie object itself back, just the value it holds.

You would set cookie in browser corresponding to some controller action. If you want to set the cookie for all actions then you may consider using a before filter and apply that filter to all your controller actions.

Please note that if you specify a :domain when setting a cookie, you must also specify the domain when deleting the cookie.

e.g. cookies[:user_name] = "david"

You can also use cookies.signed[:key]=... to have the cookie value encrypted to prevent it from external modification.

   cookies.signed[:key] = {
       :value => 'a yummy cookie',
       :expires => 1.year.from_now,
       :domain => 'domain.com'
     }

     cookies.delete(:key, :domain => 'domain.com')

You can simplify for cookies you want to hang around for a while

cookies.permanent[:some_cookie] = "gingerbread"


https://www.justinweiss.com/articles/how-rails-sessions-work/

Sessions are little bits of data you want to keep around for more than one request.

session[:current_user_id] = @user.id

What is a session? A session is just a place to store data during one request that you can read during later requests.

You can set some data in a controller action:

app/controllers/sessions_controller.rb

def create
  # ...
  session[:current_user_id] = @user.id
  # ...
end

And read it in another:
app/controllers/users_controller.rb

def index
  current_user = User.find_by_id(session[:current_user_id])
  # ...
end

It might not seem that interesting. But it takes coordination between your user’s browser and your Rails app to make everything connect up. And it all starts with cookies.

When you request a webpage, the server can set a cookie when it responds back:

~ jweiss$ curl -I http://www.google.com | grep Set-Cookie

Set-Cookie: NID=67=J2xeyegolV0SSneukSOANOCoeuDQs7G1FDAK2j-nVyaoejz-4K6aouUQtyp5B_rK3Z7G-EwTIzDm7XQ3_ZUVNnFmlGfIHMAnZQNd4kM89VLzCsM0fZnr_N8-idASAfBEdS; expires=Wed, 16-Sep-2015 05:44:42 GMT; path=/; domain=.google.com; HttpOnly

Your browser will store those cookies. And until the cookie expires, every time you make a request, your browser will send the cookies back to the server:

...
> GET / HTTP/1.1
> User-Agent: curl/7.37.1
> Host: www.google.com
> Accept: */*
> Cookie: NID=67=J2xeyegolV0SSneukSOANOCoeuDQs7G1FDAK2j-nVyaoejz-4K6aouUQtyp5B_rK3Z7G-EwTIzDm7XQ3_ZUVNnFmlGfIHMAnZQNd4kM89VLzCsM0fZnr_N8-idASAfBEdS; expires=Wed, 16-Sep-2015 05:44:42 GMT; path=/; domain=.google.com; HttpOnly
...

Set-Cookie: 1P_JAR=2019-09-19-16;
expires=Sat, 19-Oct-2019 16:18:55 GMT;
path=/;
domain=.google.com;
SameSite=none
Set-Cookie: NID=188=j0vqCiA-9VenBdu5FT-GieqCnIPxFlWnkjwU8tOJi-0yJ89djgA9NGZm3iA4T2MelaEd-i6bobd3JZ4554Vtr4JniHzrnKIIeX7NLFvBTtorXShhc-XDby-1Jx1U7AdiqZOC2zB_yKtQ4KmEoVPndafATN2z3urcY-sg4uuvqDk; expires=Fri, 20-Mar-2020 16:18:55 GMT;
path=/;
domain=.google.com;


Session Storage

https://guides.rubyonrails.org/security.html#session-storage

Rails uses ActionDispatch::Session::CookieStore as the default session storage.

Rails CookieStore saves the session hash in a cookie on the client-side. The server retrieves the session hash from the cookie and eliminates the need for a session ID. That will greatly increase the speed of the application, but it is a controversial storage option and you have to think about the security implications and storage limitations of it:

  • Cookies have a size limit of 4kB. Use cookies only for data which is relevant for the session.

  • Cookies are stored on the client-side. The client may preserve cookie contents even for expired cookies. The client may copy cookies to other machines. Avoid storing sensitive data in cookies.

rovide a secure connection over SSL

config.force_ssl = true

  • Cookies are temporary by nature. The server can set expiration time for the cookie, but the client may delete the cookie and its contents before that. Persist all data that is of more permanent nature on the server side.

  • Session cookies do not invalidate themselves and can be maliciously reused. It may be a good idea to have your application invalidate old session cookies using a stored timestamp.

  • Rails encrypts cookies by default. The client cannot read or edit the contents of the cookie, without breaking encryption. If you take appropriate care of your secrets, you can consider your cookies to be generally secured.

The CookieStore uses the encrypted cookie jar to provide a secure, encrypted location to store session data. Cookie-based sessions thus provide both integrity as well as confidentiality to their contents.

The encryption key, as well as the verification key used for signed cookies, is derived from the secret_key_base configuration value.

Secrets must be long and random. Use rails secret to get new unique secrets.

secret_key_base

https://medium.com/@michaeljcoyne/understanding-the-secret-key-base-in-ruby-on-rails-ce2f6f9968a1


Start using encrypted secrets

https://www.engineyard.com/blog/encrypted-rails-secrets-on-rails-5.1

The default secrets.yml generated by Rails read the secret_key_base from the environment variable SECRET_KEY_BASE. You can follow this pattern when adding your other secrets.

Rails Authentication from scratch

https://www.youtube.com/watch?v=Hw6WtWJwRtU You need to generate a key.
On your Rails root directory, run

bin/rails secrets:setup


sinai-id.org locally stored data

_rails-devise_session
Name
_rails-devise_session
Content
WjhEV0drMC9ORU1EK1FIZGt2L0Q3dHRUdWZFSUErOFMrb3RhOUt4ZGhId050cjVMdUFiQUpGZHhySXdMZ1lZemxCYUw3OFpxSXp3RzlrQzhRQXh3V0hOOTEvSHN6UlJzSzl5NlFTdFBBMGZXWmphS0hrZjFyVC9tWHR3ekxPSE4vR3c3Q093ZC9qWnVoSnNtOGtoT2hqYS9HeFNoLzlKUFM3MzkyTVdGSC9Xd2h2dytENUJMaHdHNk0wc0dLQy9zQlEyYUVhOCs0R1d4eHdFUWJuZjRKVm03RVVNdzh2T2haS1RXR3dpemRZZkJObUdkOFpWci9aZDU3S05VMkFqeS0tS0NpaDhYTHNyRXhVOXlKYUp1MTBsdz09--170fa6789e4c125b6c33008b93e14a986c9591df
Domain
sinai-id.org
Path
/
Send for
Any kind of connection
Accessible to script
No (HttpOnly)
Created
Thursday, September 19, 2019 at 10:24:16 AM
Expires
When the browsing session ends
remember_user_token
Name
remember_user_token
Content
W1s0ODddLCIkMmEkMTEkcXpvM29jS0suM3FyMVRTMlhZaXB2LiIsIjE1Njg5MTM4NTYuOTAyNzA2MSJd--a009d84342673b62a806e3a4253268fd368a14d4
Domain
sinai-id.org
Path
/
Send for
Any kind of connection
Accessible to script
No (HttpOnly)
Created
Thursday, September 19, 2019 at 10:24:16 AM
Expires
Thursday, October 3, 2019 at 10:24:16 AM

Cookie expiration is different from Rail 5.1 to 5.2

https://blog.bigbinary.com/2017/10/09/expirty-option-for-signed-and-encrypted-cookies-in-rails-5-2


Tuesday September 24, 2019

we learned

  • that you can not set an instance variable when you are redirecting
  • how to call the paths of the URL
    • @domain = request.domain
    • @port = request.port
    • #@base_url = request.url
    • @requested_path = params[:callback]
    • @full_path = "http://#{@domain}:#{@port}#{@requested_path}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment