Rails API + React Frontend: ¿cómo hacer que la cookie CSRF NO sea httponly?
Tengo una API de Rails 6 y un frontend de React y me gustaría mantener verify_authenticity_token
en todas las acciones del controlador.
El backend establece el token CSRF de la siguiente manera en application_controller.rb
:
class ApplicationController < ActionController::Base
...
include ActionController::Cookies
after_action :set_csrf_cookie
...
protected
def verified_request?
super || request.headers['X-CSRF-Token'] === cookies['X-CSRF-Token']
end
def set_csrf_cookie
if protect_against_forgery? && current_user
cookies['X-CSRF-Token'] = {
value: form_authenticity_token,
httponly: false
}
end
end
end
El frontend intenta usar js-cookie para obtener las cookies. Tengo lo siguiente en un archivo cookies.js
:
import Cookies from 'js-cookie'
const getCSRFToken = () => {
window.Cookies = Cookies;
const token = Cookies.get('X-CSRF-Token')
return token
}
export default getCSRFToken
Y llamo a esta función cuando creo una solicitud Axios. La función para construir la solicitud toma parámetros como método, URL, datos, etc.:
export const newAxiosIns = params => {
// Los parámetros serán un hash de distintos encabezados
const defaultParams = {
baseURL: baseUrl,
withCredentials: true,
headers: {
common: {
'X-CSRF-TOKEN': getCSRFToken()
}
}
}
const axiosIns = axios.create(defaultParams)
return axiosIns(params)
}
Pero las cookies terminan siendo httponly
en Chrome:
Me pregunté si tenía que ver con el form_authenticity_token
, así que hice un token falso con un valor de ‘faker’, pero tampoco era httponly
.
¡Gracias!
davy.ai
Solución
El problema parece ser que la bandera
httponly
está establecida entrue
cuando se establece el token CSRF en el métodoset_csrf_cookie
en elApplicationController
. Esto significa que la cookie no se puede acceder desde JavaScript, por lo que la bibliotecajs-cookie
no puede recuperarla.Para solucionar este problema, puedes establecer la bandera
httponly
enfalse
al configurar la cookie del token CSRF en elApplicationController
:Esto permitirá que el frontend recupere la cookie del token CSRF utilizando la biblioteca
js-cookie
.Además, ten en cuenta que el nombre del encabezado que se utiliza para enviar el token CSRF en el frontend (
X-CSRF-TOKEN
) es diferente del nombre del encabezado que se lee en el métodoverified_request?
en el backend (X-CSRF-Token
). Asegúrate de utilizar el mismo nombre de encabezado en ambos lugares.Entonces, la función
newAxiosIns
debería verse así en cambio:Con estos cambios, la cookie del token CSRF ahora debería poder ser recuperada por el frontend.