0

I have created a Rails app that I'm using as api app (with an angular front end). When I try to create a session on SessionsController#create, I am setting session[:user_id] and returning a user object. My front end app is successfully getting this object and redirecting the browser to #/dashboard. DashboardComponent has a guard that calls my SessionsController#logged_in which checks for a session in my rails app. When I'm running locally, this works with no issues. However, when deployed to Heroku, session[:user_id] is empty. I'm not sure what I'm doing wrong. I know it's not a CORS or a CSRF issue because my client app gets the user object (I am logging it to the console).

Here is my initializers/session_store.rb

if Rails.env == "production"
  Rails.application.config.session_store :cookie_store, key: "_myapp", domain: "api-app.herokuapp.com"
else
  Rails.application.config.session_store :cookie_store, key: "_myapp"
end

And just for fun, here's my initializers/cors.rb

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins "http://localhost:4200", "https://angular-app.herokuapp.com"
    resource "*", 
      headers: :any, 
      methods: [:get, :post, :put, :patch, :delete, :options, :head], 
      credentials: true
  end
end

SessionsController.rb

class SessionsController < ApplicationController
    include CurrentUserConcern
  
    def create
      user = User
              .find_by(email: params["email"])
              .try(:authenticate, params["password"])
  
      if user
        session[:user_id] = user.id
        render json: user, status: :created
      else
        head :unauthorized
      end
    end
  
    def logged_in
      if @current_user
        render json: @current_user, status: :ok
      else
        head :no_content
      end
    end
  
    def logout
      reset_session
      head :no_content
    end
  end

current_user_concern.rb

module CurrentUserConcern
  extend ActiveSupport::Concern

  included do
    before_action :set_current_user, only: [:logged_in]
  end

  def set_current_user
    puts session[:user_id]
    if session[:user_id]
      @current_user = User.find(session[:user_id])
    end
  end
end

I can provide any other code that might help

kroe761
  • 3,296
  • 9
  • 52
  • 81
  • The cookie isn't being shared between the api domain (api-app.herokuapp.com) and the angular domain (angular-app.herokuapp.com). It will always look like a new session to the api app. Need to update your Rails.application.config.session_store to work across subdomains. https://stackoverflow.com/questions/10402777/share-session-cookies-between-subdomains-in-rails for some hints, likely need to set the tld_length. – dbugger Dec 16 '20 at 17:06
  • I modified the production config on `session_store.rb` to this: `Rails.application.config.session_store :cookie_store, key: "_myapp", domain: :all, tld_length: 2` but this did not resolve my issue. – kroe761 Dec 16 '20 at 17:23
  • A cookie isn't added. I also tried adding my client app domain to the session_store, like this: `Rails.application.config.session_store :cookie_store, key: "_myapp", domain: "thawing-river-95379.herokuapp.com", tld_length: 2`, but it also had no effect – kroe761 Dec 16 '20 at 19:13
  • What does your angular code look like to call the api login? Guessing it does not do anything with the cookie, betting you need to set it. – dbugger Dec 16 '20 at 19:35

1 Answers1

1

I was able to solve this issue with a custom domain name. i set my angular app to use www.kroe761.com and my api to use api.kroe761.com. i then set my session_store to this: Rails.application.config.session_store :cookie_store, key: "_myapp", domain: :all, tld_length: 2

So, clearly the issue had something to do with the domains of the client and api being different. I don't know how to configure everything under that scenario (if you do, please add an answer for my edification), but for now the issue is resolved.

kroe761
  • 3,296
  • 9
  • 52
  • 81