1

stack app using React for the Front-End and Rails as my API, the problem I am facing is that I cannot set the cookie in my browser when I deploy my application, the front end I deployed it using Netlify and for the back end I used Heroku, the problem I have is that anytime I try to log in a user I get the error "This attempt to set a cookie via Set-Cooke header was blocked because it had the "SameSite=Lax" attribute but came from a cross-site response which was not the response to a top-level navigation" I have been trying to fix this for the last few days, looking for an answer, so I started by doing a few things for example I have on my back end application activated the Cors gem and also I have added a cors.rb file to my initializers here is the code I have

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'http://localhost:3000'
    resource '*',
             headers: :any,
             methods: %i[get post put patch delete options head],
             credentials: true
  end
  
  allow do
    origins 'https://vibrant-heyrovsky-039c58.netlify.app'
    resource '*',
             headers: :any,
             methods: %i[get post put patch delete options head],
             credentials: true
  end
end

I also added a current.rb file to my model to have access to the attributes from the user

class Current < ActiveSupport::CurrentAttributes
  attribute :user
end

and inside my application_controller.rb file I added the following code to set the current user

class ApplicationController < ActionController::Base
  skip_before_action :verify_authenticity_token
  before_action :set_current_user

  def set_current_user
    Current.user = User.find_by(id: session[:user_id]) if session[:user_id]
  end
end

my sessions_controller looks like this

class SessionsController < ApplicationController
  def create
    user = User
      .find_by(email: params['user']['email'])
      .try(:authenticate, params['user']['password'])

    if user
      session[:user_id] = user.id
      render json: {
        status: :created,
        logged_in: true,
        user: user
      }
    else
      render json: { status: 401 }
    end
  end

  def logged_in
    if Current.user
      render json: {
        logged_in: true,
        user: Current.user
      }
    else
      render json: {
        logged_in: false,
        user: nil
      }
    end
  end

  def logout
    # reset_session
    session[:user_id] = nil
    render json: { status: 200, logged_out: true }
  end
end

on my front end the way I am making calls to my back end is by using RTK query and have mode: cors added as well and credentials include here is the code

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

export const checkLoginStatusapi = createApi({
  reducerPath: 'checkLoginStatus',
  baseQuery: fetchBaseQuery({
    baseUrl: 'https://lavista-authentication-api.herokuapp.com',
    // baseUrl: 'http://localhost:3001',
    credentials: 'include',
    mode: 'cors',
  }),
  tagTypes: ['Session', 'Expenses'],
  endpoints: (builder) => ({
    userSession: builder.mutation({
      query(body) {
        return {
          url: 'sessions',
          method: 'POST',
          body,
        };
      },
      invalidatesTags: ['Session'],
    }),
    registerUser: builder.mutation({
      query(body) {
        return {
          url: 'registrations',
          method: 'POST',
          body,
        };
      },
      invalidatesTags: ['Session'],
    }),
    getLoginUserInfo: builder.query({
      query: () => 'logged_in',
      providesTags: ['Session'],
    }),

    logoutUser: builder.mutation({
      query() {
        return {
          url: 'logout',
          method: 'DELETE',
        };
      },
    }),
    getUserExpenses: builder.query({
      query: () => 'expenses/',
      providesTags: ['Expenses'],
    }),
    postUserExpenses: builder.mutation({
      query(body) {
        return {
          url: 'expenses',
          method: 'POST',
          body,
        };
      },
      invalidatesTags: ['Expenses'],
    }),
    updateExpenses: builder.mutation({
      query(data) {
        const { id, ...body } = data;
        return {
          url: `expenses/${id}.json`,
          method: 'PUT',
          body,
        };
      },
      invalidatesTags: ['Expenses'],
    }),
    deleteExpense: builder.mutation({
      query(id) {
        return {
          url: `expenses/${id}.json`,
          method: 'DELETE',
        };
      },
      invalidatesTags: ['Expenses'],
    }),
  }),
});

export const {
  useGetLoginUserInfoQuery,
  useLogoutUserMutation,
  useUserSessionMutation,
  useRegisterUserMutation,
  useGetUserExpensesQuery,
  usePostUserExpensesMutation,
  useUpdateExpensesMutation,
  useDeleteExpenseMutation,
} = checkLoginStatusapi;

I have researched for an answer everywhere and can't seem to find how to fix it yet. the last thing I can provide is the response i get from the headers which include Access-Control-Allow-Credentials set to true and the Access-Control-Allow-Origin is looking at my front end app web address. Which i got from a previous question Set cookies for cross-origin requests But even after doing all it I can't seem to make it work yet.

Cosmel
  • 45
  • 9

0 Answers0