'Why is session[:user_id] nil in some controller actions but not all?

Junior Developer here. Just when I thought I understood Rails entirely, totally stumped yet again. For the life of me, I cannot figure out why session[:user_id] is nil for some controller actions but not all.
I tried everything, helpers, fixing routes and checking cookie setup etc. I have access to session[user_id]/current_user in my #create method within UsersController, so I should have access to it within the adjacent method inside the same controller right?

Any ruby/rails experts willing to give input? This is my first stack overflow post. Go easy on me if I'm breaking any conventional rules of the site. [My Rails Backend Code][1] [React FrontEnd][2]

UPDATE: I have made great progress with devise so far. Able to sign up and login from my react frontend. However, I can't seem to keep the user logged in. I believe the CSRF token might be resetting after each login or sign up. RAILS BACKEND https://github.com/jasonronalddavis/TextStory REACT FRONTEND https://github.com/jasonronalddavis/TextStory_front_end

RAILS BACKEND sessionsController

def get_current_user
    @user = current_api_v1_user
    sign_in(@user)
    if signed_in?(@user)
    render json: UserSerializer.new( @user)
  else
    render json: {
      error: "Not logged in"
    }
  end
end

REACT FRONETEND src/action/user.js

export const getCurrentUser = () => {
  return dispatch => {
    return fetch("http://localhost:3001/api/v1/get_current_user", {
      credentials: "include",
      method: "GET",
      headers: {
        "Content-Type": "application/json",
      'Accept': 'application/json'
      },    
    })
      .then(r => r.json())
      .then(response => {
        if (response.error) {
          alert(response.error)
        } else { 
          const stories = response.data.relationships.story_texts.data

          dispatch(setUser(response.data)) 
           dispatch(userAttr(response.data))  
           dispatch(userStories(stories))
        }
      })
      .catch(console.log())
  }
}


Solution 1:[1]

If you want to build an authentication system to learn about making wheels you need to separate it from the responsibilites of CRUD'ing users which is something completely different.

In the case of classical cookie based auth system this would typically be called SessionsController:

# Handles user authentication
module API
  module V1
    class SessionController < ApplicationController
      # Sign the user in given a name and password 
      # POST /api/v1/sessions
      def create
        user = User.find_by(params[:name])
        if user&.authenticate(params[:password])
          sign_in(user)
          render json: user,
            status: :created
        else
          # always return meaningful HTTP status codes and write your JS 
          # around it 
          render json: {error: "invalid name or password"},
            status: :not_found 
        end
      end
      
      # Resets the users session by overwriting the session identifier cookie
      # DELETE /api/v1/session
      def destroy
        sign_out
        head :no_content # default in later versions of Rails
      end
      
      # GET /api/v1/session
      def show
        render json: current_user
      end
      
      private
      
      def sign_in(user)
        session[:user_id] = user.id 
      end

      def sign_out
        session.delete(:user_id)
      end
    end
  end
end

This is modeled as CRUD but we are actually just modifying the session storage (typically a cookie). Using a middleware based approach to authentication like Warden would be superior though as this allows you mock authentication in your tests and use it thoughout the middleware stack like for example in your routes.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 max