0

I am trying to set up a minimal layer of authentication between my Rails backend and my React front end, but I am running into some problems.

  1. I cannot seem to find the cookie key value that the server passes down to my client. In the network tab, I see it in the response: Set-Cookie:_skillcoop_session=...., but when I use js-cookie to look for the above cookie, _skillcoop_session, I only see one called identity-token=... and its value is different from _skillcoop_session. How do I access _skillcoop_session in the browser?

  2. What header key do I pass up to the server to signal to my backend to use 'this' header key to match up with the session it has stored off? In this post, Justin Weiss seems to suggest that I make the request to the server with a header like: Cookie: _skillcoop_session=....

  3. Am I doing this all wrong? Would I be better off using a gem like devise?

  4. Also in order to load the session in my other controllers, I have had to do something like session['init'] = true, and I learned to do this from this SO post. This seems hacky. Why do I have to manually reload the session in separate controller actions after I've set it previously in a different controller action in a different request?

I'm currently just stubbing out the user and the authentication -- all I want to do to get the plumping in place is set a session[:user_id] and be able to read that session data in other controller actions. For this I have two main files for consideration: UsersController and Transport.js. In UsersController I am just stubbing the session[:user_id] with the number 1 and in Transport.js I'd like to pass the cookie received from the server so that the backend can maintain a session between requests with a client.

Here is my controller:

class UsersController < ApplicationController

  def create
    session[:user_id] = 1
    render json: user_stub, status: :ok
  end

  def show
    puts "user id: #{session[:user_id]}"
    # should return, 1, but is returning, nil...why?
    render json: user_stub, status: :ok
  end

  private

  def user_stub
    {
      id: 1,
      email: params['email'] || 'fakeemail@gmail.com',
      password: params['password'] || 'fake password'
    }
  end
end

Here is the main location of my app where I make my request to the server - it's in an abstraction I call Transport.js:

require('es6-promise').polyfill();
require('isomorphic-fetch');
var cookie = require('js-cookie');


const GET = 'GET';
const POST = 'POST';

function Transport() {
}

Transport.prototype.get = function(url, options = {}) {
  return this.query(GET, url, null, options);
};

Transport.prototype.post = function(url, dataString, options = {}) {
  return this.query(POST, url, dataString, options);
};

Transport.prototype.query = function(method, url, dataString, options = {}) {
  var data;

  if (dataString) {
    data = JSON.parse(dataString);
  }

  switch(method) {
    case GET:
      return fetch(url, Object.assign({headers: {'Cookie': cookie.get('_skillcoop_session')}}, options, {
        method: method
      }));
    case POST:
      return fetch(url, Object.assign({
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
      }, options, {
        method: method
      }));
    default:
      throw new Error("This HTTP Method is not supported.");
  }
};

module.exports = Transport;
robskrob
  • 2,720
  • 4
  • 31
  • 58

1 Answers1

1
  1. According to this SO post, one cannot access the Set-Cookie header in JS. Thus, I suppose my attempts to handle Set-Cookie in the response headers was a fools effort.

  2. According to the NPM package that I'm using to make HTTP requests, I need to pass {credentials: 'same-origin'} key value pair in the second argument to fetch, which will 'automatically send cookies for the current domain'. That did the trick -- the session object is available and contains the user_id that was set in the session in the previous request in a different action.

  3. Yes. I changed up how I approached this problem. I leaned very heavily on this Reddit post. In short, I use ruby-jwt on the backend and store the token in localStorage on the front end. Each request out to the server will include the token in a header AUTHORIZATION.

  4. In following steps 1 and 2, it looks like I no longer have to 'reload the session'.

robskrob
  • 2,720
  • 4
  • 31
  • 58